antlr4除了运算符之外的所有单词

时间:2017-12-26 23:15:04

标签: antlr4

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._#+=]除了运算符之外的任何内容(ANDORNOTLPARENRPAREN,{{1} },DQUOTE)。

2 个答案:

答案 0 :(得分:1)

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

因此,您可以使用此语法使WORD规则具有通用性:

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

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

如最后指定WORD,如果所有先前的词法分析器规则(以上在源代码中已定义的所有规则)都失败,则仅尝试使用输入。

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

答案 1 :(得分:1)

尝试类似这样的语法:

select s.Dim, s.Frequency, s.Date, max(s.Version)
from sample_tbl s 
inner ( 
SELECT Dim, Frequency, max(Date) as max_date
FROM   sample_tbl 
group by Dim, Frequency
) t on t.Dim = s.Dim, t.Frequency = s.Frequency t.max_date = s.Date 
GROUP BY s.Dim, s.Frequency, s.Date ;

也许您想在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+; 中使用转义序列,然后查看this example如何执行此操作。

这个语法允许你:

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