如何解决即使语法是每个语法,Yacc 的语法错误
即使语法符合语法,我的 yacc 解析器也显示语法错误。 我的 Yacc 代码:
%{
void yyerror (char *s);
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int symbols[100];
int yylex();
int symbolVal(char symbol);
void updateSymbolVal(char symbol,int val);
%}
%union {int num; char id;}
%start line
%token WHILE
%token lt
%token gt
%token exit_command
%token <num> number
%token <id> identifier
%type <num> line exp term
%type <id> assignment
%type <num> condition
%%
line: assignment {;}
|line assignment {;}
|exit_command {exit(EXIT_SUCCESS);}
|line exit_command {exit(EXIT_SUCCESS);}
|whileLoop {;}
|condition {;}
;
whileLoop: WHILE '(' condition ')' '{' assignment '}' {printf("while loop condition var:%d\n",$3);}
;
assignment : identifier '=' exp {updateSymbolVal($1,$3);}
;
exp : term {$$ = $1;}
| exp '+' term {$$ = $1 + $3;}
| exp '-' term {$$ = $1 - $3;}
;
term : number {$$ = $1;}
| identifier {$$ = symbolVal($1);}
;
condition : identifier cond_op identifier {$$ = $1;}
|identifier cond_op number {$$ = $1;}
;
cond_op : lt
| gt
;
%%
int computeSymbolIndex(char token){
int idx = -1;
if(islower(token)){
idx = token - 'a' +26;
}
else if(isupper(token)){
idx = token - 'A' + 26;
}
return idx;
}
int symbolVal(char symbol){
int bucket = computeSymbolIndex(symbol);
return symbols[bucket];
}
void updateSymbolVal(char symbol,int val){
int bucket = computeSymbolIndex(symbol);
symbols[bucket] = val;
}
int main(void){
int i;
for(i=0;i<52;i++){
symbols[i] = 0;
}
return yyparse();
}
void yyerror (char *s){fprintf (stderr,"%s\n",s);}
我的 Lex 代码:
%{
#include "y.tab.h"
%}
%%
"while" {printf("while\n"); return WHILE;}
"exit" {return exit_command;}
[a-zA-Z] {yylval.id = yytext[0]; return identifier;}
[0-9]+ {yylval.num = atoi(yytext); return number;}
"<" {return lt;}
">" {return gt;}
[ \t\n] ;
[-+=;] {return yytext[0];}
. ;
%%
int yywrap (void)
{
return 1;
}
while(i>0){i = i-1}
"while" 按照 lex 打印,但下一行输出是 "Syntax Error"。
即使是“while 循环条件变量”也没有被打印出来。
特别是while循环的语法错误。
诸如条件语句赋值等所有其他事情似乎都可以正常工作。
为什么会这样?
解决方法
您有一个词法分析器回退规则,它会默默地丢弃无法识别的字符:
. ;
正如您刚刚发现的那样,这真的不是一个好主意。在这种情况下,没有其他规则识别 (
或 )
,因此上述规则将忽略它们。但是,您的解析器需要一个括号。它没有得到一个,所以它报告了一个语法错误。
更好的是以下回退规则,它可以取代前面的规则:
/* [-+=;] {return yytext[0];} */ /* now redundant*/
. {return yytext[0];}
这接受词法分析器中的任何字符。但是,大多数字符在语法中的任何地方都没有用作字符文字,因此它们会被解析器视为无效标记,从而导致语法错误。
您可以通过在 lex 回退规则中写入错误来获得更精确的错误消息,但是您需要确保所有 vslid 字符都被识别:
[-+=;(){}] {return yytext[0];}
. {return yytext[0];}
就我个人而言,我会将 <>
添加到该列表中,而不是拥有专用规则(和不必要的令牌名称。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。