野牛多规则符号

时间:2015-12-05 01:13:10

标签: bison flex-lexer

我有一个符号表,其中包含变量/符号的名称,数据和数据类型(存储为char)。我想这样的符号被视为一个iexpr,如果它是一个整数或rexpr,如果它是一个真实的。这些是我现在拥有的规则:

iexpr: INT_TOKEN
    | iexpr PLUS iexpr { $$ = $1 + $3; }
    | iexpr MINUS iexpr { $$ = $1 - $3; }
    | iexpr DIVIDE iexpr {$$ = $1/$3;}
    | iexpr MOD iexpr{$$ = $1 % $3;}
    | LPARENT iexpr RPARENT{$$=$2;}
    | SYMBOL {  symrec *s;
                s = getsym($1);
                if(s!=0){
                    if(s->type == 'i'){
                        $$ = atoi(s->data);
                    }
                }
             }
;
rexpr: REAL_TOKEN 
    | rexpr PLUS rexpr {  $$ = $1 + $3; }
    | rexpr MINUS rexpr { $$ = $1 - $3; }
    | iexpr PLUS rexpr {  $$ = (double) $1 + $3; }
    | iexpr MINUS rexpr { $$ = (double) $1 - $3; }
    | rexpr PLUS iexpr {  $$ = $1 + (double) $3; }
    | rexpr MINUS iexpr { $$ = $1 - (double) $3; }
    | rexpr DIVIDE rexpr {$$ = $1/$3;}
    | rexpr MULTIPLY rexpr{$$ = $1 * $3;}
    | rexpr DIVIDE iexpr {$$ = $1 / (double) $3;}
    | rexpr MULTIPLY iexpr {$$= $1 * (double) $3;}
    | iexpr DIVIDE rexpr {$$ = (double) $1 / $3;}
    | iexpr MULTIPLY rexpr {$$ = (double) $1 * $3;}
    | rexpr MOD rexpr {$$ = (int)$1 % (int)$3;}
    | rexpr MOD iexpr {$$ = (int)$1 % $3;}
    | iexpr MOD rexpr {$$ =  $1 % (int)$3;}
    | LPARENT rexpr RPARENT{$$ =$2;}
    | SYMBOL {  symrec *s;
                s = getsym($1);
                if(s!=0){
                    if(s->type == 'r'){
                        $$ = atof(s->data);
                    }
                }
             }
;

然而,rexpr中的规则从未被使用,因为它只将它视为iexpr。我怎样才能使它根据类型描述符被视为该类型而不仅仅是一个整数?

编辑:所以我试图更改我的lex文件,以便它为每种类型返回一个不同的标记。为此,我需要包含我的符号表头文件,以便我可以检查该名称并根据其类型返回不同的符号。这是代码:

[a-zA-Z]+ { yylval.string = strdup(yytext);
            symrec *s;
            s = getsym(yylval.string);
            if(s!=0){
                if(s->type == 'r'){
                    return RSYMBOL;
                }else if(s->type == 'i'){
                    return ISYMBOL;
                }
            }else{
             return SYMBOL;
            }
          }

但现在我有一个错误,说我对我的标题函数有多个定义,因为我将它包含在两个文件中。

2 个答案:

答案 0 :(得分:2)

如果您希望令牌类型根据符号的声明类型而变化,则需要在词法分析器中查找符号(因为这是生成令牌类型的原因)。

您实际上需要返回三种不同令牌类型中的一种:

  • INT_SYMBOL
  • REAL_SYMBOL
  • UNDECLARED_SYMBOL

一般来说,最好在解析完成后在AST上单独传递中进行类型检查。 (或者,如果您没有生成AST,则可以在语义操作中执行此操作。)这样可以生成更好的错误消息,并且可以在类型错误后继续解析更容易。 / p>

答案 1 :(得分:1)

如果你想这样做,你需要让词法分析器为ISYMBOLRSYMBOL返回不同的标记,否则你会在{{{{}}的两次减少之间得到减少/减少冲突1}}因为解析器不知道它是什么。这意味着您需要在词法分析器操作中执行符号表查找,而不是在解析器操作中。

通常,尝试在解析器中进行这样的类型检查是一个坏主意,因为它会使语法更加复杂并导致许多难以解决的冲突。