@flomsstaar/expression-tree 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -0
- package/build/example.d.ts +1 -0
- package/build/example.js +18 -0
- package/build/index.d.ts +16 -0
- package/build/index.js +16 -0
- package/build/src/enums/binary_node_operator.d.ts +7 -0
- package/build/src/enums/binary_node_operator.js +8 -0
- package/build/src/enums/node_type.d.ts +6 -0
- package/build/src/enums/node_type.js +7 -0
- package/build/src/enums/unary_node_operator.d.ts +5 -0
- package/build/src/enums/unary_node_operator.js +6 -0
- package/build/src/errors/division_by_zero_error.d.ts +3 -0
- package/build/src/errors/division_by_zero_error.js +6 -0
- package/build/src/errors/invalid_expression_error.d.ts +3 -0
- package/build/src/errors/invalid_expression_error.js +6 -0
- package/build/src/errors/invalid_number_error.d.ts +4 -0
- package/build/src/errors/invalid_number_error.js +8 -0
- package/build/src/errors/invalid_square_root_error.d.ts +3 -0
- package/build/src/errors/invalid_square_root_error.js +6 -0
- package/build/src/errors/missing_parenthese_error.d.ts +3 -0
- package/build/src/errors/missing_parenthese_error.js +6 -0
- package/build/src/errors/unknown_binary_operator_error.d.ts +3 -0
- package/build/src/errors/unknown_binary_operator_error.js +6 -0
- package/build/src/errors/unknown_node_type_error.d.ts +3 -0
- package/build/src/errors/unknown_node_type_error.js +6 -0
- package/build/src/errors/unknown_unary_operator_error.d.ts +3 -0
- package/build/src/errors/unknown_unary_operator_error.js +6 -0
- package/build/src/expression_cutter.d.ts +4 -0
- package/build/src/expression_cutter.js +7 -0
- package/build/src/expression_evaluator.d.ts +10 -0
- package/build/src/expression_evaluator.js +74 -0
- package/build/src/expression_parser.d.ts +14 -0
- package/build/src/expression_parser.js +94 -0
- package/build/src/expression_tree.d.ts +10 -0
- package/build/src/expression_tree.js +18 -0
- package/build/src/index.d.ts +1 -0
- package/build/src/index.js +1 -0
- package/build/src/models/base_node.d.ts +5 -0
- package/build/src/models/base_node.js +6 -0
- package/build/src/models/binary_node.d.ts +8 -0
- package/build/src/models/binary_node.js +13 -0
- package/build/src/models/number_node.d.ts +6 -0
- package/build/src/models/number_node.js +12 -0
- package/build/src/models/unary_node.d.ts +7 -0
- package/build/src/models/unary_node.js +11 -0
- package/build/src/render_expression.d.ts +2 -0
- package/build/src/render_expression.js +56 -0
- package/build/tests/expression_cutter.test.d.ts +1 -0
- package/build/tests/expression_cutter.test.js +9 -0
- package/build/tests/expression_evaluator.test.d.ts +1 -0
- package/build/tests/expression_evaluator.test.js +110 -0
- package/build/tests/expression_parser.test.d.ts +1 -0
- package/build/tests/expression_parser.test.js +44 -0
- package/build/tests/expression_tree.test.d.ts +1 -0
- package/build/tests/expression_tree.test.js +12 -0
- package/build/tests/inputs/expression_cutter_input.d.ts +1 -0
- package/build/tests/inputs/expression_cutter_input.js +230 -0
- package/build/tests/inputs/expression_parser_input.d.ts +2 -0
- package/build/tests/inputs/expression_parser_input.js +197 -0
- package/build/tests/inputs/expression_tree_input.d.ts +1 -0
- package/build/tests/inputs/expression_tree_input.js +44 -0
- package/build/tests/number_node.test.d.ts +1 -0
- package/build/tests/number_node.test.js +16 -0
- package/build/tests/render_expression.test.d.ts +1 -0
- package/build/tests/render_expression.test.js +85 -0
- package/build/vitest.config.d.ts +2 -0
- package/build/vitest.config.js +10 -0
- package/package.json +47 -0
- package/src/enums/binary_node_operator.ts +7 -0
- package/src/enums/node_type.ts +6 -0
- package/src/enums/unary_node_operator.ts +5 -0
- package/src/errors/division_by_zero_error.ts +6 -0
- package/src/errors/invalid_expression_error.ts +6 -0
- package/src/errors/invalid_number_error.ts +6 -0
- package/src/errors/invalid_square_root_error.ts +6 -0
- package/src/errors/missing_parenthese_error.ts +6 -0
- package/src/errors/unknown_binary_operator_error.ts +6 -0
- package/src/errors/unknown_node_type_error.ts +6 -0
- package/src/errors/unknown_unary_operator_error.ts +6 -0
- package/src/expression_cutter.ts +9 -0
- package/src/expression_evaluator.ts +76 -0
- package/src/expression_parser.ts +117 -0
- package/src/expression_tree.ts +19 -0
- package/src/models/base_node.ts +5 -0
- package/src/models/binary_node.ts +13 -0
- package/src/models/number_node.ts +12 -0
- package/src/models/unary_node.ts +12 -0
- package/src/render_expression.ts +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# expression-tree
|
|
2
|
+
|
|
3
|
+
[](https://sonarqube.florentmarques.fr/dashboard?id=expression-tree)
|
|
4
|
+
[](https://sonarqube.florentmarques.fr/dashboard?id=expression-tree)
|
|
5
|
+
[](https://sonarqube.florentmarques.fr/dashboard?id=expression-tree)
|
|
6
|
+
|
|
7
|
+
## Concept
|
|
8
|
+
|
|
9
|
+
This is a simple expression tree implementation in TypeScript. It allows you to parse mathematical expressions and evaluate them using a tree structure.
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- [x] Parse mathematical expressions into a tree structure.
|
|
16
|
+
- [x] Evaluate expressions using the tree.
|
|
17
|
+
- [x] Support for basic arithmetic operations
|
|
18
|
+
- [x] addition
|
|
19
|
+
- [x] subtraction
|
|
20
|
+
- [x] multiplication
|
|
21
|
+
- [x] division
|
|
22
|
+
- [x] exponentiation
|
|
23
|
+
- [x] unary minus
|
|
24
|
+
- [x] parentheses
|
|
25
|
+
- [x] operator precedence
|
|
26
|
+
- [x] operator associativity
|
|
27
|
+
- [ ] square root
|
|
28
|
+
- [ ] absolute value
|
|
29
|
+
- [ ] trigonometric functions (sin, cos, tan)
|
|
30
|
+
- [ ] logarithm
|
|
31
|
+
|
|
32
|
+
## Example
|
|
33
|
+
|
|
34
|
+
```shell
|
|
35
|
+
$ bun run index.ts
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Output:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
-------------------
|
|
42
|
+
expected: 6 - -2 + 5 = 13
|
|
43
|
+
actual: 6 - -2 + 5 = 13
|
|
44
|
+
same ? true
|
|
45
|
+
-------------------
|
|
46
|
+
expected: 6 + -(2 + 5) = -1
|
|
47
|
+
actual: 6 + -(2 + 5) = -1
|
|
48
|
+
same ? true
|
|
49
|
+
-------------------
|
|
50
|
+
expected: 6 + -2 * 5 = -4
|
|
51
|
+
actual: 6 + -2 * 5 = -4
|
|
52
|
+
same ? true
|
|
53
|
+
-------------------
|
|
54
|
+
expected: 6 + 4 / 2 * 5 = 16
|
|
55
|
+
actual: 6 + 4 / 2 * 5 = 16
|
|
56
|
+
same ? true
|
|
57
|
+
-------------------
|
|
58
|
+
expected: 6 + -(2 * 5) = -4
|
|
59
|
+
actual: 6 + -(2 * 5) = -4
|
|
60
|
+
same ? true
|
|
61
|
+
-------------------
|
|
62
|
+
expected: 6 + 2 * 3 - 1 = 11
|
|
63
|
+
actual: 6 + 2 * 3 - 1 = 11
|
|
64
|
+
same ? true
|
|
65
|
+
-------------------
|
|
66
|
+
expected: 6 + 2 * 3 - 1 + 2 ^ 2 = 15
|
|
67
|
+
actual: 6 + 2 * 3 - 1 + 2 ^ 2 = 15
|
|
68
|
+
same ? true
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Development
|
|
72
|
+
|
|
73
|
+
To install dependencies:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
bun install
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
To run:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
bun run index.ts
|
|
83
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/build/example.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ExpressionTree } from './src/expression_tree.js';
|
|
2
|
+
function testExpression(expression, expectedResult) {
|
|
3
|
+
const expressionTree = new ExpressionTree();
|
|
4
|
+
console.log('-------------------');
|
|
5
|
+
const expected = `${expression} = ${expectedResult}`;
|
|
6
|
+
const actual = `${expression} = ${expressionTree.evaluate(expression)}`;
|
|
7
|
+
console.log('expected:', expected);
|
|
8
|
+
console.log('actual: ', actual);
|
|
9
|
+
console.log('same ? ', expected === actual);
|
|
10
|
+
}
|
|
11
|
+
// testExpression('sqrt(6 + 4 / 2 * 5)', 4)
|
|
12
|
+
testExpression('6 - -2 + 5', 13);
|
|
13
|
+
testExpression('6 + -(2 + 5)', -1);
|
|
14
|
+
testExpression('6 + -2 * 5', -4);
|
|
15
|
+
testExpression('6 + 4 / 2 * 5', 16);
|
|
16
|
+
testExpression('6 + -(2 * 5)', -4);
|
|
17
|
+
testExpression('6 + 2 * 3 - 1', 11);
|
|
18
|
+
testExpression('6 + 2 * 3 - 1 + 2 ^ 2', 15);
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { ExpressionTree } from './src/expression_tree.js';
|
|
2
|
+
export { ExpressionParser } from './src/expression_parser.js';
|
|
3
|
+
export { ExpressionEvaluator } from './src/expression_evaluator.js';
|
|
4
|
+
export { ExpressionCutter } from './src/expression_cutter.js';
|
|
5
|
+
export { InvalidExpressionError } from './src/errors/invalid_expression_error.js';
|
|
6
|
+
export { InvalidNumberError } from './src/errors/invalid_number_error.js';
|
|
7
|
+
export { MissingClosingParenthesisError } from './src/errors/missing_parenthese_error.js';
|
|
8
|
+
export { UnknownBinaryOperatorError } from './src/errors/unknown_binary_operator_error.js';
|
|
9
|
+
export { UnknownUnaryOperatorError } from './src/errors/unknown_unary_operator_error.js';
|
|
10
|
+
export { DivisionByZeroError } from './src/errors/division_by_zero_error.js';
|
|
11
|
+
export { NegativeSquareRootError } from './src/errors/invalid_square_root_error.js';
|
|
12
|
+
export { UnknownNodeTypeError } from './src/errors/unknown_node_type_error.js';
|
|
13
|
+
export { BaseNode } from './src/models/base_node.js';
|
|
14
|
+
export { BinaryNode } from './src/models/binary_node.js';
|
|
15
|
+
export { UnaryNode } from './src/models/unary_node.js';
|
|
16
|
+
export { NumberNode } from './src/models/number_node.js';
|
package/build/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { ExpressionTree } from './src/expression_tree.js';
|
|
2
|
+
export { ExpressionParser } from './src/expression_parser.js';
|
|
3
|
+
export { ExpressionEvaluator } from './src/expression_evaluator.js';
|
|
4
|
+
export { ExpressionCutter } from './src/expression_cutter.js';
|
|
5
|
+
export { InvalidExpressionError } from './src/errors/invalid_expression_error.js';
|
|
6
|
+
export { InvalidNumberError } from './src/errors/invalid_number_error.js';
|
|
7
|
+
export { MissingClosingParenthesisError } from './src/errors/missing_parenthese_error.js';
|
|
8
|
+
export { UnknownBinaryOperatorError } from './src/errors/unknown_binary_operator_error.js';
|
|
9
|
+
export { UnknownUnaryOperatorError } from './src/errors/unknown_unary_operator_error.js';
|
|
10
|
+
export { DivisionByZeroError } from './src/errors/division_by_zero_error.js';
|
|
11
|
+
export { NegativeSquareRootError } from './src/errors/invalid_square_root_error.js';
|
|
12
|
+
export { UnknownNodeTypeError } from './src/errors/unknown_node_type_error.js';
|
|
13
|
+
export { BaseNode } from './src/models/base_node.js';
|
|
14
|
+
export { BinaryNode } from './src/models/binary_node.js';
|
|
15
|
+
export { UnaryNode } from './src/models/unary_node.js';
|
|
16
|
+
export { NumberNode } from './src/models/number_node.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export var BinaryNodeOperator;
|
|
2
|
+
(function (BinaryNodeOperator) {
|
|
3
|
+
BinaryNodeOperator["SUM"] = "addition";
|
|
4
|
+
BinaryNodeOperator["SUBTRACT"] = "subtraction";
|
|
5
|
+
BinaryNodeOperator["MULTIPLY"] = "multiplication";
|
|
6
|
+
BinaryNodeOperator["DIVIDE"] = "division";
|
|
7
|
+
BinaryNodeOperator["POWER"] = "power";
|
|
8
|
+
})(BinaryNodeOperator || (BinaryNodeOperator = {}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BinaryNode } from './models/binary_node.js';
|
|
2
|
+
import type { BaseNode } from './models/base_node.js';
|
|
3
|
+
import { UnaryNode } from './models/unary_node.js';
|
|
4
|
+
import { NumberNode } from './models/number_node.js';
|
|
5
|
+
export declare class ExpressionEvaluator {
|
|
6
|
+
evaluate(node: BaseNode): number;
|
|
7
|
+
protected evaluateBinaryNode(node: BinaryNode): number;
|
|
8
|
+
protected evaluateUnaryNode(node: UnaryNode): number;
|
|
9
|
+
protected evaluateNumberNode(node: NumberNode): number;
|
|
10
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { BinaryNode } from './models/binary_node.js';
|
|
2
|
+
import { UnaryNode } from './models/unary_node.js';
|
|
3
|
+
import { NumberNode } from './models/number_node.js';
|
|
4
|
+
import { UnknownNodeTypeError } from './errors/unknown_node_type_error.js';
|
|
5
|
+
import { BinaryNodeOperator } from './enums/binary_node_operator.js';
|
|
6
|
+
import { UnaryNodeOperator } from './enums/unary_node_operator.js';
|
|
7
|
+
import { NegativeSquareRootError } from './errors/invalid_square_root_error.js';
|
|
8
|
+
import { UnknownUnaryOperatorError } from './errors/unknown_unary_operator_error.js';
|
|
9
|
+
import { UnknownBinaryOperatorError } from './errors/unknown_binary_operator_error.js';
|
|
10
|
+
import { DivisionByZeroError } from './errors/division_by_zero_error.js';
|
|
11
|
+
export class ExpressionEvaluator {
|
|
12
|
+
evaluate(node) {
|
|
13
|
+
if (node instanceof BinaryNode) {
|
|
14
|
+
return this.evaluateBinaryNode(node);
|
|
15
|
+
}
|
|
16
|
+
else if (node instanceof UnaryNode) {
|
|
17
|
+
return this.evaluateUnaryNode(node);
|
|
18
|
+
}
|
|
19
|
+
else if (node instanceof NumberNode) {
|
|
20
|
+
return this.evaluateNumberNode(node);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
throw new UnknownNodeTypeError(node.type);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
evaluateBinaryNode(node) {
|
|
27
|
+
switch (node.operator) {
|
|
28
|
+
case BinaryNodeOperator.SUM: {
|
|
29
|
+
return this.evaluate(node.left) + this.evaluate(node.right);
|
|
30
|
+
}
|
|
31
|
+
case BinaryNodeOperator.SUBTRACT: {
|
|
32
|
+
return this.evaluate(node.left) - this.evaluate(node.right);
|
|
33
|
+
}
|
|
34
|
+
case BinaryNodeOperator.MULTIPLY: {
|
|
35
|
+
return this.evaluate(node.left) * this.evaluate(node.right);
|
|
36
|
+
}
|
|
37
|
+
case BinaryNodeOperator.DIVIDE: {
|
|
38
|
+
const leftValue = this.evaluate(node.left);
|
|
39
|
+
const rightValue = this.evaluate(node.right);
|
|
40
|
+
if (rightValue === 0) {
|
|
41
|
+
throw new DivisionByZeroError();
|
|
42
|
+
}
|
|
43
|
+
return leftValue / rightValue;
|
|
44
|
+
}
|
|
45
|
+
case BinaryNodeOperator.POWER: {
|
|
46
|
+
return Math.pow(this.evaluate(node.left), this.evaluate(node.right));
|
|
47
|
+
}
|
|
48
|
+
default:
|
|
49
|
+
throw new UnknownBinaryOperatorError(node.operator);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
evaluateUnaryNode(node) {
|
|
53
|
+
switch (node.operator) {
|
|
54
|
+
case UnaryNodeOperator.NEGATE: {
|
|
55
|
+
return -this.evaluate(node.value);
|
|
56
|
+
}
|
|
57
|
+
case UnaryNodeOperator.ABSOLUTE: {
|
|
58
|
+
return Math.abs(this.evaluate(node.value));
|
|
59
|
+
}
|
|
60
|
+
case UnaryNodeOperator.SQUARE_ROOT: {
|
|
61
|
+
const leftValue = this.evaluate(node.value);
|
|
62
|
+
if (leftValue < 0) {
|
|
63
|
+
throw new NegativeSquareRootError();
|
|
64
|
+
}
|
|
65
|
+
return Math.sqrt(leftValue);
|
|
66
|
+
}
|
|
67
|
+
default:
|
|
68
|
+
throw new UnknownUnaryOperatorError(node.operator);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
evaluateNumberNode(node) {
|
|
72
|
+
return node.value;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseNode } from './models/base_node.js';
|
|
2
|
+
import { BinaryNodeOperator } from './enums/binary_node_operator.js';
|
|
3
|
+
export declare class ExpressionParser {
|
|
4
|
+
protected tokens: string[];
|
|
5
|
+
protected pos: number;
|
|
6
|
+
protected peek(): string | null;
|
|
7
|
+
protected consume(): string;
|
|
8
|
+
protected match(expected: string[]): string | null;
|
|
9
|
+
parse(expression: string[]): BaseNode;
|
|
10
|
+
protected parseExpression(): BaseNode;
|
|
11
|
+
protected parseTerm(): BaseNode;
|
|
12
|
+
protected parseFactor(): BaseNode;
|
|
13
|
+
protected mapRowOperator(operator: string): BinaryNodeOperator;
|
|
14
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { InvalidExpressionError } from './errors/invalid_expression_error.js';
|
|
2
|
+
import { BinaryNodeOperator } from './enums/binary_node_operator.js';
|
|
3
|
+
import { UnknownBinaryOperatorError } from './errors/unknown_binary_operator_error.js';
|
|
4
|
+
import { NumberNode } from './models/number_node.js';
|
|
5
|
+
import { UnaryNode } from './models/unary_node.js';
|
|
6
|
+
import { UnaryNodeOperator } from './enums/unary_node_operator.js';
|
|
7
|
+
import { MissingClosingParenthesisError } from './errors/missing_parenthese_error.js';
|
|
8
|
+
import { InvalidNumberError } from './errors/invalid_number_error.js';
|
|
9
|
+
import { BinaryNode } from './models/binary_node.js';
|
|
10
|
+
export class ExpressionParser {
|
|
11
|
+
tokens = [];
|
|
12
|
+
pos = 0;
|
|
13
|
+
peek() {
|
|
14
|
+
return this.tokens[this.pos] ?? null;
|
|
15
|
+
}
|
|
16
|
+
consume() {
|
|
17
|
+
if (this.pos >= this.tokens.length) {
|
|
18
|
+
throw new InvalidExpressionError();
|
|
19
|
+
}
|
|
20
|
+
return this.tokens[this.pos++];
|
|
21
|
+
}
|
|
22
|
+
match(expected) {
|
|
23
|
+
const token = this.peek();
|
|
24
|
+
if (token && expected.includes(token)) {
|
|
25
|
+
this.consume();
|
|
26
|
+
return token;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
parse(expression) {
|
|
31
|
+
this.tokens = [...expression];
|
|
32
|
+
this.pos = 0;
|
|
33
|
+
const node = this.parseExpression();
|
|
34
|
+
if (this.pos < this.tokens.length) {
|
|
35
|
+
throw new InvalidExpressionError();
|
|
36
|
+
}
|
|
37
|
+
return node;
|
|
38
|
+
}
|
|
39
|
+
parseExpression() {
|
|
40
|
+
let node = this.parseTerm();
|
|
41
|
+
while (this.match(['+', '-'])) {
|
|
42
|
+
const operator = this.mapRowOperator(this.tokens[this.pos - 1]);
|
|
43
|
+
const right = this.parseTerm();
|
|
44
|
+
node = new BinaryNode(operator, node, right);
|
|
45
|
+
}
|
|
46
|
+
return node;
|
|
47
|
+
}
|
|
48
|
+
parseTerm() {
|
|
49
|
+
let node = this.parseFactor();
|
|
50
|
+
while (this.match(['^', '*', '/'])) {
|
|
51
|
+
const operator = this.mapRowOperator(this.tokens[this.pos - 1]);
|
|
52
|
+
const right = this.parseFactor();
|
|
53
|
+
node = new BinaryNode(operator, node, right);
|
|
54
|
+
}
|
|
55
|
+
return node;
|
|
56
|
+
}
|
|
57
|
+
parseFactor() {
|
|
58
|
+
const token = this.peek();
|
|
59
|
+
if (token === '-') {
|
|
60
|
+
this.consume(); // consume '-'
|
|
61
|
+
const value = this.parseFactor();
|
|
62
|
+
return new UnaryNode(UnaryNodeOperator.NEGATE, value);
|
|
63
|
+
}
|
|
64
|
+
if (token === '(') {
|
|
65
|
+
this.consume(); // consume '('
|
|
66
|
+
const node = this.parseExpression();
|
|
67
|
+
if (this.consume() !== ')') {
|
|
68
|
+
throw new MissingClosingParenthesisError();
|
|
69
|
+
}
|
|
70
|
+
return node;
|
|
71
|
+
}
|
|
72
|
+
const value = Number(this.consume());
|
|
73
|
+
if (Number.isNaN(value)) {
|
|
74
|
+
throw new InvalidNumberError(token);
|
|
75
|
+
}
|
|
76
|
+
return new NumberNode(value);
|
|
77
|
+
}
|
|
78
|
+
mapRowOperator(operator) {
|
|
79
|
+
switch (operator) {
|
|
80
|
+
case '+':
|
|
81
|
+
return BinaryNodeOperator.SUM;
|
|
82
|
+
case '-':
|
|
83
|
+
return BinaryNodeOperator.SUBTRACT;
|
|
84
|
+
case '*':
|
|
85
|
+
return BinaryNodeOperator.MULTIPLY;
|
|
86
|
+
case '/':
|
|
87
|
+
return BinaryNodeOperator.DIVIDE;
|
|
88
|
+
case '^':
|
|
89
|
+
return BinaryNodeOperator.POWER;
|
|
90
|
+
default:
|
|
91
|
+
throw new UnknownBinaryOperatorError(operator);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ExpressionCutter } from './expression_cutter.js';
|
|
2
|
+
import { ExpressionParser } from './expression_parser.js';
|
|
3
|
+
import { ExpressionEvaluator } from './expression_evaluator.js';
|
|
4
|
+
export declare class ExpressionTree {
|
|
5
|
+
protected cutter: ExpressionCutter;
|
|
6
|
+
protected parser: ExpressionParser;
|
|
7
|
+
protected evaluator: ExpressionEvaluator;
|
|
8
|
+
constructor(cutter?: ExpressionCutter, parser?: ExpressionParser, evaluator?: ExpressionEvaluator);
|
|
9
|
+
evaluate(expression: string): number;
|
|
10
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ExpressionCutter } from './expression_cutter.js';
|
|
2
|
+
import { ExpressionParser } from './expression_parser.js';
|
|
3
|
+
import { ExpressionEvaluator } from './expression_evaluator.js';
|
|
4
|
+
export class ExpressionTree {
|
|
5
|
+
cutter;
|
|
6
|
+
parser;
|
|
7
|
+
evaluator;
|
|
8
|
+
constructor(cutter = new ExpressionCutter(), parser = new ExpressionParser(), evaluator = new ExpressionEvaluator()) {
|
|
9
|
+
this.cutter = cutter;
|
|
10
|
+
this.parser = parser;
|
|
11
|
+
this.evaluator = evaluator;
|
|
12
|
+
}
|
|
13
|
+
evaluate(expression) {
|
|
14
|
+
const cutExpression = this.cutter.cut(expression);
|
|
15
|
+
const baseNode = this.parser.parse(cutExpression);
|
|
16
|
+
return this.evaluator.evaluate(baseNode);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BaseNode } from './base_node.js';
|
|
2
|
+
import { BinaryNodeOperator } from '../enums/binary_node_operator.js';
|
|
3
|
+
export declare class BinaryNode extends BaseNode {
|
|
4
|
+
operator: BinaryNodeOperator;
|
|
5
|
+
left: BaseNode;
|
|
6
|
+
right: BaseNode;
|
|
7
|
+
constructor(operator: BinaryNodeOperator, left: BaseNode, right: BaseNode);
|
|
8
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseNode } from './base_node.js';
|
|
2
|
+
import { NodeType } from '../enums/node_type.js';
|
|
3
|
+
export class BinaryNode extends BaseNode {
|
|
4
|
+
operator;
|
|
5
|
+
left;
|
|
6
|
+
right;
|
|
7
|
+
constructor(operator, left, right) {
|
|
8
|
+
super(NodeType.BINARY);
|
|
9
|
+
this.operator = operator;
|
|
10
|
+
this.left = left;
|
|
11
|
+
this.right = right;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseNode } from './base_node.js';
|
|
2
|
+
import { NodeType } from '../enums/node_type.js';
|
|
3
|
+
export class NumberNode extends BaseNode {
|
|
4
|
+
value;
|
|
5
|
+
constructor(value) {
|
|
6
|
+
super(NodeType.NUMBER);
|
|
7
|
+
this.value = value;
|
|
8
|
+
}
|
|
9
|
+
toString() {
|
|
10
|
+
return this.value.toString();
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BaseNode } from './base_node.js';
|
|
2
|
+
import type { UnaryNodeOperator } from '../enums/unary_node_operator.js';
|
|
3
|
+
export declare class UnaryNode extends BaseNode {
|
|
4
|
+
operator: UnaryNodeOperator;
|
|
5
|
+
value: BaseNode;
|
|
6
|
+
constructor(operator: UnaryNodeOperator, value: BaseNode);
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseNode } from './base_node.js';
|
|
2
|
+
import { NodeType } from '../enums/node_type.js';
|
|
3
|
+
export class UnaryNode extends BaseNode {
|
|
4
|
+
operator;
|
|
5
|
+
value;
|
|
6
|
+
constructor(operator, value) {
|
|
7
|
+
super(NodeType.UNARY);
|
|
8
|
+
this.operator = operator;
|
|
9
|
+
this.value = value;
|
|
10
|
+
}
|
|
11
|
+
}
|