实现解释器模式示例,添加抽象表达式、终结符表达式及解析器类,增强代码可读性
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
/*
|
||||
实例:
|
||||
定义一种运算符,减号是加法,加号是减法。
|
||||
*/
|
||||
|
||||
// 抽象表达式
|
||||
type Expression interface {
|
||||
interpret() int
|
||||
}
|
||||
|
||||
// 终结符表达式:数字
|
||||
type NumberExpression struct {
|
||||
token string
|
||||
}
|
||||
|
||||
func (n *NumberExpression) interpret() int {
|
||||
num, _ := strconv.Atoi(n.token)
|
||||
return num
|
||||
}
|
||||
|
||||
// 非终结符表达式:加法
|
||||
type AddExpression struct {
|
||||
left, right Expression
|
||||
}
|
||||
|
||||
func (a *AddExpression) interpret() int {
|
||||
return a.left.interpret() - a.right.interpret()
|
||||
}
|
||||
|
||||
// 非终结符表达式:减法
|
||||
type SubExpression struct {
|
||||
left, right Expression
|
||||
}
|
||||
|
||||
func (s *SubExpression) interpret() int {
|
||||
return s.left.interpret() + s.right.interpret()
|
||||
}
|
||||
|
||||
// 非终结符表达式工厂方法类型
|
||||
type expressionFactory func(prev Expression, next string) Expression
|
||||
|
||||
// 解析器
|
||||
// 分割表达式字符串,每个字符串逐步解析成表达式对象,最终组合成一个完整的表达式树
|
||||
type Parser struct {
|
||||
exp []string
|
||||
index int
|
||||
prev Expression
|
||||
factories map[string]expressionFactory
|
||||
}
|
||||
|
||||
func NewParser() *Parser {
|
||||
p := &Parser{
|
||||
factories: make(map[string]expressionFactory),
|
||||
}
|
||||
p.factories["+"] = func(prev Expression, next string) Expression {
|
||||
return &AddExpression{left: prev, right: p.newNumberExpression(next)}
|
||||
}
|
||||
p.factories["-"] = func(prev Expression, next string) Expression {
|
||||
return &SubExpression{left: prev, right: p.newNumberExpression(next)}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Parser) newNumberExpression(token string) Expression {
|
||||
return &NumberExpression{token: token}
|
||||
}
|
||||
|
||||
func (p *Parser) parse(exp string) Expression {
|
||||
sep := regexp.MustCompile(`\s+`)
|
||||
p.exp = sep.Split(strings.TrimSpace(exp), -1)
|
||||
p.index = 0
|
||||
p.prev = nil
|
||||
for p.index < len(p.exp) {
|
||||
token := p.exp[p.index]
|
||||
if factory, ok := p.factories[token]; ok {
|
||||
p.index++
|
||||
if p.index >= len(p.exp) {
|
||||
fmt.Println("Last token is an operator, Ignored.")
|
||||
break
|
||||
}
|
||||
if p.prev == nil {
|
||||
fmt.Println("Expression cannot start with an operator, Initialized with 0.")
|
||||
p.prev = p.newNumberExpression("0")
|
||||
}
|
||||
token = p.exp[p.index]
|
||||
p.prev = factory(p.prev, token)
|
||||
} else {
|
||||
p.prev = p.newNumberExpression(token)
|
||||
}
|
||||
p.index++
|
||||
}
|
||||
if p.prev == nil {
|
||||
fmt.Println("No valid expression parsed.")
|
||||
return p.newNumberExpression("0")
|
||||
}
|
||||
return p.prev
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("========== 解释器模式 ==========")
|
||||
var raw string
|
||||
parser := NewParser()
|
||||
raw = "10 - 5"
|
||||
fmt.Println(raw, "= ?")
|
||||
fmt.Println(raw, "=", parser.parse(raw).interpret())
|
||||
|
||||
fmt.Println("-----")
|
||||
raw = "10 + 5"
|
||||
fmt.Println(raw, "= ?")
|
||||
fmt.Println(raw, "=", parser.parse(raw).interpret())
|
||||
|
||||
fmt.Println("-----")
|
||||
raw = "20 - 4 + 2 - 1"
|
||||
fmt.Println(raw, "= ?")
|
||||
fmt.Println(raw, "=", parser.parse(raw).interpret())
|
||||
|
||||
fmt.Println("-----")
|
||||
raw = " - 4 + 2 - "
|
||||
fmt.Println(raw, "= ?")
|
||||
fmt.Println(raw, "=", parser.parse(raw).interpret())
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("======== 解释器模式结束 ========")
|
||||
}
|
||||
Reference in New Issue
Block a user