diff --git a/CMakeLists.txt b/CMakeLists.txt index f47f3a1..4b246b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(Compiler C) # Compilar el parser con Bison: add_custom_command( OUTPUT ../src/frontend/syntactic-analysis/bison-parser.c ../src/frontend/syntactic-analysis/bison-parser.h - COMMAND bison --debug -d ../src/frontend/syntactic-analysis/bison-grammar.y -o ../src/frontend/syntactic-analysis/bison-parser.c) + COMMAND bison -t -d ../src/frontend/syntactic-analysis/bison-grammar.y -o ../src/frontend/syntactic-analysis/bison-parser.c) # Seleccionar estrategia según el compilador de C disponible en el sistema: if (CMAKE_C_COMPILER_ID STREQUAL "GNU") diff --git a/src/frontend/lexical-analysis/flex-actions.c b/src/frontend/lexical-analysis/flex-actions.c index 1dd6af6..b77406f 100644 --- a/src/frontend/lexical-analysis/flex-actions.c +++ b/src/frontend/lexical-analysis/flex-actions.c @@ -19,11 +19,15 @@ TokenID DoublePatternAction(const char * lexeme) { } TokenID StringPatternAction(const char * lexeme) { - LogDebug("DoublePatternAction: '%s'.", lexeme); - yylval = lexeme; + LogDebug("StringPatternAction: '%s'.", lexeme); return STRING; } +TokenID EscapeStringPatternAction(const char * lexeme) { + LogDebug("EscapeStringPatternAction: '%s'.", lexeme); + return ESCAPESTRING; +} + void IgnoredPatternAction(const char * lexeme) { LogDebug("IgnoredPatternAction: '%s'.", lexeme); } diff --git a/src/frontend/lexical-analysis/flex-actions.h b/src/frontend/lexical-analysis/flex-actions.h index 2562494..e0453b3 100644 --- a/src/frontend/lexical-analysis/flex-actions.h +++ b/src/frontend/lexical-analysis/flex-actions.h @@ -17,55 +17,58 @@ typedef enum TokenID { // tokens continúen desde el valor "258" lo que permite proteger los IDs // internos que Bison reserva para crear "tokens literales": YYUNDEF = 257, - - // Operadores aritméticos. + ADD, SUB, MUL, DIV, POW, - - // Brackets. - OPEN_PARENTHESIS, - CLOSE_PARENTHESIS, - OPEN_BRACES, - CLOSE_BRACES, - OPEN_BRACKETS, - CLOSE_BRACKETS, - FUNCTION, IF, ELSE, FOR, + WHILE, PRINT, SEMICOLON, - COMPOSITE, + SQUOTE, DERIVATIVE, INTEGRATE, BETWEEN, - AND, + AND_INT, EVALUATE, IN, - - COLON, - COMMA, - GREATER, - GREATER_EQUAL, - LESSER, - LESSER_EQUAL, + OPEN_BRACES, + OPEN_BRACKETS, + CLOSE_BRACES, + CLOSE_BRACKETS, + OPEN_PARENTHESIS, + CLOSE_PARENTHESIS, ASSIGN, EQUAL, - + AND, + OR, + NOT, ADD_ASSIGN, INCREMENT, SUB_ASSIGN, DECREMENT, - QUOTE, - - // Tipos de dato. - INTEGER, + MUL_ASSIGN, + DIV_ASSIGN, + DQUOTE, + COMMA, + COLON, + LESSER, + LESSER_EQUAL, + GREATER, + GREATER_EQUAL, + COMPARE, + VAR, + ERR, + TAYLOR, + ESCAPESTRING, DOUBLE, + INTEGER, STRING } TokenID; @@ -86,4 +89,6 @@ TokenID UnknownPatternAction(const char * lexeme); TokenID StringPatternAction(const char * lexeme); +TokenID EscapeStringPatternAction(const char * lexeme); + #endif diff --git a/src/frontend/lexical-analysis/flex-patterns.l b/src/frontend/lexical-analysis/flex-patterns.l index d9070e6..81f3b71 100644 --- a/src/frontend/lexical-analysis/flex-patterns.l +++ b/src/frontend/lexical-analysis/flex-patterns.l @@ -19,7 +19,8 @@ digit [0-9] char [a-zA-Z] decimal [.] endline \n -whitespace [ \f\n\r\t\v] +/* whitespace [\f\n\r\t\v\0 ] */ +whitespace [ \f\n\r\t\v] %% @@ -28,60 +29,62 @@ whitespace [ \f\n\r\t\v] "*" { return MUL; } "/" { return DIV; } "^" { return POW; } - "fun" { return FUNCTION; } "function" { return FUNCTION; } - "if" { return IF; } "else" { return ELSE; } "for" { return FOR; } +"while" { return WHILE; } "print" { return PRINT; } ";" { return SEMICOLON; } - "o" { return COMPOSITE; } -"'"+ { return DERIVATIVE; } +"'" { return SQUOTE; } "derivative" { return DERIVATIVE; } - "integrate" { return INTEGRATE; } "int" { return INTEGRATE; } - "between" { return BETWEEN; } -"and" { return AND; } -"~" { return AND; } - +"and" { return AND_INT; } +"~" { return AND_INT; } "evaluate" { return EVALUATE; } +"eval" { return EVALUATE; } +"," { return COMMA; } +":" { return COLON; } +"<" { return LESSER; } +"<=" { return LESSER_EQUAL; } +">" { return GREATER; } +">=" { return GREATER_EQUAL; } "in" { return IN; } - "{" { return OPEN_BRACES; } -"}" { return CLOSE_BRACES; } - -"{" { return OPEN_BRACKETS; } -"}" { return CLOSE_BRACKETS; } - +"}" { return CLOSE_BRACES; } +"[" { return OPEN_BRACKETS; } +"]" { return CLOSE_BRACKETS; } "(" { return OPEN_PARENTHESIS; } ")" { return CLOSE_PARENTHESIS; } +"=" { return ASSIGN; } +"==" { return EQUAL; } +"&&" { return AND; } +"||" { return OR; } +"!" { return NOT; } +"+=" { return ADD_ASSIGN; } +"++" { return INCREMENT; } +"-=" { return SUB_ASSIGN; } +"--" { return DECREMENT; } +"*=" { return MUL_ASSIGN; } +"/=" { return DIV_ASSIGN; } +"\"" { return DQUOTE; } +"var" { return VAR; } +"err" { return ERR; } +"taylor" { return TAYLOR; } -":" { return COLON; } -"," { return COMMA; } -">" { return GREATER; } -">=" { return GREATER_EQUAL; } -"<" { return LESSER; } -"<=" { return LESSER_EQUAL; } -"=" { return ASSIGN; } -"==" { return EQUAL; } - -"+=" { return ADD_ASSIGN; } -"++" { return INCREMENT; } -"-=" { return SUB_ASSIGN; } -"--" { return DECREMENT; } -"\"" { return QUOTE; } - -{digit}+ { return IntegerPatternAction(yytext); } {digit}+{decimal}{digit}+ { return DoublePatternAction(yytext); } +{digit}+ { return IntegerPatternAction(yytext); } + {char}+ { return StringPatternAction(yytext); } +\"{char}+\" { return EscapeStringPatternAction(yytext); } + {whitespace} { IgnoredPatternAction(yytext); } . { return UnknownPatternAction(yytext); } diff --git a/src/frontend/syntactic-analysis/bison-grammar.y b/src/frontend/syntactic-analysis/bison-grammar.y index 4d60429..e245492 100644 --- a/src/frontend/syntactic-analysis/bison-grammar.y +++ b/src/frontend/syntactic-analysis/bison-grammar.y @@ -5,50 +5,58 @@ %} // IDs de los tokens generados desde Flex: + %token ADD %token SUB %token MUL %token DIV %token POW - -%token OPEN_PARENTHESIS -%token CLOSE_PARENTHESIS - -%token OPEN_BRACES -%token CLOSE_BRACES -%token OPEN_BRACKETS -%token CLOSE_BRACKETS - %token FUNCTION %token IF %token ELSE %token FOR +%token WHILE %token PRINT %token SEMICOLON %token COMPOSITE +%token SQUOTE %token DERIVATIVE %token INTEGRATE %token BETWEEN -%token AND +%token AND_INT %token EVALUATE %token IN - -%token COLON -%token COMMA -%token GREATER -%token GREATER_EQUAL -%token LESSER -%token LESSER_EQUAL +%token OPEN_BRACES +%token OPEN_BRACKETS +%token CLOSE_BRACES +%token CLOSE_BRACKETS +%token OPEN_PARENTHESIS +%token CLOSE_PARENTHESIS %token ASSIGN %token EQUAL +%token AND +%token OR +%token NOT %token ADD_ASSIGN %token INCREMENT %token SUB_ASSIGN %token DECREMENT -%token QUOTE - -%token INTEGER +%token MUL_ASSIGN +%token DIV_ASSIGN +%token DQUOTE +%token COMMA +%token COLON +%token LESSER +%token LESSER_EQUAL +%token GREATER +%token GREATER_EQUAL +%token COMPARE +%token VAR +%token ERR +%token TAYLOR +%token ESCAPESTRING %token DOUBLE +%token INTEGER %token STRING // Reglas de asociatividad y precedencia (de menor a mayor): @@ -58,41 +66,184 @@ %% -program: expression SEMICOLON { $$ = ProgramGrammarAction($1); } +program: statements // { $$ = ProgramGrammarAction($1); } ; -expression: expression ADD expression { $$ = AdditionExpressionGrammarAction($1, $3); } - | expression SUB expression { $$ = SubtractionExpressionGrammarAction($1, $3); } - | expression MUL expression { $$ = MultiplicationExpressionGrammarAction($1, $3); } - | expression DIV expression { $$ = DivisionExpressionGrammarAction($1, $3); } - | expression POW expression { $$ = PowerExpressionGrammarAction($1, $3); } - | function { $$ = FunctionExpressionGrammarAction($1); } - | factor { $$ = FactorExpressionGrammarAction($1); } +expression: constant + | STRING + | expression ADD expression // { $$ = AdditionExpressionGrammarAction($1, $3); } + | expression SUB expression // { $$ = SubtractionExpressionGrammarAction($1, $3); } + | expression MUL expression // { $$ = MultiplicationExpressionGrammarAction($1, $3); } + | expression DIV expression // { $$ = DivisionExpressionGrammarAction($1, $3); } + | expression POW expression // { $$ = PowerExpressionGrammarAction($1, $3); } + | OPEN_PARENTHESIS expression CLOSE_PARENTHESIS + | SUB expression + | number ; -boolean: string LESSER constant { $$ = LesserExpressionGrammarAction($1, $3); } - | string LESSER_EQUAL constant { $$ = LesserEqualExpressionGrammarAction($1, $3); } - | string GREATER constant { $$ = GreaterExpressionGrammarAction($1, $3); } - | string GREATER_EQUAL constant { $$ = GreaterEqualExpressionGrammarAction($1, $3); } - | string EQUAL constant { $$ = EqualExpressionGrammarAction($1, $3); } +domain: STRING LESSER number // { $$ = LesserExpressionGrammarAction($1, $3); } + | STRING LESSER_EQUAL number // { $$ = LesserEqualExpressionGrammarAction($1, $3); } + | STRING GREATER number // { $$ = GreaterExpressionGrammarAction($1, $3); } + | STRING GREATER_EQUAL number // { $$ = GreaterEqualExpressionGrammarAction($1, $3); } + | STRING EQUAL number // { $$ = EqualExpressionGrammarAction($1, $3); } + | number LESSER STRING // { $$ = LesserExpressionGrammarAction($1, $3); } + | number LESSER_EQUAL STRING // { $$ = LesserEqualExpressionGrammarAction($1, $3); } + | number GREATER STRING // { $$ = GreaterExpressionGrammarAction($1, $3); } + | number GREATER_EQUAL STRING // { $$ = GreaterEqualExpressionGrammarAction($1, $3); } + | number EQUAL STRING // { $$ = EqualExpressionGrammarAction($1, $3); } + | number LESSER STRING LESSER number + | number LESSER_EQUAL STRING LESSER number + | number LESSER STRING LESSER_EQUAL number + | number LESSER_EQUAL STRING LESSER_EQUAL number ; -factor: OPEN_PARENTHESIS expression CLOSE_PARENTHESIS { $$ = ExpressionFactorGrammarAction($2); } - | constant { $$ = ConstantFactorGrammarAction($1); } +boolean: number LESSER number + | number LESSER_EQUAL number + | number GREATER number + | number GREATER_EQUAL number + | number EQUAL number + | boolean OR boolean + | boolean AND boolean + | NOT boolean ; + +constant: DOUBLE + | INTEGER + | SUB constant + ; + +declare_function: FUNCTION STRING ASSIGN function + | FUNCTION STRING ASSIGN OPEN_BRACES functions CLOSE_BRACES + ; + +function: expression + | expression COLON domain + | composite + | taylor + ; + +functions: function + | function COMMA functions + ; + +composite: STRING COMPOSITE STRING + | composite COMPOSITE STRING + ; + +numbers: number + | number COMMA numbers + ; + +strings: STRING + | STRING COMMA strings + +numArray: OPEN_BRACKETS numbers CLOSE_BRACKETS + ; + +stringArray: OPEN_BRACKETS strings CLOSE_BRACKETS + ; + +evaluate: EVALUATE STRING IN number //{ $$ = IntegerConstantGrammarAction($1); } + | EVALUATE STRING IN numArray //{ $$ = IntegerConstantGrammarAction($1); } + | STRING OPEN_PARENTHESIS number CLOSE_PARENTHESIS //{ $$ = IntegerConstantGrammarAction($1); } + | EVALUATE stringArray IN number //{ $$ = IntegerConstantGrammarAction($1); } + | EVALUATE stringArray IN numArray //{ $$ = IntegerConstantGrammarAction($1); } + | stringArray OPEN_PARENTHESIS number CLOSE_PARENTHESIS //{ $$ = IntegerConstantGrammarAction($1); } + ; + +integrate: INTEGRATE STRING BETWEEN number AND_INT number + | INTEGRATE STRING number AND_INT number + | INTEGRATE stringArray BETWEEN number AND_INT number + | INTEGRATE stringArray number AND_INT number + | integrate ERR constant + ; + +squotes: SQUOTE + | SQUOTE squotes + ; + +statement: evaluate SEMICOLON + | integrate SEMICOLON + | derivative SEMICOLON + | declare_function SEMICOLON + | if_statement + | ifelse_statement + | for_statement + | while_statement + | print SEMICOLON + | declare_variable SEMICOLON + | assign_variable SEMICOLON + ; + +print: PRINT OPEN_PARENTHESIS number CLOSE_PARENTHESIS + | PRINT OPEN_PARENTHESIS STRING CLOSE_PARENTHESIS + | PRINT OPEN_PARENTHESIS escapedString CLOSE_PARENTHESIS + ; + +escapedString: ESCAPESTRING + | ESCAPESTRING ADD escapedString + ; + +statements: statement + | statement statements + ; + +derivative: DERIVATIVE STRING IN constant + | DERIVATIVE INTEGER STRING IN constant + | STRING squotes OPEN_PARENTHESIS constant CLOSE_PARENTHESIS + | DERIVATIVE stringArray IN constant + | DERIVATIVE INTEGER stringArray IN constant + | stringArray squotes OPEN_PARENTHESIS constant CLOSE_PARENTHESIS + | derivative ERR constant + ; + +if_statement: IF OPEN_PARENTHESIS boolean CLOSE_PARENTHESIS OPEN_BRACKETS statements CLOSE_BRACKETS + | IF OPEN_PARENTHESIS boolean CLOSE_PARENTHESIS statement + ; + +ifelse_statement: if_statement ELSE OPEN_BRACKETS statements CLOSE_BRACKETS + | ELSE statement + ; + +for_statement: FOR OPEN_PARENTHESIS declare_variable SEMICOLON boolean SEMICOLON assign_variable CLOSE_PARENTHESIS OPEN_BRACKETS statements CLOSE_BRACKETS + | FOR OPEN_PARENTHESIS SEMICOLON boolean SEMICOLON assign_variable CLOSE_PARENTHESIS OPEN_BRACKETS statements CLOSE_BRACKETS + | FOR OPEN_PARENTHESIS declare_variable SEMICOLON boolean SEMICOLON assign_variable CLOSE_PARENTHESIS statement + | FOR OPEN_PARENTHESIS SEMICOLON boolean SEMICOLON assign_variable CLOSE_PARENTHESIS statement + ; + +taylor: TAYLOR INTEGER STRING + ; + +while_statement: WHILE OPEN_PARENTHESIS boolean CLOSE_PARENTHESIS OPEN_BRACKETS statements CLOSE_BRACKETS + | WHILE OPEN_PARENTHESIS boolean CLOSE_PARENTHESIS statement + ; + +declare_variable: VAR STRING + | VAR STRING ASSIGN number + | VAR STRING ASSIGN expression + ; + +number: evaluate + | integrate + | derivative + | constant + | number ADD number + | number DIV number + | number SUB number + | number POW number + | number MUL number + | SUB number + | OPEN_PARENTHESIS number CLOSE_PARENTHESIS + ; + +assign_variable: STRING ASSIGN number + | STRING ADD_ASSIGN number + | STRING SUB_ASSIGN number + | STRING MUL_ASSIGN number + | STRING DIV_ASSIGN number + | STRING INCREMENT + | STRING DECREMENT + | STRING ASSIGN expression + ; -constant: DOUBLE { $$ = DoubleConstantGrammarAction($1); } - | INTEGER { $$ = IntegerConstantGrammarAction($1) } - ; - -function: FUNCTION string ASSIGN expression SEMICOLON { $$ = FunctionGrammarAction($2, $4); } - | FUNCTION string ASSIGN expression COLON boolean SEMICOLON { $$ = RestrictedFunctionGrammarAction($2, $4, $6); } - | FUNCTION string { $$ = PiecewiseFunctionGrammarAction(); } - ; - -string: STRING { $$ = StringGrammarAction($1); } - ; - -piecewise: FUNCTION string ASSIGN OPEN_BRACES expression COLON boolean CLOSE_BRACES SEMICOLON - %% diff --git a/src/main.c b/src/main.c index a21c104..82c110c 100644 --- a/src/main.c +++ b/src/main.c @@ -10,9 +10,9 @@ CompilerState state; // Punto de entrada principal del compilador. const int main(const int argumentCount, const char ** arguments) { -#ifdef YYDEBUG - yydebug = 1; -#endif + #ifdef YYDEBUG + yydebug = 1; + #endif // Inicializar estado de la aplicación. state.result = 0; state.succeed = false;