解析时是否可以统计某个元素出现的次数?

发布于 2025-01-10 08:32:32 字数 614 浏览 1 评论 0原文

我试图找到一种方法来跟踪构建解析树时元素出现的次数。假设我的语法如下所示:

grammar sample;

@members {
     private int xCount= 0;
     private int yCount= 0;
     private int zCount= 0;
}
// rules
fileData        : part1 part2 EOF;
part1           : x+ y+ z+;
part2           : z+ y+ x+;

// I want to count these:
x               : a+ b+ c+ {xCount++;};
y               : c+ b+ a+ {yCount++;};
z               : a+ c+ b+ {zCount++;};

// lexer rules
a               : '1';
b               : '2';
c               : '3';

我如何利用计数的变量并说出类似 {System.out.println("found 4 x's, 5 y's, and 6 z's");} 解析何时完成?

I am trying to find a way to keep track of the number of times an element appears when building a parse tree. Let's say my grammar looks something like this:

grammar sample;

@members {
     private int xCount= 0;
     private int yCount= 0;
     private int zCount= 0;
}
// rules
fileData        : part1 part2 EOF;
part1           : x+ y+ z+;
part2           : z+ y+ x+;

// I want to count these:
x               : a+ b+ c+ {xCount++;};
y               : c+ b+ a+ {yCount++;};
z               : a+ c+ b+ {zCount++;};

// lexer rules
a               : '1';
b               : '2';
c               : '3';

How can I make use of the variables counted and say something like {System.out.println("found 4 x's, 5 y's, and 6 z's");} when the parsing is complete?

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

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

发布评论

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

评论(1

┊风居住的梦幻卍 2025-01-17 08:32:32

您可以简单地在启动规则 (fileData) 的末尾打印它:

fileData
 : part1 part2 EOF
   {System.out.println("found...");}
 ;

或者将一个方法添加到您的 @members 部分:

grammar sample;

@members {
     private int xCount = 0;
     private int yCount = 0;
     private int zCount = 0;

     public String getCounters() {
         return String.format("found %d x's, %d y's, and %d z's\n", xCount, yCount, zCount);
     }
}
// rules
fileData        : part1 part2 EOF;
part1           : x+ y+ z+;
part2           : z+ y+ x+;

// I want to count these:
x               : a+ b+ c+ {xCount++;};
y               : c+ b+ a+ {yCount++;};
z               : a+ c+ b+ {zCount++;};

// lexer rules
a               : '1';
b               : '2';
c               : '3';

然后像这样使用它:

String input = "123321132132321123";
sampleLexer lexer = new sampleLexer(CharStreams.fromString(input));
sampleParser parser = new sampleParser(new CommonTokenStream(lexer));

System.out.println(parser.fileData().toStringTree(parser));
System.out.println(parser.getCounters());

这将打印:

(fileData (part1 (x (a 1) (b 2) (c 3)) (y (c 3) (b 2) (a 1)) (z (a 1) (c 3) (b 2))) (part2 (z (a 1) (c 3) (b 2)) (y (c 3) (b 2) (a 1)) (x (a 1) (b 2) (c 3))) <EOF>)
found 2 x's, 2 y's, and 2 z's

但 IMO 更好的选择是将(Java)代码与语法分开,并将其移至侦听器中。因此,从语法中删除嵌入的代码:

grammar sample;

// rules
fileData        : part1 part2 EOF;
part1           : x+ y+ z+;
part2           : z+ y+ x+;

// I want to count these:
x               : a+ b+ c+;
y               : c+ b+ a+;
z               : a+ c+ b+;

// lexer rules
a               : '1';
b               : '2';
c               : '3';

并创建一个监听器:

class CounterListener extends sampleBaseListener {

  private int xCount = 0;
  private int yCount = 0;
  private int zCount = 0;

  @Override
  public void enterX(sampleParser.XContext ctx) {
    this.xCount++;
  }

  @Override
  public void enterY(sampleParser.YContext ctx) {
    this.yCount++;
  }

  @Override
  public void enterZ(sampleParser.ZContext ctx) {
    this.zCount++;
  }

  public String getCounters() {
    return String.format("In listener found %d x's, %d y's, and %d z's\n", this.xCount, this.yCount, this.zCount);
  }
}

并像这样使用它:

String input = "123321132132321123";
sampleLexer lexer = new sampleLexer(CharStreams.fromString(input));
sampleParser parser = new sampleParser(new CommonTokenStream(lexer));

CounterListener listener = new CounterListener();
ParseTreeWalker.DEFAULT.walk(listener, parser.fileData());

System.out.println(listener.getCounters());

导致:

In listener found 2 x's, 2 y's, and 2 z's

请参阅: https://github.com/antlr/antlr4/blob/master/doc/listeners.md

请注意:中的注释“//词法分析器规则”

// lexer rules
a               : '1';
b               : '2';
c               : '3';

不是非常正确:它们是解析器规则,而不是词法分析器规则。 ANTLR 对上面的代码片段进行如下解释:

a               : T_0;
b               : T_1;
c               : T_2;

T_0 : '1';
T_1 : '2';
T_2 : '3';

其中 T_0T_1T_2 是词法分析器规则。

You can simply print it at the end of your start rule (fileData):

fileData
 : part1 part2 EOF
   {System.out.println("found...");}
 ;

or add a method to your @members section:

grammar sample;

@members {
     private int xCount = 0;
     private int yCount = 0;
     private int zCount = 0;

     public String getCounters() {
         return String.format("found %d x's, %d y's, and %d z's\n", xCount, yCount, zCount);
     }
}
// rules
fileData        : part1 part2 EOF;
part1           : x+ y+ z+;
part2           : z+ y+ x+;

// I want to count these:
x               : a+ b+ c+ {xCount++;};
y               : c+ b+ a+ {yCount++;};
z               : a+ c+ b+ {zCount++;};

// lexer rules
a               : '1';
b               : '2';
c               : '3';

and then use it like this:

String input = "123321132132321123";
sampleLexer lexer = new sampleLexer(CharStreams.fromString(input));
sampleParser parser = new sampleParser(new CommonTokenStream(lexer));

System.out.println(parser.fileData().toStringTree(parser));
System.out.println(parser.getCounters());

which will print:

(fileData (part1 (x (a 1) (b 2) (c 3)) (y (c 3) (b 2) (a 1)) (z (a 1) (c 3) (b 2))) (part2 (z (a 1) (c 3) (b 2)) (y (c 3) (b 2) (a 1)) (x (a 1) (b 2) (c 3))) <EOF>)
found 2 x's, 2 y's, and 2 z's

But an IMO better option is to separate the (Java) code from your grammar, and move this into a listener. So remove the embedded code from the grammar:

grammar sample;

// rules
fileData        : part1 part2 EOF;
part1           : x+ y+ z+;
part2           : z+ y+ x+;

// I want to count these:
x               : a+ b+ c+;
y               : c+ b+ a+;
z               : a+ c+ b+;

// lexer rules
a               : '1';
b               : '2';
c               : '3';

and create a listener:

class CounterListener extends sampleBaseListener {

  private int xCount = 0;
  private int yCount = 0;
  private int zCount = 0;

  @Override
  public void enterX(sampleParser.XContext ctx) {
    this.xCount++;
  }

  @Override
  public void enterY(sampleParser.YContext ctx) {
    this.yCount++;
  }

  @Override
  public void enterZ(sampleParser.ZContext ctx) {
    this.zCount++;
  }

  public String getCounters() {
    return String.format("In listener found %d x's, %d y's, and %d z's\n", this.xCount, this.yCount, this.zCount);
  }
}

and use it like this:

String input = "123321132132321123";
sampleLexer lexer = new sampleLexer(CharStreams.fromString(input));
sampleParser parser = new sampleParser(new CommonTokenStream(lexer));

CounterListener listener = new CounterListener();
ParseTreeWalker.DEFAULT.walk(listener, parser.fileData());

System.out.println(listener.getCounters());

resulting in:

In listener found 2 x's, 2 y's, and 2 z's

See: https://github.com/antlr/antlr4/blob/master/doc/listeners.md

Note that the comment "// lexer rules" in:

// lexer rules
a               : '1';
b               : '2';
c               : '3';

is not really correct: they're parser rules, not lexer rules. The snippet above is interpreted by ANTLR like this:

a               : T_0;
b               : T_1;
c               : T_2;

T_0 : '1';
T_1 : '2';
T_2 : '3';

where T_0, T_1 and T_2 are the lexer rules.

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