Javascript 如何为下面的标准编写语法-ANTLR4语法-自定义表达式

Javascript 如何为下面的标准编写语法-ANTLR4语法-自定义表达式,javascript,antlr,antlr4,grammar,Javascript,Antlr,Antlr4,Grammar,我正在编写一个简单的表达式,我正在寻找一种为这些表达式编写语法的方法,这样ANTLR就可以使用这个文件生成lexer和parser 我的表达式没有任何赋值。它们只是一些预先存在的字段上的一系列操作不需要对其进行评估。 我有一堆预定义的函数(如SUM、MEAN、SUBSTR,后端可以理解),这些函数应用于一些现有字段 我需要的运算符是:-+,-,*/ 括号:(,)用于打开和关闭。 函数(关键字):求和、平均值、最大值SUBSTR 示例:- (A+B),这也可以是和(A,B) (平均值(A,B,C)

我正在编写一个简单的表达式,我正在寻找一种为这些表达式编写语法的方法,这样ANTLR就可以使用这个文件生成lexer和parser

我的表达式没有任何赋值。它们只是一些预先存在的字段上的一系列操作不需要对其进行评估。

我有一堆预定义的函数(如SUM、MEAN、SUBSTR,后端可以理解),这些函数应用于一些现有字段

我需要的运算符是:-+,-,*/ 括号:(,)用于打开和关闭。 函数(关键字):求和、平均值、最大值SUBSTR

示例:-

  • (A+B),这也可以是(A,B)
  • (平均值(A,B,C)+最大值(X,最小值(Y,Z))+2)/4
  • SUBSTR(“测试1”,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: '//' ~[\r\n]* -> skip;
    WS: [ \t\n]+ -> skip;
    
    最后,我还必须对用户键入的表达式运行一些验证。如果我在只接受数字的MAX()函数中输入字符串,我应该能够知道错误所在的行/位置并通知用户。我相信这是在分析阶段?但只要把它放在那里,以防有任何输入,如果这个语法能帮助我识别它。

    几句话:

    • 我不会将负号粘贴到lexer中的数字上,而是匹配n个一元表达式
    • 您的
      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: '//' ~[\r\n]* -> skip;
    WS: [ \t\n]+ -> skip;
    
    最后,我还必须对用户键入的表达式运行一些验证。如果我在只接受数字的MAX()函数中输入字符串,我应该能够知道错误所在的行/位置并通知用户。我相信这是在分析阶段?但只要把它放在那里,以防有任何输入,如果这个语法能帮助我识别它


    这种语义检查应该在解析之后进行。解析器创建一个解析树。然后在访问者内部遍历此解析树并评估输入。然后,如果评估输入的类型不适合某些函数,则可能会产生错误/警告。

    我首先要阅读ANTLR文档和/或学习一些ANTLR教程。当你已经完成了,并且陷入了实际编写语法的过程中,你可以自由地提出这样的问题。像你这样的问题,没有实际的技术问题,而是“有人能指导我吗?”,在这里不太合适(见:)。我想你已经开始写语法了,请把它添加到你的问题中,并解释它的错误。@BartKiers我的错,我应该在发布问题之前添加它。你现在可以看一下吗?我还添加了3个测试片段。我只是想看看这个语法是否有效,我是否遗漏了一些小格。我已经从您的一个答案中添加了函数实现,这证明非常有用。我的表达式有时会以括号开始(第二个示例),因此我添加了(expr)+,这是正确的方法吗?谢谢Bart,现在有意义了。只是一个简单的问题——“expr:MIN expr”在这一行中,MIN表示什么?另外,如果在解析后我必须检查匹配的括号,我是否必须将函数语法写成“function:ID OPEN\u PAR arguments?CLOSE\u PAR”;这对于标记化是必要的吗?或者像我在上述语法中所做的那样,仅仅添加一个标记作为OPEN_PART和CLOSE_PAR就足够了?
    MIN
    代表负数。这是与
    -
    MIN:'-'匹配的规则“…正如我在上述语法中所做的那样足够吗?”是的,这样就可以了。我有这样一个表达式:-(Fields.V1)*(Fields.V2)+(Constants.Value1)*(Constants.Value2)。ANTLR解析器根据上面的语法(FieldsV1)*(FieldsV2)+(常量)生成以下文本。如您所见,文本中缺少Fields.V1和Fields.V2中的“点”,并且还有一个