Lex-yacc程序显示语法错误 [英] Lex - yacc program showing syntax error

查看:309
本文介绍了Lex-yacc程序显示语法错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了对输入执行算术运算,已编写了以下两个代码,但是它始终使我出现语法错误 这是lex程序

The following two codes have been written in order to perform arithmetic operations on input , but it gives me syntax error all the time Here is the lex program

%{ 
#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

可能是什么问题?

推荐答案

存在三个问题.

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

The first problem is that your grammar only recognizes a single expression:

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

因此,如果您输入两个表达式,则会出现语法错误.

So if you enter two expressions, there is a syntax error.

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

The second problem is that your scanner does not actually recognize a newline character as an END token:

'\n'  {return END;}

'不是(f)lex的特殊字符. (有关可接受的模式字符的完整列表,请参见 Flex手册. ),因此该规则正在查找三个字符:撇号,换行符和另一个撇号.如果提供该输入,则将获得预期"输出:

' is not a special character for (f)lex. (See the Flex manual for a complete list of accepted pattern characters.) So that rule is looking for three characters: an apostrophe, a newline, and another apostrophe. If you provide that input, you will get the "expected" output:

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

你想写的是

\n    { return END; }

但这也不是很理想.这将在单个表达式后立即返回.一个更有趣的语法将允许使用任意数量的表达式:

But that's probably not ideal either. That will return immediately after a single expression. A more interesting grammar would allow for any number of expressions:

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

%%

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

file.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)并接受任意数量的输入行.
  • 我从野牛输入中删除了#include "y.tab.h",因为没有必要在解析器文件中包含解析器标头.
  • 我将expr的空生产移到了S生产中,这样它就不会尝试打印空表达式的值.
  • Changes:

    • I removed all of the single-character patterns from the flex input because they all have the same effect: return the single character read. That includes the newline character, because of the following change.
    • I changed the start production for the grammar so that it looks for a newline character explicitly (rather than END) and accepts any number of input lines.
    • I removed the #include "y.tab.h" from the bison input because it is not necessary to include the parser header in the parser file.
    • I moved the empty production for expr into the S production so that it does not attempt to print the value of an empty expression.
    • 最后,您尝试在开始生产时明确识别END令牌.这可能有效,但不建议这样做.

      Finally, you attempt to explicitly recognize an END token in your start production. That may work but it is not recommended.

      Yacc/野牛通过添加看起来与您的规则S完全一样的外部规则来自动扩充语法:它可以识别开始的非终结符,后跟END.因此,无需添加自己的作品.

      Yacc/bison automatically augment your grammar by adding an outer rule which looks precisely like your rule S: it recognizes the start non-terminal followed by END. So adding your own production is unnecessary.

      这篇关于Lex-yacc程序显示语法错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆