ANTLR规则表示除此之外的所有符号

时间:2011-09-18 11:27:53

标签: antlr semantics predicate

一个新手问题。比方说,我有一个词法分析器规则,只列出所有可接受的符号:

ACCEPTED_SYMBOLS:   ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'\-' |'\+' | '=' |
                  '\\'|':' |'\"'|'\''|'<' |'>' |',' |'.' |'?' | '/'  ) ;

但有时我想要另一个接受所有符号的规则,例如'='

 ACCEPTED_SYMBOLS_EXCEPT_EQUAL: ('~' |'!' |'@' |'#' |'$' |'%' |'^' |'\-' |'\+' | 
                      '\\'|':' |'\"'|'\''|'<' |'>' |',' |'.' |'?' | '/'  ) ;

基本上我只是重复没有'='的列表。

但这听起来像是定义令牌的愚蠢方式。如果我得到另一个ACCEPTED_SYMBOLS_EXCEPT_HASH / COLON /等怎么办?

是否可以编写一个基于ACCEPTED_SYMBOLS派生匹配符号的解析器规则?语义谓词听起来像是选择,但我是ANTLR的新手,并且不知道如何使用它。

1 个答案:

答案 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标记。

你必须意识到词法分析器独立于解析器运行:它只是创建从顶部到底部通过词法分析器规则的标记,尽可能地尝试匹配,并且它不关心当时的解析器是什么匹配。