无法在 bison/flex 中完成多项作业
can't make work multiple assignments in bison/flex
大家好,我正在努力学习野牛。我在 github 上找到了一个简单的工作表达式解析器,它可以执行以下操作:
作业(如a = 34; b = a;)
正在打印(如打印 a;)
正在退出(键入 exit;它将终止)
我想了解基本规则是如何运作的。所以我试图修改规则以允许进行多项作业(比如这个:a = b = c = 5;)。
为此,我添加了一个新的行规则,其工作方式如下:
line : assegn ';' {;}
| exit_command ';' {exit(EXIT_SUCCESS);}
| print exp ';' {printf("Printing %d\n", );}
| line assignment ';' {;}
| line print exp ';' {printf("Printing %d\n", );}
| line exit_command ';' {exit(EXIT_SUCCESS);}
;
然后我添加了以下新规则
assegn : assignment {;}
| identifiers {;}
;
identifiers : assignment {$$=;}
| identifier '=' identifiers {updateSymbolVal(,);}
;
作业是这样的
assignment : identifier '=' exp {$$=; updateSymbolVal(,); }
;
最后我能够编译由 bison 和 flex 生成的文件,但是当我尝试进行多重赋值时 returns 我的语法错误。
有人可以解释一下我在哪里犯了错误吗?这是我开始的原始示例。 https://github.com/jengelsma/yacc-tutorial.git
这是我的 bison 文件的代码:
%{
void yyerror (char *s);
#include <stdio.h> /* C declarations used in actions */
#include <stdlib.h>
int symbols[52];
int symbolVal(char symbol);
void updateSymbolVal(char symbol, int val);
int val;
%}
%union {int num; char id;} /* Yacc definitions */
%start line
%token print
%token exit_command
%token <num> number
%token <id> identifier
%type <num> line exp term
%type <id> assignment
%type <num> identifiers
%%
/*the original line was line : assignment ';' {;}*/
line : assegn ';' {;}
| exit_command ';' {exit(EXIT_SUCCESS);}
| print exp ';' {printf("Printing %d\n", );}
| line assignment ';' {;}
| line print exp ';' {printf("Printing %d\n", );}
| line exit_command ';' {exit(EXIT_SUCCESS);}
;
assegn : assignment {;}
| identifiers {;}
;
identifiers : assignment {$$=;}
| identifier '=' identifiers {updateSymbolVal(,);}
;
assignment : identifier '=' exp {$$=; updateSymbolVal(,); }
;
exp : term {$$ = ;}
| exp '+' term {$$ = + ;}
| exp '-' term {$$ = - ;}
;
term : number {$$ = ;}
| identifier {$$ = symbolVal();}
;
%% /* C code */
int computeSymbolIndex(char token)
{
int idx = -1;
if(islower(token)) {
idx = token - 'a' + 26;
} else if(isupper(token)) {
idx = token - 'A';
}
return idx;
}
/* returns the value of a given symbol */
int symbolVal(char symbol)
{
int bucket = computeSymbolIndex(symbol);
return symbols[bucket];
}
/* updates the value of a given symbol */
void updateSymbolVal(char symbol, int val)
{
int bucket = computeSymbolIndex(symbol);
symbols[bucket] = val;
}
int main (void) {
/* init symbol table */
int i;
for(i=0; i<52; i++) {
symbols[i] = 0;
}
return yyparse ( );
}
void yyerror (char *s) {fprintf (stderr, "%s\n", s);}
这是我的 flex 文件:
%{
#include "exppars.tab.h"
%}
%%
"print" {return print;}
"exit" {return exit_command;}
[a-zA-Z] {yylval.id = yytext[0]; return identifier;}
[0-9]+ {yylval.num = atoi(yytext); return number;}
[ \t\n] ;
[-+=;] {return yytext[0];}
. {ECHO; yyerror ("unexpected character");}
%%
int yywrap (void) {return 1;}
好的,看来我找到了一种答案。
- 我注意到语法错误仅在我尝试执行时出现
在第一个输入之后进行多重赋值。
为了解决这个问题,我添加了一条新规则。现在规则块看起来像这样:
line : assegn ';' {;}
| exit_command ';' {exit(EXIT_SUCCESS);}
| print exp ';' {printf("Printing %d\n", );}
| line assegn ';' {;}
| line print exp ';' {printf("Printing %d\n", );}
| line exit_command ';' {exit(EXIT_SUCCESS);}
;
当我尝试做长多重赋值时,下一个问题出现了,例如:a = b = c = d = 5;。我只是将值分配给 c 和 d,而不是其他人。
似乎代码 { $$ = $1} 没有像我预期的那样工作。所以我添加了一个新的 int 变量来存储上次赋值的值。生产规则现在看起来像这样:
identifiers : assignment { val = ;}
| identifier '=' identifiers {updateSymbolVal(,val);}
;
assignment : identifier '=' exp {$$=; updateSymbolVal(,);}
;
exp : term { $$ = ; @1;}
| exp '+' term { $$ = + ; }
| exp '-' term { $$ = - ; }
;
term : number {$$ = ;}
| identifier {$$ = symbolVal();}
;
现在开始工作了。
大家好,我正在努力学习野牛。我在 github 上找到了一个简单的工作表达式解析器,它可以执行以下操作:
作业(如a = 34; b = a;)
正在打印(如打印 a;)
正在退出(键入 exit;它将终止)
我想了解基本规则是如何运作的。所以我试图修改规则以允许进行多项作业(比如这个:a = b = c = 5;)。
为此,我添加了一个新的行规则,其工作方式如下:
line : assegn ';' {;}
| exit_command ';' {exit(EXIT_SUCCESS);}
| print exp ';' {printf("Printing %d\n", );}
| line assignment ';' {;}
| line print exp ';' {printf("Printing %d\n", );}
| line exit_command ';' {exit(EXIT_SUCCESS);}
;
然后我添加了以下新规则
assegn : assignment {;}
| identifiers {;}
;
identifiers : assignment {$$=;}
| identifier '=' identifiers {updateSymbolVal(,);}
;
作业是这样的
assignment : identifier '=' exp {$$=; updateSymbolVal(,); }
;
最后我能够编译由 bison 和 flex 生成的文件,但是当我尝试进行多重赋值时 returns 我的语法错误。
有人可以解释一下我在哪里犯了错误吗?这是我开始的原始示例。 https://github.com/jengelsma/yacc-tutorial.git
这是我的 bison 文件的代码:
%{
void yyerror (char *s);
#include <stdio.h> /* C declarations used in actions */
#include <stdlib.h>
int symbols[52];
int symbolVal(char symbol);
void updateSymbolVal(char symbol, int val);
int val;
%}
%union {int num; char id;} /* Yacc definitions */
%start line
%token print
%token exit_command
%token <num> number
%token <id> identifier
%type <num> line exp term
%type <id> assignment
%type <num> identifiers
%%
/*the original line was line : assignment ';' {;}*/
line : assegn ';' {;}
| exit_command ';' {exit(EXIT_SUCCESS);}
| print exp ';' {printf("Printing %d\n", );}
| line assignment ';' {;}
| line print exp ';' {printf("Printing %d\n", );}
| line exit_command ';' {exit(EXIT_SUCCESS);}
;
assegn : assignment {;}
| identifiers {;}
;
identifiers : assignment {$$=;}
| identifier '=' identifiers {updateSymbolVal(,);}
;
assignment : identifier '=' exp {$$=; updateSymbolVal(,); }
;
exp : term {$$ = ;}
| exp '+' term {$$ = + ;}
| exp '-' term {$$ = - ;}
;
term : number {$$ = ;}
| identifier {$$ = symbolVal();}
;
%% /* C code */
int computeSymbolIndex(char token)
{
int idx = -1;
if(islower(token)) {
idx = token - 'a' + 26;
} else if(isupper(token)) {
idx = token - 'A';
}
return idx;
}
/* returns the value of a given symbol */
int symbolVal(char symbol)
{
int bucket = computeSymbolIndex(symbol);
return symbols[bucket];
}
/* updates the value of a given symbol */
void updateSymbolVal(char symbol, int val)
{
int bucket = computeSymbolIndex(symbol);
symbols[bucket] = val;
}
int main (void) {
/* init symbol table */
int i;
for(i=0; i<52; i++) {
symbols[i] = 0;
}
return yyparse ( );
}
void yyerror (char *s) {fprintf (stderr, "%s\n", s);}
这是我的 flex 文件:
%{
#include "exppars.tab.h"
%}
%%
"print" {return print;}
"exit" {return exit_command;}
[a-zA-Z] {yylval.id = yytext[0]; return identifier;}
[0-9]+ {yylval.num = atoi(yytext); return number;}
[ \t\n] ;
[-+=;] {return yytext[0];}
. {ECHO; yyerror ("unexpected character");}
%%
int yywrap (void) {return 1;}
好的,看来我找到了一种答案。
- 我注意到语法错误仅在我尝试执行时出现 在第一个输入之后进行多重赋值。
为了解决这个问题,我添加了一条新规则。现在规则块看起来像这样:
line : assegn ';' {;}
| exit_command ';' {exit(EXIT_SUCCESS);}
| print exp ';' {printf("Printing %d\n", );}
| line assegn ';' {;}
| line print exp ';' {printf("Printing %d\n", );}
| line exit_command ';' {exit(EXIT_SUCCESS);}
;
当我尝试做长多重赋值时,下一个问题出现了,例如:a = b = c = d = 5;。我只是将值分配给 c 和 d,而不是其他人。 似乎代码 { $$ = $1} 没有像我预期的那样工作。所以我添加了一个新的 int 变量来存储上次赋值的值。生产规则现在看起来像这样:
identifiers : assignment { val = ;} | identifier '=' identifiers {updateSymbolVal(,val);} ; assignment : identifier '=' exp {$$=; updateSymbolVal(,);} ; exp : term { $$ = ; @1;} | exp '+' term { $$ = + ; } | exp '-' term { $$ = - ; } ; term : number {$$ = ;} | identifier {$$ = symbolVal();} ;
现在开始工作了。