在ANTLR 4解析树中获取令牌的正确StopIndex时出现问题

在ANTLR 4解析树中获取令牌的正确StopIndex时出现问题,antlr,antlr4,Antlr,Antlr4,目标 我一直在尝试编写一个简单的逐步简化算法,它将简化给定的逻辑方程并显示简化步骤。首先,我决定实现括号中的缩减。要检索所有嵌套括号,我使用ANTLR 材料 我为逻辑表达式编写了一个简单的语法,试图使用ANTLRv4的左递归功能: Binary.g4 grammar Binary; expr : LPAREN expr RPAREN #ParExpr | NOT expr #NotBlock | expr AND expr #A

目标

我一直在尝试编写一个简单的逐步简化算法,它将简化给定的逻辑方程并显示简化步骤。首先,我决定实现括号中的缩减。要检索所有嵌套括号,我使用ANTLR

材料

我为逻辑表达式编写了一个简单的语法,试图使用ANTLRv4的左递归功能:

Binary.g4

grammar Binary;

expr
    : LPAREN expr RPAREN   #ParExpr
    | NOT expr             #NotBlock
    | expr AND expr        #AndBlock
    | expr OR expr         #OrBlock
    | expr IMP expr        #ImplBlock
    | expr EQ expr         #EqualBlock
    | expr XOR expr        #XorBlock
    | INT                  #Int
    | VAR                  #Var
    | WS                   #WS
    ;

NOT: '¬';

AND: '∧';

OR: '∨';

IMP: '⇒';

EQ: '≡';

XOR: '⊕';

LPAREN: '(';

RPAREN: ')';

INT: '0' | '1';

VAR: ('a' .. 'z' | 'A' .. 'Z') ('a' .. 'z' | 'A' .. 'Z')*;

WS: [ \r\n\t] + -> skip;
我的想法是使用侦听器遍历由ANTLR解析树生成的树,并在退出ParExpr节点时触发我的事件。在那里,我将使用CharStream检索括号的内容并对其进行简化

括号Listener.java

公共类括号Listener扩展了BinaryBaseListener{
私有布尔值更改=false;
@凌驾
public void exitParExpr(BinaryParser.ParExprContext ctx){
final CharStream input=ctx.start.getInputStream();
如果(!已更改){
final int a=ctx.start.getStartIndex();
final int b=ctx.stop.getStopIndex();
最终间隔=新间隔(a,b);
最终字符串分支=input.getText(interval);
//简化“分支”中的值
//如果“分支”值更改,则将“更改”变量设置为true
}
System.out.println(input.getText(新的间隔(ctx.start.getStartIndex(),ctx.stop.getStopIndex());
}
}
问题

出乎意料的是,使用CharStream检索ParExprContext的内容似乎有问题。调试代码后,ctx.stop.getStopIndex()中似乎有问题,因为它返回的值低于需要的值

例如,通过给出如下代码表达式

((A)∧(B)∨((A)∧(B)∧B) )⇒B

它产生了这样的结果:

(A∧B)
((A∧B)∨((A∧B
(((A∧B)∨((A∧B)
问题

因此,我想问,如何正确获取给定区间的索引?我想我的语法有一个错误,导致了这些意想不到的结果。上述表达式的AST为:


我准备提供所需的任何额外资料。

我获取了您的语法和侦听器代码,并编写了一个程序来运行它。我还为您的输入打印了令牌流和解析树。这正是人们所期待的。但是,我从监听器输出的println()中得到的结果,如下所示,与您在问题中提供的不同。我的程序的输出对于Java和C#是相同的结果,令牌索引从0到19(EOF令牌)。我只能想,也许你正在使用一个旧的工具和运行时。确保您正在使用Antlr工具的4.8版本和运行时

parse completed.
Token 0 7 channel DEFAULT_TOKEN_CHANNEL (
Token 1 7 channel DEFAULT_TOKEN_CHANNEL (
Token 2 10 channel DEFAULT_TOKEN_CHANNEL A
Token 3 2 channel DEFAULT_TOKEN_CHANNEL ∧
Token 4 10 channel DEFAULT_TOKEN_CHANNEL B
Token 5 8 channel DEFAULT_TOKEN_CHANNEL )
Token 6 3 channel DEFAULT_TOKEN_CHANNEL ∨
Token 7 7 channel DEFAULT_TOKEN_CHANNEL (
Token 8 7 channel DEFAULT_TOKEN_CHANNEL (
Token 9 10 channel DEFAULT_TOKEN_CHANNEL A
Token 10 2 channel DEFAULT_TOKEN_CHANNEL ∧
Token 11 10 channel DEFAULT_TOKEN_CHANNEL B
Token 12 8 channel DEFAULT_TOKEN_CHANNEL )
Token 13 2 channel DEFAULT_TOKEN_CHANNEL ∧
Token 14 10 channel DEFAULT_TOKEN_CHANNEL B
Token 15 8 channel DEFAULT_TOKEN_CHANNEL )
Token 16 8 channel DEFAULT_TOKEN_CHANNEL )
Token 17 4 channel DEFAULT_TOKEN_CHANNEL ⇒
Token 18 10 channel DEFAULT_TOKEN_CHANNEL B
Token 19 -1 channel DEFAULT_TOKEN_CHANNEL <EOF>

( implBlock
  ( parExpr
    ( DEFAULT_TOKEN_CHANNEL i=0 txt=( tt=7
    )
    ( orBlock
      ( parExpr
        ( DEFAULT_TOKEN_CHANNEL i=1 txt=( tt=7
        )
        ( andBlock
          ( var
            ( DEFAULT_TOKEN_CHANNEL i=2 txt=A tt=10
          ) )
          ( DEFAULT_TOKEN_CHANNEL i=3 txt=∧ tt=2
          )
          ( var
            ( DEFAULT_TOKEN_CHANNEL i=4 txt=B tt=10
        ) ) )
        ( DEFAULT_TOKEN_CHANNEL i=5 txt=) tt=8
      ) )
      ( DEFAULT_TOKEN_CHANNEL i=6 txt=∨ tt=3
      )
      ( parExpr
        ( DEFAULT_TOKEN_CHANNEL i=7 txt=( tt=7
        )
        ( andBlock
          ( parExpr
            ( DEFAULT_TOKEN_CHANNEL i=8 txt=( tt=7
            )
            ( andBlock
              ( var
                ( DEFAULT_TOKEN_CHANNEL i=9 txt=A tt=10
              ) )
              ( DEFAULT_TOKEN_CHANNEL i=10 txt=∧ tt=2
              )
              ( var
                ( DEFAULT_TOKEN_CHANNEL i=11 txt=B tt=10
            ) ) )
            ( DEFAULT_TOKEN_CHANNEL i=12 txt=) tt=8
          ) )
          ( DEFAULT_TOKEN_CHANNEL i=13 txt=∧ tt=2
          )
          ( var
            ( DEFAULT_TOKEN_CHANNEL i=14 txt=B tt=10
        ) ) )
        ( DEFAULT_TOKEN_CHANNEL i=15 txt=) tt=8
    ) ) )
    ( DEFAULT_TOKEN_CHANNEL i=16 txt=) tt=8
  ) )
  ( DEFAULT_TOKEN_CHANNEL i=17 txt=⇒ tt=4
  )
  ( var
    ( DEFAULT_TOKEN_CHANNEL i=18 txt=B tt=10
) ) )

Start 1 Stop 5 (A∧B)
Start 8 Stop 12 (A∧B)
Start 7 Stop 15 ((A∧B)∧B)
Start 0 Stop 16 ((A∧B)∨((A∧B)∧B))
解析完成。
令牌0 7通道默认\u令牌\u通道(
令牌1 7信道默认\u令牌\u信道(
令牌2 10信道默认\u令牌\u信道A
令牌3 2信道默认\u令牌\u信道∧
令牌4 10信道默认\u令牌\u信道B
令牌5 8信道默认值(令牌信道)
令牌6 3信道默认\u令牌\u信道∨
令牌7 7信道默认\u令牌\u信道(
令牌8 7信道默认\u令牌\u信道(
令牌9 10信道默认\u令牌\u信道A
令牌10 2信道默认\u令牌\u信道∧
令牌11 10信道默认\u令牌\u信道B
令牌12 8信道默认值(令牌信道)
令牌13 2信道默认\u令牌\u信道∧
令牌14 10信道默认\u令牌\u信道B
令牌15 8信道默认值(令牌信道)
令牌16 8信道默认值(令牌信道)
令牌17 4信道默认\u令牌\u信道⇒
令牌18 10信道默认\u令牌\u信道B
令牌19-1信道默认\u令牌\u信道
(IMPLOCK)
(parExpr)
(默认\u令牌\u通道i=0 txt=(tt=7
)
(奥布洛克)
(parExpr)
(默认\u令牌\u通道i=1 txt=(tt=7
)
(和块
(var)
(默认令牌信道i=2 txt=A tt=10
) )
(默认\u令牌\u通道i=3)=∧ tt=2
)
(var)
(默认令牌信道i=4 txt=B tt=10
) ) )
(默认令牌信道i=5 txt=)tt=8
) )
(默认\u令牌\u通道i=6)=∨ tt=3
)
(parExpr)
(默认\u令牌\u通道i=7 txt=(tt=7
)
(和块
(parExpr)
(默认\u令牌\u通道i=8 txt=(tt=7
)
(和块
(var)
(默认令牌信道i=9 txt=A tt=10
) )
(默认\u令牌\u通道i=10)=∧ tt=2
)
(var)
(默认令牌信道i=11 txt=B tt=10
) ) )
(默认令牌信道i=12 txt=)tt=8
) )
(默认\u令牌\u通道i=13)=∧ tt=2
)
(var)
(默认令牌信道i=14 txt=B tt=10
) ) )
(默认令牌信道i=15 txt=)tt=8
) ) )
(默认令牌信道i=16 txt=)tt=8
) )
(默认\u令牌\u通道i=17)=⇒ tt=4
)
(var)
(默认令牌信道i=18 txt=B tt=10
) ) )
开始1停止5(A∧(B)
启动8停止12(A∧(B)
启动7停止15((A∧(B)∧(B)
开始0停止16((A∧(B)∨((A)∧(B)∧B) )

我获取了您的语法和侦听器代码,并编写了一个程序来运行它。我还为您的输入打印了令牌流和解析树。这正是人们所期待的。但是,我从监听器输出的println()中得到的结果,如下所示,与您在问题中提供的不同。我的程序的输出对于Java和C#是相同的结果,令牌索引从0到19(EOF令牌)。我只能想,也许你正在使用一个旧的工具和运行时。确保您正在使用Antlr工具的4.8版本和运行时

parse completed.
Token 0 7 channel DEFAULT_TOKEN_CHANNEL (
Token 1 7 channel DEFAULT_TOKEN_CHANNEL (
Token 2 10 channel DEFAULT_TOKEN_CHANNEL A
Token 3 2 channel DEFAULT_TOKEN_CHANNEL ∧
Token 4 10 channel DEFAULT_TOKEN_CHANNEL B
Token 5 8 channel DEFAULT_TOKEN_CHANNEL )
Token 6 3 channel DEFAULT_TOKEN_CHANNEL ∨
Token 7 7 channel DEFAULT_TOKEN_CHANNEL (
Token 8 7 channel DEFAULT_TOKEN_CHANNEL (
Token 9 10 channel DEFAULT_TOKEN_CHANNEL A
Token 10 2 channel DEFAULT_TOKEN_CHANNEL ∧
Token 11 10 channel DEFAULT_TOKEN_CHANNEL B
Token 12 8 channel DEFAULT_TOKEN_CHANNEL )
Token 13 2 channel DEFAULT_TOKEN_CHANNEL ∧
Token 14 10 channel DEFAULT_TOKEN_CHANNEL B
Token 15 8 channel DEFAULT_TOKEN_CHANNEL )
Token 16 8 channel DEFAULT_TOKEN_CHANNEL )
Token 17 4 channel DEFAULT_TOKEN_CHANNEL ⇒
Token 18 10 channel DEFAULT_TOKEN_CHANNEL B
Token 19 -1 channel DEFAULT_TOKEN_CHANNEL <EOF>

( implBlock
  ( parExpr
    ( DEFAULT_TOKEN_CHANNEL i=0 txt=( tt=7
    )
    ( orBlock
      ( parExpr
        ( DEFAULT_TOKEN_CHANNEL i=1 txt=( tt=7
        )
        ( andBlock
          ( var
            ( DEFAULT_TOKEN_CHANNEL i=2 txt=A tt=10
          ) )
          ( DEFAULT_TOKEN_CHANNEL i=3 txt=∧ tt=2
          )
          ( var
            ( DEFAULT_TOKEN_CHANNEL i=4 txt=B tt=10
        ) ) )
        ( DEFAULT_TOKEN_CHANNEL i=5 txt=) tt=8
      ) )
      ( DEFAULT_TOKEN_CHANNEL i=6 txt=∨ tt=3
      )
      ( parExpr
        ( DEFAULT_TOKEN_CHANNEL i=7 txt=( tt=7
        )
        ( andBlock
          ( parExpr
            ( DEFAULT_TOKEN_CHANNEL i=8 txt=( tt=7
            )
            ( andBlock
              ( var
                ( DEFAULT_TOKEN_CHANNEL i=9 txt=A tt=10
              ) )
              ( DEFAULT_TOKEN_CHANNEL i=10 txt=∧ tt=2
              )
              ( var
                ( DEFAULT_TOKEN_CHANNEL i=11 txt=B tt=10
            ) ) )
            ( DEFAULT_TOKEN_CHANNEL i=12 txt=) tt=8
          ) )
          ( DEFAULT_TOKEN_CHANNEL i=13 txt=∧ tt=2
          )
          ( var
            ( DEFAULT_TOKEN_CHANNEL i=14 txt=B tt=10
        ) ) )
        ( DEFAULT_TOKEN_CHANNEL i=15 txt=) tt=8
    ) ) )
    ( DEFAULT_TOKEN_CHANNEL i=16 txt=) tt=8
  ) )
  ( DEFAULT_TOKEN_CHANNEL i=17 txt=⇒ tt=4
  )
  ( var
    ( DEFAULT_TOKEN_CHANNEL i=18 txt=B tt=10
) ) )

Start 1 Stop 5 (A∧B)
Start 8 Stop 12 (A∧B)
Start 7 Stop 15 ((A∧B)∧B)
Start 0 Stop 16 ((A∧B)∨((A∧B)∧B))
解析完成。
令牌0 7通道默认\u令牌\u通道(
令牌1 7信道默认\u令牌\u信道(
令牌2 10信道默认值