@foxystar/molang 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 +82 -0
- package/esm/LRUCache.d.ts +6 -0
- package/esm/LRUCache.js +30 -0
- package/esm/diagnostics/error.d.ts +12 -0
- package/esm/diagnostics/error.js +37 -0
- package/esm/diagnostics/suggestions.d.ts +2 -0
- package/esm/diagnostics/suggestions.js +35 -0
- package/esm/index.d.ts +8 -0
- package/esm/index.js +6 -0
- package/esm/molang.d.ts +2 -0
- package/esm/molang.js +22 -0
- package/esm/package.json +3 -0
- package/esm/parser/expression.d.ts +87 -0
- package/esm/parser/expression.js +19 -0
- package/esm/parser/parser.d.ts +20 -0
- package/esm/parser/parser.js +490 -0
- package/esm/runtime/context.d.ts +19 -0
- package/esm/runtime/context.js +51 -0
- package/esm/runtime/math.d.ts +32 -0
- package/esm/runtime/math.js +89 -0
- package/esm/runtime/runtime.d.ts +34 -0
- package/esm/runtime/runtime.js +537 -0
- package/package.json +39 -0
- package/script/LRUCache.d.ts +6 -0
- package/script/LRUCache.js +33 -0
- package/script/diagnostics/error.d.ts +12 -0
- package/script/diagnostics/error.js +42 -0
- package/script/diagnostics/suggestions.d.ts +2 -0
- package/script/diagnostics/suggestions.js +40 -0
- package/script/index.d.ts +8 -0
- package/script/index.js +27 -0
- package/script/molang.d.ts +2 -0
- package/script/molang.js +29 -0
- package/script/package.json +3 -0
- package/script/parser/expression.d.ts +87 -0
- package/script/parser/expression.js +22 -0
- package/script/parser/parser.d.ts +20 -0
- package/script/parser/parser.js +494 -0
- package/script/runtime/context.d.ts +19 -0
- package/script/runtime/context.js +57 -0
- package/script/runtime/math.d.ts +32 -0
- package/script/runtime/math.js +92 -0
- package/script/runtime/runtime.d.ts +34 -0
- package/script/runtime/runtime.js +567 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MolangRuntimeError = exports.MolangParseError = void 0;
|
|
4
|
+
class MolangError extends Error {
|
|
5
|
+
constructor(message, start, end, source) {
|
|
6
|
+
super(MolangError.formatError(message, start, end, source));
|
|
7
|
+
this.name = this.constructor.name;
|
|
8
|
+
}
|
|
9
|
+
static formatError(message, pos, end, src) {
|
|
10
|
+
let line = 1;
|
|
11
|
+
let lastLineStart = 0;
|
|
12
|
+
for (let i = 0; i < pos; i++) {
|
|
13
|
+
if (src[i] === "\n") {
|
|
14
|
+
line++;
|
|
15
|
+
lastLineStart = i + 1;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const column = pos - lastLineStart + 1;
|
|
19
|
+
const lines = src.split("\n");
|
|
20
|
+
const lineText = lines[line - 1] ?? "";
|
|
21
|
+
//const pointer = " ".repeat(column - 1) + "^";
|
|
22
|
+
const span = Math.max(1, end - pos);
|
|
23
|
+
const underlineLength = Math.min(span, Math.max(1, lineText.length - column + 1));
|
|
24
|
+
const pointer = " ".repeat(column - 1) +
|
|
25
|
+
"^".repeat(underlineLength);
|
|
26
|
+
return (`${message} at line ${line - 1}, column ${column}\n` +
|
|
27
|
+
`${lineText}\n` +
|
|
28
|
+
`${pointer}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
class MolangParseError extends MolangError {
|
|
32
|
+
constructor(message, position, source) {
|
|
33
|
+
super(message, position, position + 1, source);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.MolangParseError = MolangParseError;
|
|
37
|
+
class MolangRuntimeError extends MolangError {
|
|
38
|
+
constructor(message, expr, source) {
|
|
39
|
+
super(message, expr.start, expr.end, source);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.MolangRuntimeError = MolangRuntimeError;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findBestMatch = exports.levenshtein = void 0;
|
|
4
|
+
function levenshtein(a, b) {
|
|
5
|
+
const dp = Array.from({ length: a.length + 1 }, () => new Array(b.length + 1).fill(0));
|
|
6
|
+
for (let i = 0; i <= a.length; i++) {
|
|
7
|
+
dp[i][0] = i;
|
|
8
|
+
}
|
|
9
|
+
for (let j = 0; j <= b.length; j++) {
|
|
10
|
+
dp[0][j] = j;
|
|
11
|
+
}
|
|
12
|
+
for (let i = 1; i <= a.length; i++) {
|
|
13
|
+
for (let j = 1; j <= b.length; j++) {
|
|
14
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
15
|
+
dp[i][j] = Math.min(dp[i - 1][j] + 1, // deletion
|
|
16
|
+
dp[i][j - 1] + 1, // insertion
|
|
17
|
+
dp[i - 1][j - 1] + cost // substitution
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return dp[a.length][b.length];
|
|
22
|
+
}
|
|
23
|
+
exports.levenshtein = levenshtein;
|
|
24
|
+
function findBestMatch(name, candidates) {
|
|
25
|
+
let best = null;
|
|
26
|
+
let bestScore = Infinity;
|
|
27
|
+
for (const c of candidates) {
|
|
28
|
+
const d = levenshtein(name.toLowerCase(), c.toLowerCase());
|
|
29
|
+
if (d < bestScore) {
|
|
30
|
+
bestScore = d;
|
|
31
|
+
best = c;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Heuristic: only suggest if it's "close enough"
|
|
35
|
+
if (best !== null && bestScore <= 2) {
|
|
36
|
+
return best;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
exports.findBestMatch = findBestMatch;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { evaluate } from "./molang.js";
|
|
2
|
+
export { MolangParser } from "./parser/parser.js";
|
|
3
|
+
export type { Expr, ExprBase, Program, Statement, Token, TokenType } from "./parser/expression.js";
|
|
4
|
+
export * from "./runtime/context.js";
|
|
5
|
+
export { MolangMath } from "./runtime/math.js";
|
|
6
|
+
export { MolangRuntime } from "./runtime/runtime.js";
|
|
7
|
+
export type { MolangOptions } from "./runtime/runtime.js";
|
|
8
|
+
export * from "./diagnostics/error.js";
|
package/script/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.MolangRuntime = exports.MolangMath = exports.MolangParser = exports.evaluate = void 0;
|
|
18
|
+
var molang_js_1 = require("./molang.js");
|
|
19
|
+
Object.defineProperty(exports, "evaluate", { enumerable: true, get: function () { return molang_js_1.evaluate; } });
|
|
20
|
+
var parser_js_1 = require("./parser/parser.js");
|
|
21
|
+
Object.defineProperty(exports, "MolangParser", { enumerable: true, get: function () { return parser_js_1.MolangParser; } });
|
|
22
|
+
__exportStar(require("./runtime/context.js"), exports);
|
|
23
|
+
var math_js_1 = require("./runtime/math.js");
|
|
24
|
+
Object.defineProperty(exports, "MolangMath", { enumerable: true, get: function () { return math_js_1.MolangMath; } });
|
|
25
|
+
var runtime_js_1 = require("./runtime/runtime.js");
|
|
26
|
+
Object.defineProperty(exports, "MolangRuntime", { enumerable: true, get: function () { return runtime_js_1.MolangRuntime; } });
|
|
27
|
+
__exportStar(require("./diagnostics/error.js"), exports);
|
package/script/molang.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.evaluate = void 0;
|
|
7
|
+
const parser_js_1 = require("./parser/parser.js");
|
|
8
|
+
const runtime_js_1 = require("./runtime/runtime.js");
|
|
9
|
+
const context_js_1 = require("./runtime/context.js");
|
|
10
|
+
const LRUCache_js_1 = __importDefault(require("./LRUCache.js"));
|
|
11
|
+
const MAX_CACHE_SIZE = 2048;
|
|
12
|
+
const cache = new LRUCache_js_1.default(MAX_CACHE_SIZE);
|
|
13
|
+
function evaluate(input, context = {}) {
|
|
14
|
+
if (context === context_js_1.DEFAULT_CONTEXT) {
|
|
15
|
+
context = (0, context_js_1.mergeContext)(context_js_1.DEFAULT_CONTEXT, {});
|
|
16
|
+
}
|
|
17
|
+
else if (!Object.prototype.isPrototypeOf.call(context_js_1.DEFAULT_CONTEXT, context)) {
|
|
18
|
+
Object.setPrototypeOf(context, context_js_1.DEFAULT_CONTEXT);
|
|
19
|
+
}
|
|
20
|
+
let program = cache.get(input);
|
|
21
|
+
if (!program) {
|
|
22
|
+
const parser = new parser_js_1.MolangParser(input);
|
|
23
|
+
program = parser.parseProgram();
|
|
24
|
+
cache.set(input, program);
|
|
25
|
+
}
|
|
26
|
+
const runtime = new runtime_js_1.MolangRuntime(context, input, { strict: false });
|
|
27
|
+
return runtime.evaluateProgram(program);
|
|
28
|
+
}
|
|
29
|
+
exports.evaluate = evaluate;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export declare const TOKEN_REGEX: RegExp;
|
|
2
|
+
export type ExprBase = {
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
};
|
|
6
|
+
export type Expr = ({
|
|
7
|
+
type: "Literal";
|
|
8
|
+
value: unknown;
|
|
9
|
+
} & ExprBase) | ({
|
|
10
|
+
type: "Identifier";
|
|
11
|
+
name: string;
|
|
12
|
+
path: string[];
|
|
13
|
+
} & ExprBase) | ({
|
|
14
|
+
type: "BinaryExpression";
|
|
15
|
+
operator: string;
|
|
16
|
+
left: Expr;
|
|
17
|
+
right: Expr;
|
|
18
|
+
} & ExprBase) | ({
|
|
19
|
+
type: "CallExpression";
|
|
20
|
+
callee: Expr;
|
|
21
|
+
arguments: Expr[];
|
|
22
|
+
} & ExprBase) | ({
|
|
23
|
+
type: "UnaryExpression";
|
|
24
|
+
operator: string;
|
|
25
|
+
expression: Expr;
|
|
26
|
+
} & ExprBase) | ({
|
|
27
|
+
type: "ArrayLiteral";
|
|
28
|
+
elements: Expr[];
|
|
29
|
+
} & ExprBase) | ({
|
|
30
|
+
type: "IndexExpression";
|
|
31
|
+
array: Expr;
|
|
32
|
+
index: Expr;
|
|
33
|
+
} & ExprBase) | ({
|
|
34
|
+
type: "ArrowExpression";
|
|
35
|
+
left: Expr;
|
|
36
|
+
right: Expr;
|
|
37
|
+
} & ExprBase) | ({
|
|
38
|
+
type: "ConditionalExpression";
|
|
39
|
+
condition: Expr;
|
|
40
|
+
then: Expr;
|
|
41
|
+
else?: Expr;
|
|
42
|
+
} & ExprBase);
|
|
43
|
+
export type Statement = ({
|
|
44
|
+
type: "ExprStatement";
|
|
45
|
+
expr: Expr;
|
|
46
|
+
} & ExprBase) | ({
|
|
47
|
+
type: "AssignStatement";
|
|
48
|
+
target: Expr;
|
|
49
|
+
value: Expr;
|
|
50
|
+
} & ExprBase) | ({
|
|
51
|
+
type: "ReturnStatement";
|
|
52
|
+
value?: Expr;
|
|
53
|
+
} & ExprBase) | ({
|
|
54
|
+
type: "BreakStatement";
|
|
55
|
+
} & ExprBase) | ({
|
|
56
|
+
type: "ContinueStatement";
|
|
57
|
+
} & ExprBase) | ({
|
|
58
|
+
type: "LoopStatement";
|
|
59
|
+
count: Expr;
|
|
60
|
+
body: Statement;
|
|
61
|
+
} & ExprBase) | ({
|
|
62
|
+
type: "ForEachStatement";
|
|
63
|
+
iterator: Expr;
|
|
64
|
+
iterable: Expr;
|
|
65
|
+
body: Statement;
|
|
66
|
+
} & ExprBase) | ({
|
|
67
|
+
type: "ConditionalStatement";
|
|
68
|
+
condition: Expr;
|
|
69
|
+
then: Statement;
|
|
70
|
+
else?: Statement;
|
|
71
|
+
} & ExprBase) | ({
|
|
72
|
+
type: "BlockStatement";
|
|
73
|
+
body: Statement[];
|
|
74
|
+
} & ExprBase);
|
|
75
|
+
export type Program = {
|
|
76
|
+
type: "Program";
|
|
77
|
+
body: Statement[];
|
|
78
|
+
start: number;
|
|
79
|
+
end: number;
|
|
80
|
+
};
|
|
81
|
+
export type TokenType = "number" | "string" | "identifier" | "assignment" | "operator" | "parenthesis" | "brace" | "comma" | "bracket" | "semicolon" | "eof";
|
|
82
|
+
export type Token = {
|
|
83
|
+
type: TokenType;
|
|
84
|
+
value: string;
|
|
85
|
+
start: number;
|
|
86
|
+
end: number;
|
|
87
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TOKEN_REGEX = void 0;
|
|
4
|
+
exports.TOKEN_REGEX = new RegExp([
|
|
5
|
+
// number
|
|
6
|
+
"^(?<number>-?\\d+(?:\\.\\d+)?)",
|
|
7
|
+
// string (double OR single quotes)
|
|
8
|
+
"(?<string>\"[^\"]*\"|'[^']*')",
|
|
9
|
+
// identifier + dotted path
|
|
10
|
+
"(?<identifier>[a-zA-Z_][a-zA-Z0-9_]*(?:\\.[a-zA-Z_][a-zA-Z0-9_]*)*)",
|
|
11
|
+
"(?<assignment>=(?!=))",
|
|
12
|
+
"(?<operator>\\?\\?|->|>>>|>>|<<|\\|\\||&&|==|!=|<=|>=|\\^|\\||&|\\?|:|[+\\-*/<>!])",
|
|
13
|
+
// grouping
|
|
14
|
+
"(?<parenthesis>[()])",
|
|
15
|
+
"(?<bracket>[\\[\\]])",
|
|
16
|
+
"(?<brace>[{}])",
|
|
17
|
+
// punctuation
|
|
18
|
+
"(?<comma>,)",
|
|
19
|
+
"(?<semicolon>;)",
|
|
20
|
+
// whitespace
|
|
21
|
+
"(?<whitespace>\\s+)"
|
|
22
|
+
].join("|^"));
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Program } from "./expression.js";
|
|
2
|
+
export declare class MolangParser {
|
|
3
|
+
private input;
|
|
4
|
+
private tokens;
|
|
5
|
+
private position;
|
|
6
|
+
constructor(input: string);
|
|
7
|
+
private tokenize;
|
|
8
|
+
private peek;
|
|
9
|
+
private consume;
|
|
10
|
+
parseProgram(): Program;
|
|
11
|
+
private parseStatement;
|
|
12
|
+
private parseExpression;
|
|
13
|
+
private parseBinaryExpression;
|
|
14
|
+
private tryFold;
|
|
15
|
+
private getOperatorPrecedence;
|
|
16
|
+
private parseConditionalExpression;
|
|
17
|
+
private parsePrimaryExpression;
|
|
18
|
+
private parseUnary;
|
|
19
|
+
private parseAtom;
|
|
20
|
+
}
|