【Go-设计模式】解释器模式 详解

shadowLogo

概念;

解释器模式 定义一套 语言文法,并设计该 语言解释器,使用户能使用 特定文法 控制解释器行为

编译原理 中,一个 算术表达式 通过 词法分析器 形成 词法单元
而后这些词法单元再通过 语法分析器 构建 语法分析树,最终形成一颗 抽象的语法分析树
这里的 词法分析器语法分析器 都可以看做是 解释器

解释器模式(Interpreter Pattern):是指给定一个 语言(表达式),定义它的 文法 的一种表示,
并定义一个 解释器, 使用该解释器来解释 语言中的句子(表达式)

解释器模式意义 在于,它 分离多种复杂功能的实现,每个功能 只需 关注自身的解释
对于 调用者 不用关心 内部的解释器的工作,只需要用 简单的方式组合命令 就可以。

translation


UML:

uml

  • Context
    环境角色,含有 解释器之外的全局信息
  • AbstractExpression
    抽象表达式, 声明一个 抽象的解释操作,这个方法为 抽象语法树所有的节点所共享
  • TerminalExpression
    终结符表达式,实现与文法中的 终结符相关的解释操作
  • NonTermialExpression
    非终结符表达式,为文法中的 非终结符实现解释操作

示例:

语法树节点 接口:

type Node interface {
	Interpret() int64
}

具体的 语法树节点:

数值 语法树节点:

type ValNode struct {
	val int64
}

func (this *ValNode) Interpret() int64 {
	return this.val
}

加法 语法树节点:

type AddNode struct {
	leftNode  Node
	rightNode Node
}

func (this *AddNode) Interpret() int64 {
	return this.leftNode.Interpret() + this.rightNode.Interpret()
}

减法 语法树节点:

type SubNode struct {
	leftNode  Node
	rightNode Node
}

func (this *SubNode) Interpret() int64 {
	return this.leftNode.Interpret() - this.rightNode.Interpret()
}

语法分析器:

type GrammarParser struct {
	expression []string
	index      int64
	prevNode   Node
}

func (this *GrammarParser) newValNode() Node {
	value, _ := strconv.ParseInt(this.expression[this.index], 10, 64)
	this.index++
	return &ValNode{
		val: value,
	}
}

func (this *GrammarParser) newAddNode() Node {
	this.index++
	return &AddNode{
		leftNode:  this.prevNode,
		rightNode: this.newValNode(),
	}
}

func (this *GrammarParser) newSubNode() Node {
	this.index++
	return &SubNode{
		leftNode:  this.prevNode,
		rightNode: this.newValNode(),
	}
}

func (this *GrammarParser) Parse(exp string) {
	this.expression = strings.Split(exp, " ")

	for {
		if this.index >= int64(len(this.expression)) {
			return
		}
		switch this.expression[this.index] {
		case "加":
			this.prevNode = this.newAddNode()
		case "减":
			this.prevNode = this.newSubNode()
		default:
			this.prevNode = this.newValNode()
		}
	}
}

func (this *GrammarParser) Result() Node {
	return this.prevNode
}

func NewGrammarParser() *GrammarParser {
	return &GrammarParser{
		expression: []string{},
		index:      0,
		prevNode:   nil,
	}
}

测试:

package main

import (
	"fmt"

	"DemoProject/design/base23/interpreter"	// 根据自己的项目路径定制
)

func main() {
	// interpreter
	grammarParser := interpreter.NewGrammarParser()

	exp := "666 加 777 减 7"
	grammarParser.Parse(exp)

	result := grammarParser.Result().Interpret()
	fmt.Println("表达式【", exp, "】的结果为:", result)
}

注意事项:

应用场景:

  • 可以将一个 需要解释执行的语言中的句子 表示为一个 抽象语法树
  • 一些 重复出现的问题 可以用一种 简单的语言 来表达
  • 一个 简单语法 需要 解释的场景

例如:编译器、运算表达式计算、正则表达式、机器人...

缺点:

解释器模式 会引起 类膨胀
解释器模式 采用 递归调用方法,将会导致 调试非常复杂效率可能降低

posted @ 2021-12-17 15:52  在下右转,有何贵干  阅读(120)  评论(0)    收藏  举报