1
0
Fork 0

实现解释器模式示例,添加抽象表达式、终结符表达式及解析器类,增强代码可读性

This commit is contained in:
IvisTang 2026-01-06 00:35:17 +08:00
parent 3a23a4d95a
commit cc215c9d70
3 changed files with 374 additions and 0 deletions

133
go/interpreter/main.go Normal file
View File

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

109
python/interpreter/main.py Normal file
View File

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

132
ts/src/interpreter/index.ts Normal file
View File

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