Go和Java實(shí)現(xiàn)解釋器模式
下面通過一個(gè)四則運(yùn)算來說明解釋器模式的使用。
1、解釋器模式
解釋器模式提供了評估語言的語法或表達(dá)式的方式,它屬于行為型模式。這種模式實(shí)現(xiàn)了一個(gè)表達(dá)式接口,該接口
解釋一個(gè)特定的上下文。這種模式被用在 SQL 解析、符號處理引擎等。
-
意圖:給定一個(gè)語言,定義它的文法表示,并定義一個(gè)解釋器,這個(gè)解釋器使用該標(biāo)識來解釋語言中的句子。
-
主要解決:對于一些固定文法構(gòu)建一個(gè)解釋句子的解釋器。
-
何時(shí)使用:如果一種特定類型的問題發(fā)生的頻率足夠高,那么可能就值得將該問題的各個(gè)實(shí)例表述為一個(gè)簡單
語言中的句子。這樣就可以構(gòu)建一個(gè)解釋器,該解釋器通過解釋這些句子來解決該問題。
-
如何解決:構(gòu)建語法樹,定義終結(jié)符與非終結(jié)符。
-
關(guān)鍵代碼:構(gòu)建環(huán)境類,包含解釋器之外的一些全局信息,一般是 HashMap。
-
應(yīng)用實(shí)例:編譯器、運(yùn)算表達(dá)式計(jì)算。
-
優(yōu)點(diǎn):1、可擴(kuò)展性比較好,靈活。 2、增加了新的解釋表達(dá)式的方式。 3、易于實(shí)現(xiàn)簡單文法。
-
缺點(diǎn):1、可利用場景比較少。 2、對于復(fù)雜的文法比較難維護(hù)。 3、解釋器模式會引起類膨脹。 4、解釋器模
式采用遞歸調(diào)用方法。
-
使用場景:1、可以將一個(gè)需要解釋執(zhí)行的語言中的句子表示為一個(gè)抽象語法樹。 2、一些重復(fù)出現(xiàn)的問題可
以用一種簡單的語言來進(jìn)行表達(dá)。 3、一個(gè)簡單語法需要解釋的場景。
-
注意事項(xiàng):可利用場景比較少,JAVA 中如果碰到可以用 expression4J 代替。
-
適用性:
當(dāng)有一個(gè)語言需要解釋執(zhí)行,并且你可將該語言中的句子表示為一個(gè)抽象語法樹時(shí),可使用解釋器模式,而當(dāng)
存在當(dāng)下情況時(shí)該模式效果最好:
該文法簡單對于復(fù)雜的文法,文法的層次變得龐大而無法管理。
效率不是一個(gè)關(guān)鍵問題最高效的解釋器通常不是通過直接解釋語法分析樹實(shí)現(xiàn)的,而是首先將它們轉(zhuǎn)換成另文章來源:http://www.zghlxwxcb.cn/news/detail-650461.html
一種形式。文章來源地址http://www.zghlxwxcb.cn/news/detail-650461.html
2、Go實(shí)現(xiàn)解釋器模式
package interpreter
// ========== ArithmeticInterpreter ==========
type ArithmeticInterpreter interface {
Interpret() int
}
package interpreter
// ========== NumInterpreter ==========
type NumInterpreter struct {
Value int
}
func NewNumInterpreter(value int) *NumInterpreter {
return &NumInterpreter{Value: value}
}
func (numInterpreter *NumInterpreter) Interpret() int {
return numInterpreter.Value
}
package interpreter
// ========== AddInterpreter ==========
type AddInterpreter struct {
left ArithmeticInterpreter
right ArithmeticInterpreter
}
func NewAddInterpreter(left, right ArithmeticInterpreter) *AddInterpreter {
return &AddInterpreter{left: left, right: right}
}
func (addInterpreter *AddInterpreter) Interpret() int {
return addInterpreter.left.Interpret() + addInterpreter.right.Interpret()
}
package interpreter
// ========== SubInterpreter ==========
type SubInterpreter struct {
left ArithmeticInterpreter
right ArithmeticInterpreter
}
func NewSubInterpreter(left, right ArithmeticInterpreter) *SubInterpreter {
return &SubInterpreter{left: left, right: right}
}
func (subInterpreter *SubInterpreter) Interpret() int {
return subInterpreter.left.Interpret() - subInterpreter.right.Interpret()
}
package interpreter
// ========== MultiInterpreter ==========
type MultiInterpreter struct {
left ArithmeticInterpreter
right ArithmeticInterpreter
}
func NewMultiInterpreter(left, right ArithmeticInterpreter) *MultiInterpreter {
return &MultiInterpreter{left: left, right: right}
}
func (multiInterpreter *MultiInterpreter) Interpret() int {
return multiInterpreter.left.Interpret() * multiInterpreter.right.Interpret()
}
package interpreter
// ========== DivInterpreter ==========
type DivInterpreter struct {
left ArithmeticInterpreter
right ArithmeticInterpreter
}
func NewDivInterpreter(left, right ArithmeticInterpreter) *DivInterpreter {
return &DivInterpreter{left: left, right: right}
}
func (divInterpreter *DivInterpreter) Interpret() int {
return divInterpreter.left.Interpret() / divInterpreter.right.Interpret()
}
package interpreter
const (
ADD = "+"
SUB = "-"
MUL = "*"
DIV = "/"
)
// =========== OperatorUtil ==========
type OperatorUtil struct{}
func (OperatorUtil *OperatorUtil) IsOperator(symbol string) bool {
return ("+" == symbol || "-" == symbol || "*" == symbol)
}
func (operatorUtil *OperatorUtil) GetInterpreter(left, right ArithmeticInterpreter, symbol string) ArithmeticInterpreter {
if ADD == symbol {
return NewAddInterpreter(left, right)
} else if SUB == symbol {
return NewSubInterpreter(left, right)
} else if MUL == symbol {
return NewMultiInterpreter(left, right)
} else if DIV == symbol {
return NewDivInterpreter(left, right)
}
return nil
}
package interpreter
import (
"fmt"
"strconv"
"strings"
)
type Calculator struct{}
var (
operatorUtil = OperatorUtil{}
stack = make([]ArithmeticInterpreter, 0)
)
func (calculator *Calculator) Parse(expression string) {
elements := strings.Split(expression, " ")
var leftExpr, rightExpr ArithmeticInterpreter
for i := 0; i < len(elements); i++ {
operator := elements[i]
if operatorUtil.IsOperator(operator) {
// 出棧
leftExpr = stack[len(stack)-1]
stack = stack[:len(stack)-1]
i++
ele, _ := strconv.Atoi(elements[i])
rightExpr = NewNumInterpreter(ele)
fmt.Printf("出棧: %d 和 %d \n", leftExpr.Interpret(), rightExpr.Interpret())
stack = append(stack, operatorUtil.GetInterpreter(leftExpr, rightExpr, operator))
fmt.Println("應(yīng)用運(yùn)算符: " + operator)
} else {
ele, _ := strconv.Atoi(elements[i])
numInterpreter := NewNumInterpreter(ele)
stack = append(stack, numInterpreter)
fmt.Printf("入棧: %d \n", numInterpreter.Interpret())
}
}
}
func (calculator *Calculator) Result() int {
value := stack[len(stack)-1]
stack = stack[:len(stack)-1]
return value.Interpret()
}
package main
import (
"fmt"
. "proj/interpreter"
)
func main() {
calculator := Calculator{}
calculator.Parse("10 + 30")
fmt.Println("result:", calculator.Result())
calculator.Parse("10 + 30 - 20")
fmt.Println("result: ", calculator.Result())
calculator.Parse("100 * 2 + 400 - 20 + 66")
fmt.Println("result:", calculator.Result())
}
# 程序輸出
入棧: 10
出棧: 10 和 30
應(yīng)用運(yùn)算符: +
result: 40
入棧: 10
出棧: 10 和 30
應(yīng)用運(yùn)算符: +
出棧: 40 和 20
應(yīng)用運(yùn)算符: -
result: 20
入棧: 100
出棧: 100 和 2
應(yīng)用運(yùn)算符: *
出棧: 200 和 400
應(yīng)用運(yùn)算符: +
出棧: 600 和 20
應(yīng)用運(yùn)算符: -
出棧: 580 和 66
應(yīng)用運(yùn)算符: +
result: 40
入棧: 10
出棧: 10 和 30
應(yīng)用運(yùn)算符: +
出棧: 40 和 20
應(yīng)用運(yùn)算符: -
result: 20
入棧: 100
出棧: 100 和 2
應(yīng)用運(yùn)算符: *
出棧: 200 和 400
應(yīng)用運(yùn)算符: +
出棧: 600 和 20
應(yīng)用運(yùn)算符: -
出棧: 580 和 66
應(yīng)用運(yùn)算符: +
result: 646
3、Java實(shí)現(xiàn)解釋器模式
package com.interpreter;
// ========== ArithmeticInterpreter ==========
public interface ArithmeticInterpreter {
int interpret();
}
package com.interpreter;
// ========== ArithmeticInterpreter ==========
public abstract class Interpreter implements ArithmeticInterpreter{
protected ArithmeticInterpreter left;
protected ArithmeticInterpreter right;
public Interpreter(ArithmeticInterpreter left, ArithmeticInterpreter right) {
this.left = left;
this.right = right;
}
}
package com.interpreter;
// ========== NumInterpreter ==========
public class NumInterpreter implements ArithmeticInterpreter {
private int value;
public NumInterpreter(int value) {
this.value = value;
}
@Override
public int interpret() {
return this.value;
}
}
package com.interpreter;
// ========== AddInterpreter ==========
public class AddInterpreter extends Interpreter {
public AddInterpreter() {
super(left, right);
}
@Override
public int interpret() {
return this.left.interpret() + this.right.interpret();
}
}
package com.interpreter;
// ========== MultiInterpreter ==========
public class MultiInterpreter extends Interpreter {
public MultiInterpreter(ArithmeticInterpreter left, ArithmeticInterpreter right) {
super(left, right);
}
@Override
public int interpret() {
return this.left.interpret() * this.right.interpret();
}
}
package com.interpreter;
// ========== SubInterpreter ==========
public class SubInterpreter extends Interpreter {
public SubInterpreter(ArithmeticInterpreter left, ArithmeticInterpreter right) {
super(left, right);
}
@Override
public int interpret() {
return this.left.interpret() - this.right.interpret();
}
}
package com.interpreter;
// ========== DivInterpreter ==========
public class DivInterpreter extends Interpreter {
public DivInterpreter(ArithmeticInterpreter left, ArithmeticInterpreter right) {
super(left, right);
}
@Override
public int interpret() {
return this.left.interpret() / this.right.interpret();
}
}
package com.interpreter;
// =========== OperatorUtil ==========
public class OperatorUtil {
private final static String ADD = "+";
private final static String SUB = "-";
private final static String MUL = "*";
private final static String DIV = "/";
public static boolean isOperator(String symbol) {
return ("+".equals(symbol) || "-".equals(symbol) || "*".equals(symbol));
}
public static Interpreter getInterpreter(ArithmeticInterpreter left, ArithmeticInterpreter right, String symbol) {
if (ADD.equals(symbol)) {
return new AddInterpreter(left, right);
} else if (SUB.equals(symbol)) {
return new SubInterpreter(left, right);
} else if (MUL.equals(symbol)) {
return new MultiInterpreter(left, right);
} else if (DIV.equals(symbol)) {
return new DivInterpreter(left, right);
}
return null;
}
}
package com.interpreter;
import java.util.Stack;
// ========== Calculator ==========
public class Calculator {
private final Stack<ArithmeticInterpreter> stack = new Stack<>();
public void parse(String expression) {
String[] elements = expression.split(" ");
ArithmeticInterpreter leftExpr, rightExpr;
for (int i = 0; i < elements.length; i++) {
String operator = elements[i];
if (OperatorUtil.isOperator(operator)) {
leftExpr = this.stack.pop();
rightExpr = new NumInterpreter(Integer.parseInt(elements[++i]));
System.out.println("出棧: " + leftExpr.interpret() + " 和 " + rightExpr.interpret());
this.stack.push(OperatorUtil.getInterpreter(leftExpr, rightExpr, operator));
System.out.println("應(yīng)用運(yùn)算符: " + operator);
} else {
NumInterpreter numInterpreter = new NumInterpreter(Integer.parseInt(elements[i]));
this.stack.push(numInterpreter);
System.out.println("入棧: " + numInterpreter.interpret());
}
}
}
public int result() {
return this.stack.pop().interpret();
}
}
package com.interpreter;
public class Test {
public static void main(String[] args) {
Calculator calculator = new Calculator();
calculator.parse("10 + 30");
System.out.println("result: " + calculator.result());
calculator.parse("10 + 30 - 20");
System.out.println("result: " + calculator.result());
calculator.parse("100 * 2 + 400 - 20 + 66");
System.out.println("result: " + calculator.result());
}
}
# 程序輸出
入棧: 10
出棧: 10 和 30
應(yīng)用運(yùn)算符: +
result: 40
入棧: 10
出棧: 10 和 30
應(yīng)用運(yùn)算符: +
出棧: 40 和 20
應(yīng)用運(yùn)算符: -
result: 20
入棧: 100
出棧: 100 和 2
應(yīng)用運(yùn)算符: *
出棧: 200 和 400
應(yīng)用運(yùn)算符: +
出棧: 600 和 20
應(yīng)用運(yùn)算符: -
出棧: 580 和 66
應(yīng)用運(yùn)算符: +
result: 646
到了這里,關(guān)于Go和Java實(shí)現(xiàn)解釋器模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!