Parser和Lexer规则重叠

时间:2016-06-24 11:45:24

标签: parsing antlr4

我在Antlr4中有语法,用于解析和验证自定义语言。其中我的语法应该视为“有效”以下

  

//将字符串值分配给变量
  myVar = 'aString';
  //带字符串参数的函数
  firstFunction('thisIsAnArg');
  //具有字符串参数的函数,具有特定格式(日期)
  secondFunction('26/06/2016');

以下是我语法的“相关”部分

/*
 * Parser Rules
*/
function_call
     : firstFunction'(' literal ')'
     | secondFunction '(' date_formated_string ')'

literal
    : SINGLE_QUOTE_STRING
    | date_formated_string
    | '(' literal ')'  // recursive parentheses
    ;

date_formated_string
    : '\'' day = (TWO_DIGITS | ONE_DIGIT) ('/') month = (TWO_DIGITS | ONE_DIGIT) ('/') year = FOUR_DIGITS '\'';

/*
 * Lexer Rules
 */
SINGLE_QUOTE_STRING:            '\'' (~'\'' | '\'\'')* '\'';

这里的问题是,secondFunction的参数被词法分析器解析为SINGLE_QUOTE_STRING,因此当尝试匹配secondFunction时,解析器会抛出异常。解决方案是将date_formated_string规则移动到词法分析器。但是这样我就失去了在Listener课程中(日,月,年)分隔日期的能力。

对此有何想法?

1 个答案:

答案 0 :(得分:0)

  

虽然由于各种原因我开始时都是“否定”(请参阅​​问题的评论讨论),但我决定关注@LucasTrzesniewski并将其他验证逻辑放入代码而不是语法文件。

逻辑很简单:

  • 我创建了一个ValidationListener,它扩展/继承了构建语法(.g4文件)时创建的BaseListener。我覆盖了我需要进行任何其他验证的任何方法。在我的情况下,我覆盖了EnterFunction_call
  • 我现在制作的每个Listener都必须延长/继承ValidationListener而不是BaseListener
  • 每次我覆盖任何Listener中的方法时,都会覆盖ValidationListener,我必须确保首先调用base.{methodName}(),以便在自定义之前运行“自定义”验证别的。

我可以将验证直接放在我创建的每个Listener上并省略ValidationListener,但大多数验证在听众中很常见(正如我所说的那样,我希望将它们放在一起)在语法水平上)并使用上述设计我可以实现更好的分离。然而,代码维护有一个小的(恕我直言)缺点,因为正如我所说,我必须确保首先调用base.{methodName}(),这是一个人们可能忘记做的“手动”步骤。