支持连续的加减法,想要实现这一个功能,最重要的是编写语法图
1+1的语法图是 INTEGER PLUS INTEGER
1+2-3+4-5的语法图是 INTEGER ((PLUS|MINUS) INTEGER)*, *代表0个或多个
再简单点用括号标上 1 (+ 2) (- 3) (+ 4) (- 5),提取公共的部分得出连续加减法的语法图,我们用factorAst代表INTEGER,来容纳更多的可能性
词法解析器不变
修改语法解析
java
@Data
public class FactorAst extends Ast{
private Integer value;
public FactorAst(Integer value) {
this.value = value;
}
}
@Data
public class ProgramAst extends Ast{
private Ast leftValue;
private TokenType op;
private Ast rightValue;
public ProgramAst(Ast leftValue,TokenType op, Ast rightValue) {
this.leftValue = leftValue;
this.op = op;
this.rightValue = rightValue;
}
}
// 语法解析器
public class Parser {
private Lexer lexer ; // 词法解析器
private Token currentToken; // 当前的词法单元
public Parser(Lexer lexer) {
this.lexer = lexer;
this.currentToken = this.lexer.getNextToken();
}
public Ast programAst(){ // 程序节点
// programAst : factorAst ((PLUS|MINUS) factorAst)*
// factorAst: INTEGER
Ast node = this.factorAst();
while(Arrays.asList(TokenType.PLUS,TokenType.MINUS).contains(this.currentToken.getType())){
Token op = this.currentToken;
if(op.getType() == TokenType.PLUS){
this.eat(TokenType.PLUS);
}else if(op.getType() == TokenType.MINUS){
this.eat(TokenType.MINUS);
}
node = new ProgramAst(node ,op.getType(),this.factorAst());
}
return node;
}
public Ast factorAst(){
Token left = this.currentToken;
this.eat(TokenType.INTEGER);
return new FactorAst((Integer)left.getValue());
}
public void eat(TokenType tokenType){ // 确认当前的词性是否正确
if(tokenType == this.currentToken.getType()){
this.currentToken = this.lexer.getNextToken();
}else{
this.error("语法错误");
}
}
public void error(String msg){ // 报错函数
throw new RuntimeException(msg);
}
public Ast parse(){ // 获取语法树
return this.programAst();
}
}
修改解释器
java
// 目标执行器
public class Interpreter {
private Parser parser; // 语法解析器
public Interpreter(Parser parser) {
this.parser = parser;
}
public Object visitProgramAst(Ast ast){ // 访问programAst节点
ProgramAst programAst = (ProgramAst) ast;
if(programAst.getOp() == TokenType.PLUS){
return (Integer)this.visit(programAst.getLeftValue()) + (Integer)this.visit(programAst.getRightValue()); // 加法计算
}else if(programAst.getOp() == TokenType.MINUS){
return (Integer)this.visit(programAst.getLeftValue()) - (Integer)this.visit(programAst.getRightValue()); // 减法计算
}
return null;
}
public Object visitFactorAst(Ast ast){
FactorAst factorAst = (FactorAst) ast;
return factorAst.getValue();
}
public Object visit(Ast ast){ // 使用反射通过类名调用对应的函数
String methodName = "visit" + ast.getClass().getSimpleName();
try {
Method method = this.getClass().getDeclaredMethod(methodName , Ast.class );
return method.invoke(this, ast);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Integer expr() {
Ast ast = parser.parse(); // 获取语法树
Integer result = (Integer)this.visit(ast); // 遍历获取结果
return result;
}
}
执行测试
java
private static void testInterpreter() {
Lexer lexer = new Lexer(" 11 + 14 - 22 ");
Parser parser = new Parser(lexer);
Interpreter interpreter = new Interpreter(parser);
Integer result = interpreter.expr();
System.out.println("计算结果:" + result);
}
执行打印 计算结果:3