From 85e17ede84f00332c0636fa8a7ce123ec2607262 Mon Sep 17 00:00:00 2001 From: Jacob Date: Sat, 30 Nov 2024 11:15:18 -0500 Subject: [PATCH] Addition with floats is now entirely possible. --- Makefile | 2 +- src/grammar.y | 8 ++++---- src/include/lexer.h | 6 ++++++ src/lexer.c | 43 +++++++++++++++++++++++++++++++++++++------ 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 445f3bf..d46c45a 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ TEST_OBJ_DIR = $(TEST_BUILD_DIR)/obj CC = clang LINK = clang CFLAGS = -Wall -DDBG -ggdb -LDFLAGS = +LDFLAGS = -lm SRC_FILES = $(wildcard $(SRC_DIR)/*.c) OBJ_FILES = $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC_FILES)) diff --git a/src/grammar.y b/src/grammar.y index cf17279..67e30c7 100644 --- a/src/grammar.y +++ b/src/grammar.y @@ -35,13 +35,13 @@ input: ; exp: - NUM { $$ = ast_init(AST_TYPE_NUM, ast_type_num_init($1)); } + NUM { $$ = ast_init(AST_TYPE_NUM, ast_num_data_init($1)); } | NUM PLUS NUM { AST* argv[2] = { - ast_init(AST_TYPE_NUM, ast_type_num_init($1)), - ast_init(AST_TYPE_NUM, ast_type_num_init($3)) + ast_init(AST_TYPE_NUM, ast_num_data_init($1)), + ast_init(AST_TYPE_NUM, ast_num_data_init($3)) }; - $$ = ast_init(AST_TYPE_CALL, ast_type_call_init("+", 2, argv)); + $$ = ast_init(AST_TYPE_CALL, ast_call_data_init("+", 2, argv)); }; %% diff --git a/src/include/lexer.h b/src/include/lexer.h index 9fb7631..e040ea2 100644 --- a/src/include/lexer.h +++ b/src/include/lexer.h @@ -17,6 +17,12 @@ extern YYSTYPE yylval; extern char* inp; +// Accumulate an integer. +int acc_int(int c); + +// Accumulate a floating-point number. +double acc_float(int c); + // Called by `yyparse()` (in bison-generated files.) int yylex(); void yyerror(char const* s); diff --git a/src/lexer.c b/src/lexer.c index c06c44b..06bc4c9 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -1,9 +1,45 @@ #include #include #include +#include #include "include/lexer.h" +int acc_int(int c) { + int value = c - '0'; + while (isdigit(*inp)) { + value = value * 10 + (*inp - '0'); // Accumulate value. + inp++; + } + return value; +} + +double acc_float(int c) { + double value = (double)(c - '0'); + + // Grab everything prior to '.'. + while (isdigit(*inp)) { + value = value * 10 + (*inp - '0'); // Accumulate value. + inp++; + } + + if (*inp == '.') { + char* oinp = inp++; + while (isdigit(*inp)) { + // Accumulate as int, divide once at end. + value = value + (((double)(*inp - '0'))/pow(10.0l, (double)(inp-oinp))); // Accumulate value. + inp++; + } + } + + // > 1.20000 + // = 1.0 + 2/10 + + // > 1.23 + // = 1.2 + 3/100 + return value; +} + int yylex() { if (*inp == '\0') return YYEOF; @@ -15,12 +51,7 @@ int yylex() { // Check for NUM. if (isdigit(c)) { - int value = c - '0'; - while (isdigit(*inp)) { - value = value * 10 + (*inp - '0'); // Accumulate value. - inp++; - } - yylval.fval = value; // Set the token value. + yylval.fval = acc_float(c); // Set the token value. return NUM; }