我已经创建了一个语法来解析简单的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,一切都会通过,但是错误数量的括号不会被捕获为语法错误。 (这被解析成一棵树,因此^和!之后的标记)我错过了什么?
答案 0 :(得分:4)
正如其他人已经提到的,您的表达式必须以EOF
结尾,但嵌套表达式当然不能以EOF
结尾。
从EOF
移除expression
,为您的解析器创建一个以EOF
结尾的正确“入口点”。
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(); }
;
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);
}
}
要运行演示,请执行:
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代码:
创建的图片
答案 1 :(得分:1)
在表达式的定义中,可以有包含嵌套表达式的括号,但嵌套表达式必须以EOF结尾。在示例输入中,嵌套表达式不以EOF结尾。