奇数野牛解析
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 产生错误消息。
以此为借口,我知道解析结构的格式很奇怪,老师希望它是~大致~这种格式。
我正在使用 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 产生错误消息。