代码之家  ›  专栏  ›  技术社区  ›  Craig Otis

antlr lexer匹配意外规则

  •  1
  • Craig Otis  · 技术社区  · 6 年前

    我正在重新学习一些基本的Antlr,试图写一个语法来生成待办事项:

    Meeting at 12pm for 20 minutes
    

    我遇到的问题是,三个lexer规则特别是“不匹配”,这取决于它们使用的上下文:

    HOUR: [0-9]|'1'[0-9]|'2'[0-3];
    MINUTE: [0-5][0-9];
    NONZERO_NUMBER: [1-9][0-9]*;
    

    有些案子我想 12 匹配 HOUR 规则,还有其他我想匹配的时候 MINUTE ,等等,但是解析器规则似乎无法影响lexer对上下文敏感。

    例如,上面的字符串( Read Books... )不解析,因为 德意志北方银行 匹配为 小时 ,还有 20 ,语法分析器需要 NONZERO_NUMBER 所以失败了。

    line 1:20 mismatched input '20' expecting NONZERO_NUMBER
    

    如果我将持续时间值更改为 故意不 匹配 小时 规则,没关系:

    Meeting at 12pm for 120 minutes // Note 120 minutes doesn't match HOUR or MINUTE
    

    有什么方法可以“说服”雷克瑟去匹配 预期 在尝试其他/早期规则之前,标记(为解析器定义)?

    以下是我清晰的语法:

    SIDNOTE:我意识到还有其他奇怪的东西,比如一个事件名称只能是一个单词,但我一次只能处理一个问题。

    grammar Sprint;
    
    event: eventName timePhrase? durationPhrase?;
    
    durationPhrase: 'for' duration;
    
    timePhrase: 'at' time;
    
    duration: (NONZERO_NUMBER MINUTE_STR) | (NONZERO_NUMBER HOUR_STR);
    
    time: ((HOUR ':' MINUTE) | (HOUR)) AMPM?;
    
    eventName: WORD;
    
    MINUTE_STR: 'minute'('s')?;
    
    HOUR_STR: 'hour'('s')?;
    
    HOUR: [0-9]|'1'[0-9]|'2'[0-3];
    
    MINUTE: [0-5][0-9];
    
    NONZERO_NUMBER: [1-9][0-9]*;
    
    AMPM: ('A'|'a'|'P'|'p')('M'|'m');
    
    WORD: ('a'..'z' | 'A'..'Z')+;
    
    WS: (' '|[\n\t\r]) -> skip;
    
    2 回复  |  直到 6 年前
        1
  •  3
  •   rici    6 年前

    试图在lexer中完成解析器的工作通常是错误的。如果lexer只识别整数,那么解析器就不会在排序如何解释数字时遇到问题。在动作或谓语中,你可以拒绝8:63的次数。

        2
  •  0
  •   Jiri Tousek    6 年前

    有什么方法可以“说服”雷克瑟去匹配 预期 在尝试其他/早期规则之前,标记(为解析器定义)?

    不,您不能说服LeXER与预期的令牌匹配,因为LyxER没有任何期望(正式地,它在规则语法上操作,而解析器在上下文无关语法上操作)。lexer和解析器独立运行 * ,理论上可以先在没有任何解析器的情况下运行lexer,然后在lexer输出上启动解析器。


    *在antlr 3中有一个例外,我找不到antlr 4是否也是这样-antlr3解析器和lexer共享一个 org.antlr.runtime.RecognizerSharedState 实例。但是,使用此方法来影响lexer如何匹配标记仍然是有风险的,因为您无法直接控制lexer何时标记特定输入(即,它可以根据某个解析器规则进行查找,并在进入解析器并试图影响它之前标记输入)。