行为型 解析器模式

为什么需要解析器模式

解析器模式的使用范围主要集中在编译器、规则匹配、正则匹配、计算器(刷题)等领域。

例如leetcode basic calculator

主要理解就是表达式之间的串联,根据语法规则来解读输入来实现的程式就是解释器。主要对各个规则(例如加减乘除)的实现。

实现

实现起来代码量一点都不少,如果不是有大量的operation,其实非常不建议这么做的。

go.mod

module interpreter

go 1.13

interpreter.go

package interpreter

import (
	"container/list"
	"log"
	"strconv"
	"strings"
)

type Expression interface {
	interpret() int64
}

type SubtractionExpression struct {
	exp1 Expression
	exp2 Expression
}

func NewSubtractionExpression(exp1 Expression, exp2 Expression) SubtractionExpression {
	return SubtractionExpression{
		exp1: exp1,
		exp2: exp2,
	}
}

func (exp SubtractionExpression) interpret() int64 {
	return exp.exp1.interpret() - exp.exp2.interpret()
}

type AddExpression struct {
	exp1 Expression
	exp2 Expression
}

func NewAddExpression(exp1 Expression, exp2 Expression) AddExpression {
	return AddExpression{
		exp1: exp1,
		exp2: exp2,
	}
}

func (exp AddExpression) interpret() int64 {
	return exp.exp1.interpret() + exp.exp2.interpret()
}

type NumberExpression struct {
	number int64
}

func NewNumberExpressionFromInt64(number int64) NumberExpression {
	return NumberExpression{
		number: number,
	}
}

func NewNumberExpressionFromString(number string) NumberExpression {
	num, err := strconv.ParseInt(number, 10, 64)
	if err != nil {
		log.Fatal("Invalid expression for num", number)
	}
	return NumberExpression{
		number: num,
	}
}

func (exp NumberExpression) interpret() int64 {
	return exp.number
}

// Demo example how to use

type ExpressionInterpreter struct {
	nums *list.List
}

func NewExpressionInterpreter() ExpressionInterpreter {
	return ExpressionInterpreter{
		nums: list.New(),
	}
}

func (demoInterpreter ExpressionInterpreter) Interpret(str string) int64 {
	elements := strings.Fields(str)
	length := len(elements)
	nums := demoInterpreter.nums
	//1 2 3 + -
	for i := 0; i < (length+1)/2; i++ {
		nums.PushBack(NewNumberExpressionFromString(elements[i]))
	}
	for i := (length + 1) / 2; i < length; i++ {
		num1Ele := nums.Front()
		num2Ele := num1Ele.Next()
		num1Exp := num1Ele.Value.(NumberExpression)
		num2Exp := num2Ele.Value.(NumberExpression)
		nums.Remove(num1Ele)
		nums.Remove(num2Ele)
		var expression Expression
		switch elements[i] {
		case "+":
			expression = NewAddExpression(num1Exp, num2Exp)
		case "-":
			expression = NewSubtractionExpression(num1Exp, num2Exp)
		default:
			log.Fatal("Unrecoginzed expression: ", elements[i])
		}
		nums.PushFront(NewNumberExpressionFromInt64(expression.interpret()))
	}
	return nums.Front().Value.(NumberExpression).interpret()
}

interpreter_test.go

package interpreter_test

import (
	"interpreter"
	"testing"
)

func TestINterpreter(t *testing.T) {
	calculator := interpreter.NewExpressionInterpreter()
	result := calculator.Interpret("1 2 3 + -")
	if result != 0 {
		t.Fatal("Wrong interpreter implementation, got wrong output:", result)
	}
}

执行: go test interpreter -v

Previous
Next