16

ANTLR 3では、次のことを実行できます。

    andExpression
  :  (andnotExpression        -> andnotExpression)
     (AND? a=andnotExpression -> ^(AndNode $andExpression $a))* 
  ;

新しいバージョンでそれを行う方法はありますか?

4

2 に答える 2

30

Sam(280Z28)が述べたように、ANTLR4には書き換え演算子がありません。

パーサーを生成するとき、ANTLR 4は、すべてのパーサールールの「enter」および「exit」イベントをリッスンするために使用できるいくつかのリスナークラスを作成します。

また、ANTLR 4は「直接左再帰ルール」をサポートしているため、以下に示すように、式ルールを1つのルールで定義できます。

grammar Expr;

parse
 : expression EOF
 ;

expression
 : '(' expression ')'
 | IDENTIFIER
 | NOT expression
 | expression AND? expression
 | expression OR expression
 ;

LPAREN     : '(';
RPAREN     : ')';
NOT        : 'NOT';
AND        : 'AND';
OR         : 'OR';
IDENTIFIER : [a-zA-Z_] [a-zA-Z_0-9]*;
SPACE      : [ \t\r\n]+ -> skip;

入力を解析する"a b OR NOT c AND d"と、次の解析ツリーが作成されます。

ここに画像の説明を入力してください

ANTLRWorks2を使用して作成された画像、ありがとうサム!非常に印象的なIDE、私はそれが大好きです!)

パーサークラスとリスナークラスを生成します。

java -cp antlr-4.0-complete.jar org.antlr.v4.Tool Expr.g4

そして、次のクラスが生成され、ツリーを「歩く」のに役立ちます。

public class ExprBaseListener implements ExprListener {

    @Override public void enterExpression(ExprParser.ExpressionContext ctx) { }
    @Override public void exitExpression(ExprParser.ExpressionContext ctx) { }

    @Override public void enterParse(ExprParser.ParseContext ctx) { }
    @Override public void exitParse(ExprParser.ParseContext ctx) { }

    @Override public void enterEveryRule(ParserRuleContext<Token> ctx) { }
    @Override public void exitEveryRule(ParserRuleContext<Token> ctx) { }
    @Override public void visitTerminal(TerminalNode<Token> node) { }
    @Override public void visitErrorNode(ErrorNode<Token> node) { }
}

ExprParser.ExpressionContext次に、を調べて、の選択肢のどれが一致するかを確認する必要があります。expressionここで、「ツリーラベル」が役立ちます。次のようにルールを変更expressionします。

expression
 : '(' expression ')'           # EXPR
 | IDENTIFIER                   # ID_EXPR
 | 'NOT' expression             # NOT_EXPR
 | expression 'AND'? expression # AND_EXPR
 | expression 'OR' expression   # OR_EXPR
 ;

パーサーとリスナーを再生成すると、ExprBaseListener次のようになります。

public class ExprBaseListener implements ExprListener {
    @Override public void enterAND_EXPR(ExprParser.AND_EXPRContext ctx) { }
    @Override public void exitAND_EXPR(ExprParser.AND_EXPRContext ctx) { }

    @Override public void enterOR_EXPR(ExprParser.OR_EXPRContext ctx) { }
    @Override public void exitOR_EXPR(ExprParser.OR_EXPRContext ctx) { }

    @Override public void enterEXPR(ExprParser.EXPRContext ctx) { }
    @Override public void exitEXPR(ExprParser.EXPRContext ctx) { }

    @Override public void enterNOT_EXPR(ExprParser.NOT_EXPRContext ctx) { }
    @Override public void exitNOT_EXPR(ExprParser.NOT_EXPRContext ctx) { }

    @Override public void enterID_EXPR(ExprParser.ID_EXPRContext ctx) { }
    @Override public void exitID_EXPR(ExprParser.ID_EXPRContext ctx) { }

    @Override public void enterParse(ExprParser.ParseContext ctx) { }
    @Override public void exitParse(ExprParser.ParseContext ctx) { }

    @Override public void enterEveryRule(ParserRuleContext ctx) { }
    @Override public void exitEveryRule(ParserRuleContext ctx) { }
    @Override public void visitTerminal(TerminalNode node) { }
    @Override public void visitErrorNode(ErrorNode node) { }
}

expressionつまり、個別のEnterメソッドとExitメソッドのラベルごとに作成されます。

ここで、AND式のイベントの入力のみに関心があるとします。ExprBaseListenerこれを拡張してオーバーライドするカスタムクラスを作成できますenterAND_EXPR

public class ExprWalker extends ExprBaseListener {

    @Override 
    public void enterAND_EXPR(ExprParser.AND_EXPRContext ctx) { 
        java.util.List<ExprParser.ExpressionContext> e = ctx.expression();
        System.out.println("AND -> " + e.get(0).getText() + ", " + e.get(1).getText());
    }
}

これをすべてテストするには、小さなドライバークラスを作成します。

import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

public class Main {

    public static void main(String[] args) throws Exception {

        String input = "a b OR NOT c AND d";
        ExprLexer lexer = new ExprLexer(new ANTLRInputStream(input));
        ExprParser parser = new ExprParser(new CommonTokenStream(lexer));
        ParseTree tree = parser.parse();
        ParseTreeWalker walker = new ParseTreeWalker();
        walker.walk(new ExprWalker(), tree);
    }
}

そしてそれを実行します:

java -cp antlr-4.0-complete.jar org.antlr.v4.Tool Expr.g4
javac -cp antlr-4.0-complete.jar * .java
java -cp。:antlr-4.0-complete.jarメイン

その後、コンソールに次のように印刷されます。

AND-> a、bORNOTcANDd
AND-> NOTc、d
于 2013-01-28T19:25:26.553 に答える
5

ANTLR 4には、書き換え演算子やANTLR 3のようなオプションはありませんoutput=AST。ANTLR4パーサーによって生成されるツリーは解析ツリーであり、その形状は文法規則によって暗黙的に定義されます。

于 2013-01-28T18:08:53.150 に答える