一个新手问题。比方说,我有一个词法分析器规则,只列出所有可接受的符号:
ACCEPTED_SYMBOLS: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'\-' |'\+' | '=' |
'\\'|':' |'\"'|'\''|'<' |'>' |',' |'.' |'?' | '/' ) ;
但有时我想要另一个接受所有符号的规则,例如'='
ACCEPTED_SYMBOLS_EXCEPT_EQUAL: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'\-' |'\+' |
'\\'|':' |'\"'|'\''|'<' |'>' |',' |'.' |'?' | '/' ) ;
基本上我只是重复没有'='的列表。
但这听起来像是定义令牌的愚蠢方式。如果我得到另一个ACCEPTED_SYMBOLS_EXCEPT_HASH / COLON /等怎么办?
是否可以编写一个基于ACCEPTED_SYMBOLS派生匹配符号的解析器规则?语义谓词听起来像是选择,但我是ANTLR的新手,并且不知道如何使用它。
答案 0 :(得分:2)
让我们说在a
规则中,所有ACCEPTED_SYMBOLS
字符都有效,但在规则b
内,=
无效。
您可以使用predicate这样做:
a
: ACCEPTED_SYMBOLS
;
b
: t=ACCEPTED_SYMBOLS {!$t.text.equals("=")}?
;
ACCEPTED_SYMBOLS
: '~' | '!' | '@' | '#' | '$' | '%' | '^' | '-' | '+' | '=' |
'\\' | ':' | '"' | '\'' | '<' | '>' | ',' | '.' | '?' | '/'
;
请注意,只需要在ANTLR语法的文字字符串中对单引号和反斜杠进行转义。
或者,没有谓词:
a
: any
;
b
: SYMBOLS
;
any
: SYMBOLS
| EQ
;
SYMBOLS
: '~' | '!' | '@' | '#' | '$' | '%' | '^' | '-' | '+' |
'\\' | ':' | '"' | '\'' | '<' | '>' | ',' | '.' | '?' | '/'
;
EQ
: '='
;
请注意,您无法按以下顺序定义规则:
ACCEPTED_SYMBOLS: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'-' |'+' | '=' |
'\\'|':' |'"'|'\''|'<' |'>' |',' |'.' |'?' | '/' ) ;
ACCEPTED_SYMBOLS_EXCEPT_EQUAL: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'-' |'+' |
'\\'|':' |'"'|'\''|'<' |'>' |',' |'.' |'?' | '/' ) ;
ANTLR会抛出一个错误,即永远不会创建令牌ACCEPTED_SYMBOLS_EXCEPT_EQUAL
,因为之前的规则已经匹配ACCEPTED_SYMBOLS_EXCEPT_EQUAL
可以匹配的所有内容。
如果你改变规则:
ACCEPTED_SYMBOLS_EXCEPT_EQUAL: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'-' |'+' |
'\\'|':' |'"'|'\''|'<' |'>' |',' |'.' |'?' | '/' ) ;
ACCEPTED_SYMBOLS: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'-' |'+' | '=' |
'\\'|':' |'"'|'\''|'<' |'>' |',' |'.' |'?' | '/' ) ;
然后规则ACCEPTED_SYMBOLS
只能匹配'='
。所有其他字符将被标记为ACCEPTED_SYMBOLS_EXCEPT_EQUAL
标记。
你必须意识到词法分析器独立于解析器运行:它只是创建从顶部到底部通过词法分析器规则的标记,尽可能地尝试匹配,并且它不关心当时的解析器是什么匹配。