跳过监听器中的子表达式

huangapple go评论52阅读模式
英文:

Skipping sub-expressions in listener

问题

我对你的要求进行翻译,只保留代码部分:

infixOp: OR | AND;

assignment: Identifier EQUALS expression;

expression:
    Identifier |
    assignment |
    expression infixOp expression |
    LEFTBRACKET expression RIGHTBRACKET;

在你的监听器中,你可以在 enterExpression() 方法中采取适当的措施来跳过赋值表达式,这可以通过检查当前上下文中是否存在 assignment 来实现。这可以在语法树遍历期间以编程方式完成,而不仅仅依靠语法规则来跳过。

英文:

Let's say I have logical expressions in this form

((a OR b) AND c) OR (d AND e = (f OR g))

I'm interested in getting a, b, c, d and ignore e, f, g (everything that has to do with assignments).

My attempt was something like this

infixOp : OR | AND ;

assignment : Identifier EQUALS expression ;

expression  :
	Identifier |
	assignment |
	expression infixOp expression | 
	LEFTBRACKET expression RIGHTBRACKET ;

Then in my listener in enterExpression() I just printed expressionContext.getTokens(identifierType). Of course, this is too much and I got all of them.

How could "skip" over an assignment expression? Could this be done in the grammar? Or it can only be done programatically?

答案1

得分: 1

你可以创建一个小的监听器并跟踪进入和退出赋值的情况。然后在enterExpression方法内,检查是否不在赋值内且Identifier标记具有值。

语法的快速演示:

grammar T;

parse
 : expression EOF
 ;

expression
 : '(' expression ')'
 | expression 'AND' expression
 | expression 'OR' expression
 | assignment
 | Identifier
 ;

assignment
 : Identifier '=' expression
 ;

Identifier : [a-z]+;
Space      : [ \t\r\n] -> skip;

以及Java类:

public class Main {

    public static void main(String[] args) {

        TLexer lexer = new TLexer(CharStreams.fromString("((a OR b) AND c) OR (d AND e = (f OR g))"));
        TParser parser = new TParser(new CommonTokenStream(lexer));

        MyListener listener = new MyListener();

        ParseTreeWalker.DEFAULT.walk(listener, parser.parse());

        System.out.println(listener.ids);
    }
}

class MyListener extends TBaseListener {

    public List<String> ids = new ArrayList<String>();
    private boolean inAssignment  = false;

    @Override
    public void enterExpression(TParser.ExpressionContext ctx) {
        if (!this.inAssignment && ctx.Identifier() != null) {
            this.ids.add(ctx.Identifier().getText());
        }
    }

    @Override
    public void enterAssignment(TParser.AssignmentContext ctx) {
        this.inAssignment = true;
    }

    @Override
    public void exitAssignment(TParser.AssignmentContext ctx) {
        this.inAssignment = false;
    }
}

将会打印:

[a, b, c, d]
英文:

What you can do is create a small listener and keep track of the fact when you enter- and exit an assignment. Then inside the enterExpression method, check if you're NOT inside an assignment AND the Identifier token has a value.

A quick demo for the grammar:

grammar T;

parse
 : expression EOF
 ;

expression
 : &#39;(&#39; expression &#39;)&#39;
 | expression &#39;AND&#39; expression
 | expression &#39;OR&#39; expression
 | assignment
 | Identifier
 ;


assignment
 : Identifier &#39;=&#39; expression
 ;

Identifier : [a-z]+;
Space      : [ \t\r\n] -&gt; skip;

and Java class:

public class Main {

    public static void main(String[] args) {

        TLexer lexer = new TLexer(CharStreams.fromString(&quot;((a OR b) AND c) OR (d AND e = (f OR g))&quot;));
        TParser parser = new TParser(new CommonTokenStream(lexer));

        MyListener listener = new MyListener();

        ParseTreeWalker.DEFAULT.walk(listener, parser.parse());

        System.out.println(listener.ids);
    }
}

class MyListener extends TBaseListener {

    public List&lt;String&gt; ids = new ArrayList&lt;String&gt;();
    private boolean inAssignment  = false;

    @Override
    public void enterExpression(TParser.ExpressionContext ctx) {
        if (!this.inAssignment &amp;&amp; ctx.Identifier() != null) {
            this.ids.add(ctx.Identifier().getText());
        }
    }

    @Override
    public void enterAssignment(TParser.AssignmentContext ctx) {
        this.inAssignment = true;
    }

    @Override
    public void exitAssignment(TParser.AssignmentContext ctx) {
        this.inAssignment = false;
    }
}

will print:

[a, b, c, d]

答案2

得分: 0

也许类似于:

if (!(expressionContext.parent() instanceof AssignmentContext)) {
    expressionContext.getTokens(identifierType);
}

您可以通过遍历解析树结构并检查表达式上下文中的不同成员来找到它。

英文:

Maybe something like:

    if (!(expressionContext.parent() instanceof AssignmentContext)) {
        expressionContext.getTokens(identifierType);
    }

You can fine that by walking the parse tree structure and check the different members in the expression context.

huangapple
  • 本文由 发表于 2023年2月10日 15:54:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75408271.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定