antlr4 除运算符外的所有单词

antlr4 all words except the operators

grammar TestGrammar;
AND : 'AND' ;
OR  : 'OR'|',' ;
NOT : 'NOT' ;
LPAREN : '(' ;
RPAREN : ')' ;
DQUOTE : '"' ;
WORD : [a-z0-9._#+=]+(' '[a-z0-9._#+=]+)* ;
WS : [ \t\r\n]+ -> skip ;

quotedword : DQUOTE WORD DQUOTE;
expression
    : LPAREN expression+ RPAREN
    | expression (AND expression)+
    | expression (OR​ expression)+
    | expression (NOT​ expression)+
    | NOT expression+
    | quotedword
    | WORD;

我已经为 antlr4 实现了上面的语法。 我还有很长的路要走,但现在我的问题是, 我怎样才能使 WORD 通用?基本上我希望这个 [a-z0-9._#+=] 是除运算符 (ANDORNOTLPARENRPARENDQUOTE, SPACE).

词法分析器将使用可以匹配给定输入的第一条规则。只有当那个规则不能匹配它时,它才会尝试下一个。

因此,您可以使用以下语法使 WORD 规则通用:

AND : 'AND' ;
OR  : 'OR'|',' ;
NOT : 'NOT' ;
LPAREN : '(' ;
RPAREN : ')' ;
DQUOTE : '"' ;
WS : [ \t\r\n]+ -> skip ;
WORD: .+? ;

确保在这种情况下使用非贪婪运算符 ? 因为一旦调用 WORD 规则将消耗所有后续输入。

由于最后指定了 WORD,只有在所有先前的词法分析器规则(所有已在上面源代码中定义的规则)都失败的情况下,才会尝试使用输入。

编辑:如果您不希望您的WORD 规则匹配任何 输入,那么您只需修改我提供的规则。但我的回答的本质是,在词法分析器中,只要源代码中的顺序正确,你就不必担心两条规则可能匹配相同的输入。

试试这样的语法:

grammar TestGrammar;
...
WORD : Letter+;
QUOTEDWORD : '"' (~["\\r\n])* '"' // disallow quotes, backslashes and crlf in literals
WS : [ \t\r\n]+ -> skip ;

fragment Letter : 
    [a-zA-Z$_] // these are the "java letters" below 0x7F
  | ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F which are not a surrogate
  | [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
;

expression:
  ...
  | QUOTEDWORD
  | WORD+;

也许您想在 QUOTEDWORD 中使用转义序列,然后查看 this example 如何执行此操作。

此语法允许您:

  • 将引用的单词解释为字符串文字(保留其中的所有空格)
  • 用空格分隔多个单词(忽略)