【问题标题】:Lex - yacc program showing syntax errorLex - yacc 程序显示语法错误
【发布时间】:2017-02-07 12:15:23
【问题描述】:

为了对输入执行算术运算,编写了以下两个代码,但它一直给我语法错误 这是 lex 程序

%{ 
#include "y.tab.h" 
#include <stdlib.h>
%}



%%

[0-9]+ {yylval =  atoi(yytext);return ID;}

[*-+/()] {return yytext[0];}

'\n'  {return END;}


. {return yytext[0];}

%%

这是 yacc 程序:

 %{
     #include <stdio.h>
     #include <stdlib.h>
     #include "y.tab.h"     
 %}
 %token ID END  
 %%
 S: expr END { printf("Answer is : %d\n",$$);   exit(1);  }   
 expr: ID
 | 
 | expr '+' expr { $$ = $1+$3;}
 | expr '-' expr { $$ = $1-$3;}
 | expr '*' expr { $$ = $1*$3;}
 | expr '/' expr { $$ = $1/$3;}
 | '(' expr ')' {$$ = $2;}
 ;
 %%
 int main()
 {
     yyparse();
 }

输出:

 2+3

 2+3
 Syntax error

可能是什么问题?

【问题讨论】:

  • 你已经显示了输出——很好。不清楚您的输入是什么。
  • 2+3 是我的输入。如果正确,它应该显示:答案是 5
  • 除了我在回答中提到的错误之外,您还需要通过定义运算符优先级来解决移位减少冲突。

标签: yacc lex


【解决方案1】:

存在三个问题。

第一个问题是你的语法只能识别一个表达式:

S: expr END { printf("Answer is : %d\n",$$);   exit(1);  }

所以如果输入两个表达式,就会出现语法错误。

第二个问题是您的扫描仪实际上并没有将换行符识别为END 令牌:

'\n'  {return END;}

' 不是 (f)lex 的特殊字符。 (有关接受的模式字符的完整列表,请参阅Flex manual。)因此该规则正在寻找三个字符:撇号、换行符和另一个撇号。如果您提供该输入,您将获得“预期”输出:

$ ./badexpr
2+3'
'
Answer is : 5
$

你想写的是

\n    { return END; }

但这可能也不理想。这将在单个表达式之后立即返回。更有趣的语法将允许任意数量的表达式:

文件.l

%{ 
#include <stdlib.h>
#include "y.tab.h" 
%}

%%

[0-9]+ {yylval =  atoi(yytext);return ID;}
.|\n   {return yytext[0];}

文件.y

%{
     #include <stdio.h>
     #include <stdlib.h>
%}
%token ID
%%
S: /* %empty */
 | S expr '\n'   { printf("Answer is : %d\n",$2); }
 | S '\n'
expr: ID
 | expr '+' expr { $$ = $1+$3;}
 | expr '-' expr { $$ = $1-$3;}
 | expr '*' expr { $$ = $1*$3;}
 | expr '/' expr { $$ = $1/$3;}
 | '(' expr ')' {$$ = $2;}
 ;
 %%
 int main()
 {
     yyparse();
 }

变化:

  • 我从 flex 输入中删除了所有单字符模式,因为它们都具有相同的效果:返回读取的单字符。由于以下更改,这包括换行符。
  • 我更改了语法的开始产生式,使其显式查找换行符(而不是 END)并接受任意数量的输入行。
  • 我从 bison 输入中删除了 #include "y.tab.h",因为没有必要在解析器文件中包含解析器头。
  • 我将expr 的空产生式移到S 产生式中,这样它就不会尝试打印空表达式的值。

最后,您尝试在开始生产中显式识别END 令牌。这可能有效,但不建议这样做。

Yacc/bison 通过添加一个看起来与您的规则 S 完全相同的外部规则来自动增强您的语法:它识别开始非终结符后跟 END。因此,无需添加您自己的作品。

【讨论】:

  • 是的,这行得通。非常感谢 。我假设换行符被视为一个字符,而 lex 遵循相同的原则来识别它。
猜你喜欢
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-27
相关资源
最近更新 更多