Flex和Bison C加法器在不执行表达式

时间:2016-11-15 00:32:30

标签: c bison flex-lexer

我一直在尝试实施计算器,但我找不到此Flex,Bison和C程序的来源。我真的不知道我做错了什么。这是我的文件:

henry@FusionReactor:~/Downloads/YASPLANG$ ls
a.out       compiler.output  compiler.y  lex.yy.c
compiler.l  compiler.tab.c   file.o      README

我的语法:

henry@FusionReactor:~/Downloads/YASPLANG$ cat compiler.y
%{
  #include <stdio.h>
  void yyerror(const char *msg) {
    fprintf(stderr, "%s\n", msg);
  }
  int yydebug = 1;
%}
%code requires
  {
    #define YYSTYPE double
  }
/*
%union {
    char c;
    char *s;
    double d;
}
*/
%define parse.error verbose
%define parse.lac full
%token NUM
%token PLUS
%token NEWLINE
%left PLUS
%%
answered: %empty      {;              }
| answered answer     {;              }//{ printf("%lg is answered.\n",$2); $$ = $1; }
;
answer: NEWLINE       { $$ = 0.0;    }
| expr  NEWLINE       { $$ = $1;     }
;

expr:  expr PLUS expr { $$ = $1 + $3; }//printf("%lg\n", $$ = $1 + $3); printf("Doing %lg + %lg.\n", $1, $3); }
| NUM                 { $$ = $1;      }//printf("%lg\n", $$ = $1);      printf("Found number: %lg.\n",   $1); }
;
%%

我的词霸:

henry@FusionReactor:~/Downloads/YASPLANG$ cat compiler.l
%{
  int yylex(void);
  #include "compiler.tab.c"
%}

%%

[ \t]              ;

'\n'               ;//{ return NEWLINE;                                                                   }

'+'                { return PLUS;                                                                      }

^[0-9]+(\.[0-9]+)? { sscanf(yytext, "%lf", &yylval); printf("%lf = %s\n", yylval, yytext); return NUM; }

%%

int main(const char **argv, int argc) {
  return yyparse();
}

我使用这些命令编译它(我将所有内容保存在我的下载中,文件夹名称是首字母缩略词,让我们不要太担心):

henry@FusionReactor:~/Downloads/YASPLANG$ bison --report=all --verbose --debug compiler.y
henry@FusionReactor:~/Downloads/YASPLANG$ flex compiler.l
henry@FusionReactor:~/Downloads/YASPLANG$ gcc lex.yy.c -lfl

当我执行并输入“5 + 5 [NEWLINE]”两次时,我得到:

henry@FusionReactor:~/Downloads/YASPLANG$ ./a.out
Starting parse
Entering state 0
Reducing stack by rule 1 (line 26):
-> $$ = nterm answered ()
Stack now 0
Entering state 1
Reading a token: 5 + 5
5.000000 = 5
Next token is token NUM ()
Shifting token NUM ()
Entering state 3
Reducing stack by rule 6 (line 34):
   $1 = token NUM ()
-> $$ = nterm expr ()
Stack now 0 1
Entering state 6
Reading a token: +5
5 + 5
5.000000 = 5
Next token is token NUM ()
LAC: initial context established for NUM
LAC: checking lookahead NUM: Err
Constructing syntax error message
LAC: checking lookahead $end: Err
LAC: checking lookahead NUM: Err
LAC: checking lookahead PLUS: S7
LAC: checking lookahead NEWLINE: S8
syntax error, unexpected NUM, expecting PLUS or NEWLINE
Error: popping nterm expr ()
Stack now 0 1
Error: popping nterm answered ()
Stack now 0
Cleanup: discarding lookahead token NUM ()
Stack now 0
henry@FusionReactor:~/Downloads/YASPLANG$ 

我非常困惑,如果有可能告诉它如何以及为什么不起作用,那将非常有帮助。

1 个答案:

答案 0 :(得分:1)

在(f)lex中,模式'+'匹配两个或更多&#39; 的序列,因为'只是一个普通字符。如果您想匹配单个 + ,请使用"+"\+[+]

同样,'\n'匹配三字符序列&#39; ENTER &#39; 。只需使用\n

最后,^[0-9]+(\.[0-9]+)?只匹配一行开头的数字,因为模式以^开头。您希望它在任何地方匹配,因此丢失^

报告没有明显错误的原因是(f)lex添加了一个隐式默认规则,它匹配任何单个字符并执行ECHO操作(将字符写入stdout。默认规则几乎不是什么你想要;我强烈建议你使用

%option nodefault

压制它。然后,您必须提供自己的默认规则,并采取更明智的行动。