Gcc Bison解析器始终打印“;语法错误“;
我正在尝试构建一个3地址代码生成器,它将生成:Gcc Bison解析器始终打印“;语法错误“;,gcc,compiler-errors,gnu,yacc,lex,Gcc,Compiler Errors,Gnu,Yacc,Lex,我正在尝试构建一个3地址代码生成器,它将生成: input:x=a+3*(b/7) output: t1=b/7 t2=3*t1 t3=a+t2 x=t3 无论我输入什么,输出都是“语法错误”。 我用的是Windows10 Yacc代码: 基本问题是在yacc文件中对令牌使用双引号(“--strings)(没有为它们定义任何代码,因此它们是无用的),并在lex文件中返回单字符令牌。因此,解析器中不会识别任何令牌 将yacc文件中所有单字符标记上的所有“字符替换为”“+”变为“+”,“\n
input:x=a+3*(b/7)
output: t1=b/7
t2=3*t1
t3=a+t2
x=t3
无论我输入什么,输出都是“语法错误”。
我用的是Windows10
Yacc代码:
基本问题是在yacc文件中对令牌使用双引号(
“
--strings)(没有为它们定义任何代码,因此它们是无用的),并在lex文件中返回单字符令牌。因此,解析器中不会识别任何令牌
将yacc文件中所有单字符标记上的所有“
字符替换为”
“+”变为“+”
,“\n”
变为“\n”
)
一旦您解决了这个问题,您就会遇到另一个问题:{DIGITS}+
和{NAME}
的lex规则不会返回令牌,因此令牌将被忽略(导致语法错误)
对于一般的解析器调试问题,通常值得使用-DYYDEBUG
编译,并坚持使用yydebug=1在调用yyparse之前,将code>转换为main,这将导致解析器打印看到的令牌和访问的状态的跟踪。我经常把
if (getenv("YYDEBUG")) yydebug = 1;
进入main并将其保留在那里——这样通常不会启用调试,但是如果在运行程序之前设置环境变量YYDEBUG=1
,您将看到调试跟踪(无需重新编译)
为了返回令牌,您的lexer规则需要返回该令牌。因此,您的NUMBER
词法规则应该是:
{NUMBER} {
strcpy(yylval.ivar,yytext);
return NUMBER;
}
与名称类似。请注意,代码块的开头必须与模式在同一行上——如果它在单独的行上,它将不会与模式关联。基本问题是,您在yacc文件中对标记使用双引号(“
--strings)(没有为它们定义任何代码,因此它们是无用的),并在lex文件中返回单字符标记。因此,解析器中不会识别任何标记
将yacc文件中所有单字符标记上的所有“
字符替换为”
“+”
变为“+”
,“\n”
变为“\n”
)
一旦您解决了这个问题,您就会遇到另一个问题:{DIGITS}+
和{NAME}
的lex规则不会返回令牌,因此令牌将被忽略(导致语法错误)
对于一般的解析器调试问题,通常值得使用-DYYDEBUG
进行编译,并在调用yyparse之前将yydebug=1;
粘贴到main中,这将导致解析器打印看到的标记和访问的状态的跟踪
if (getenv("YYDEBUG")) yydebug = 1;
进入main并将其保留在那里——这样通常不会启用调试,但是如果在运行程序之前设置环境变量YYDEBUG=1
,您将看到调试跟踪(无需重新编译)
为了返回令牌,您的lexer规则需要返回
令牌。因此数字
的lexer规则应该是:
{NUMBER} {
strcpy(yylval.ivar,yytext);
return NUMBER;
}
与NAME
类似。请注意,开头的{
的代码块必须与模式在同一行上——如果它在单独的行上,它将不会与模式相关联。请将您的代码和错误消息嵌入问题中,而不要包含链接。@Amitairron Irron代码和消息是提供的,除了Chris Dodd的优秀答案外,您还可能遇到pro问题是因为您的语法不允许空行。另外,为语句列表编写正确的递归规则也不是一个好主意;最好是program:line | program line
。请将代码和错误消息嵌入问题中,而不是包含链接。@amitairon-Irron-code和消息作为根据Chris Dodd的优秀答案,您可能会遇到问题,因为您的语法不允许空行。此外,为语句列表编写正确的递归规则并不是一个好主意;最好是program:line | program line
。
{NUMBER} {
strcpy(yylval.ivar,yytext);
return NUMBER;
}