为什么 Antlr 认为缺少括号?

发布于 2024-11-19 17:55:05 字数 784 浏览 5 评论 0原文

我创建了一个语法来解析简单的 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)))

它失败了: line 1:29 extraneous input ')' Expected EOF

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

I've created a grammar to parse simple ldap query syntax. The grammer is:

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(); };

Now this grammar works fine for:

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

However, when I try and run:

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

It fails with: line 1:29 extraneous input ')' expecting EOF

If I remove the EOF off the expression grammar, everything passes, but then wrong numbers of brackets are not caught as being a syntax error. (This is being parsed into a tree, hence the ^ and ! after tokens) What have I missed?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

财迷小姐 2024-11-26 17:55:05

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

表达式中删除EOF,并为解析器创建一个以EOF结尾的正确“入口点”。

file: Tg

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

Windows:

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 代码:

在此处输入图像描述

使用 graphviz-dev.appspot.com

As already mentioned by others, your expression has to end with a EOF, but a nested expression cannot end with an EOF, of course.

Remove the EOF from expression, and create a proper "entry point" for your parser that ends with the EOF.

file: 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);
  }
}

To run the demo, do:

*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

Windows:

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

which produces the DOT code representing the following AST:

enter image description here

image created using graphviz-dev.appspot.com

尤怨 2024-11-26 17:55:05

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

In your definition of expression, there can be parentheses containing a nested expression, but the nested expression has to end in EOF. In your sample input, the nested expression doesn't end in EOF.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文