我有一个简单的表达式,我正在编写,我正在寻找一种方法来编写这样的表达式的语法,以便ANTLR可以使用这个文件生成词法分析器和解析器。
我的表达式没有赋值。它们只是对一些已经存在的字段的一堆操作。不需要求值
我有一堆预定义的函数(如SUM, MEAN, SUBSTR,后端理解),这些函数应用于一些现有的字段。
需要的操作符是:- +、-、*、/括号:(,)表示开始和结束。函数(关键字):SUM, MEAN, MAX SUBSTR.
的例子:
- (A + B),也可以是SUM(A, B)
- (平均(A, B, C) +马克斯(X, MIN (Y, Z)) + 2)/4
- SUBSTR("TEST1"0 6)
表达式可以扩展为多行。
这是我写的基本版本。
grammar ExpressionGrammar;
parse: (expr)+ EOF
;
expr: expr '/' expr
| expr '*' expr
| expr '+' expr
| expr '-' expr
| NUM
| function
;
function : ID '(' arguments? ')';
arguments: expr ( ',' expr)*;
/* Tokens */
OPEN_PAR : '(' ;
CLOSE_PAR : ')' ;
NUM : '0' | '-'?[1-9][0-9]*;
ID : [a-zA-Z_] [a-zA-Z]*;
COMMENT: '//' ~[rn]* -> skip;
WS: [ tn]+ -> skip;
最后,我还必须对用户键入的表达式运行一些验证。如果我在MAX()函数中输入一个字符串,它只接受数字,我应该能够知道错误所在的行/位置并通知用户。我相信这是在解析阶段发生的。只是把它放在那里,以防有任何输入,如果这个语法可以帮助我识别。
几点说明:
- 我不会将减号粘合到词法分析器中的数字上,而是匹配一个一元表达式
- 您缺少
expr
规则'(' expr ')'
中的嵌套表达式 - 您可能还想在
expr
规则中匹配ID
*
和/
通常具有相同的优先级,因此应分组在相同的备选项中(+
和-
相同)
这样更有意义:
parse: (expr)+ EOF
;
expr: MIN expr
| expr ( MUL | DIV ) expr
| expr ( ADD | MIN ) expr
| NUM
| ID
| function
| '(' expr ')'
;
function : ID '(' arguments? ')';
arguments: expr ( ',' expr)*;
/* Tokens */
MUL : '*';
DIV : '/';
MIN : '-';
ADD : '+';
OPEN_PAR : '(' ;
CLOSE_PAR : ')' ;
NUM : '0' | [1-9][0-9]*;
ID : [a-zA-Z_] [a-zA-Z]*;
COMMENT: '//' ~[rn]* -> skip;
WS: [ tn]+ -> skip;
最后,我还必须对用户键入的表达式运行一些验证。如果我在MAX()函数中输入一个字符串,它只接受数字,我应该能够知道错误所在的行/位置并通知用户。我相信这是在解析阶段发生的。只是把它放在那里,以防有任何输入,如果这个语法可以帮助我识别。
这种语义检查应该在解析之后进行。解析器创建一个解析树。然后在访问者内部遍历该解析树并对输入求值。然后,如果计算的输入不具有某些函数的正确类型,则可以产生错误/警告。