定义
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
优点
- 扩展性强,若要新增乘,除,添加相应的非终结表达式,修改计算逻辑即可。
缺点
- 需要建大量的类,因为每一种语法都要建一个非终结符的类。
- 解释的时候采用递归调用方法,导致有时候函数的深度会很深,影响效率。
场景
如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
代码
package Interpreter
import "strings"
type Expression interface {
Interpret(variables map[string]Expression) int
}
type Integer struct {
integer int
}
func (n *Integer) Interpret(variables map[string]Expression) int {
return n.integer
}
type Plus struct {
leftOperand Expression
rightOperand Expression
}
func (p *Plus) Interpret(variables map[string]Expression) int {
return p.leftOperand.Interpret(variables) + p.rightOperand.Interpret(variables)
}
func (e *Evaluator) Interpret(context map[string]Expression) int {
return e.syntaxTree.Interpret(context)
}
type Variable struct {
name string
}
type Node struct {
value interface{}
next *Node
}
type Stack struct {
top *Node
size int
}
func (s *Stack) Push(value interface{}) {
s.top = &Node{
value: value,
next: s.top,
}
s.size++
}
func (s *Stack) Pop() interface{} {
if s.size == 0 {
return nil
}
value := s.top.value
s.top = s.top.next
s.size--
return value
}
func (v *Variable) Interpret(variables map[string]Expression) int {
value, found := variables[v.name]
if !found {
return 0
}
return value.Interpret(variables)
}
type Evaluator struct {
syntaxTree Expression
}
func NewEvaluator(expression string) *Evaluator {
expressionStack := new(Stack)
for _, token := range strings.Split(expression, " ") {
switch token {
case "+":
right := expressionStack.Pop().(Expression)
left := expressionStack.Pop().(Expression)
subExpression := &Plus{left, right}
expressionStack.Push(subExpression)
default:
expressionStack.Push(&Variable{token})
}
}
syntaxTree := expressionStack.Pop().(Expression)
return &Evaluator{syntaxTree: syntaxTree}
}
package Interpreter
import "testing"
import "github.com/stretchr/testify/assert"
func TestInterpret(t *testing.T) {
expression := "w x z +"
sentence := NewEvaluator(expression)
variable := make(map[string]Expression)
variable["w"] = &Integer{6}
variable["x"] = &Integer{10}
variable["z"] = &Integer{41}
result := sentence.Interpret(variable)
assert.Equal(t, 51, result)
}
其他设计模式