代码之家  ›  专栏  ›  技术社区  ›  Sonny

ANTLR4解析器生成:条件表达式的简单语法问题

  •  0
  • Sonny  · 技术社区  · 7 年前

    我正在尝试为一种简单的语言生成一个lexer和解析器。目前,该语言只能解析条件表达式。条件表达式很像C语言中的表达式,因为我只是在这里学习基本知识,所以我们在C语言中拥有的所有问题我都不关心实现。

    我有以下语法:

    grammar Simple ;
    
    cond_expr     : left_paren operand operator operand right_paren ;
    operand       : function_expr | ID | literal | cond_expr ;
    function_expr : ID left_paren paramList right_paren ;
    paramList     : param (',' param)* ;
    param         : ID | function_expr ;
    literal       : string | number ;
    string        : '"' sentence '"' ;
    sentence      : (WORD | WORD (' ' WORD)*)* ;
    number        : INTEGER | FLOAT ;
    left_paren    : LEFT_PAREN ;
    right_paren   : RIGHT_PAREN ;
    operator      : OPERATOR ;
    
    INTEGER     : [0-9]+ ;
    FLOAT       : INTEGER '.' INTEGER | '.' INTEGER ;
    LEFT_PAREN  : '(' ;
    RIGHT_PAREN : ')' ;
    ID          : [A-Za-z]+[A-Za-z0-9_]* ;
    WORD        : [A-Za-z]+ ;
    OPERATOR    : ('==' | '>=' | '<=' | '!=' | '&&' | '||' | '~') ;
    WS          : (' '|'\r'|'\n'|'\t') -> channel(HIDDEN);
    

    当我在上面运行解析器时,我并没有得到预期的结果。以下是一个错误输出的示例:

    ~/sandbox $ grun Simple cond_expr -tree
    (a (c, d (e, f)) != b)
    line 1:2 mismatched input ' ' expecting OPERATOR
    line 1:5 mismatched input ',' expecting OPERATOR
    line 1:8 mismatched input ' ' expecting ')'
    (cond_expr (left_paren () (operand a) (operator  ) (operand (cond_expr (left_paren () (operand c) (operator ,  ) (operand d) (right_paren   ( e ,   f))) (right_paren )))
    

    我的语法有什么错误?非常感谢您的帮助。

    1 回复  |  直到 7 年前
        1
  •  2
  •   GRosenberg    7 年前

    语法似乎是所需DSL的EBNF表示的直接实现。要使其在ANTLR中正常工作,还需要做更多的工作。原样:

    1) 规则存在相互左递归问题 function_expr , paramList param ;

    2) sentence 什么都比不上;

    3) WS 隐藏在lexer中,所以 句子 无论如何都无法匹配;);

    4) the ID 规则阴影 WORD 所以 WORD 永远不会发出令牌。

    (您应该在1和2上收到工具警告;不要忽略,因为警告指示运行时行为 可以 受到影响。)

    表达式规则的基本形式是在单个规则中列出表达式的所有可选形式。

    expr  : LPAREN expr RPAREN 
          | expr operator expr
          | function
          | string
          | number
          | ID
          ;
    
    function  : ID LPAREN ( ID | function ) (',' ( ID | function ))* RPAREN ;
    
    string        : STRING ;
    number        : INTEGER | FLOAT ;
    operator      : OPERATOR ;
    
    STRING : '"' .*? '"' ;
    

    (未经测试)

    所以 (a (c, d (e, f)) != b) 应正确评估

    expr (function ( ID, function ( ID, ID ) ) operator ID