Bison 和 Flex 代码每隔一段时间工作一次

Bison and Flex code works every other time

我正在使用 Bison 和 Flex 创建一个基本的 Lisp 解释器,所以现在我正在尝试制作一个也读取一组括号的中缀加法器。出于某种原因,我的代码似乎每隔一段时间才有效

lisp.l

 %option noyywrap
%{
    #include <stdlib.h>
    #include <stdio.h>
    #include "lisp.tab.h"
//  #include "lisp.h"
    #include <string.h>
    #define YYSTYPE double

    #define YY_DECL int yylex()
%}

%%

[ \t]    ;  {/* eat up whitespace */}
[0-9]+(\.[0-9]+)?   {yylval.dval = atof(yytext); return DOUBLE;}
"+"             {return ADD; }
"-"         {return SUB; }
"/"         {return DIVIDE; }
"*"         {return MULTIPLY; }
"let"           {return LET;}
"print"         {return PRINT;}
"EQ"            {return EQUAL;}
"LT"            {return LESSTHAN;}
"LE"            {return LESSTHANEQUAL;}
"GT"            {return GREATERTHAN;}
"GE"            {return GREATERTHANEQUAL;}
"NE"            {return NOTEQUAL;}
"if"            {return IF;}
";"             {return IGNORE;}
[a-zA-Z]+       {return identifier;}
"("         {return LEFTPAR;}
")"         {return RIGHTPAR;}


%%

lisp.y

%{


    #include <stdio.h>
    #include <stdlib.h>
//  #include <map>
    #include <string.h>
    #include <math.h>
    #include "lisp.tab.h"


//  static std::map<std::string, double> symbolsMap;

//  double symbolValMap(std::string symbol);
//  void updateSymbolValMap(std::string symbol, double val);

    extern int yylex();

    extern FILE* yyin;

    extern int yyparse();

    void yyerror(const char* msg);
%}

%union {
    double dval;
}
%token<dval> DOUBLE
%token<id> identifier
%token LET PRINT EQUAL LESSTHAN LESSTHANEQUAL GREATERTHAN GREATERTHANEQUAL
%token NOTEQUAL IF IGNORE LEFTPAR RIGHTPAR MULTIPLY DIVIDE SUB ADD


%type<dval> mixed_expression
%type<id> varName

%left SUB ADD MULTIPLY DIVIDE

%start program


%%
program:
    | program line
    ;

line: '\n'
    | mixed_expression '\n'   {printf("\tResult: %f\n", );}
    | '(stop)\n'          {printf("bye!\n"); exit(0); }
    ;

mixed_expression: DOUBLE        {$$ = ;}
    | LEFTPAR ADD  mixed_expression mixed_expression RIGHTPAR     {$$ =  + ; printf("Result: %g","%1f", $$);}
    | LEFTPAR SUB  mixed_expression mixed_expression RIGHTPAR     { $$ =  - ; }
    | LEFTPAR MULTIPLY mixed_expression mixed_expression RIGHTPAR {$$ =  * ;}
    | LEFTPAR DIVIDE mixed_expression mixed_expression RIGHTPAR   {$$ =  / ;}
    | LEFTPAR  mixed_expression RIGHTPAR                { $$ = ; }
    ;


%%
int main() {
    yyin = stdin;
    do { 
        yyparse();
    } while(!feof(yyin));
    return 0;
}
/*void updateSymbolValMap(std::string symbol, double val)
{
//  symbolsMap[symbol] = val;
}
double symbolValMap(std::string symbol)
{
// return symbolsMap[symbol];
    return 0;
}*/
void yyerror(char const* msg)
{
    fprintf(stderr, "Parse error: %s\n", msg);
    yyparse();
}

当我运行代码并传入参数时,输出如下:

(- 4 5)
Result: -1
(* 8 9)
Parse error: syntax error
Parse error: syntax error
Parse error: syntax error
Parse error: syntax error

生成文件

all = lisp

lisp.tab.c lisp.tab.h: lisp.y
    bison -d lisp.y

lex.yy.c: lisp.l lisp.tab.h
    flex lisp.l

lisp:   lex.yy.c lisp.tab.c lisp.tab.h
    gcc lisp.tab.c lex.yy.c -lm -o lisp

clean:
    rm lisp lisp.tab.c lex.yy.c lisp.tab.h

无论如何,我每隔一段时间就会收到一个解析错误。任何帮助将不胜感激。

要实现这一点:

line: '\n'
    | mixed_expression '\n'   {printf("\tResult: %f\n", );}

您的词法分析器 return 标记 \n 是必要的。但是你的词法分析器永远不会那样做。事实上,一个换行符在你的词法分析器中不匹配任何规则,所以它会执行default action(见第三段),它只是将不匹配的字符打印到标准输出并继续寻找令牌,不向解析器传递任何内容。

此外,这根本行不通:

   | '(stop)\n'          {printf("bye!\n"); exit(0); }

因为'(stop)\n'不是C字符字面量,词法分析器肯定无法return它。我怀疑您会收到来自 lex 的关于此的警告。将符号更改为 "(stop)\n" 将使警告静音,但它仍然不会产生可以从词法分析器 returned 的标记。

还有许多其他问题,包括您使用的语义值标签 (<id>) 没有出现在您的 %union 声明中,并且您将其声明为未定义的 non-terminal (varName)。此外,优先级声明 (%left SUB ADD MULTIPLY DIVIDE) 毫无意义,因为这些标记不会进入 shift-reduce 冲突。