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

This commit is contained in:
2026-01-06 00:35:17 +08:00
parent 3a23a4d95a
commit cc215c9d70
3 changed files with 374 additions and 0 deletions
+132
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======== 解释器模式结束 ========");
})();