c-为什么表达式计算器程序出现语法错误



我尝试了以下输入

a=10;

打印a;

打印1+2+3;

a=5+10;

当我尝试用上面的输入执行文件时,我遇到语法错误编译时没有错误

这是代码

Flex

%{
/* 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);   }
[ tn]     {printf("token is space");}
.   {printf("Invalid character '%c', ignoredn", 
yytext[0]);
}
%%

对于野牛,我们使用一个符号表,它是一个数组。我们获取变量(由TOK_ID表示的标识符(,并将其转换为索引,在那里我们可以存储表达式的值。

Bison文件

%{
/* 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",$2);
}
| stmt TOK_PRINTLN expr TOK_SEMICOLON
{
printf("%d n",$3);
}
| stmt expr TOK_SEMICOLON
{
;
}
;
expr_stmt: TOK_ID TOK_EQ expr
{
setSTVal($1, $3);
}
;
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 %dn",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进行调试时;并且a=5;它可以捕获令牌a,但之后抛出语法错误它无法捕获=以及之后的一切。

我不明白为什么它只捕获第一个数字/命令/字符串,然后抛出语法错误

如果我将您的语法简化为

/* ... */
%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",$2);
}
;

expr: /* empty expression */
expr TOK_ADD expr
{
$$ = $1 + $3;
}
/* ... */
| INTEGER
{
$$ = $1;
};
| TOK_ID
{
$$ =  getSTVal($1);
}
| TOK_ID TOK_EQ expr
{
setSTVal($1, $3);
}
;

它与输入文件一起工作

a = 10;
print
a;
print 1+2+3;
a = 5
+
10;
print a;

正如预期的那样。它不是很优雅,但应该为你指明正确的方向。

您的问题是TOK_ID在两个规则中,当解析器在expr中时,第二次出现TOK_EQ,并且没有针对TOK_ID TOK_EQ的规则,只有针对TOK_ID

如果手头有Bison文档,您可以查找mfcalc示例。

最新更新