mimo-lang 1.1.1 → 2.0.6
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/.gitattributes +24 -0
- package/LICENSE +21 -0
- package/README.md +71 -39
- package/adapters/browserAdapter.js +86 -0
- package/adapters/nodeAdapter.js +101 -0
- package/bin/cli.js +80 -0
- package/bin/commands/convert.js +27 -0
- package/bin/commands/doctor.js +139 -0
- package/bin/commands/eval.js +39 -0
- package/bin/commands/fmt.js +109 -0
- package/bin/commands/help.js +72 -0
- package/bin/commands/lint.js +117 -0
- package/bin/commands/repl.js +24 -0
- package/bin/commands/run.js +64 -0
- package/bin/commands/test.js +126 -0
- package/bin/utils/colors.js +38 -0
- package/bin/utils/formatError.js +47 -0
- package/bin/utils/fs.js +57 -0
- package/bin/utils/version.js +8 -0
- package/build.js +18 -0
- package/bun.lock +74 -0
- package/index.js +48 -77
- package/index.web.js +364 -0
- package/interpreter/BuiltinFunction.js +32 -0
- package/interpreter/ErrorHandler.js +120 -0
- package/interpreter/ExpressionEvaluator.js +106 -0
- package/interpreter/Interpreter.js +172 -0
- package/interpreter/MimoError.js +112 -0
- package/interpreter/ModuleLoader.js +236 -0
- package/interpreter/StatementExecutor.js +107 -0
- package/interpreter/Utils.js +82 -0
- package/interpreter/Values.js +87 -0
- package/interpreter/coreBuiltins.js +490 -0
- package/interpreter/environment.js +99 -0
- package/interpreter/evaluators/binaryExpressionEvaluator.js +111 -0
- package/interpreter/evaluators/collectionEvaluator.js +151 -0
- package/interpreter/evaluators/functionCallEvaluator.js +76 -0
- package/interpreter/evaluators/literalEvaluator.js +27 -0
- package/interpreter/evaluators/moduleAccessEvaluator.js +25 -0
- package/interpreter/evaluators/templateLiteralEvaluator.js +20 -0
- package/interpreter/executors/BaseExecutor.js +37 -0
- package/interpreter/executors/ControlFlowExecutor.js +206 -0
- package/interpreter/executors/FunctionExecutor.js +126 -0
- package/interpreter/executors/PatternMatchExecutor.js +93 -0
- package/interpreter/executors/VariableExecutor.js +144 -0
- package/interpreter/index.js +8 -0
- package/interpreter/stdlib/array/accessFunctions.js +61 -0
- package/interpreter/stdlib/array/arrayUtils.js +36 -0
- package/interpreter/stdlib/array/higherOrderFunctions.js +285 -0
- package/interpreter/stdlib/array/searchFunctions.js +77 -0
- package/interpreter/stdlib/array/setFunctions.js +49 -0
- package/interpreter/stdlib/array/transformationFunctions.js +68 -0
- package/interpreter/stdlib/array.js +85 -0
- package/interpreter/stdlib/assert.js +143 -0
- package/interpreter/stdlib/datetime.js +170 -0
- package/interpreter/stdlib/env.js +54 -0
- package/interpreter/stdlib/fs.js +161 -0
- package/interpreter/stdlib/http.js +92 -0
- package/interpreter/stdlib/json.js +70 -0
- package/interpreter/stdlib/math.js +309 -0
- package/interpreter/stdlib/object.js +142 -0
- package/interpreter/stdlib/path.js +69 -0
- package/interpreter/stdlib/regex.js +134 -0
- package/interpreter/stdlib/string.js +260 -0
- package/interpreter/suggestions.js +46 -0
- package/lexer/Lexer.js +245 -0
- package/lexer/TokenTypes.js +131 -0
- package/lexer/createToken.js +11 -0
- package/lexer/tokenizers/commentTokenizer.js +45 -0
- package/lexer/tokenizers/literalTokenizer.js +163 -0
- package/lexer/tokenizers/symbolTokenizer.js +69 -0
- package/lexer/tokenizers/whitespaceTokenizer.js +36 -0
- package/package.json +29 -13
- package/parser/ASTNodes.js +448 -0
- package/parser/Parser.js +188 -0
- package/parser/expressions/atomicExpressions.js +165 -0
- package/parser/expressions/conditionalExpressions.js +0 -0
- package/parser/expressions/operatorExpressions.js +79 -0
- package/parser/expressions/primaryExpressions.js +77 -0
- package/parser/parseStatement.js +184 -0
- package/parser/parserExpressions.js +115 -0
- package/parser/parserUtils.js +19 -0
- package/parser/statements/controlFlowParsers.js +106 -0
- package/parser/statements/functionParsers.js +314 -0
- package/parser/statements/moduleParsers.js +57 -0
- package/parser/statements/patternMatchParsers.js +124 -0
- package/parser/statements/variableParsers.js +155 -0
- package/repl.js +325 -0
- package/test.js +47 -0
- package/tools/PrettyPrinter.js +3 -0
- package/tools/convert/Args.js +46 -0
- package/tools/convert/Registry.js +91 -0
- package/tools/convert/Transpiler.js +78 -0
- package/tools/convert/plugins/README.md +66 -0
- package/tools/convert/plugins/alya/index.js +10 -0
- package/tools/convert/plugins/alya/to_alya.js +289 -0
- package/tools/convert/plugins/alya/visitors/expressions.js +257 -0
- package/tools/convert/plugins/alya/visitors/statements.js +403 -0
- package/tools/convert/plugins/base_converter.js +228 -0
- package/tools/convert/plugins/javascript/index.js +10 -0
- package/tools/convert/plugins/javascript/mimo_runtime.js +265 -0
- package/tools/convert/plugins/javascript/to_js.js +155 -0
- package/tools/convert/plugins/javascript/visitors/expressions.js +197 -0
- package/tools/convert/plugins/javascript/visitors/patterns.js +102 -0
- package/tools/convert/plugins/javascript/visitors/statements.js +236 -0
- package/tools/convert/plugins/python/index.js +10 -0
- package/tools/convert/plugins/python/mimo_runtime.py +811 -0
- package/tools/convert/plugins/python/to_py.js +329 -0
- package/tools/convert/plugins/python/visitors/expressions.js +272 -0
- package/tools/convert/plugins/python/visitors/patterns.js +100 -0
- package/tools/convert/plugins/python/visitors/statements.js +257 -0
- package/tools/convert.js +102 -0
- package/tools/format/CommentAttacher.js +190 -0
- package/tools/format/CommentLexer.js +152 -0
- package/tools/format/Printer.js +849 -0
- package/tools/format/config.js +107 -0
- package/tools/formatter.js +169 -0
- package/tools/lint/Linter.js +391 -0
- package/tools/lint/config.js +114 -0
- package/tools/lint/rules/consistent-return.js +62 -0
- package/tools/lint/rules/max-depth.js +56 -0
- package/tools/lint/rules/no-empty-function.js +45 -0
- package/tools/lint/rules/no-magic-numbers.js +46 -0
- package/tools/lint/rules/no-shadow.js +113 -0
- package/tools/lint/rules/no-unused-vars.js +26 -0
- package/tools/lint/rules/prefer-const.js +19 -0
- package/tools/linter.js +261 -0
- package/tools/replFormatter.js +93 -0
- package/tools/stamp-version.js +32 -0
- package/web/index.js +9 -0
- package/bun.lockb +0 -0
- package/cli.js +0 -84
- package/compiler/execute/interpreter.js +0 -68
- package/compiler/execute/interpreters/binary.js +0 -12
- package/compiler/execute/interpreters/call.js +0 -10
- package/compiler/execute/interpreters/if.js +0 -10
- package/compiler/execute/interpreters/try-catch.js +0 -10
- package/compiler/execute/interpreters/while.js +0 -8
- package/compiler/execute/utils/createfunction.js +0 -11
- package/compiler/execute/utils/evaluate.js +0 -20
- package/compiler/execute/utils/operate.js +0 -23
- package/compiler/lexer/processToken.js +0 -40
- package/compiler/lexer/tokenTypes.js +0 -4
- package/compiler/lexer/tokenizer.js +0 -74
- package/compiler/parser/expression/comparison.js +0 -18
- package/compiler/parser/expression/identifier.js +0 -29
- package/compiler/parser/expression/number.js +0 -10
- package/compiler/parser/expression/operator.js +0 -21
- package/compiler/parser/expression/punctuation.js +0 -31
- package/compiler/parser/expression/string.js +0 -6
- package/compiler/parser/parseExpression.js +0 -27
- package/compiler/parser/parseStatement.js +0 -34
- package/compiler/parser/parser.js +0 -45
- package/compiler/parser/statement/call.js +0 -26
- package/compiler/parser/statement/function.js +0 -29
- package/compiler/parser/statement/if.js +0 -34
- package/compiler/parser/statement/return.js +0 -10
- package/compiler/parser/statement/set.js +0 -11
- package/compiler/parser/statement/show.js +0 -10
- package/compiler/parser/statement/try-catch.js +0 -25
- package/compiler/parser/statement/while.js +0 -22
- package/converter/go/convert.js +0 -110
- package/converter/js/convert.js +0 -107
- package/jsconfig.json +0 -27
- package/vite.config.js +0 -17
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
// processToken.js
|
|
2
|
-
|
|
3
|
-
import { OPERATORS } from "./tokenTypes.js";
|
|
4
|
-
|
|
5
|
-
export const isOperator = (char) => OPERATORS.includes(char);
|
|
6
|
-
|
|
7
|
-
export const processToken = (currentToken, currentType, tokens) => {
|
|
8
|
-
if (currentToken) {
|
|
9
|
-
tokens.push({ type: currentType, value: currentToken });
|
|
10
|
-
return { currentToken: "", currentType: null };
|
|
11
|
-
}
|
|
12
|
-
return { currentToken, currentType };
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const processStringToken = (inString, currentToken, tokens) => {
|
|
16
|
-
inString = !inString;
|
|
17
|
-
if (!inString) {
|
|
18
|
-
tokens.push({ type: "string", value: currentToken });
|
|
19
|
-
currentToken = "";
|
|
20
|
-
}
|
|
21
|
-
return { inString, currentToken };
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export const processOperatorToken = (char, index, input, currentType, currentToken, tokens) => {
|
|
25
|
-
if (currentToken) {
|
|
26
|
-
({ currentToken, currentType } = processToken(currentToken, currentType, tokens));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
currentType = "operator";
|
|
31
|
-
currentToken += char;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (index < input.length - 1 && isOperator(input[index + 1])) {
|
|
35
|
-
currentToken += input[index + 1];
|
|
36
|
-
index++; // Skip the next operator character
|
|
37
|
-
}
|
|
38
|
-
tokens.push({ type: currentType, value: currentToken });
|
|
39
|
-
return { currentToken: "", currentType: null, i:index };
|
|
40
|
-
};
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { processToken, processStringToken, processOperatorToken, isOperator } from './processToken.js';
|
|
2
|
-
import { PUNCTUATION } from './tokenTypes.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @typedef {Object} Token
|
|
6
|
-
* @property {string} type - The type of the token (e.g., 'number', 'identifier', 'operator', etc.).
|
|
7
|
-
* @property {string} value - The value of the token (e.g., '42', 'x', '+', etc.).
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Generate tokens from the given input.
|
|
12
|
-
* @param {string} input - The input to be tokenized.
|
|
13
|
-
* @returns {Token[]} An array of tokens.
|
|
14
|
-
*/
|
|
15
|
-
function generateTokens(input) {
|
|
16
|
-
const tokens = [];
|
|
17
|
-
let currentToken = "";
|
|
18
|
-
let currentType = null;
|
|
19
|
-
let inComment = false;
|
|
20
|
-
let inString = false;
|
|
21
|
-
|
|
22
|
-
for (let i = 0; i < input.length; i++) {
|
|
23
|
-
const char = input[i];
|
|
24
|
-
|
|
25
|
-
if (inComment) {
|
|
26
|
-
if (char === "\n") {
|
|
27
|
-
inComment = false;
|
|
28
|
-
}
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (char === "/" && input[i + 1] === "/") {
|
|
33
|
-
inComment = true;
|
|
34
|
-
i++; // Skip the second '/'
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (char === '"') {
|
|
39
|
-
({ inString, currentToken } = processStringToken(inString, currentToken, tokens));
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (inString) {
|
|
44
|
-
currentToken += char;
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (/\s/.test(char)) {
|
|
49
|
-
({ currentToken, currentType } = processToken(currentToken, currentType, tokens));
|
|
50
|
-
continue;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (isOperator(char)) {
|
|
54
|
-
({ currentToken, currentType, i } = processOperatorToken(char, i, input, currentType, currentToken, tokens));
|
|
55
|
-
}else if (PUNCTUATION.includes(char)) {
|
|
56
|
-
({ currentToken, currentType } = processToken(currentToken, currentType, tokens));
|
|
57
|
-
tokens.push({ type: "punctuation", value: char });
|
|
58
|
-
} else {
|
|
59
|
-
currentToken += char;
|
|
60
|
-
if (!currentType) {
|
|
61
|
-
currentType = /[a-zA-Z]/.test(char)
|
|
62
|
-
? "identifier"
|
|
63
|
-
: /[0-9]/.test(char)
|
|
64
|
-
? "number"
|
|
65
|
-
: null;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
({ currentToken, currentType } = processToken(currentToken, currentType, tokens));
|
|
71
|
-
return tokens;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export { generateTokens };
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression.js";
|
|
2
|
-
|
|
3
|
-
export function comparisonExpression(tokens, index) {
|
|
4
|
-
const operator = tokens[index++].value;
|
|
5
|
-
let left = parseExpression(tokens, index);
|
|
6
|
-
index = left.index; // Update the index
|
|
7
|
-
let right = parseExpression(tokens, index);
|
|
8
|
-
index = right.index; // Update the index
|
|
9
|
-
return {
|
|
10
|
-
expression: {
|
|
11
|
-
type: "comparison",
|
|
12
|
-
operator,
|
|
13
|
-
left: left.expression,
|
|
14
|
-
right: right.expression,
|
|
15
|
-
},
|
|
16
|
-
index,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression.js";
|
|
2
|
-
|
|
3
|
-
export function identifierExpression(tokens, index) {
|
|
4
|
-
if (
|
|
5
|
-
tokens[index + 1]?.value === "[" &&
|
|
6
|
-
tokens[index + 3]?.value === "]"
|
|
7
|
-
) {
|
|
8
|
-
const name = tokens[index].value;
|
|
9
|
-
index += 2; // Skip identifier and '['
|
|
10
|
-
const indexExpression = parseExpression(tokens, index);
|
|
11
|
-
index = indexExpression.index; // Update the index
|
|
12
|
-
if (tokens[index]?.value === "]") {
|
|
13
|
-
index++; // Skip ']'
|
|
14
|
-
}
|
|
15
|
-
return {
|
|
16
|
-
expression: {
|
|
17
|
-
type: "indexAccess",
|
|
18
|
-
name,
|
|
19
|
-
index: indexExpression.expression,
|
|
20
|
-
},
|
|
21
|
-
index,
|
|
22
|
-
};
|
|
23
|
-
} else {
|
|
24
|
-
return {
|
|
25
|
-
expression: { type: "variable", name: tokens[index++].value },
|
|
26
|
-
index,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression.js";
|
|
2
|
-
|
|
3
|
-
export function operatorExpression(tokens, index) {
|
|
4
|
-
let operator = tokens[index++].value;
|
|
5
|
-
let left = parseExpression(tokens, index);
|
|
6
|
-
index = left.index; // Update the index
|
|
7
|
-
if (tokens[index]?.type === "operator") {
|
|
8
|
-
operator += tokens[index++].value; // Handle two-character operators like '=='
|
|
9
|
-
}
|
|
10
|
-
let right = parseExpression(tokens, index);
|
|
11
|
-
index = right.index; // Update the index
|
|
12
|
-
return {
|
|
13
|
-
expression: {
|
|
14
|
-
type: "binary",
|
|
15
|
-
operator,
|
|
16
|
-
left: left.expression,
|
|
17
|
-
right: right.expression,
|
|
18
|
-
},
|
|
19
|
-
index,
|
|
20
|
-
};
|
|
21
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression.js";
|
|
2
|
-
|
|
3
|
-
export function punctuationExpression(tokens, index) {
|
|
4
|
-
if (tokens[index].value === "[") {
|
|
5
|
-
index++; // Skip '['
|
|
6
|
-
const elements = [];
|
|
7
|
-
while (
|
|
8
|
-
tokens[index]?.type !== "punctuation" &&
|
|
9
|
-
tokens[index]?.value !== "]"
|
|
10
|
-
) {
|
|
11
|
-
let result = parseExpression(tokens, index);
|
|
12
|
-
elements.push(result.expression);
|
|
13
|
-
index = result.index; // Update the index
|
|
14
|
-
if (
|
|
15
|
-
tokens[index]?.type === "punctuation" &&
|
|
16
|
-
tokens[index]?.value === ","
|
|
17
|
-
) {
|
|
18
|
-
index++; // Skip ',' between elements
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
if (tokens[index]?.value === "]") {
|
|
22
|
-
index++; // Skip ']'
|
|
23
|
-
}
|
|
24
|
-
return { expression: { type: "list", elements }, index };
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
expression: { type: "punctuation", value: tokens[index++].value },
|
|
29
|
-
index,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { comparisonExpression } from "./expression/comparison.js";
|
|
2
|
-
import { identifierExpression } from "./expression/identifier.js";
|
|
3
|
-
import { numberExpression } from "./expression/number.js";
|
|
4
|
-
import { operatorExpression } from "./expression/operator.js";
|
|
5
|
-
import { punctuationExpression } from "./expression/punctuation.js";
|
|
6
|
-
import { stringExpression } from "./expression/string.js";
|
|
7
|
-
|
|
8
|
-
export const parseExpression = (tokens, index) => {
|
|
9
|
-
// console.log("expression..", tokens[index].type, tokens[index].value);
|
|
10
|
-
|
|
11
|
-
switch (tokens[index].type) {
|
|
12
|
-
case "number":
|
|
13
|
-
return numberExpression(tokens, index);
|
|
14
|
-
case "string":
|
|
15
|
-
return stringExpression(tokens, index);
|
|
16
|
-
case "identifier":
|
|
17
|
-
return identifierExpression(tokens, index);
|
|
18
|
-
case "operator":
|
|
19
|
-
return operatorExpression(tokens, index);
|
|
20
|
-
case "punctuation":
|
|
21
|
-
return punctuationExpression(tokens, index);
|
|
22
|
-
default:
|
|
23
|
-
if (["<", ">", ">=", "<=", "==", "!="].includes(tokens[index].value)) {
|
|
24
|
-
return comparisonExpression(tokens, index);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { ifStatement } from "./statement/if.js";
|
|
2
|
-
import { setStatement } from "./statement/set.js";
|
|
3
|
-
import { tryCatchStatement } from "./statement/try-catch.js";
|
|
4
|
-
import { whileStatement } from "./statement/while.js";
|
|
5
|
-
import { functionStatement } from "./statement/function.js";
|
|
6
|
-
import { callStatement } from "./statement/call.js";
|
|
7
|
-
import { returnStatement } from "./statement/return.js";
|
|
8
|
-
import { showStatement } from "./statement/show.js";
|
|
9
|
-
|
|
10
|
-
export const parseStatement = (tokens, index) => {
|
|
11
|
-
let statement = { type: "statement" };
|
|
12
|
-
|
|
13
|
-
if (tokens[index].value === "set") {
|
|
14
|
-
({ statement, index } = setStatement(tokens, index));
|
|
15
|
-
} else if (tokens[index].value === "if") {
|
|
16
|
-
({ statement, index } = ifStatement(tokens, index));
|
|
17
|
-
} else if (tokens[index].value === "while") {
|
|
18
|
-
({ statement, index } = whileStatement(tokens, index));
|
|
19
|
-
} else if (tokens[index].value === "try") {
|
|
20
|
-
({ statement, index } = tryCatchStatement(tokens, index));
|
|
21
|
-
} else if (tokens[index].value === "function") {
|
|
22
|
-
({ statement, index } = functionStatement(tokens, index));
|
|
23
|
-
} else if (tokens[index].value === "call") {
|
|
24
|
-
({ statement, index } = callStatement(tokens, index));
|
|
25
|
-
} else if (tokens[index].value === "return") {
|
|
26
|
-
({ statement, index } = returnStatement(tokens, index));
|
|
27
|
-
} else if (tokens[index].value === "show") {
|
|
28
|
-
({ statement, index } = showStatement(tokens, index));
|
|
29
|
-
} else {
|
|
30
|
-
index++;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return { statement, index };
|
|
34
|
-
};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { parseStatement } from "./parseStatement.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @typedef {import('../lexer/tokenizer.js').Token} Token
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {Object} Node
|
|
10
|
-
* @property {string} type - The type of the node (e.g., 'binary', 'assignment', 'literal', etc.).
|
|
11
|
-
* optionals
|
|
12
|
-
* @property {string} [operator] - The operator (e.g., '+', '-', '*', '/', etc.).
|
|
13
|
-
* @property {Node} [left] - The left node.
|
|
14
|
-
* @property {Node} [right] - The right node.
|
|
15
|
-
* @property {Node} [condition] - The expression node.
|
|
16
|
-
* @property {Node} [consequent] - The consequent node.
|
|
17
|
-
* @property {Node} [expression] - The expression node.
|
|
18
|
-
* @property {Node} [alternate] - The alternate node.
|
|
19
|
-
* @property {string} [target] - The target of the assignment.
|
|
20
|
-
* @property {number} [value] - The value to be assigned.
|
|
21
|
-
* @property {string} [name] - The name of functions and variables.
|
|
22
|
-
* @property {string[]} [params] - The parameters of a function.
|
|
23
|
-
* @property {Node[]} [body] - The body of a block statement.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Parse the list of tokens into an abstract syntax tree (AST).
|
|
28
|
-
* @param {Token[]} tokens - The list of tokens to be parsed.
|
|
29
|
-
* @returns {Node[]} An array of AST nodes.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
export function parseTokens(tokens) {
|
|
33
|
-
let index = 0;
|
|
34
|
-
|
|
35
|
-
const program = [];
|
|
36
|
-
while (index < tokens.length) {
|
|
37
|
-
let statement;
|
|
38
|
-
let result = parseStatement(tokens, index);
|
|
39
|
-
statement = result.statement;
|
|
40
|
-
index = result.index; // Update the index
|
|
41
|
-
program.push(statement);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return program;
|
|
45
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression.js";
|
|
2
|
-
|
|
3
|
-
export const callStatement = (tokens, index) => {
|
|
4
|
-
let statement = { type: "call" };
|
|
5
|
-
statement.name = tokens[index + 1]?.value;
|
|
6
|
-
index += 2; // Skip 'call' and function name
|
|
7
|
-
statement.args = [];
|
|
8
|
-
statement.target = null;
|
|
9
|
-
if (tokens[index].value === "(") {
|
|
10
|
-
index++; // Skip '('
|
|
11
|
-
while (tokens[index].value !== ")") {
|
|
12
|
-
if (tokens[index].value !== ",") {
|
|
13
|
-
let result = parseExpression(tokens, index);
|
|
14
|
-
statement.args.push(result.expression);
|
|
15
|
-
index = result.index; // Update the index
|
|
16
|
-
} else {
|
|
17
|
-
index++; // Skip ','
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
index++; // Skip ')'
|
|
21
|
-
}
|
|
22
|
-
if ((tokens[index++].value = "->")) {
|
|
23
|
-
statement.target = tokens[index++].value;
|
|
24
|
-
}
|
|
25
|
-
return { statement, index };
|
|
26
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { parseStatement } from "../parseStatement.js";
|
|
2
|
-
|
|
3
|
-
// #file:statement/function.js
|
|
4
|
-
export const functionStatement = (tokens, index) => {
|
|
5
|
-
index++; // Skip 'function'
|
|
6
|
-
let statement = { type: "function" };
|
|
7
|
-
statement.name = tokens[index++]?.value;
|
|
8
|
-
index++; // Skip 'function' and function name
|
|
9
|
-
statement.params = [];
|
|
10
|
-
while (tokens[index] && tokens[index]?.value !== ")") {
|
|
11
|
-
statement.params.push(tokens[index]?.value);
|
|
12
|
-
index++; // Skip parameter
|
|
13
|
-
if (tokens[index]?.value === ",") {
|
|
14
|
-
index++; // Skip ','
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
index++; // Skip ')'
|
|
18
|
-
const body = [];
|
|
19
|
-
while (tokens[index] && tokens[index].value !== "endfunction") {
|
|
20
|
-
let result = parseStatement(tokens, index);
|
|
21
|
-
body.push(result.statement);
|
|
22
|
-
index = result.index; // Update the index
|
|
23
|
-
}
|
|
24
|
-
if (tokens[index] && tokens[index].value === "endfunction") {
|
|
25
|
-
index++;
|
|
26
|
-
}
|
|
27
|
-
statement.body = body;
|
|
28
|
-
return { statement, index };
|
|
29
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression.js";
|
|
2
|
-
import { parseStatement } from "../parseStatement.js";
|
|
3
|
-
|
|
4
|
-
export function ifStatement(tokens, index) {
|
|
5
|
-
let statement = { type: "if" };
|
|
6
|
-
index++;
|
|
7
|
-
let result = parseExpression(tokens, index);
|
|
8
|
-
statement.condition = result.expression;
|
|
9
|
-
index = result.index; // Update the index
|
|
10
|
-
statement.consequent = [];
|
|
11
|
-
|
|
12
|
-
while (
|
|
13
|
-
tokens[index] &&
|
|
14
|
-
tokens[index].value !== "endif" &&
|
|
15
|
-
tokens[index].value !== "else"
|
|
16
|
-
) {
|
|
17
|
-
let result = parseStatement(tokens, index);
|
|
18
|
-
statement.consequent.push(result.statement);
|
|
19
|
-
index = result.index; // Update the index
|
|
20
|
-
}
|
|
21
|
-
if (tokens[index].value === "else") {
|
|
22
|
-
index++;
|
|
23
|
-
statement.alternate = [];
|
|
24
|
-
while (tokens[index] && tokens[index].value !== "endif") {
|
|
25
|
-
let result = parseStatement(tokens, index);
|
|
26
|
-
statement.alternate.push(result.statement);
|
|
27
|
-
index = result.index; // Update the index
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (tokens[index].value === "endif") {
|
|
31
|
-
index++;
|
|
32
|
-
}
|
|
33
|
-
return { statement, index };
|
|
34
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression.js";
|
|
2
|
-
|
|
3
|
-
// #file:statement/return.js
|
|
4
|
-
export const returnStatement = (tokens, index) => {
|
|
5
|
-
let statement = { type: "return" };
|
|
6
|
-
let result = parseExpression(tokens, index + 1);
|
|
7
|
-
statement.expression = result.expression;
|
|
8
|
-
index = result.index; // Update the index
|
|
9
|
-
return { statement, index };
|
|
10
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression.js";
|
|
2
|
-
|
|
3
|
-
export function setStatement(tokens, index) {
|
|
4
|
-
let statement = { type: "assignment" };
|
|
5
|
-
index++;
|
|
6
|
-
statement.target = tokens[index++].value;
|
|
7
|
-
let result = parseExpression(tokens, index);
|
|
8
|
-
statement.value = result.expression;
|
|
9
|
-
index = result.index; // Update the index
|
|
10
|
-
return { statement, index };
|
|
11
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression.js";
|
|
2
|
-
|
|
3
|
-
export const showStatement = (tokens, index) => {
|
|
4
|
-
let statement = { type: "print" };
|
|
5
|
-
index++; // Skip 'show'
|
|
6
|
-
let result = parseExpression(tokens, index);
|
|
7
|
-
statement.value = result.expression;
|
|
8
|
-
index = result.index; // Update the index
|
|
9
|
-
return { statement, index };
|
|
10
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { parseStatement } from "../parseStatement.js";
|
|
2
|
-
|
|
3
|
-
export const tryCatchStatement = (tokens, index) => {
|
|
4
|
-
let statement = { type: "try-catch" };
|
|
5
|
-
statement.tryBlock = [];
|
|
6
|
-
index++;
|
|
7
|
-
while (tokens[index] && tokens[index].value !== "catch") {
|
|
8
|
-
let result = parseStatement(tokens, index);
|
|
9
|
-
statement.tryBlock.push(result.statement);
|
|
10
|
-
index = result.index; // Update the index
|
|
11
|
-
}
|
|
12
|
-
if (tokens[index].value === "catch") {
|
|
13
|
-
index++;
|
|
14
|
-
statement.catchBlock = [];
|
|
15
|
-
while (tokens[index] && tokens[index].value !== "endtry") {
|
|
16
|
-
let result = parseStatement(tokens, index);
|
|
17
|
-
statement.catchBlock.push(result.statement);
|
|
18
|
-
index = result.index; // Update the index
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
if (tokens[index].value === "endtry") {
|
|
22
|
-
index++;
|
|
23
|
-
}
|
|
24
|
-
return { statement, index };
|
|
25
|
-
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { parseExpression } from "../parseExpression.js";
|
|
2
|
-
import { parseStatement } from "../parseStatement.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export const whileStatement = (tokens, index) => {
|
|
6
|
-
index++; // Skip 'while'
|
|
7
|
-
let statement = { type: "while" };
|
|
8
|
-
let result = parseExpression(tokens, index);
|
|
9
|
-
statement.condition = result.expression;
|
|
10
|
-
index = result.index; // Update the index
|
|
11
|
-
const body = [];
|
|
12
|
-
while (tokens[index] && tokens[index].value !== "endwhile") {
|
|
13
|
-
let result = parseStatement(tokens, index);
|
|
14
|
-
body.push(result.statement);
|
|
15
|
-
index = result.index; // Update the index
|
|
16
|
-
}
|
|
17
|
-
if (tokens[index].value === "endwhile") {
|
|
18
|
-
index++;
|
|
19
|
-
}
|
|
20
|
-
statement.body = body;
|
|
21
|
-
return { statement, index };
|
|
22
|
-
};
|
package/converter/go/convert.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
let declaredVariables = new Set();
|
|
2
|
-
|
|
3
|
-
function generateGoCodeFromAst(node) {
|
|
4
|
-
switch (node.type) {
|
|
5
|
-
case "function":
|
|
6
|
-
return generateFunction(node);
|
|
7
|
-
case "assignment":
|
|
8
|
-
return generateAssignment(node);
|
|
9
|
-
case "while":
|
|
10
|
-
return generateWhile(node);
|
|
11
|
-
case "if":
|
|
12
|
-
return generateIf(node);
|
|
13
|
-
case "return":
|
|
14
|
-
return generateReturn(node);
|
|
15
|
-
case "call":
|
|
16
|
-
return generateCall(node);
|
|
17
|
-
case "print":
|
|
18
|
-
return generatePrint(node);
|
|
19
|
-
case "literal":
|
|
20
|
-
return node.value;
|
|
21
|
-
case "variable":
|
|
22
|
-
return node.name;
|
|
23
|
-
case "binary":
|
|
24
|
-
return generateBinary(node);
|
|
25
|
-
default:
|
|
26
|
-
throw new Error(`Unknown node type: ${node.type}`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function generateGoCodeFromAstArray(ast) {
|
|
31
|
-
declaredVariables = new Set();
|
|
32
|
-
const functionCode = ast
|
|
33
|
-
.filter((node) => node.type === "function")
|
|
34
|
-
.map(generateGoCodeFromAst)
|
|
35
|
-
.join("\n\n");
|
|
36
|
-
const otherCode = ast
|
|
37
|
-
.filter((node) => node.type !== "function")
|
|
38
|
-
.map(generateGoCodeFromAst)
|
|
39
|
-
.join("\n");
|
|
40
|
-
return formatGoCode(`
|
|
41
|
-
package main
|
|
42
|
-
|
|
43
|
-
import "fmt"
|
|
44
|
-
|
|
45
|
-
${functionCode}
|
|
46
|
-
|
|
47
|
-
func main() {
|
|
48
|
-
${otherCode}
|
|
49
|
-
}
|
|
50
|
-
`);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function generateFunction(node) {
|
|
54
|
-
const params = node.params.map((p) => `${p} any`).join(", ");
|
|
55
|
-
const body = node.body.map(generateGoCodeFromAst).join("\n");
|
|
56
|
-
return `func ${node.name}(${params}) any {\n${body}\n}`;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function generateAssignment(node) {
|
|
60
|
-
let prefix = "";
|
|
61
|
-
if (!declaredVariables.has(node.target)) {
|
|
62
|
-
prefix = "var ";
|
|
63
|
-
declaredVariables.add(node.target);
|
|
64
|
-
}
|
|
65
|
-
return `${prefix}${node.target} = ${generateGoCodeFromAst(node.value)}`;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function generateWhile(node) {
|
|
69
|
-
const condition = generateGoCodeFromAst(node.condition);
|
|
70
|
-
const body = node.body.map(generateGoCodeFromAst).join("\n");
|
|
71
|
-
return `for ${condition} {\n${body}\n}`;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function generateIf(node) {
|
|
75
|
-
const condition = generateGoCodeFromAst(node.condition);
|
|
76
|
-
const consequent = node.consequent.map(generateGoCodeFromAst).join("\n");
|
|
77
|
-
return `if ${condition} {\n${consequent}\n}`;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function generateReturn(node) {
|
|
81
|
-
return `return ${generateGoCodeFromAst(node.expression)}`;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function generateCall(node) {
|
|
85
|
-
const args = node.args.map(generateGoCodeFromAst).join(", ");
|
|
86
|
-
let callCode = `${node.name}(${args})`;
|
|
87
|
-
if (node.target) {
|
|
88
|
-
let prefix = "";
|
|
89
|
-
if (!declaredVariables.has(node.target)) {
|
|
90
|
-
prefix = "var ";
|
|
91
|
-
declaredVariables.add(node.target);
|
|
92
|
-
}
|
|
93
|
-
callCode = `${prefix}${node.target} = ${callCode}`;
|
|
94
|
-
}
|
|
95
|
-
return callCode;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function generatePrint(node) {
|
|
99
|
-
return `fmt.Println(${generateGoCodeFromAst(node.value)})`;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function generateBinary(node) {
|
|
103
|
-
const left = generateGoCodeFromAst(node.left);
|
|
104
|
-
const right = generateGoCodeFromAst(node.right);
|
|
105
|
-
return `${left} ${node.operator} ${right}`;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function formatGoCode(code) {
|
|
109
|
-
return code;
|
|
110
|
-
}
|