意图
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
结构
- 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;
}
@Override
public 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;
}
@Override
public 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()
方法解析表达式和项。