Gcc Bison解析器始终打印“;语法错误“;

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

我正在尝试构建一个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”
变为
“\n”

一旦您解决了这个问题,您就会遇到另一个问题:
{DIGITS}+
{NAME}
的lex规则不会返回令牌,因此令牌将被忽略(导致语法错误)

对于一般的解析器调试问题,通常值得使用
-DYYDEBUG
编译,并坚持使用
yydebug=1转换为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;
         }