为什么我会得到表达式计算器程序的语法错误?
Why do I get syntax error for the expression evaluator program?
我尝试了以下输入
一个=10;
打印一个;
打印 1+2+3;
一=5+10;
当我尝试使用上述输入执行文件时出现语法错误
编译没有报错
这是代码
弹性
%{
/* header files */
%}
/* regex */
%option yylineno
%%
"println" { printf("token is println"); return(TOK_PRINTLN);}
"print" { printf("token is print"); return(TOK_PRINTLN); }
"main()" { return(TOK_MAIN); }
{digit}+ { /* convert to int and store its val*/
printf("token is %d", yylval.int_val);
return INTEGER;
}
{id} {
/* convert to char */
printf("token is %c", yylval.id_val);
return(TOK_ID);
}
";" { return(TOK_SEMICOLON); }
"+" { return(TOK_ADD); }
"-" { return(TOK_SUB); } /* not req */
"*" { return(TOK_MUL); }
"/" { return(TOK_DIV); } /* not req */
"=" { return(TOK_EQ); }
[ \t\n] {printf("token is space");}
. {printf("Invalid character '%c', ignored\n",
yytext[0]);
}
%%
对于野牛,我们使用一个符号table,它是一个数组。
我们获取变量(由 TOK_ID 表示的标识符)并将其转换为索引,我们可以在其中存储表达式的值。
野牛档案
%{
/* header file and fucn dec*/
%}
%union{
int int_val;
char id_val;
}
/* 标记和类型 */
%开始 stmt
%right TOK_EQ
%left TOK_ADD TOK_SUB
%left TOK_MUL TOK_DIV
%%
/* grammar */
stmt: expr_stmt TOK_SEMICOLON
{; /* do nothing*/
}
| TOK_PRINTLN expr TOK_SEMICOLON
{
printf("%d \n",);
}
| stmt TOK_PRINTLN expr TOK_SEMICOLON
{
printf("%d \n",);
}
| stmt expr TOK_SEMICOLON
{
;
}
;
expr_stmt: TOK_ID TOK_EQ expr
{
setSTVal(, );
}
;
expr:
/*expr stuff */
;
%%
int getSTIndex(char c){
/* return index*/
}
int getSTVal(char c){
/* set val*/
}
void setSTVal(char c, int v){
/* set table val*/
}
int yyerror(char *s)
{
printf("\nsyntax error on line no %d\n",yylineno);
return 0;
}
void initializeSymbolTable(){
for(int i=0; i<100; i++)symbol_table[i] = 0; /*avoiding garbage val*/
/* initializn stuff */
}
int main()
{
initializeSymbolTable();
yyparse(); /* C routine produced by lex */
return 0;
}
当我尝试使用输入 a=5 进行调试时;和一个= 5;
它可以捕获令牌 a 但之后会抛出语法错误
它无法捕获 = 以及之后的所有内容。
我不明白为什么它只捕获第一个 digit/command/string 然后抛出语法错误
如果我把你的语法稍微简化一下
/* ... */
%start input
/* ... */
input: /* empty file/no input */
| input stmt
/* each statement is an "expr" followed by a semicolon */
stmt: expr TOK_SEMICOLON
{
;
}
/* This is a function and should go into the rule "expr", too, btw. */
| TOK_PRINTLN expr TOK_SEMICOLON
{
printf("%d \n",);
}
;
expr: /* empty expression */
expr TOK_ADD expr
{
$$ = + ;
}
/* ... */
| INTEGER
{
$$ = ;
};
| TOK_ID
{
$$ = getSTVal();
}
| TOK_ID TOK_EQ expr
{
setSTVal(, );
}
;
它适用于输入文件
a = 10;
print
a;
print 1+2+3;
a = 5
+
10;
print a;
符合预期。它不是很优雅,但应该为您指明正确的方向。
你的问题是 TOK_ID
在两个规则中,第二次出现 TOK_EQ
时解析器在 expr
并且没有 TOK_ID TOK_EQ
的规则仅 TOK_ID
一个人。 (比那复杂一点,承认)
如果您手边有 Bison 文档,您可以查找 mfcalc
示例。
我尝试了以下输入
一个=10;
打印一个;
打印 1+2+3;
一=5+10;
当我尝试使用上述输入执行文件时出现语法错误 编译没有报错
这是代码
弹性
%{
/* header files */
%}
/* regex */
%option yylineno
%%
"println" { printf("token is println"); return(TOK_PRINTLN);}
"print" { printf("token is print"); return(TOK_PRINTLN); }
"main()" { return(TOK_MAIN); }
{digit}+ { /* convert to int and store its val*/
printf("token is %d", yylval.int_val);
return INTEGER;
}
{id} {
/* convert to char */
printf("token is %c", yylval.id_val);
return(TOK_ID);
}
";" { return(TOK_SEMICOLON); }
"+" { return(TOK_ADD); }
"-" { return(TOK_SUB); } /* not req */
"*" { return(TOK_MUL); }
"/" { return(TOK_DIV); } /* not req */
"=" { return(TOK_EQ); }
[ \t\n] {printf("token is space");}
. {printf("Invalid character '%c', ignored\n",
yytext[0]);
}
%%
对于野牛,我们使用一个符号table,它是一个数组。 我们获取变量(由 TOK_ID 表示的标识符)并将其转换为索引,我们可以在其中存储表达式的值。
野牛档案
%{
/* header file and fucn dec*/
%}
%union{
int int_val;
char id_val;
}
/* 标记和类型 */ %开始 stmt
%right TOK_EQ
%left TOK_ADD TOK_SUB
%left TOK_MUL TOK_DIV
%%
/* grammar */
stmt: expr_stmt TOK_SEMICOLON
{; /* do nothing*/
}
| TOK_PRINTLN expr TOK_SEMICOLON
{
printf("%d \n",);
}
| stmt TOK_PRINTLN expr TOK_SEMICOLON
{
printf("%d \n",);
}
| stmt expr TOK_SEMICOLON
{
;
}
;
expr_stmt: TOK_ID TOK_EQ expr
{
setSTVal(, );
}
;
expr:
/*expr stuff */
;
%%
int getSTIndex(char c){
/* return index*/
}
int getSTVal(char c){
/* set val*/
}
void setSTVal(char c, int v){
/* set table val*/
}
int yyerror(char *s)
{
printf("\nsyntax error on line no %d\n",yylineno);
return 0;
}
void initializeSymbolTable(){
for(int i=0; i<100; i++)symbol_table[i] = 0; /*avoiding garbage val*/
/* initializn stuff */
}
int main()
{
initializeSymbolTable();
yyparse(); /* C routine produced by lex */
return 0;
}
当我尝试使用输入 a=5 进行调试时;和一个= 5; 它可以捕获令牌 a 但之后会抛出语法错误 它无法捕获 = 以及之后的所有内容。
我不明白为什么它只捕获第一个 digit/command/string 然后抛出语法错误
如果我把你的语法稍微简化一下
/* ... */
%start input
/* ... */
input: /* empty file/no input */
| input stmt
/* each statement is an "expr" followed by a semicolon */
stmt: expr TOK_SEMICOLON
{
;
}
/* This is a function and should go into the rule "expr", too, btw. */
| TOK_PRINTLN expr TOK_SEMICOLON
{
printf("%d \n",);
}
;
expr: /* empty expression */
expr TOK_ADD expr
{
$$ = + ;
}
/* ... */
| INTEGER
{
$$ = ;
};
| TOK_ID
{
$$ = getSTVal();
}
| TOK_ID TOK_EQ expr
{
setSTVal(, );
}
;
它适用于输入文件
a = 10;
print
a;
print 1+2+3;
a = 5
+
10;
print a;
符合预期。它不是很优雅,但应该为您指明正确的方向。
你的问题是 TOK_ID
在两个规则中,第二次出现 TOK_EQ
时解析器在 expr
并且没有 TOK_ID TOK_EQ
的规则仅 TOK_ID
一个人。 (比那复杂一点,承认)
如果您手边有 Bison 文档,您可以查找 mfcalc
示例。