antlr4 - 任何文本和关键字
antlr4 - any text and keywords
我正在尝试解析以下内容:
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
。我该如何解决?我觉得我在这里缺少一些概念,但很难开始。
也许您缺少的概念是规则优先级。
[1] Lexer 规则 匹配最长可能的字符串 具有优先权。
正如您提到的,上面的 ANYTHING 令牌规则匹配 "select a",它比(隐式)令牌规则 'select' 匹配的时间长,因此它的优先级。非贪婪行为用问号表示。
ANYTHING : (~(']' | '['))+?
只是使 ANYTHING 规则成为非贪婪规则并不能完全解决您的问题,因为在正确匹配 'select' 之后,词法分析器将为 space 生成一个 ANYTHING 标记,因为 .. .
[2] Lexer 规则首先出现 具有优先权。
切换词法分析器规则 WHITE_SPACE 和任何东西都可以解决这个问题。下面的语法应该解析你的例子。
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" 中的 space 将被 WHITESPACE 规则吞没。要正确管理它,您需要 ANTLR island grammars.
'希望对您有所帮助!
我正在尝试解析以下内容:
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
。我该如何解决?我觉得我在这里缺少一些概念,但很难开始。
也许您缺少的概念是规则优先级。
[1] Lexer 规则 匹配最长可能的字符串 具有优先权。
正如您提到的,上面的 ANYTHING 令牌规则匹配 "select a",它比(隐式)令牌规则 'select' 匹配的时间长,因此它的优先级。非贪婪行为用问号表示。
ANYTHING : (~(']' | '['))+?
只是使 ANYTHING 规则成为非贪婪规则并不能完全解决您的问题,因为在正确匹配 'select' 之后,词法分析器将为 space 生成一个 ANYTHING 标记,因为 .. .
[2] Lexer 规则首先出现 具有优先权。
切换词法分析器规则 WHITE_SPACE 和任何东西都可以解决这个问题。下面的语法应该解析你的例子。
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" 中的 space 将被 WHITESPACE 规则吞没。要正确管理它,您需要 ANTLR island grammars.
'希望对您有所帮助!