奇数野牛解析

Odd bison parsing

以此为借口,我知道解析结构的格式很奇怪,老师希望它是~大致~这种格式。

我正在使用 flex 和 bison 做一个简单的 "calculator" 解析器形成一个赋值,但是在使用模数时我得到奇怪或不寻常的答案输出。 IT 似乎适用于所有其他操作

Input:   "10 % 5"
Output:  "  % 10"
Input:    "101 % 12"
Output:   "  % 101"
Input: "2^(-1 + 15/5) - 3*(4-1) + (-6)"
Output: "-11" //Correct

bison.y

的相关部分
command : pexpri    {printf("%d\n", ); return;}
        ;

pexpri  : '-' expri '+' termi   {$$ = - + ;} /* Super glued on unary, also reduce conflict, TODO: find bug */
        | '-' expri '-' termi   {$$ = - - ;}
        | '-' expri             {$$ = -;}
        | expri                 {$$ = ;}
        ;
expri   : expri '+' termi   {$$ =  + ;} /* Addition subtraction level operations*/
        | expri '-' termi   {$$ =  - ;}
        | termi             {$$ = ;}
        ;
termi   : termi '*' factori     {$$ =  * ;} /* Multiplication division level operations*/
        | termi '/' factori     {$$ =  / ;}
        | termi '%' factori     {$$ =  % ;}
        | factori               {$$ = ;}
        ;
factori : factori '^' parti {$$ = pow(, );} /* Exponentiation level operations */
        | parti             {$$ = ;}
        ;
parti   : '(' pexpri ')'        {$$ = ;} /* Parentheses handling or terminal, also adds even more reduction errors.... */
        | INTEGER
        ;

相关部分tokenizer.l

0           { /* To avoid useless trailing zeros. */
                yylval.iVal = atoi(yytext);
                return INTEGER;
            }
[1-9][0-9]* {
                yylval.iVal = atoi(yytext);
                return INTEGER;
            }
[-()^\+\*/]         {return *yytext;}

main 函数本质上只是 yyparse 的包装器。

我不明白它如何或为什么在输出中打印模数符号,因为整个代码中唯一的打印是在命令部分。我知道代码不是最好的(事实上,它很糟糕),但非常感谢任何见解。

此外,如果有人能帮助我弄清楚如何以更优雅的方式管理一元否定(希望不要剧透太多),那我也将不胜感激。 (我不能只使用 %precidence 或 %left)我目前设置它的方式不明确并且会导致减少错误。

如果你仔细观察

[-()^\+\*/]         {return *yytext;}

您会注意到它不会匹配 %。最可能的结果是 (f)lex 的默认回退规则将适用。该规则匹配任何单个字符并使用 ECHO 将匹配的标记复制到输出流。

在我看来,空白字符也可能符合默认规则。应明确忽略它们。

顺便说一句,没有必要在字符 类 内对正则表达式运算符进行反斜杠转义,因为它们在该上下文中没有特殊含义。因此,正确且更易于阅读的规则是

[-+*/%^()]         {return *yytext;}

但是,我强烈建议使用后备规则而不是列出所有可能的单字符标记。如果回退规则处理无效的单字符标记,则解析器将通过标记错误来响应。

[[:space:]]+      { /* Ignore whitespace*/ }
0|[1-9][0-9]*     { yylval.iVal = atoi(yytext); return INTEGER; }
.                 { return *yytext; /* Fallback rule */ }

默认回退规则在解析时很少有用,我发现添加

很有用
%option nodefault

到我的 flex prolog,如果需要回退规则,这将导致 flex 产生错误消息。