2015-02-08 286 views
0

我的任務是實現一個訪客,將打開下面的語法來計算數學表達式爲AST:ANTLR4 - 利用訪問者把語法樹轉換成AST

grammar SmallC; 


program : exp 
; 

exp : lexp ((op = '>' | op = '<' |op = '>=' | op = '<=' | op = '!=' | op = '==') lexp)? 
; 

lexp : term ((op = '+'|op = '-') term)* 
; 

term: factor((op = '%'| op = '\*'| op = '/') factor)* 
; 

factor : Number 
; 

Number : [0-9]+ 
;  

目前,ANTLR表達創建下列樹「 3 * 6" :

程序 - >經驗 - > lexp - >項 - >(因子*因子) - >數值 - >(3 * 6)

我想是這樣的:

程序 - >乘法(3,6)

我試着通過實現訪問函數來開始這個過程,該函數將遍歷樹並輸出一些數據結構,但它失敗了。這裏是我的課:

Main.Java

import org.antlr.v4.runtime.*; 

public class Main { 

public static void main(String[] args) { 

ANTLRInputStream input = new ANTLRInputStream("3*6"); 
SmallCLexer lexer = new SmallCLexer(null); 
lexer.setInputStream(input); 

CommonTokenStream tokens = new CommonTokenStream(lexer); 
tokens.fill(); 

SmallCParser parser = new SmallCParser(null); 
parser.setBuildParseTree(true); 
parser.setTokenStream(tokens); 

ParserRuleContext tree = parser.program(); 
MyVisitor visitor = new MyVisitor(); 
visitor.visit(tree); 

} 

} 

MyVisitor.java

import org.antlr.v4.runtime.*; 


public class MyVisitor extends SmallCBaseVisitor<SmallCNode> { 


@Override public SmallCNode visitExp(SmallCParser.ExpContext ctx) { 
    if (ctx.lexp().size() == 2) { 
     SmallCLexp lhs = (SmallCLexp) ctx.lexp(0).accept(this); 
     SmallCLexp rhs = (SmallCLexp) ctx.lexp(1).accept(this); 
     String op = ctx.op.getText(); 
     return new SmallCExp(lhs,rhs,op); 
    } else { 
     visitLexp(ctx.lexp(0)); 
    } 


} 

@Override public SmallCNode visitLexp(SmallCParser.LexpContext ctx) { 
    if (ctx.term().size() == 2) { 
     SmallCTerm lhs = (SmallCTerm) ctx.term(0).accept(this); 
     SmallCTerm rhs = (SmallCTerm) ctx.term(1).accept(this); 
     String op = ctx.op.getText(); 
     return new SmallCLexp(lhs,rhs,op); 
    } else { 
     visitTerm(ctx.term(0)); 
    } 


} 

@Override public SmallCNode visitTerm(SmallCParser.TermContext ctx) { 
    if (ctx.factor().size() == 2) { 
     SmallCFactor lhs = (SmallCFactor) ctx.factor(0).accept(this); 
     SmallCFactor rhs = (SmallCFactor) ctx.factor(1).accept(this); 
     String op = ctx.op.getText(); 
     return new SmallCTerm(lhs,rhs,op); 
    } else { 
     visitFactor(ctx.factor(0)); 
    } 



} 

@Override public SmallCNode visitFactor(SmallCParser.FactorContext ctx) { 
     String fc = ctx.getText(); 
     return new SmallCFactor(fc); 
} 

這裏是我的節點類:

public class SmallCNode { 

} 


public class SmallCExp extends SmallCNode{ 
    SmallCLexp lhs; 
    SmallCLexp rhs; 
    String op; 
    public SmallCExp(SmallCLexp lhs, SmallCLexp rhs, String op) { 
     super(); 
     this.lhs = lhs; 
     this.rhs = rhs; 
     this.op = op; 
    } 
} 

public class SmallCLexp extends SmallCNode { 
    SmallCTerm lhs; 
    SmallCTerm rhs; 
    String op; 
    public SmallCLexp(SmallCTerm lhs, SmallCTerm rhs, String op) { 
     super(); 
     this.lhs = lhs; 
     this.rhs = rhs; 
     this.op = op; 
    } 
} 

public class SmallCTerm extends SmallCNode{ 
    SmallCFactor lhs; 
    SmallCFactor rhs; 
    String op; 
    public SmallCTerm(SmallCFactor lhs, SmallCFactor rhs, String op) { 
     super(); 
     this.lhs = lhs; 
     this.rhs = rhs; 
     this.op = op; 
} 

} 

public class SmallCFactor extends SmallCNode { 
    String factor; 

    public SmallCFactor(String factor) { 
     super(); 
     this.factor = factor; 
} 

}

當我運行Main.java,我得到這個呃ror:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    This method must return a result of type SmallCNode 

    at MyVisitor.visitExp(MyVisitor.java:8) 
    at MyVisitor.visitExp(MyVisitor.java:1) 
    at SmallCParser$ExpContext.accept(SmallCParser.java:151) 
    at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visitChildren(AbstractParseTreeVisitor.java:70) 
    at SmallCBaseVisitor.visitProgram(SmallCBaseVisitor.java:20) 
    at SmallCParser$ProgramContext.accept(SmallCParser.java:103) 
    at org.antlr.v4.runtime.tree.AbstractParseTreeVisitor.visit(AbstractParseTreeVisitor.java:42) 
    at Main.main(Main.java:20) 

現在,我對這件事很陌生,我意識到可能有很多我失蹤。我不知道如何從這裏繼續,我會很感激,如果我能得到,我很想念:)

回答

1

許多在代碼中else塊不返回SmallCNode的事情的清單,他們必須

它不應該是:

@Override public SmallCNode visitTerm(SmallCParser.TermContext ctx) { 
if (ctx.factor().size() == 2) { 
    SmallCFactor lhs = (SmallCFactor) ctx.factor(0).accept(this); 
    SmallCFactor rhs = (SmallCFactor) ctx.factor(1).accept(this); 
    String op = ctx.op.getText(); 
    return new SmallCTerm(lhs,rhs,op); 
} else { 
    visitFactor(ctx.factor(0)); 
} 

但:

@Override public SmallCNode visitTerm(SmallCParser.TermContext ctx) { 
if (ctx.factor().size() == 2) { 
    SmallCFactor lhs = (SmallCFactor) ctx.factor(0).accept(this); 
    SmallCFactor rhs = (SmallCFactor) ctx.factor(1).accept(this); 
    String op = ctx.op.getText(); 
    return new SmallCTerm(lhs,rhs,op); 
} else { 
    return visitFactor(ctx.factor(0)); 
}