我试图解析以下内容:
SELECT name-of-key[random text]
Run Code Online (Sandbox Code Playgroud)
这是我想要构建的更大语法的一部分.为了清楚起见,我把它留下了.
我想出了以下规则:
select : 'select' NAME '[' anything ']'
;
anything : (ANYTHING | NAME)+
;
NAME : ('a'..'z' | 'A'..'Z' | '0'..'9' | '-' | '_')+
;
ANYTHING : (~(']' | '['))+
;
WHITESPACE : ('\t' | ' ' | '\r' | '\n')+ -> skip
;
Run Code Online (Sandbox Code Playgroud)
这似乎不起作用.例如,输入SELECT a[hello world!]
提供以下错误:
line 1:0 mismatched input 'SELECT a' expecting 'SELECT'
Run Code Online (Sandbox Code Playgroud)
这是错误的,因为输入SELECT a
被识别ANYTHING
,而不是select
.我该如何解决这个问题?我觉得我在这里遗漏了一些概念,但很难开始.
也许你缺少的概念是规则优先权.
[1] Lexer规则匹配最长的字符串具有优先权.
正如您所提到的,上面的ANYTHING标记规则匹配"select a",它比(隐式)标记规则"select"匹配的更长,因此它的优先级.非贪婪行为用问号表示.
ANYTHING : (~(']' | '['))+?
Run Code Online (Sandbox Code Playgroud)
只是让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 : (~(']' | '['))+?
;
Run Code Online (Sandbox Code Playgroud)
我个人避免使用隐式令牌规则,特别是如果你的语法很复杂,正是因为令牌规则的优先级.我会写这个.
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)+ ;
Run Code Online (Sandbox Code Playgroud)
另请注意,"hello world"中的空格将被WHITESPACE规则吞噬.要正确管理它,您需要ANTLR 岛语法.
'希望这可以帮助!
归档时间: |
|
查看次数: |
1318 次 |
最近记录: |