[注意作業]在YACC解析賦值語句時得到一個語法錯誤
我需要一個提示,爲什麼下面的代碼失敗時,我嘗試運行測試用例:int a = 3;
所有的代碼編譯沒有警告或錯誤,並且據我所知結構是正確的。我覺得在assignment
的規則中必定存在問題。
錯誤消息說:ERROR: syntax error at symbol "a" on line 1
這是.lex文件:
%{
#include "calc.h"
#include "symbol-table.h"
#include "tok.h"
int yyerror(char *s);
int yylinenum = 1;
%}
digit [0-9]
int_const {digit}+
float_const {digit}+[.]{digit}+
id [a-zA-Z]+[a-zA-Z0-9]*
%%
{int_const} { yylval.int_val = atoi(yytext); return INTEGER_LITERAL; }
{float_const} { yylval.float_val = atof(yytext); return FLOAT_LITERAL; }
"=" { yylval.str_val = strdupclean(yylval.str_val, yytext); return EQUALS; }
"+" { yylval.str_val = strdupclean(yylval.str_val, yytext); return PLUS; }
"*" { yylval.str_val = strdupclean(yylval.str_val, yytext); return MULT; }
"-" { yylval.str_val = strdupclean(yylval.str_val, yytext); return MINUS; }
"/" { yylval.str_val = strdupclean(yylval.str_val, yytext); return DIV; }
"(" { yylval.str_val = strdupclean(yylval.str_val, yytext); return OPAREN; }
")" { yylval.str_val = strdupclean(yylval.str_val, yytext); return CPAREN; }
";" { yylval.str_val = strdupclean(yylval.str_val, yytext); return SEMIC; }
"sqrt" { yylval.str_val = strdupclean(yylval.str_val, yytext); return SQRT; }
{id} { yylval.str_val = strdupclean(yylval.str_val, yytext);
/*HINT: One way to simplify parsing is to have lex return what
* type of variable we have. IVAR = int, FVAR = float
* UVAR = unknown var.
* Naturally, you may use your own solution.
*/
if (strcmp(yylval.str_val, "int")) {return IVAR;}
else if (strcmp(yylval.str_val, "float")) {return FVAR;}
else {return UVAR;}
}
[ \t]* {}
[\n] { yylinenum++; }
. { yyerror("Unknown Symbol"); exit(1); }
%%
,這是YACC文件:
%{
#include "calc.h"
#include "symbol-table.h"
int yyerror(char *s);
int yylex(void);
%}
%union{
int int_val;
float float_val;
char* str_val;
}
%start input
%token <int_val> INTEGER_LITERAL
%token <float_val> FLOAT_LITERAL
%token <float_val> SQRT
%token OPAREN CPAREN SEMIC IVAR FVAR UVAR
%type <int_val> int_exp
%type <float_val> float_exp
%type <str_val> IVAR FVAR UVAR
%right EQUALS /*right associative, everything on the right side of the = should be evaluated and stored*/
%left PLUS MINUS/*The order matters, by listing PLUS/MIUS first and then MULT/DIV we are */
%left MULT DIV /*telling yacc to evaluate MULTs & DIVs before PLUSes and MINUSes*/
%%
input: /*empty*/
| int_exp { printf("Result %d\n", $1); }
| float_exp { printf("Result %f\n", $1); }
| assignment { printf("Result \n"); }
;
int_exp: INTEGER_LITERAL { $$ = $1; }
| int_exp PLUS int_exp { $$ = $1 + $3; }
| int_exp MULT int_exp { $$ = $1 * $3; }
| int_exp MINUS int_exp { $$ = $1 - $3; }
| int_exp DIV int_exp { $$ = $1/$3; }
| OPAREN int_exp CPAREN { $$ = $2; }
;
float_exp: FLOAT_LITERAL { $$ = $1; }
| float_exp PLUS float_exp { $$ = $1 + $3; }
| float_exp MULT float_exp { $$ = $1 * $3; }
| float_exp MINUS float_exp { $$ = $1 - $3; }
| float_exp DIV float_exp { $$ = $1/$3; }
| int_exp PLUS float_exp { $$ = (float)$1 + $3; }
| int_exp MULT float_exp { $$ = (float)$1 * $3; }
| int_exp MINUS float_exp { $$ = (float)$1 - $3; }
| int_exp DIV float_exp { $$ = (float)$1/$3; }
| float_exp PLUS int_exp { $$ = (float)$1 + $3; }
| float_exp MULT int_exp { $$ = (float)$1 * $3; }
| float_exp MINUS int_exp { $$ = (float)$1 - $3; }
| float_exp DIV int_exp { $$ = (float)$1/$3; }
| OPAREN float_exp CPAREN { $$ = $2; }
| SQRT OPAREN float_exp CPAREN { $$ = sqrt((double)$3); }
| SQRT OPAREN int_exp CPAREN { $$ = sqrt((double)$3); }
;
assignment: UVAR EQUALS float_exp SEMIC { //if UVAR exists and is float, update value
//if UVAR doesn't exist, error: unknown type
symbol_table_node *n1 = symbol_table_find($1, *st);
if(n1) {
if(n1->type == FLOAT_TYPE) {
n1->val.float_val = $3;
} else {
//error
}
//error, variable not defined
//if UVAR is not float, error: illegal assignment
}
}
| UVAR EQUALS int_exp SEMIC {
symbol_table_node *n1 = symbol_table_find($1, *st);
if(n1) {
if(n1->type == INT_TYPE) {
n1->val.int_val = $3;
} else {
//error
}
}
}
| IVAR UVAR EQUALS int_exp SEMIC { //UVAR should not be in symbol table
if(symbol_table_find($2, *st)) {
//error
} else {
//how to handle errors?
symbol_table_add_i($2, $4, *st);
}
}
| FVAR UVAR EQUALS float_exp SEMIC {
if(symbol_table_find($2, *st)) {
} else {
symbol_table_add_f($2, $4, *st);
}
}
;
%%
int yyerror(char *s){
extern int yylinenum; /* defined and maintained in lex.c*/
extern char *yytext; /* defined and maintained in lex.c*/
printf("ERROR: %s at symbol \"%s\" on line %d\n", s, yytext, yylinenum);
return -1;
}