【问题标题】:Make a simple calculator using flex and bison使用 flex 和 bison 做一个简单的计算器
【发布时间】:2023-03-17 10:13:01
【问题描述】:

我正在尝试使用 flex 和 bison 生成器制作一个非常简单的计算器。 它只适用于整数。 我正确编译了词法分析器文件,没有错误;但是当我编译解析器文件时,它向我显示了一些警告:

  • 警告:1 个非终结符在语法中无用
  • 警告:2 条规则在语法中无用
  • 21.1-4:警告:语法中的非终结符无用:行
  • 21.9-1:警告:语法中的规则无用:行:NWL
  • 22.9-55:警告:1 个非终结符在语法中无用:Exp NWL

在显示这些警告后生成输出文件。
我通过 gcc 编译了输出文件;它制作了一个 .exe 文件。
当我运行 .exe 文件并尝试计算时,它显示了这个错误:

  • 语法错误

请帮帮我。

我的代码:
词法分析器文件

%option noyywrap
%{
#define YYSTYPE double
#include <stdio.h>
#include "x.tab.h"
%}
DIG         [0-9]
%%
{DIG}+      { yylval = atoi(yytext); return NUM; }
"+"                             { return PLS; }
"-"                             { return MNS; }
"*"                             { return MUL; }
"/"                             { return DIV; }
"\n"                                { return NWL; }
"("                             { return LFT; }
")"                             { return RIT; }
%%

解析器文件

%{
#include <stdio.h>
#define YYSTYPE double
int yyerror (char const *s);
extern int yylex (void);
%}
%token  PLS MNS
%token  MUL DIV
%token  NWL
%token  NUM
%token  LFT RIT
%left   PLS MNS
%left   MUL DIV
%%
Exp:    NUM             { $$ = $1; };
Exp:    Exp PLS Exp     { $$ = $1 + $3; };
Exp:    Exp MNS Exp     { $$ = $1 - $3; };
Exp:    Exp MUL Exp     { $$ = $1 * $3; };
Exp:    Exp DIV Exp     { $$ = $1 / $3; };
Exp:    LFT Exp RIT     { $$ = $2; };
Line:   NWL;
Line:   Exp NWL         { printf("%f\n", $1); };
;
%%
int yyerror(char const *s) {
  printf("%s\n", s);
}
int main(){
    int ret = yyparse();
    if (ret){
    fprintf(stderr, "%d error found.\n",ret);
    }
    return 0;
}

【问题讨论】:

  • 您是否用{...} 包围了#define#include 语句? (每个文件的顶部。)
  • 有没有关于C 语法错误的更多细节?错误信息还说了什么?
  • 我认为不是C语法错误;因为当我在计算器中写东西时,它会显示这个错误:语法错误(不再)。
  • 您需要查找 Yacc/Bison 的 | 运算符。你写的不是表达对同一个非终结符的替代减少的正确方法。
  • @user207421 没错; foo: bar; foo: quxfoo: bar | qux 完全一样。这只是风格的问题。此外,顺序无关紧要 - 除了在未使用 %start sym 明确说明时确定起始符号。

标签: c parsing bison flex-lexer yacc


【解决方案1】:

语法的开始符号是Exp,而不是Line。要么将Line 规则放在首位,要么使用%start Line 声明。 %start 声明应位于 %% 之前,与 %token 声明位于同一部分。

这应该会让你的程序可以处理第一行,比如3 + 4 ;-)

如果您希望它处理多行,则应添加另一条规则——*.y 文件的固定语法部分示例,Seq(行序列)是开始符号:

Seq:    /* empty */
|       Seq Line
Exp:    NUM             { $$ = $1; };
Exp:    Exp PLS Exp     { $$ = $1 + $3; };
Exp:    Exp MNS Exp     { $$ = $1 - $3; };
Exp:    Exp MUL Exp     { $$ = $1 * $3; };
Exp:    Exp DIV Exp     { $$ = $1 / $3; };
Exp:    LFT Exp RIT     { $$ = $2; };
Line:   NWL
Line:   Exp NWL         { printf("%f\n", $1); };

【讨论】:

  • 建议使用%empty 明确规则RHS 为空。很像在形式语言理论中使用ε
  • @akim %empty 仅限野牛。我会发表评论。
  • (问题是关于 Bison 和 Flex。)
  • 除非必要,否则仍然没有理由使用扩展程序——与位置跟踪和重入支持等其他野牛功能不同,%empty 指令不会增加太多价值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-28
  • 2013-05-17
  • 2020-12-18
相关资源
最近更新 更多