2012-04-12 7 views
2

Ich habe gelesen, dass Sie die '^' und '!' Operatoren, um einen Syntaxbaum zu erstellen, der dem in ANTLR Works angezeigten ähnlich ist (obwohl Sie sie nicht brauchen, um in ANTLR Works einen schönen Baum zu erhalten). Meine Frage ist dann, wie kann ich einen solchen Baum bauen? Ich habe ein paar Seiten auf Baumkonstruktion gesehen, die beiden Betreiber und umschreibt mit, und doch sagen, ich habe eine Eingabezeichenfolge abc abc123 und eine Grammatik:Wie kann ich einen ANTLR Works-Syntaxbaum erstellen?

grammar test; 

program : idList; 
idList : id* ; 
id : ID ; 

ID : LETTER (LETTER | NUMBER)* ; 
LETTER : 'a' .. 'z' | 'A' .. 'Z' ; 
NUMBER : '0' .. '9' ; 

ANTLR Works folgende Ausgabe:

ANTLR Works Interpreter Output

Was ich nicht verstehe, ist, wie Sie den 'IdList' Knoten oben auf diesem Baum (wie auch die Grammatik tatsächlich) bekommen können. Wie kann ich diesen Baum mit Umschreibungen und diesen Operatoren reproduzieren?

Antwort

2

Was ich nicht verstehe, ist, wie Sie den 'idList' Knoten oben auf diesem Baum (sowie die Grammatik als eine Tatsache) bekommen können. Wie kann ich diesen Baum mit Umschreibungen und diesen Operatoren reproduzieren?

Sie können ^ und ! nicht alleine verwenden. Diese Operatoren arbeiten nur mit vorhandenen Token, während Sie zusätzliche Token erstellen möchten (und diese zum Stamm Ihrer Subbäume machen). Sie können tun, dass rewrite rules and defining some imaginary tokens verwenden.

Eine schnelle Demo:

grammar test; 

options { 
    output=AST; 
    ASTLabelType=CommonTree; 
} 

tokens { 
    IdList; 
    Id; 
} 

@parser::members { 

    private static void walk(CommonTree tree, int indent) { 
    if(tree == null) return; 
    for(int i = 0; i < indent; i++, System.out.print(" ")); 
    System.out.println(tree.getText()); 
    for(int i = 0; i < tree.getChildCount(); i++) { 
     walk((CommonTree)tree.getChild(i), indent + 1); 
    } 
    } 

    public static void main(String[] args) throws Exception { 
    testLexer lexer = new testLexer(new ANTLRStringStream("abc abc123")); 
    testParser parser = new testParser(new CommonTokenStream(lexer)); 
    walk((CommonTree)parser.program().getTree(), 0); 
    } 
} 

program : idList EOF -> idList; 
idList : id*  -> ^(IdList id*); 
id  : ID   -> ^(Id ID); 

ID : LETTER (LETTER | DIGIT)*; 
SPACE : ' ' {skip();}; 

fragment LETTER : 'a' .. 'z' | 'A' .. 'Z'; 
fragment DIGIT : '0' .. '9'; 

Wenn Sie die Demo oben laufen, sehen Sie die folgenden auf der Konsole ausgegeben werden:

IdList 
    Id 
     abc 
    Id 
     abc123 

Wie Sie sehen können, müssen imaginäre Token auch starten mit einem Großbuchstaben, genau wie Lexer-Regeln. Wenn Sie die imaginären Token die gleichen text wie die Parser-Regel geben, wollen sie repräsentieren, etwas tun, wie diese statt:

idList : id*  -> ^(IdList["idList"] id*); 
id  : ID   -> ^(Id["id"] ID); 

, die gedruckt werden:

idList 
    id 
     abc 
    id 
     abc123 
+0

Danke für so eine eingehende Antwort. Aus irgendeinem Grund konnte ich das nie aus der Dokumentation herausholen. –

+0

Gern geschehen @ChrisCovert. –