【问题标题】:ANTLR4: lexer rule for: Any string as long as it doesn't contain these two side-by-side characters?ANTLR4:词法分析器规则:任何字符串,只要它不包含这两个并排字符?
【发布时间】:2015-04-16 09:06:44
【问题描述】:

有没有办法在ANTLR4中表达这一点:

任何字符串,只要它不立即包含星号 后跟一个正斜杠?

这不起作用:(~'*/')* 因为 ANTRL 抛出此错误:multi-character literals are not allowed in lexer sets: '*/'

这可行但不正确:(~[*/])*,因为它禁止包含单个字符 */ 的字符串。

【问题讨论】:

  • 你能提供更多关于你想要达到的目标的细节吗? string-without-*/ 必须绝对被识别为单个词法分析器标记吗?
  • 嗨,马克。是的,单个词法分析器标记:词法分析器规则应该返回单个字符串,只要它不包含 */
  • 在 ANTLR 中确实应该有一种简单的方法来做到这一点。

标签: antlr grammar antlr4 lexer lexical-analysis


【解决方案1】:

我有类似的问题,我的解决方案:( ~'*' | ( '*'+ ~[/*]) )* '*'*

【讨论】:

  • 如果你用 /*..*/ cmets 为语言编写了多个词法分析器,你应该已经知道这个技巧了。
【解决方案2】:

我能做到的最接近的是将测试放在解析器而不是词法分析器中。这并不完全符合您的要求,但确实有效。

诀窍是在必须测试任何邪恶字符的任何字符串之前使用语义谓词。实际测试是用 Java 完成的。

grammar myTest;

@header
{
    import java.util.*;
}

@parser::members
{
    boolean hasEvilCharacters(String input)
    {
        if (input.contains("*/"))
        {
            return false;
        }
        else
        {
            return true;
        }
    }
}

// Mimics a very simple sentence, such as: 
//   I am clean.
//   I have evil char*/acters.
myTest
    : { hasEvilCharacters(_input.LT(1).getText()) }? String 
      (Space { hasEvilCharacters(_input.LT(1).getText()) }? String)* 
      Period EOF
    ;

String
    : ('A'..'Z' | 'a'..'z')+      
    ;

Space
    : ' '
    ;

Period
    : '.'
    ;

通过 NetBeans 8.0.1 中 ANTLRWorks 2 中的 TestRig 使用 ANTLR 4.4 进行测试。

【讨论】:

  • 谢谢詹姆斯!哇,解决这么简单的问题需要做大量的工作。
  • 有人能解释一下这是如何工作的吗?我看不到它在哪里捕获包含“*”的令牌。 (我
  • 查看解析方法hasEvilCharacters(),由myTest解析器规则中的语义谓词调用。如需更多信息,请阅读 The Definitive ANTLR 4 Reference 中的第 10 章。
【解决方案3】:

如果不允许的序列很少,则存在没有解析器/词法分析器操作的解决方案:

grammar NotParser;

program
    : (starslash | notstarslash)+
    ; 

notstarslash
    : NOT_STAR_SLASH
    ;

starslash
    : STAR_SLASH
    ;

STAR_SLASH
    : '*'+ '/'
    ;

NOT_STAR_SLASH
    : (F_NOT_STAR_SLASH | F_STAR_NOT_SLASH) +
    ;

fragment F_NOT_STAR_SLASH
    : ~('*'|'/')
    ;

fragment F_STAR_NOT_SLASH
    : '*'+ ~('*'|'/')
    | '*'+ EOF
    | '/'
    ;

这个想法是组成的令牌

  • 所有既不是“*”也不是“/”的标记
  • 所有以“*”开头但后面不跟“/”或单个“/”的标记

有一些处理特殊情况的规则(多个''后跟'/',或尾随'')

【讨论】:

  • ...如果文件中的最后一个字符是“*”,ANTLR 会发生什么? ~'/' 测试做什么或接受什么?
  • 现在应该处理特殊情况(尾随 ''、单个 '/'、多个 '')。也许解析树与预期不符……但在不了解应用程序的情况下很难调整。
  • 你和我的答案的复杂性和不可扩展性表明了一个弱点——或者它是一个机会?——在 ANTLR 4 中。
猜你喜欢
  • 2019-05-07
  • 2015-02-15
  • 1970-01-01
  • 2019-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多