ANTLR3:参数和语义谓词(“找不到符号”、“类型非法开始”)

发布于 2024-10-16 15:54:18 字数 535 浏览 8 评论 0原文

我想在ANTLR3中实现一个“分支”。

我认为使用

branch[boolean is_a]
    : ({ $is_a}? => a)
    | ({!$is_a}? => b);

可以解决问题,但我收到编译错误“找不到符号”和“非法类型开始”,因为在生成的源中,即 DFA45.specialStateTransition(...)没有参数is_a

我尝试省略 =>1,和/或省略 $is_a$

第一个集合 ab 不是不相交的。

事实上 b 的类型是 ((C) => c) |一个。

1)因为我不明白 {...} 之间的区别? => ...{...}? ...

I would like to realize a "branch" in ANTLR3.

I figured using

branch[boolean is_a]
    : ({ $is_a}? => a)
    | ({!$is_a}? => b);

would do the trick, but I get the compiling errors "cannot find symbol" and "illegal start of type", because in the in the generated source i.e. DFA45.specialStateTransition(...) does not have a parameter is_a.

I tried omitting the =>¹, and/or omitting the $ of $is_a.

The FIRST sets of a and b are not disjoint.

In fact b is of type ((C) => c) | a.

¹) as I don't understand the difference between {...}? => ... and {...}? ...

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

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

发布评论

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

评论(1

朮生 2024-10-23 15:54:19

我不是 100% 确定你为什么会收到这个错误:我需要查看你的整个语法。无论如何,没有必要同时检查 is_a !is_a。并且 $is_ais_a 都是有效的。

假设您正在解析一个数字列表,并且每第 4 个数字,您希望通过不同的“分支”进行处理。其语法如下所示:

grammar T;

parse
@init{int n = 1;}
  :  (number[n\%4 == 0] {n++;})+ EOF
  ;


number [boolean multipleOf4]
  :  {multipleOf4}?=> Int {System.out.println("branch A -> " + $Int.text);}
  |                   Int {System.out.println("branch B :: " + $Int.text);}
  ;

Int
  :  '0'..'9'+
  ;

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

(请注意,% 是 ANTLR 语法中的保留字符(但不在字符串文字和注释中),因此需要使用反斜杠进行转义)

并且可以使用该类进行测试:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("11 22 33 44 55 66 77 88 99");
        TLexer lexer = new TLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        TParser parser = new TParser(tokens);
        parser.parse();
    }
}

现在生成一个解析器/词法分析器 (A),编译所有源文件 (B) 并运行主类 (C):

java -cp antlr-3.2.jar org.antlr.Tool T.g // A
javac -cp antlr-3.2.jar *.java            // B
java -cp .:antlr-3.2.jar Main             // C

(在 Windows 上,通过执行 来运行它java -cp .;antlr-3.2.jar Main)

产生以下输出:

branch B :: 11
branch B :: 22
branch B :: 33
branch A -> 44
branch B :: 55
branch B :: 66
branch B :: 77
branch A -> 88
branch B :: 99

所以,是的,您需要一个“门控语义谓词” ({ boolean}?=>) 在这种情况下,不是“验证语义谓词” ({boolean}?)。这两个谓词之间的区别在之前的 SO Q&A 中进行了解释: 什么是ANTLR 中的“语义谓词”?

I'm not 100% sure why you get that error: I'd need to see your entire grammar for that. Anyway, there is no need to check for both is_a and !is_a. And both $is_a and is_a are valid.

Let's say you're parsing a list of numbers, and every 4th number, you want to handle through a different "branch". A grammar for that would look like:

grammar T;

parse
@init{int n = 1;}
  :  (number[n\%4 == 0] {n++;})+ EOF
  ;


number [boolean multipleOf4]
  :  {multipleOf4}?=> Int {System.out.println("branch A -> " + $Int.text);}
  |                   Int {System.out.println("branch B :: " + $Int.text);}
  ;

Int
  :  '0'..'9'+
  ;

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

(note that the % is a reserved character inside ANTLR grammars (not inside String literals and comments though), so it needs escaping with a backslash)

And can be tested with the class:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("11 22 33 44 55 66 77 88 99");
        TLexer lexer = new TLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        TParser parser = new TParser(tokens);
        parser.parse();
    }
}

Now generate a parser/lexer (A), compile all source files (B) and run the main class (C):

java -cp antlr-3.2.jar org.antlr.Tool T.g // A
javac -cp antlr-3.2.jar *.java            // B
java -cp .:antlr-3.2.jar Main             // C

(on Windows, run it by doing java -cp .;antlr-3.2.jar Main)

which produces the following output:

branch B :: 11
branch B :: 22
branch B :: 33
branch A -> 44
branch B :: 55
branch B :: 66
branch B :: 77
branch A -> 88
branch B :: 99

So, yes, you needed a "gated semantic predicate" ({boolean}?=>) in this case, not a "validating semantic predicate" ({boolean}?). The difference between the two predicates is explained in this previous SO Q&A: What is a 'semantic predicate' in ANTLR?

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