diff --git a/go/interpreter/main.go b/go/interpreter/main.go new file mode 100644 index 0000000..cb58ba6 --- /dev/null +++ b/go/interpreter/main.go @@ -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("======== 解释器模式结束 ========") +} diff --git a/python/interpreter/main.py b/python/interpreter/main.py new file mode 100644 index 0000000..8ad351e --- /dev/null +++ b/python/interpreter/main.py @@ -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======== 解释器模式结束 ========") + + diff --git a/ts/src/interpreter/index.ts b/ts/src/interpreter/index.ts new file mode 100644 index 0000000..6e33acc --- /dev/null +++ b/ts/src/interpreter/index.ts @@ -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======== 解释器模式结束 ========"); +})();