1
0
Fork 0
design-patterns/go/interpreter/main.go

134 lines
3.0 KiB
Go

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("======== 解释器模式结束 ========")
}