为什么Antlr认为缺少括号?

时间:2011-07-14 07:00:28

标签: antlr3

我已经创建了一个语法来解析简单的ldap查询语法。语法是:

expression   :   LEFT_PAREN! ('&' | '||' | '!')^ (atom | expression)* RIGHT_PAREN! EOF ;

atom    :   LEFT_PAREN! left '='^ right RIGHT_PAREN! ;

left    :   ITEM;
right   :   ITEM;

ITEM        :   ALPHANUMERIC+; 
LEFT_PAREN  :   '(';
RIGHT_PAREN :   ')';

fragment ALPHANUMERIC
    :   ('a'..'z' | 'A'..'Z' | '0'..'9'); 

WHITESPACE : (' ' | '\t' | '\r' | '\n') { skip(); };

现在这个语法适用于:

(!(attr=hello2))
(&(attr=hello2)(attr2=12))
(||(attr=hello2)(attr2=12))

然而,当我尝试并运行时:

(||(attr=hello2)(!(attr2=12)))

它失败了:第1:29行无关输入')'期待EOF

如果我从表达式语法中删除EOF,一切都会通过,但是错误数量的括号不会被捕获为语法错误。 (这被解析成一棵树,因此^和!之后的标记)我错过了什么?

2 个答案:

答案 0 :(得分:4)

正如其他人已经提到的,您的表达式必须以EOF结尾,但嵌套表达式当然不能以EOF结尾。

EOF移除expression,为您的解析器创建一个以EOF结尾的正确“入口点”。

档案:T.g

grammar T;

options {
  output=AST;
}

parse
  :  expression EOF!
  ;

expression
  :  '('! ('&' | '||' | '!')^ (atom | expression)* ')'!
  ;

atom
  :  '('! ITEM '='^ ITEM ')'!
  ;

ITEM        
  :  ALPHANUMERIC+
  ;

fragment ALPHANUMERIC
  :  ('a'..'z' | 'A'..'Z' | '0'..'9')
  ;

WHITESPACE 
  :  (' ' | '\t' | '\r' | '\n') { skip(); }
  ;

file:Main.java

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;

public class Main {
  public static void main(String[] args) throws Exception {
    String source = "(||(attr=hello2)(!(attr2=12)))";
    TLexer lexer = new TLexer(new ANTLRStringStream(source));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    CommonTree tree = (CommonTree)parser.parse().getTree();
    DOTTreeGenerator gen = new DOTTreeGenerator();
    StringTemplate st = gen.toDOT(tree);
    System.out.println(st);
  }
}

要运行演示,请执行:

* nix中/ MacOS的:

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main

视窗:

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .;antlr-3.3.jar Main

生成表示以下AST的DOT代码:

enter image description here

使用graphviz-dev.appspot.com

创建的图片

答案 1 :(得分:1)

在表达式的定义中,可以有包含嵌套表达式的括号,但嵌套表达式必须以EOF结尾。在示例输入中,嵌套表达式不以EOF结尾。