oclang 1.2.1 → 1.2.3

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.
Files changed (66) hide show
  1. package/BUG_REGISTRY.md +1 -0
  2. package/CHANGELOG.md +9 -2
  3. package/dist/cli/index.js +1 -0
  4. package/dist/cli/ocat/commands/index.js +2 -0
  5. package/dist/cli/ocat/commands/repl.js +39 -0
  6. package/dist/cli/ocat/commands/run.js +19 -0
  7. package/dist/cli/ocat/index.js +20 -0
  8. package/dist/cli/ocm/commands/index.js +2 -0
  9. package/dist/cli/ocm/commands/init.js +41 -0
  10. package/dist/cli/ocm/commands/run.js +17 -0
  11. package/dist/cli/ocm/index.js +15 -0
  12. package/dist/cli/utils/chalkText.js +6 -0
  13. package/dist/core/ast/astBuilder.js +150 -0
  14. package/dist/core/ast/types/base/index.js +2 -0
  15. package/dist/core/ast/types/base/source.js +1 -0
  16. package/dist/core/ast/types/base/statement.js +7 -0
  17. package/dist/core/ast/types/statements/callStatement.js +1 -0
  18. package/dist/core/ast/types/statements/functionStatement.js +1 -0
  19. package/dist/core/ast/types/statements/index.js +4 -0
  20. package/dist/core/ast/types/statements/printStatement.js +1 -0
  21. package/dist/core/ast/types/statements/variableStatement.js +1 -0
  22. package/dist/core/context/contextType.js +5 -0
  23. package/dist/core/context/coreContext.js +6 -0
  24. package/dist/core/index.js +22 -0
  25. package/dist/core/lexer/tokens/attrs.js +6 -0
  26. package/dist/core/lexer/tokens/comments.js +12 -0
  27. package/dist/core/lexer/tokens/delimiters.js +11 -0
  28. package/dist/core/lexer/tokens/function.js +10 -0
  29. package/dist/core/lexer/tokens/ignored.js +3 -0
  30. package/dist/core/lexer/tokens/index.js +29 -0
  31. package/dist/core/lexer/tokens/keywords.js +3 -0
  32. package/dist/core/lexer/tokens/literals.js +14 -0
  33. package/dist/core/lexer/tokens/operators.js +3 -0
  34. package/dist/core/lexer/tokens/vars.js +12 -0
  35. package/dist/core/lexer/tokens.js +3 -0
  36. package/dist/core/parser/parser.js +84 -0
  37. package/dist/core/runner/runner.js +108 -0
  38. package/dist/core/runner/utils/string.js +14 -0
  39. package/dist/core/services/log.service.js +53 -0
  40. package/dist/project/index.js +22 -0
  41. package/dist/project/models/project.js +5 -0
  42. package/dist/project/utils/project.js +11 -0
  43. package/dist/shared/context/globalContext.js +16 -0
  44. package/dist/shared/io/json.js +7 -0
  45. package/dist/shared/manager/baseManager.js +30 -0
  46. package/dist/shared/manager/errors/coreErrors.js +8 -0
  47. package/dist/shared/manager/errors/io/extension.js +7 -0
  48. package/dist/shared/manager/errors/io/file.js +7 -0
  49. package/dist/shared/manager/errors/semantic/undefined/declared.js +24 -0
  50. package/dist/shared/manager/errors/semantic/undefined/undeclared.js +18 -0
  51. package/dist/shared/manager/errors/syntax/syntaxErrors.js +7 -0
  52. package/dist/shared/manager/errors/syntax/token.js +11 -0
  53. package/dist/shared/manager/warn/coreWarnings.js +8 -0
  54. package/dist/shared/models/func.js +1 -0
  55. package/dist/shared/models/value.js +7 -0
  56. package/dist/shared/models/var.js +1 -0
  57. package/dist/shared/utils/objects.js +6 -0
  58. package/dist/shared/utils/strformat.js +12 -0
  59. package/package.json +30 -30
  60. package/src/core/ast/astBuilder.ts +15 -153
  61. package/src/core/ast/statements/base.ts +3 -0
  62. package/src/core/ast/statements/function.ts +58 -0
  63. package/src/core/ast/statements/io.ts +51 -0
  64. package/src/core/ast/statements/vars.ts +47 -0
  65. package/src/core/lexer/tokens/keywords.ts +3 -1
  66. package/src/core/parser/parser.ts +11 -0
package/BUG_REGISTRY.md CHANGED
@@ -8,6 +8,7 @@ BUG-\<BUG-NUMBER>\<BUG-PART>-\<VERSION>-\<VERSION-FORMAT>
8
8
 
9
9
  - BUG-002A-100-MmP: CLI always uses force mode
10
10
  - BUG-002B-101-MmP: The errors in the CLI shows 'undefined'
11
+ - BUG-002C-100-MmP: Dist folder is not created
11
12
 
12
13
  ## 0.3.0 bugs
13
14
 
package/CHANGELOG.md CHANGED
@@ -16,15 +16,22 @@ PATCH version when you make backwards-compatible bug fixes.
16
16
 
17
17
  - OCM mode added
18
18
 
19
- #### 1.2.1 - Uploading error
19
+ #### 1.2.3 - AST Structure
20
+
21
+ - AST Structure updated
22
+
23
+ #### 1.2.1 & 1.2.2 - Uploading error
20
24
 
21
25
  - Uploading error in 1.2.0
22
- - Updated the CLI ```ocm init``` command
23
26
 
24
27
  ### 1.1.0 - REPL
25
28
 
26
29
  - REPL mode added
27
30
 
31
+ #### 1.1.2 - BUG-002C-100-MmP
32
+
33
+ - BUG-002C-100-MmP: Dist folder is not created
34
+
28
35
  #### 1.1.1 - BUG-002B-101-MmP
29
36
 
30
37
  - BUG-002B-100-MmP: The errors in the CLI shows 'undefined'
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from "./run.js";
2
+ export * from "./repl.js";
@@ -0,0 +1,39 @@
1
+ import readline from "readline";
2
+ import chalk from "chalk";
3
+ import { execute } from "../../../core/index.js";
4
+ export function repl() {
5
+ console.log(chalk.yellow("Orange Cat REPL v1.0.0"));
6
+ const rl = readline.createInterface({
7
+ input: process.stdin,
8
+ output: process.stdout,
9
+ prompt: chalk.cyan("ocat> "),
10
+ });
11
+ rl.prompt();
12
+ rl.on("line", (line) => {
13
+ const input = line.trim();
14
+ // comandos internos
15
+ if (input === ".exit") {
16
+ rl.close();
17
+ return;
18
+ }
19
+ if (input === ".help") {
20
+ console.log(`
21
+ .exit Exit REPL
22
+ .clear Clear screen
23
+ `);
24
+ rl.prompt();
25
+ return;
26
+ }
27
+ if (input === ".clear") {
28
+ console.clear();
29
+ rl.prompt();
30
+ return;
31
+ }
32
+ execute(input);
33
+ rl.prompt();
34
+ });
35
+ rl.on("close", () => {
36
+ console.log("\nBye!");
37
+ process.exit(0);
38
+ });
39
+ }
@@ -0,0 +1,19 @@
1
+ import { execute } from "../../../core/index.js";
2
+ import { ExtensionError } from "../../../shared/manager/errors/io/extension.js";
3
+ import chalk from "chalk";
4
+ import fs from "fs";
5
+ import { FileDoesntExistError } from "../../../shared/manager/errors/io/file.js";
6
+ export function runfile(file, options) {
7
+ if (!file.endsWith(".ocat") && !options.force) {
8
+ new ExtensionError("File must be a .ocat file. Use -f to force execution with other extensions").throw();
9
+ }
10
+ if (options.force) {
11
+ console.log(chalk.blue(`Running in force mode`));
12
+ }
13
+ if (!fs.existsSync(file)) {
14
+ new FileDoesntExistError(`File ${file} doesn't exist`)
15
+ .throw();
16
+ }
17
+ const fileText = fs.readFileSync(file, "utf8");
18
+ execute(fileText);
19
+ }
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { runfile } from "./commands/index.js";
4
+ import { repl } from "./commands/index.js";
5
+ const program = new Command();
6
+ program
7
+ .name("ocat")
8
+ .description("The Orange Cat language compiler")
9
+ .version("1.0.0");
10
+ program
11
+ .command("run")
12
+ .description("Run a file. This file must be a .ocat file")
13
+ .argument("<file>", "The file to run")
14
+ .option("-f, --force", "Force the execution with other extensions")
15
+ .action(runfile);
16
+ program
17
+ .command("inline")
18
+ .description("An REPL for the Orange Cat language")
19
+ .action(repl);
20
+ program.parse();
@@ -0,0 +1,2 @@
1
+ export * from "./init.js";
2
+ export * from "./run.js";
@@ -0,0 +1,41 @@
1
+ import inquirer from "inquirer";
2
+ import chalk, {} from "chalk";
3
+ import { chalkText } from "../../utils/chalkText.js";
4
+ import { createProject } from "../../../project/index.js";
5
+ import { fromCamelToDash } from "../../../shared/utils/strformat.js";
6
+ export async function init() {
7
+ const projectTypes = [{ name: "App", color: chalk.red }, { name: "Lib", color: chalk.yellow }];
8
+ const answers = await inquirer.prompt([
9
+ {
10
+ type: "input",
11
+ name: "name",
12
+ message: "How do you want to name your project?",
13
+ default: "myProject",
14
+ },
15
+ {
16
+ type: "input",
17
+ name: "dir",
18
+ message: "Where do you want to create your project?",
19
+ default: (answers) => answers.name,
20
+ },
21
+ {
22
+ type: "input",
23
+ name: "id",
24
+ message: "What is your project ID?",
25
+ default: (answers) => fromCamelToDash(answers.name),
26
+ },
27
+ {
28
+ type: "select",
29
+ name: "type",
30
+ message: "What type of project do you want to create?",
31
+ choices: projectTypes
32
+ .map((choice) => chalkText(choice.name, choice.color)),
33
+ }
34
+ ]);
35
+ createProject({
36
+ name: answers.name,
37
+ dir: answers.dir,
38
+ type: answers.type,
39
+ id: answers.id,
40
+ });
41
+ }
@@ -0,0 +1,17 @@
1
+ import path from "path";
2
+ import { readJSON } from "../../../shared/io/json.js";
3
+ import { runfile } from "../../ocat/commands/index.js";
4
+ import * as context from "../../../shared/context/globalContext.js";
5
+ import { defaultLoggerConfig, LoggerService } from "../../../core/services/log.service.js";
6
+ export function run() {
7
+ const projectConfig = readJSON(path.join(".ocat", "config.json"));
8
+ context.set("isProject", true);
9
+ context.set("projectConfig", projectConfig);
10
+ context.set("services", {});
11
+ context.useObject("services", services => {
12
+ return {
13
+ log: new LoggerService(defaultLoggerConfig),
14
+ };
15
+ });
16
+ runfile(projectConfig.main, { force: false });
17
+ }
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { init, run } from "./commands/index.js";
4
+ const program = new Command();
5
+ program.name("ocm").description("The Orange Cat manager").version("1.0.0");
6
+ program
7
+ .command("initialize")
8
+ .alias("init")
9
+ .description("Initialize a new Orange Cat project")
10
+ .action(async () => { await init(); });
11
+ program
12
+ .command("run")
13
+ .description("Run the project")
14
+ .action(run);
15
+ program.parse();
@@ -0,0 +1,6 @@
1
+ export function chalkText(text, color) {
2
+ return {
3
+ name: color(text),
4
+ value: text
5
+ };
6
+ }
@@ -0,0 +1,150 @@
1
+ import { createCoreContext } from "../context/coreContext.js";
2
+ import { ValueType } from "../../shared/models/value.js";
3
+ import { StatementKind } from "./types/base/index.js";
4
+ export function buildAst(cst) {
5
+ const statements = cst.children.statement ?? [];
6
+ const ast = [];
7
+ for (const statement of statements) {
8
+ let __tmp = null;
9
+ const __$tmp = () => { if (__tmp)
10
+ ast.push(__tmp); };
11
+ __tmp = printStatement(statement);
12
+ __$tmp();
13
+ __tmp = variableStatement(statement);
14
+ __$tmp();
15
+ __tmp = functionStatement(statement);
16
+ __$tmp();
17
+ __tmp = callStatement(statement);
18
+ __$tmp();
19
+ }
20
+ return ast;
21
+ }
22
+ const printStatement = (statement) => {
23
+ const printStmt = statement.children.printStatement?.[0];
24
+ if (printStmt) {
25
+ const strToken = printStmt.children.StringLiteral?.[0];
26
+ if (strToken) {
27
+ return {
28
+ kind: StatementKind.PrintStatement,
29
+ sourceInfo: {
30
+ tokens: printStmt.children,
31
+ cstNode: printStmt,
32
+ startLine: printStmt.startLine,
33
+ endLine: printStmt.endLine,
34
+ startColumn: printStmt.startColumn,
35
+ endColumn: printStmt.endColumn,
36
+ },
37
+ value: {
38
+ value: strToken.image,
39
+ type: ValueType.String,
40
+ }
41
+ };
42
+ }
43
+ const idToken = printStmt.children.Identifier?.[0];
44
+ if (idToken) {
45
+ return {
46
+ kind: StatementKind.PrintStatement,
47
+ sourceInfo: {
48
+ tokens: printStmt.children,
49
+ cstNode: printStmt,
50
+ startLine: printStmt.startLine,
51
+ endLine: printStmt.endLine,
52
+ startColumn: printStmt.startColumn,
53
+ endColumn: printStmt.endColumn,
54
+ },
55
+ value: {
56
+ value: idToken.image,
57
+ type: ValueType.Identifier,
58
+ }
59
+ };
60
+ }
61
+ }
62
+ return null;
63
+ };
64
+ const variableStatement = (statement) => {
65
+ const varStmt = statement.children.variableStatement?.[0];
66
+ if (varStmt) {
67
+ const typeToken = varStmt.children.VarType?.[0];
68
+ const idToken = varStmt.children.Identifier?.[0];
69
+ const valueToken = varStmt.children.StringLiteral?.[0] ??
70
+ varStmt.children.NumberLiteral?.[0] ??
71
+ varStmt.children.BooleanLiteral?.[0];
72
+ if (!typeToken || !idToken || !valueToken)
73
+ return null;
74
+ const setToken = varStmt.children.Set?.[0];
75
+ const constToken = varStmt.children.Const?.[0];
76
+ const type = typeToken.image;
77
+ const id = idToken.image;
78
+ const value = valueToken.image;
79
+ return {
80
+ kind: StatementKind.VariableStatement,
81
+ sourceInfo: {
82
+ tokens: varStmt.children,
83
+ cstNode: varStmt,
84
+ startLine: varStmt.startLine,
85
+ endLine: varStmt.endLine,
86
+ startColumn: varStmt.startColumn,
87
+ endColumn: varStmt.endColumn,
88
+ },
89
+ id,
90
+ var: {
91
+ type,
92
+ value,
93
+ props: {
94
+ isConst: !!constToken,
95
+ }
96
+ },
97
+ set: !!setToken,
98
+ };
99
+ }
100
+ return null;
101
+ };
102
+ const functionStatement = (statement) => {
103
+ const funcStmt = statement.children.functionStatement?.[0];
104
+ if (funcStmt) {
105
+ const idToken = funcStmt.children.Identifier?.[0];
106
+ if (!idToken)
107
+ return null;
108
+ const id = idToken.image;
109
+ const body = buildAst(funcStmt);
110
+ return {
111
+ kind: StatementKind.FunctionStatement,
112
+ sourceInfo: {
113
+ tokens: funcStmt.children,
114
+ cstNode: funcStmt,
115
+ startLine: funcStmt.startLine,
116
+ endLine: funcStmt.endLine,
117
+ startColumn: funcStmt.startColumn,
118
+ endColumn: funcStmt.endColumn,
119
+ },
120
+ id,
121
+ func: {
122
+ body,
123
+ scope: createCoreContext(),
124
+ }
125
+ };
126
+ }
127
+ return null;
128
+ };
129
+ const callStatement = (statement) => {
130
+ const callStmt = statement.children.callStatement?.[0];
131
+ if (callStmt) {
132
+ const idToken = callStmt.children.Identifier?.[0];
133
+ if (!idToken)
134
+ return null;
135
+ const id = idToken.image;
136
+ return {
137
+ kind: StatementKind.CallStatement,
138
+ sourceInfo: {
139
+ tokens: callStmt.children,
140
+ cstNode: callStmt,
141
+ startLine: callStmt.startLine,
142
+ endLine: callStmt.endLine,
143
+ startColumn: callStmt.startColumn,
144
+ endColumn: callStmt.endColumn,
145
+ },
146
+ id,
147
+ };
148
+ }
149
+ return null;
150
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./statement.js";
2
+ export * from "./source.js";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ export var StatementKind;
2
+ (function (StatementKind) {
3
+ StatementKind[StatementKind["PrintStatement"] = 0] = "PrintStatement";
4
+ StatementKind[StatementKind["VariableStatement"] = 1] = "VariableStatement";
5
+ StatementKind[StatementKind["FunctionStatement"] = 2] = "FunctionStatement";
6
+ StatementKind[StatementKind["CallStatement"] = 3] = "CallStatement";
7
+ })(StatementKind || (StatementKind = {}));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ export * from "./printStatement";
2
+ export * from "./variableStatement";
3
+ export * from "./functionStatement";
4
+ export * from "./callStatement";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export var ContextType;
2
+ (function (ContextType) {
3
+ ContextType["Variable"] = "Variable";
4
+ ContextType["Function"] = "Function";
5
+ })(ContextType || (ContextType = {}));
@@ -0,0 +1,6 @@
1
+ export function createCoreContext() {
2
+ return {
3
+ variables: {},
4
+ functions: {},
5
+ };
6
+ }
@@ -0,0 +1,22 @@
1
+ import { ocatLexer } from "./lexer/tokens.js";
2
+ import { OcatParser } from "./parser/parser.js";
3
+ import { run } from "./runner/runner.js";
4
+ import { createCoreContext } from "./context/coreContext.js";
5
+ import { buildAst } from "./ast/astBuilder.js";
6
+ import * as ctx from "../shared/context/globalContext.js";
7
+ import fs from "fs";
8
+ export function execute(code) {
9
+ const lexingResult = ocatLexer.tokenize(code);
10
+ const parser = new OcatParser();
11
+ parser.input = lexingResult.tokens;
12
+ const cst = parser.program();
13
+ const ast = buildAst(cst);
14
+ process.on("exit", () => {
15
+ if (ctx.get("isProject")) {
16
+ const logs = ctx.get("services").log.toString();
17
+ fs.writeFileSync(".ocat/logs.txt", logs);
18
+ }
19
+ });
20
+ const context = createCoreContext();
21
+ run(ast, context);
22
+ }
@@ -0,0 +1,6 @@
1
+ import { createToken, Lexer } from "chevrotain";
2
+ export const Const = createToken({
3
+ name: "Const",
4
+ pattern: /const/,
5
+ });
6
+ export const attributes = [Const];
@@ -0,0 +1,12 @@
1
+ import { createToken, Lexer } from "chevrotain";
2
+ export const LineComment = createToken({
3
+ name: "LineComment",
4
+ pattern: /\/\/[^\n]*/,
5
+ group: Lexer.SKIPPED,
6
+ });
7
+ export const BlockComment = createToken({
8
+ name: "BlockComment",
9
+ pattern: /\/\*[\s\S]*?\*\//,
10
+ group: Lexer.SKIPPED,
11
+ });
12
+ export const comments = [LineComment, BlockComment];
@@ -0,0 +1,11 @@
1
+ import { createToken } from "chevrotain";
2
+ export const LeftParen = createToken({ name: "LeftParen", pattern: /\(/ });
3
+ export const RightParen = createToken({ name: "RightParen", pattern: /\)/ });
4
+ export const LeftBrace = createToken({ name: "LeftBrace", pattern: /\{/ });
5
+ export const RightBrace = createToken({ name: "RightBrace", pattern: /\}/ });
6
+ export const LeftBracket = createToken({ name: "LeftBracket", pattern: /\[/ });
7
+ export const RightBracket = createToken({ name: "RightBracket", pattern: /\]/ });
8
+ export const LeftTag = createToken({ name: "LeftTag", pattern: /</ });
9
+ export const RightTag = createToken({ name: "RightTag", pattern: />/ });
10
+ export const Comma = createToken({ name: "Comma", pattern: /,/ });
11
+ export const delimiters = [LeftParen, RightParen, LeftBrace, RightBrace, LeftBracket, RightBracket, LeftTag, RightTag, Comma];
@@ -0,0 +1,10 @@
1
+ import { createToken } from "chevrotain";
2
+ export const Function = createToken({
3
+ name: "Function",
4
+ pattern: /func/,
5
+ });
6
+ export const Call = createToken({
7
+ name: "Call",
8
+ pattern: /call/,
9
+ });
10
+ export const functions = [Function, Call];
@@ -0,0 +1,3 @@
1
+ import { createToken } from "chevrotain";
2
+ export const WhiteSpace = createToken({ name: "WhiteSpace", pattern: /\s+/ });
3
+ export const ignored = [WhiteSpace];
@@ -0,0 +1,29 @@
1
+ export * from "./ignored.js";
2
+ export * from "./comments.js";
3
+ export * from "./keywords.js";
4
+ export * from "./literals.js";
5
+ export * from "./delimiters.js";
6
+ export * from "./vars.js";
7
+ export * from "./operators.js";
8
+ export * from "./attrs.js";
9
+ export * from "./function.js";
10
+ import { ignored } from "./ignored.js";
11
+ import { comments } from "./comments.js";
12
+ import { keywords } from "./keywords.js";
13
+ import { literals } from "./literals.js";
14
+ import { delimiters } from "./delimiters.js";
15
+ import { variablesAndConstants } from "./vars.js";
16
+ import { operators } from "./operators.js";
17
+ import { attributes } from "./attrs.js";
18
+ import { functions } from "./function.js";
19
+ export const allTokens = [
20
+ ...ignored,
21
+ ...comments,
22
+ ...keywords,
23
+ ...attributes,
24
+ ...functions,
25
+ ...literals,
26
+ ...delimiters,
27
+ ...variablesAndConstants,
28
+ ...operators,
29
+ ];
@@ -0,0 +1,3 @@
1
+ import { createToken } from "chevrotain";
2
+ export const Output = createToken({ name: "Output", pattern: /print/ });
3
+ export const keywords = [Output];
@@ -0,0 +1,14 @@
1
+ import { createToken } from "chevrotain";
2
+ export const StringLiteral = createToken({
3
+ name: "StringLiteral",
4
+ pattern: /"(?:[^\\"]|\\.)*"/,
5
+ });
6
+ export const NumberLiteral = createToken({
7
+ name: "NumberLiteral",
8
+ pattern: /\d+(\.\d+)?/,
9
+ });
10
+ export const BooleanLiteral = createToken({
11
+ name: "BooleanLiteral",
12
+ pattern: /true|false/,
13
+ });
14
+ export const literals = [StringLiteral, NumberLiteral, BooleanLiteral];
@@ -0,0 +1,3 @@
1
+ import { createToken } from "chevrotain";
2
+ export const Assign = createToken({ name: "Assign", pattern: /=/ });
3
+ export const operators = [Assign];
@@ -0,0 +1,12 @@
1
+ import { createToken } from "chevrotain";
2
+ import { ValueType } from "../../../shared/models/value.js";
3
+ export const VarType = createToken({
4
+ name: "VarType",
5
+ pattern: new RegExp(Object.values(ValueType).join("|")),
6
+ });
7
+ export const Set = createToken({ name: "Set", pattern: /set/ });
8
+ export const Identifier = createToken({
9
+ name: "Identifier",
10
+ pattern: /[a-zA-Z_]\w*/,
11
+ });
12
+ export const variablesAndConstants = [VarType, Set, Identifier];
@@ -0,0 +1,3 @@
1
+ import { Lexer } from "chevrotain";
2
+ import { allTokens } from "./tokens/index.js";
3
+ export const ocatLexer = new Lexer(allTokens);
@@ -0,0 +1,84 @@
1
+ import { CstParser } from "chevrotain";
2
+ import { ValueType } from "../../shared/models/value.js";
3
+ import * as token from "../lexer/tokens/index.js";
4
+ export class OcatParser extends CstParser {
5
+ constructor() {
6
+ super(token.allTokens, {
7
+ recoveryEnabled: true,
8
+ });
9
+ this.performSelfAnalysis();
10
+ }
11
+ program = this.RULE("program", () => {
12
+ this.MANY(() => this.SUBRULE(this.statement));
13
+ });
14
+ statement = this.RULE("statement", () => {
15
+ this.OR([
16
+ {
17
+ ALT: () => this.SUBRULE(this.printStatement, {
18
+ LABEL: "printStatement",
19
+ }),
20
+ },
21
+ {
22
+ ALT: () => this.SUBRULE(this.variableStatement, {
23
+ LABEL: "variableStatement",
24
+ }),
25
+ },
26
+ {
27
+ ALT: () => this.SUBRULE(this.functionStatement, {
28
+ LABEL: "functionStatement",
29
+ }),
30
+ },
31
+ {
32
+ ALT: () => this.SUBRULE(this.callStatement, {
33
+ LABEL: "callStatement",
34
+ }),
35
+ },
36
+ ]);
37
+ });
38
+ printStatement = this.RULE("printStatement", () => {
39
+ this.CONSUME(token.Output);
40
+ this.CONSUME(token.LeftParen);
41
+ this.OR([
42
+ ...token.literals.map((lit) => ({
43
+ ALT: () => this.CONSUME(lit, { LABEL: lit.name }),
44
+ })),
45
+ {
46
+ ALT: () => this.CONSUME(token.Identifier, { LABEL: "Identifier" }),
47
+ },
48
+ ]);
49
+ this.CONSUME(token.RightParen);
50
+ });
51
+ variableStatement = this.RULE("variableStatement", () => {
52
+ this.OPTION(() => {
53
+ this.OR([
54
+ { ALT: () => this.CONSUME(token.Set, { LABEL: "Set" }) },
55
+ { ALT: () => this.CONSUME(token.Const, { LABEL: "Const" }) },
56
+ ]);
57
+ });
58
+ const type = this.CONSUME(token.VarType).image;
59
+ this.CONSUME(token.Identifier);
60
+ this.CONSUME(token.Assign);
61
+ switch (type) {
62
+ case ValueType.String:
63
+ this.CONSUME(token.StringLiteral);
64
+ break;
65
+ case ValueType.Number:
66
+ this.CONSUME(token.NumberLiteral);
67
+ break;
68
+ case ValueType.Boolean:
69
+ this.CONSUME(token.BooleanLiteral);
70
+ break;
71
+ }
72
+ });
73
+ functionStatement = this.RULE("functionStatement", () => {
74
+ this.CONSUME(token.Function);
75
+ this.CONSUME(token.Identifier);
76
+ this.CONSUME(token.LeftBrace);
77
+ this.MANY(() => this.SUBRULE(this.statement));
78
+ this.CONSUME(token.RightBrace);
79
+ });
80
+ callStatement = this.RULE("callStatement", () => {
81
+ this.CONSUME(token.Call);
82
+ this.CONSUME(token.Identifier);
83
+ });
84
+ }