6

设计模式--解析器(Interpreter)模式

 2 years ago
source link: https://segmentfault.com/a/1190000040406700
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子

  • Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的结构不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式
  • 使用interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法
  • Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具

Go语言代码实现

Interpretor.go

package Interpreter

import "strings"

type Expression interface {
   Interpret(variables map[string]Expression)int
}

type Interger struct {
   integer int
}

func (n *Interger) 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(variable map[string]Expression)int{
   return e.syntaxTree.Interpret(variable)
}

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,
   }
}

func (v *Variable) Interpret(variable map[string]Expression)int {
   value, found := variable[v.name]
   if !found {
      return 0
   }
   return value.Interpret(variable)
}

func (s *Stack) Pop() interface{} {
   if s.size == 0{
      return nil
   }
   value := s.top.value
   s.top = s.top.next
   s.size--
   return value
}

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}
}

Interpretor_test.go

package Interpreter

import (
   "fmt"
   "testing"
)

func TestInterger(t *testing.T) {
   expression := "w x z +"
   sentence := NewEvaluator(expression)
   variables := make(map[string]Expression)
   variables["w"] = &Interger{6}
   variables["x"] = &Interger{10}
   variables["z"] = &Interger{41}
   result := sentence.Interpret(variables)
   fmt.Println(result)
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK