最近在尝试实现一个c语言编译器。其中涉及到语法树的构建。在解析表达式时,就需要考虑左递归和优先级问题。左递归,可以通过 百度百科 中的方式来消除左递归。但是由于表达式又存在优先级问题。所以消除过程十分繁琐。如下简单的计算器实现例子:
消除左递归,并添加优先级后,如下:
Num: [0-9]+
factor: Num | '(' expr3 ')'
term_tail: | ('*' expr1 | '/' expr1) term_tail
term: factor term
expr_tail: | ('+' expr2 | '-' expr2) expr_tail
expr: term expr_tail
可以看出,表达式比较复杂。如果再添加其他运算,如位移运算,逻辑运算,以及其他自定义运算。则实现起来及其复杂。
Antlr4
如果使用 antlr4则语法就会变得很简单。如下,有左递归的表达式在或中越靠前,优先级越高,factor 类则无影响。
Num: [0-9]+
expr:
Number
| '(' expr ')'
| expr ('*'|'/') expr
| expr ('+'|'-') expr
;
可以在vscode 中使用 ANTLR4 grammar syntax support 插件 测试该语法。
编写g4 文件
ctrl+s 保存以下,生成 .antlr文件夹
添加 .vscode/launch.json 写入如下内容
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug ANTLR4 grammar - Test - Expr",
"type": "antlr-debug",
"request": "launch",
"input": "test.txt", // 测试内容文件
"grammar": "Test.g4", // 语法文件
"startRule": "expr", // 入口表达式