diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a1e9d8..86397fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.0) -project(expr VERSION 1.3.0) +project(expr VERSION 1.3.1) include(cmake/CPM.cmake) configure_file(src/config.h.in config.h) set(CMAKE_CXX_STANDARD 20) diff --git a/include/parser/driver.h b/include/parser/driver.h index a4e5e73..9d1d816 100644 --- a/include/parser/driver.h +++ b/include/parser/driver.h @@ -10,8 +10,11 @@ struct driver { explicit driver(const symbol_table_t& env); const symbol_table_t& environment{}; symbol_table_t result{}; + symbol_value_t error{}; + symbol_value_t expression_result{}; int parse(const std::string& f); + auto get_symbol(const std::string& identifier) -> symbol_value_t; std::string file; bool trace_parsing; diff --git a/src/parser/driver.cpp b/src/parser/driver.cpp index 429bcd9..48c3fde 100644 --- a/src/parser/driver.cpp +++ b/src/parser/driver.cpp @@ -8,7 +8,7 @@ driver::driver(const symbol_table_t& map) : trace_parsing (false), trace_scannin int driver::parse(const std::string &f) { if(f.empty()) { #ifdef DEFAULT_EXPRESSION_VALUE - result["expression_result"] = DEFAULT_EXPRESSION_VALUE; + expression_result = DEFAULT_EXPRESSION_VALUE; #endif return 0; } @@ -17,7 +17,20 @@ int driver::parse(const std::string &f) { scan_begin(); yy::parser parse(*this); parse.set_debug_level(trace_parsing); - int res = parse(); - scan_end(); - return res; + try { + int res = parse(); + scan_end(); + return res; + } catch(std::exception& e) { + error = e.what(); + return 1; + } +} + +auto driver::get_symbol(const std::string &identifier) -> symbol_value_t { +#ifndef NDEBUG + if(!environment.contains(identifier)) + throw std::out_of_range(identifier + " not found"); +#endif + return environment.at(identifier); } diff --git a/src/parser/parser.y b/src/parser/parser.y index 63a29f7..b7deb82 100644 --- a/src/parser/parser.y +++ b/src/parser/parser.y @@ -62,61 +62,59 @@ %token FLOAT "float" %token BOOL "bool" %token STRING "string" -%nterm exp cmp op +%nterm lit exp %printer { yyo << $$; } <*>; +%left OR +%left AND +%left GT GE EE NE LE LT +%left PLUS MINUS STAR SLASH +%precedence LPAREN NOT %% %start unit; unit: statements { } -| cmp { drv.result["expression_result"] = $1; } +| exp { drv.expression_result = $1; } ; statements: - %empty {} -| statement {} -| statement ";" statements {} + %empty {} +| statement statements {} ; statement: - "identifier" ":=" cmp { drv.result[$1] = $3; } -| "type" "identifier" ":=" cmp { drv.result[$2] = $4; } -| "access_modifier" "type" "identifier" ":=" cmp { drv.result[$3] = $5; } + "identifier" ASSIGN exp { drv.result[$1] = $3; } +| "type" "identifier" ASSIGN exp { drv.result[$2] = $4; } +| "access_modifier" "type" "identifier" ASSIGN exp { drv.result[$3] = $5; } +| statement TERM { } ; -%left "+" "-"; -%left "*" "/"; -%precedence "||" "&&"; - -cmp: - op "||" op { $$ = or_($1,$3); } -| op "&&" op { $$ = and_($1,$3); } -| "!" op { $$ = not_($2); } -| op { $$ = $1; } -| "(" op ")" { $$ = $2; } -; - -op: - exp "+" exp { $$ = $1 + $3; } -| exp "-" exp { $$ = $1 - $3; } -| exp "*" exp { $$ = $1 * $3; } -| exp "/" exp { $$ = $1 / $3; } -| exp ">" exp { $$ = gt_($1,$3); } -| exp ">=" exp { $$ = ge_($1,$3); } -| exp "==" exp { $$ = ee_($1,$3); } -| exp "!=" exp { $$ = ne_($1,$3); } -| exp "<=" exp { $$ = le_($1,$3); } -| exp "<" exp { $$ = lt_($1,$3); } -| exp { $$ = $1; } +exp: + lit { $$ = $1; } +| exp PLUS exp { $$ = $1 + $3; } +| exp MINUS exp { $$ = $1 - $3; } +| exp STAR exp { $$ = $1 * $3; } +| exp SLASH exp { $$ = $1 / $3; } +| exp GT exp { $$ = gt_($1,$3); } +| exp GE exp { $$ = ge_($1,$3); } +| exp EE exp { $$ = ee_($1,$3); } +| exp NE exp { $$ = ne_($1,$3); } +| exp LE exp { $$ = le_($1,$3); } +| exp LT exp { $$ = lt_($1,$3); } +| exp OR exp { $$ = or_($1,$3); } +| exp AND exp { $$ = and_($1,$3); } +| NOT exp { $$ = not_($2); } +| LPAREN exp RPAREN { $$ = $2; } ; -exp: - cmp { $$ = $1; } -| "number" { $$ = $1; } -| "float" { $$ = $1; } -| "string" { $$ = $1; } -| "bool" { $$ = $1; } -| "identifier" { $$ = drv.environment.at($1); } +lit: + "number" { $$ = $1; } +| MINUS "number" { $$ = -$2; } +| "float" { $$ = $1; } +| MINUS "float" { $$ = -$2; } +| "string" { $$ = $1; } +| "bool" { $$ = $1; } +| "identifier" { $$ = drv.get_symbol($1); } ; %% diff --git a/src/parser/scanner.l b/src/parser/scanner.l index ffe75ab..10956b8 100644 --- a/src/parser/scanner.l +++ b/src/parser/scanner.l @@ -93,9 +93,9 @@ %{ // TODO: Remove [ðđ€\(\)] %} -id [a-z_A-Z][a-zA-Z_.0-9ðđ€\(\)]* -int [0-9]+ -flt [0-9]+[.][0-9]+f +id [a-z_A-Z]([.ðđ€\(\)a-zA-Z_0-9]*[a-zA-Z_0-9]+)? +int [0-9]+[Ll]? +flt [0-9]+[.][0-9]+[fd]? bool [Ff]alse|[Tt]rue str \"(\\.|[^"\\])*\" blank [ \t\r] @@ -114,7 +114,7 @@ type int|long|float|double|string|bool|var|auto loc.step(); %} {blank}+ loc.step(); -\n+ loc.lines(yyleng); loc.step(); +\n+ { loc.lines(yyleng); loc.step(); } "-" return yy::parser::make_MINUS (loc); "+" return yy::parser::make_PLUS (loc);