【问题标题】:Bison, flex simple calculator野牛,灵活的简单计算器
【发布时间】:2022-01-22 07:46:50
【问题描述】:

我想为简单的计算器做解析器。

输入格式如“10+20;”、“50*60;”、“4+8;1-7;”

输出应该是 30 3000 12 -6

每个 case 结尾总是有一个分号";"

我的野牛文件是这样的

%{  
#include <stdio.h> 
extern FILE* yyin;
%}

%token T_NUM

%left '+' '-'
%left '*' '/'

%% 

S   :   S E '\n'        { printf("ans = %d\n", $2); }
    |   /* empty */     { /* empty */ }
    ;

E   :   E '+' E        { $$ = $1 + $3; }
    |   E '-' E         { $$ = $1 - $3; }
    |   E '*' E         { $$ = $1 * $3; }
    |   E '/' E         { $$ = $1 / $3; }
    |   T_NUM           { $$ = $1; }
    |   '(' E ')'       { $$ = $2; }
    ;

%%          
yyerror (char *s)
{
   fprintf(stderr, "%s\n", s);  
}
yywrap()    
{
   return (1);
}

int main(int argc, char **argv)
{
   yyin = fopen("testcase.in", "r");    
   yyparse();   
   fclose(yyin);
   return 0;
}

Flex 文件如下所示:

%{ 
#include "cal.tab.h"
%}

%% 
[0-9]+          { yylval = atoi(yytext); return T_NUM; }
[-/+*()\n]      { return yytext[0]; }
[ \t]           { }

[;]             { }
.               { return 0; /* end when meet everything else */ }
%%

testcase.in 看起来像这样

34+801;

1+2;

2+3;2+4;

3/2;3*5;

./a.out 应该是这样的

835

3

5

6

1

15

但我的结果是“语法错误”

希望你能帮助我.plz~

【问题讨论】:

    标签: calculator bison


    【解决方案1】:

    你的程序没有问题;所有的碎片都在那里。您只需要尊重您自己的问题描述并编写您的扫描仪和解析器以使用分号作为终止符而不是换行符。

    您声称您希望表达式以分号结尾,并且您的示例输入具有该格式。但是您的扫描仪会忽略分号,并且您的语法要求表达式以换行符结尾。您需要忽略换行符,并要求表达式以分号结束:

    /* In cal.y, line 6 */
    S   :   S E ';'        { printf("ans = %d\n", $2); }
    /*           ^
     *           |--------- Changed semicolon to newline.
     */
    
    /* In cal.l, lines 7-8. Lines 9 and 10 removed. */
    [-/+*();]       { return yytext[0]; }
     /*    ^
      *    |-------- Changed newline to semicolon.
      */
    [ \t\n]         { }
     /*  ^
      *  |-----------Changed semicolon to newline.
      */
    

    【讨论】:

      【解决方案2】:

      S E '\n' 更改为E ';' S,因为每个表达式都以分号结尾。请注意(来自@rici 评论)替代规则是:S: S ';' E。每条规则都会导致不同的结果AST 供您稍后扫描。选择更适合您需求的。

      【讨论】:

      • 你绝对不想要右递归产生式;这将导致非常混乱的输出。此外,如果您查看示例输入,您会发现并非“每个表达式都在单独的行中”。几行有多个表达式。
      • 谢谢@rici,我编辑了这篇文章。我个人认为这两个结果 AST 是等价的。根据口味,我喜欢1-item-head ++ rest 超过all-but-last ++ 1-item-last 的列表
      • 分号作为结束符,不是分隔符,所以规则应该是S : S E ';'
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-09
      相关资源
      最近更新 更多