实现解释器模式示例,添加抽象表达式、终结符表达式及解析器类,增强代码可读性
This commit is contained in:
parent
3a23a4d95a
commit
cc215c9d70
|
|
@ -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("======== 解释器模式结束 ========")
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
"""
|
||||
实例:
|
||||
定义一种运算符,减号是加法,加号是减法。
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Callable
|
||||
|
||||
# 抽象表达式
|
||||
class Expression(ABC):
|
||||
@abstractmethod
|
||||
def interpret(self) -> int:
|
||||
pass
|
||||
|
||||
|
||||
# 终结符表达式:数字
|
||||
class NumberExpression(Expression):
|
||||
def __init__(self, token: str):
|
||||
self.token = token
|
||||
|
||||
def interpret(self) -> int:
|
||||
return int(self.token)
|
||||
|
||||
|
||||
# 非终结符表达式:加法
|
||||
class AddExpression(Expression):
|
||||
def __init__(self, left: Expression, right: Expression):
|
||||
self.left = left
|
||||
self.right = right
|
||||
|
||||
def interpret(self) -> int:
|
||||
return self.left.interpret() - self.right.interpret()
|
||||
|
||||
|
||||
# 非终结符表达式:减法
|
||||
class SubExpression(Expression):
|
||||
def __init__(self, left: Expression, right: Expression):
|
||||
self.left = left
|
||||
self.right = right
|
||||
|
||||
def interpret(self) -> int:
|
||||
return self.left.interpret() + self.right.interpret()
|
||||
|
||||
# 解析器
|
||||
class Parser:
|
||||
exp: list[str]
|
||||
index: int
|
||||
prev: Expression | None
|
||||
factories: dict[str, Callable[[Expression, str], Expression]]
|
||||
|
||||
def __init__(self):
|
||||
self.factories = {}
|
||||
self.factories["+"] = lambda prev, next: AddExpression(prev, self.newNumberExpression(next))
|
||||
self.factories["-"] = lambda prev, next: SubExpression(prev, self.newNumberExpression(next))
|
||||
|
||||
def newNumberExpression(self, token: str) -> Expression:
|
||||
return NumberExpression(token)
|
||||
|
||||
def parse(self, exp: str) -> Expression:
|
||||
self.exp = exp.split()
|
||||
self.index = 0
|
||||
self.prev = None
|
||||
while self.index < len(self.exp):
|
||||
token = self.exp[self.index]
|
||||
if token in self.factories:
|
||||
factory = self.factories[token]
|
||||
self.index += 1
|
||||
if self.index >= len(self.exp):
|
||||
print("Last token is an operator, Ignored.")
|
||||
break
|
||||
token = self.exp[self.index]
|
||||
if self.prev is None:
|
||||
print("Expression cannot start with an operator, Initialized with 0.")
|
||||
self.prev = self.newNumberExpression("0")
|
||||
self.prev = factory(self.prev, token)
|
||||
else:
|
||||
self.prev = self.newNumberExpression(token)
|
||||
self.index += 1
|
||||
if self.prev is None:
|
||||
print("No valid expression parsed.")
|
||||
return self.newNumberExpression("0")
|
||||
return self.prev
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("========== 解释器模式 ==========")
|
||||
parser = Parser()
|
||||
|
||||
raw = "10 - 5"
|
||||
print(f"{raw} = ?")
|
||||
print(f"{raw} = {parser.parse(raw).interpret()}")
|
||||
|
||||
print("-----")
|
||||
raw = "10 + 5"
|
||||
print(f"{raw} = ?")
|
||||
print(f"{raw} = {parser.parse(raw).interpret()}")
|
||||
|
||||
print("-----")
|
||||
raw = "20 - 4 + 2 - 1"
|
||||
print(f"{raw} = ?")
|
||||
print(f"{raw} = {parser.parse(raw).interpret()}")
|
||||
|
||||
print("-----")
|
||||
raw = " - 4 + 2 - "
|
||||
print(f"{raw} = ?")
|
||||
print(f"{raw} = {parser.parse(raw).interpret()}")
|
||||
|
||||
print("\n======== 解释器模式结束 ========")
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
实例:
|
||||
定义一种运算符,减号是加法,加号是减法。
|
||||
*/
|
||||
|
||||
// 抽象表达式
|
||||
interface Expression {
|
||||
interpret(): number;
|
||||
}
|
||||
|
||||
// 终结符表达式:数字
|
||||
class NumberExpression implements Expression {
|
||||
private token: string;
|
||||
constructor(token: string) {
|
||||
this.token = token;
|
||||
}
|
||||
interpret(): number {
|
||||
return parseInt(this.token);
|
||||
}
|
||||
}
|
||||
|
||||
// 非终结符表达式:加法
|
||||
class AddExpression implements Expression {
|
||||
private left: Expression;
|
||||
private right: Expression;
|
||||
constructor(left: Expression, right: Expression) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
interpret(): number {
|
||||
return this.left.interpret() - this.right.interpret();
|
||||
}
|
||||
}
|
||||
|
||||
// 非终结符表达式:减法
|
||||
class SubExpression implements Expression {
|
||||
private left: Expression;
|
||||
private right: Expression;
|
||||
constructor(left: Expression, right: Expression) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
interpret(): number {
|
||||
return this.left.interpret() + this.right.interpret();
|
||||
}
|
||||
}
|
||||
|
||||
// 非终结符表达式工厂方法类型
|
||||
type ExpressionFactory = (prev: Expression, next: string) => Expression;
|
||||
|
||||
class Parser {
|
||||
private exp: string[];
|
||||
private index: number;
|
||||
private prev: Expression | null;
|
||||
private factories: { [key: string]: ExpressionFactory };
|
||||
|
||||
constructor() {
|
||||
this.exp = [];
|
||||
this.index = 0;
|
||||
this.prev = null;
|
||||
this.factories = {
|
||||
"-": (prev: Expression, next: string) =>
|
||||
new SubExpression(prev, new NumberExpression(next)),
|
||||
"+": (prev: Expression, next: string) =>
|
||||
new AddExpression(prev, new NumberExpression(next)),
|
||||
};
|
||||
}
|
||||
|
||||
newNumberExpression(token: string): Expression {
|
||||
return new NumberExpression(token);
|
||||
}
|
||||
|
||||
parse(raw: string): Expression {
|
||||
this.exp = raw.trim().split(/\s+/);
|
||||
this.index = 0;
|
||||
this.prev = null;
|
||||
|
||||
while (this.index < this.exp.length) {
|
||||
let token = this.exp[this.index];
|
||||
if (this.factories[token]) {
|
||||
const factory = this.factories[token];
|
||||
this.index++;
|
||||
if (this.index >= this.exp.length) {
|
||||
console.log("Last token is an operator, Ignored.");
|
||||
break;
|
||||
}
|
||||
if (this.prev === null) {
|
||||
console.log(
|
||||
"Expression cannot start with an operator, Initialized with 0."
|
||||
);
|
||||
this.prev = this.newNumberExpression("0");
|
||||
}
|
||||
token = this.exp[this.index];
|
||||
this.prev = factory(this.prev, token);
|
||||
} else {
|
||||
this.prev = this.newNumberExpression(token);
|
||||
}
|
||||
this.index++;
|
||||
}
|
||||
if (this.prev === null) {
|
||||
console.log("No valid expression parsed.");
|
||||
return this.newNumberExpression("0");
|
||||
}
|
||||
return this.prev;
|
||||
}
|
||||
}
|
||||
|
||||
(function () {
|
||||
console.log("========== 解释器模式 ==========");
|
||||
const parser = new Parser();
|
||||
let raw;
|
||||
raw = "10 - 5";
|
||||
console.log(`${raw} = ?`);
|
||||
console.log(`${raw} = ${parser.parse(raw).interpret()}`);
|
||||
|
||||
console.log("-----");
|
||||
raw = "10 + 5";
|
||||
console.log(`${raw} = ?`);
|
||||
console.log(`${raw} = ${parser.parse(raw).interpret()}`);
|
||||
|
||||
console.log("-----");
|
||||
raw = "20 - 4 + 2 - 1";
|
||||
console.log(`${raw} = ?`);
|
||||
console.log(`${raw} = ${parser.parse(raw).interpret()}`);
|
||||
|
||||
console.log("-----");
|
||||
raw = " - 4 + 2 - ";
|
||||
console.log(`${raw} = ?`);
|
||||
console.log(`${raw} = ${parser.parse(raw).interpret()}`);
|
||||
|
||||
console.log("\n======== 解释器模式结束 ========");
|
||||
})();
|
||||
Loading…
Reference in New Issue