ANTLR4:词法分析器规则:只要不包含这两个并排字符的任何字符串?

ANTLR4: lexer rule for: Any string as long as it doesn't contain these two side-by-side characters?

有什么方法可以在 ANTLR4 中表达这个:

Any string as long as it doesn't contain the asterisk immediately followed by a forward slash?

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

这有效但不正确:(~[*/])* 因为它禁止包含单个字符 */.

的字符串

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

诀窍是在任何必须针对任何邪恶字符进行测试的字符串之前使用语义谓词。实际测试在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 进行了测试。

如果不允许的序列很少,则存在没有 parser/lexer 操作的解决方案:

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
    | '/'
    ;

想法是组成

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

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

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