Skip to content

Commit 94ea512

Browse files
committed
Refactor math evaluator into modular components
Replaces the monolithic evaluator implementation with a modular structure, separating operators, methods, constants, tokenization, error handling, and expression evaluation into distinct files. Removes obsolete files and introduces extensibility for custom operators, methods, and constants. This refactor improves maintainability and clarity of the math evaluation logic.
1 parent d90f2af commit 94ea512

29 files changed

+440
-39
lines changed

src/math/evaluate/associativity.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const associativity = {
2+
left: 'LEFT',
3+
right: 'RIGHT'
4+
} as const;
5+
6+
export type Associativity = typeof associativity[keyof typeof associativity]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const defaults: Record<string, number> = {
2+
pi: Math.PI,
3+
e: Math.E,
4+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type Definition = number
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { defaults } from './defaults.ts'
2+
export type { Definition } from './definition.ts'

src/math/evaluate/defaults.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type { Definition } from "./definition.ts"
2+
3+
export const defaults : Record<string, Definition> = {
4+
'+': {
5+
precedence: 1,
6+
associativity: 'LEFT',
7+
calculateFn: (a, b) => a + b
8+
},
9+
'-': {
10+
precedence: 1,
11+
associativity: 'LEFT',
12+
calculateFn: (a, b) => a - b
13+
},
14+
'*': {
15+
precedence: 2,
16+
associativity: 'LEFT',
17+
calculateFn: (a, b) => a * b
18+
},
19+
'/': {
20+
precedence: 2,
21+
associativity: 'LEFT',
22+
calculateFn: (a, b) => a / b,
23+
checkFn: (_, b) => b !== 0
24+
},
25+
'^': {
26+
precedence: 3,
27+
associativity: 'RIGHT',
28+
calculateFn: (a, b) => a ** b,
29+
checkFn: (a, b) => !(a < 0 && !Number.isInteger(b))
30+
}
31+
}

src/math/evaluate/definition.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { Associativity } from "./associativity.ts";
2+
3+
export interface Definition {
4+
/** The priority of this operator */
5+
precedence : number,
6+
/** The direction from which the operator values get parsed */
7+
associativity : Associativity,
8+
/** The function to use for calculating the corresponding result */
9+
calculateFn : (a: number, b: number) => number,
10+
/** The function to use for checking the input */
11+
checkFn?: (a: number, b: number) => boolean
12+
}

src/math/evaluate/error/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { InvalidOperatorValueError } from './invalid_operator_value_error.ts'
2+
export { InvalidMethodValueError } from './invalid_method_value_error.ts'
3+
export { UnknownTokenError } from './unknown_token_error.ts'

src/math/evaluate/error/invalid_input_error.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export class InvalidMethodValueError extends Error {
2+
public readonly method : string;
3+
public readonly args: (string | number)[];
4+
constructor(
5+
method : string,
6+
args : (string | number)[]
7+
) {
8+
super(`Invalid value for method '${method}': (${args.join(', ')})`)
9+
10+
this.method = method,
11+
this.args = args
12+
}
13+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export class InvalidOperatorValueError extends Error {
2+
public readonly operator : string;
3+
public readonly a : string | number;
4+
public readonly b : string | number;
5+
6+
constructor(
7+
operator: string,
8+
a: string | number,
9+
b: string | number
10+
) {
11+
super(`Invalid value for operator '${operator}': (${a}, ${b})`)
12+
13+
this.operator = operator,
14+
this.a = a;
15+
this.b = b;
16+
}
17+
}

0 commit comments

Comments
 (0)