我正在尝试解析以下内容:
SELECT name-of-key[random text]
这是我想要构建的更大语法的一部分。为了清楚起见,我把它留给了我们。
我提出了以下规则:
select : 'select' NAME '[' anything ']'
;
anything : (ANYTHING | NAME)+
;
NAME : ('a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_')+
;
ANYTHING : (~(']' | '['))+
;
WHITESPACE : ('\t' | ' ' | '\r' | '\n')+ -> skip
;
这似乎不起作用。例如,输入SELECT a[hello world!]
会出现以下错误:
line 1:0 mismatched input 'SELECT a' expecting 'SELECT'
这是错误的,因为输入SELECT a
被ANYTHING
识别,而不是select
。我该如何解决这个问题?我觉得我在这里缺少一些概念,但很难开始。
答案 0 :(得分:7)
也许您缺少的概念是规则优先权。
[1] Lexer规则匹配最长的字符串具有优先权。
正如您所提到的,上面的ANYTHING令牌规则匹配"选择",这比(隐式)令牌规则选择'更长。匹配,因此它的优先权。非贪婪的行为用问号表示。
ANYTHING : (~(']' | '['))+?
只是让ANYTHING规则非贪婪并不能完全解决你的问题,因为在正确匹配' select'之后,词法分析器会为空间产生一个ANYTHING标记,因为......
[2] Lexer规则首先出现具有优先权。
切换词法分析器规则WHITE_SPACE和ANYTHING解决了这个问题。下面的语法应该解析你的例子。
select : 'select' NAME '[' anything ']'
;
anything : (ANYTHING | NAME)+
;
NAME : ('a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_')+
;
WHITESPACE : ('\t' | ' ' | '\r' | '\n')+ -> skip
;
ANYTHING : (~(']' | '['))+?
;
我个人避免使用隐式令牌规则,特别是如果您的语法很复杂,正是因为令牌规则优先级。我会写这个。
SELECT : 'select' ;
L_BRACKET : '[';
R_BRACKET : ']';
NAME : ('a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_')+ ;
WHITESPACE : ('\t' | ' ' | '\r' | '\n')+ -> skip ;
ANY : . ;
select : SELECT NAME L_BRACKET anything R_BRACKET ;
anything : (~R_BRACKET)+ ;
还要注意" hello world"将被WHITESPACE规则吞噬。要正确管理它,您需要ANTLR 岛语法。
'希望这有帮助!