简单的Lex / Yacc计算器无法打印输出

时间:2017-04-22 08:53:42

标签: yacc lex

我试图理解编译器和编程语言是如何制作的。为此,我考虑创建一个简单的计算器,它只进行加法和减法。以下是我写的 Lex Yacc 文件。

calc.yacc 文件:

%{
  #include <stdio.h>
  #include <stdlib.h>

  extern int yylex();
  void yyerror(char *);
%}

%union { int number; }
%start line
%token <number> NUM
%type <number> expression

%%

line: expression  { printf("%d\n", $1); };

expression: expression '+' NUM  { $$ = $1 + $3; };
expression: expression '-' NUM  { $$ = $1 - $3; };
expression: NUM  { $$ = $1; };

%%

void yyerror(char *s) {
  fprintf(stderr, "%s", s);
  exit(1);
}

int main() {
  yyparse();
  return 0;
}

calc.lex 文件:

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

%%

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

[-+] { return yytext[0]; }

[ \t\f\v\n] { ; }

%%

int yywrap() {
  return 1;
}

它编译得很好但是当我运行它并键入2 + 4之类的东西时,它会卡住并且不会打印出答案。有人可以解释一下原因吗?我的猜测是我的语法不正确(但我不知道如何)。

1 个答案:

答案 0 :(得分:0)

我的想法与rici相同,并且适当地更改了样本:

档案%{ #include <stdio.h> #include <stdlib.h> #include "calc.y.h" %} %% [0-9]+ { yylval.number = atoi(yytext); return NUM; } [-+] { return yytext[0]; } "\n" { return EOL; } [ \t\f\v\n] { ; } %% int yywrap() { return 1; }

calc.y

档案%{ #include <stdio.h> #include <stdlib.h> extern int yylex(); void yyerror(char *); %} %union { int number; } %start input %token EOL %token <number> NUM %type <number> expression %% input: line input | line line: expression EOL { printf("%d\n", $1); }; expression: expression '+' NUM { $$ = $1 + $3; }; expression: expression '-' NUM { $$ = $1 - $3; }; expression: NUM { $$ = $1; }; %% void yyerror(char *s) { fprintf(stderr, "%s", s); exit(1); } int main() { yyparse(); return 0; }

$ flex -o calc.l.c calc.l

$ bison -o calc.y.c -d calc.y

$ gcc -o calc calc.l.c calc.y.c

$ ./calc
2 + 4
6
2 - 4
-2
234 + 432
666

编译&amp;在Windows 10(64位)上的cygwin中测试:

#include

注意:

  1. 次要问题:根据构建命令,我必须更改生成的令牌表的EOL。 (品味问题。)

  2. 我在lex源代码中以及解析器的line规则中引入了input标记。

  3. 测试时我发现第二个输入在语法错误中每次都结束。我需要一段时间,直到我认识到语法实际上现在只限于接受一行。因此,我在解析器源中插入了递归?> <script type="text/javascript"> $(document).ready(function() { $("#menu2").click(function(event) { event.preventDefault(); swal("Many thanks to everyone for making me a better programmer.!", "Message", "success"); }) }); </script> <?php规则。