意图
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
结构
- AbstractExpression声明一个程序的解释操作,这个接口为抽象语法树中所有结点所共享。
- TerminalExpression实现与文法中的终结符相关联的解释操作;一个句子中的每个终结符都需要该类的一个实例。
- NonterminalExpression对文法中的每一条规则都需要一个NonterminalExpression类;为每个符号都维护一个AbstractExpression类型的实例变量;为文法中的非终结符实现解释(Interpret)操作。
- Context构建(或被给定)表示该文法定义的语言中一个特定的句子的抽象语法树,该抽象语法树由NonterminalExpression和TerminalExpression的实例装配而成;调用解释操作。
适用性
Interpreter模式适用于当有一个语言需要解释执行,并且可能将该语言中的句子表示为一个抽象语法树时,以下情况效果最好:
- 该文法简单。对于复杂的发文,文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具时更好的选择。它们无须构建抽象语法树即可解释表达式,这样可以节省空间还可能节省时间。
- 效率不是一个关键问题。最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种形式。不过,即使在这种情况下,转换器仍然可用该模式实现。
代码示例
// 抽象表达式接口
interface AbstractExpression {Object interpret(Context context);
}// 终结符表达式
class TerminalExpression implements AbstractExpression {private String literal;public TerminalExpression(String literal) {this.literal = literal;}@Overridepublic Object interpret(Context context) {return literal;}
}// 非终结符表达式
class NonterminalExpression implements AbstractExpression {private AbstractExpression leftExpression;private AbstractExpression rightExpression;public NonterminalExpression(AbstractExpression leftExpression, AbstractExpression rightExpression) {this.leftExpression = leftExpression;this.rightExpression = rightExpression;}@Overridepublic Object interpret(Context context) {// TODO: 实现解释操作return null;}
}// 上下文
class Context {private String input;private int index;public Context(String input) {this.input = input;this.index = 0;}public char currentChar() {return input.charAt(index);}public void nextChar() {index++;}
}// 解释器
class ExpressionParser {private Context context;public ExpressionParser(String input) {this.context = new Context(input);}public AbstractExpression parse() {AbstractExpression expression = parseExpression();if (context.currentChar() != '\0') {throw new RuntimeException("Unexpected character: " + context.currentChar());}return expression;}private AbstractExpression parseExpression() {AbstractExpression leftExpression = parseTerm();while (context.currentChar() == '+') {context.nextChar();AbstractExpression rightExpression = parseTerm();leftExpression = new NonterminalExpression(leftExpression, rightExpression);}return leftExpression;}private AbstractExpression parseTerm() {if (Character.isDigit(context.currentChar())) {int number = 0;while (Character.isDigit(context.currentChar())) {number = number * 10 + (context.currentChar() - '0');context.nextChar();}return new TerminalExpression(String.valueOf(number));} else {throw new RuntimeException("Unexpected character: " + context.currentChar());}}
}// 测试
public class Main {public static void main(String[] args) {String expression = "1+2+3";ExpressionParser parser = new ExpressionParser(expression);AbstractExpression parsedExpression = parser.parse();// TODO: 构建抽象语法树并调用解释操作}
}
- AbstractExpression 接口: 定义所有表达式类必须实现的方法
interpret(Context context)
,用于解释表达式并返回结果。 - TerminalExpression 类: 代表终结符表达式,存储一个字符串并返回其值。
- NonterminalExpression 类: 代表非终结符表达式,存储两个子表达式并返回它们的加法结果。
- Context 类: 存储输入字符串和当前解析位置,提供读取字符和移动位置的方法。
- ExpressionParser 类: 解析输入字符串并生成表达式树,提供
parse()
方法解析整个表达式,以及parseExpression()
和parseTerm()
方法解析表达式和项。