简介
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子
UML图
应用场景
- 某种特定类型的问题发生的频率足够多,就可能值得将该问题的各个实例表述为一个简单语言中的句子,通过构建解释器去解释这些句子来解决问题
- 正则表达式、乐谱等
示例
乐谱的演奏
- Contex:
public class PlayContext {
private String playText;
public String getPlayText() {
return playText;
}
public void setPlayText(String playText) {
this.playText = playText;
}
}
- interpreter:
public abstract class Expression {
/**
* 解释器
*/
public void intercept(PlayContext context) {
if(!context.getPlayText().isBlank()) {
String playkey = context.getPlayText().substring(0, 1);
context.setPlayText(context.getPlayText().substring(2));
double playValue = Double.parseDouble(context.getPlayText().substring(0, context.getPlayText().indexOf(" ")));
// 将前面两者移除
context.setPlayText(context.getPlayText().substring(context.getPlayText().indexOf(" ") + 1));
execute(playkey, playValue);
}
}
/**
* 执行
*
* @param playKey
* @param playValue
*/
public abstract void execute(String playKey, double playValue);
}
音符:
public class Note extends Expression {
@Override
public void execute(String playKey, double playValue) {
String note = "";
switch (playKey) {
case "C":
note = "1";
break;
case "D":
note = "2";
break;
case "E":
note = "3";
break;
case "F":
note = "4";
break;
case "G":
note = "5";
break;
case "A":
note = "6";
break;
case "B":
note = "7";
break;
}
System.out.println(note);
}
}
音域
public class Scale extends Expression {
@Override
public void execute(String playKey, double playValue) {
String scale = "";
switch ((int) playValue) {
case 1:
scale = "低音";
break;
case 2:
scale = "中音";
break;
case 3:
scale = "高音";
break;
}
System.out.println(scale);
}
}
- 运行
public class Main {
public static void main(String[] args) {
PlayContext context = new PlayContext();
context.setPlayText("O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 ");
Expression expression;
while (!context.getPlayText().isBlank()){
String str = context.getPlayText().substring(0, 1);
switch (str){
case "O":
expression = new Scale();
break;
default:
expression = new Note();
break;
}
expression.intercept(context);
}
}
}
总结
- 优点
- 容易改变和扩展文法,该模式使用类来表示文法规则,可使用继承来改变或扩展文法
- 容易实现文法,定义抽象语法树中各个节点的类实现大体类似易于编写
- 缺点
- 文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护
- 文法复杂时建议使用其他如语法分析程序或编译器生成器等处理