utkrisht 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.
@@ -0,0 +1,375 @@
1
+ import * as logger from "./logger.js";
2
+
3
+ export function createParser(tokens) {
4
+ return {
5
+ tokens,
6
+ position: 0,
7
+ };
8
+ }
9
+
10
+ class ParseError extends Error {
11
+ constructor(message, token) {
12
+ super(message);
13
+ this.token = token;
14
+ this.name = "ParseError";
15
+ }
16
+ }
17
+
18
+ function error(utkrisht, message, token) {
19
+ logger.error(utkrisht, message, token.line)
20
+ return new ParseError(message, token)
21
+ }
22
+
23
+ function getCurrentToken(parser) {
24
+ return parser.tokens[parser.position];
25
+ }
26
+
27
+ function getNextToken(parser) {
28
+ return parser.tokens[parser.position + 1];
29
+ }
30
+
31
+ function getTokenTypeAtPosition(parser, position) {
32
+ return parser.tokens[position];
33
+ }
34
+
35
+ function isCurrentTokenType(parser, ...types) {
36
+ for (const type of types) {
37
+ if (getCurrentToken(parser).type === type) {
38
+ return true;
39
+ }
40
+ }
41
+ return false;
42
+ }
43
+
44
+ function isNextTokenType(parser, ...types) {
45
+ for (const type of types) {
46
+ if (getNextToken(parser).type === type) {
47
+ return true;
48
+ }
49
+ }
50
+ return false;
51
+ }
52
+
53
+ function isTokenTypeAtPosition(parser, position, ...types) {
54
+ for (const type of types) {
55
+ if (getTokenTypeAtPosition(parser, position).type === type) {
56
+ return true;
57
+ }
58
+ }
59
+ return false;
60
+ }
61
+
62
+
63
+ function isAtEnd(parser) {
64
+ return parser.tokens[parser.position].type === "EndOfFile";
65
+ }
66
+
67
+ function ignoreToken(parser, ...tokens) {
68
+ if (isCurrentTokenType(parser, ...tokens)) {
69
+ parser.position++;
70
+ }
71
+ }
72
+
73
+ function expectToken(utkrisht, parser, ...tokens) {
74
+ if (isCurrentTokenType(parser, ...tokens)) {
75
+ return;
76
+ }
77
+
78
+ const expected =
79
+ tokens.length === 1
80
+ ? tokens[0]
81
+ : "one of [" + tokens.join(", ") + "]"
82
+ ;
83
+
84
+ const found =
85
+ isCurrentTokenType(parser, "EndOfFile")
86
+ ? "reached end of code"
87
+ : "got " + getCurrentToken(parser).type
88
+ ;
89
+
90
+ throw error(utkrisht, "Expected " + expected + ", but " + found, getCurrentToken(parser))
91
+ }
92
+
93
+
94
+ function synchronise(parser) {
95
+ while (!isAtEnd(parser)) {
96
+ parser.position++
97
+ // if (isCurrentTokenType(parser, "NewLine")) {
98
+ // break;
99
+ // }
100
+ if (isCurrentTokenType(parser, "Loop", "When")) {
101
+ break;
102
+ }
103
+ }
104
+ }
105
+
106
+
107
+ function isCurrentTokenTypeExpressionStart(parser) {
108
+ return isCurrentTokenType(parser,
109
+ "NumericLiteral",
110
+ "StringLiteral",
111
+ "Right",
112
+ "Wrong",
113
+ "Identifier",
114
+ "LeftRoundBracket"
115
+ )
116
+ }
117
+
118
+
119
+ function parseVariableExpression(utkrisht, parser) {
120
+ if (parser.variableExpression !== undefined) {
121
+ parser.position = parser.variableExpressionEndPosition;
122
+
123
+ parser.variableExpression = undefined;
124
+ parser.variableExpressionEndPosition = undefined;
125
+
126
+ return parser.variableExpression;
127
+ }
128
+ const name = getCurrentToken(parser);
129
+ parser.position++;
130
+
131
+ const _arguments = [];
132
+ while (true) {
133
+ if (isCurrentTokenTypeExpressionStart(parser)) {
134
+ _arguments.push( { type: "Argument", name: undefined, value: parseExpression(utkrisht, parser) });
135
+
136
+ if (isCurrentTokenType(parser, "Comma")) {
137
+ parser.position++;
138
+ continue;
139
+ } else {
140
+ break;
141
+ }
142
+ }
143
+
144
+ if (isCurrentTokenType(parser, "Identifier") && isNextTokenType(parser, "Colon")) {
145
+ const name = getCurrentToken(parser);
146
+ parser.position++;
147
+ const value = parseExpression(utkrisht, parser);
148
+ _arguments.push({ type: "Argument", name, value });
149
+
150
+ if (isCurrentTokenType(parser, "Comma")) {
151
+ parser.position++;
152
+ continue;
153
+ } else {
154
+ break;
155
+ }
156
+ }
157
+
158
+ break;
159
+ }
160
+
161
+ return { type: "VariableExpression", name, _arguments }
162
+ }
163
+
164
+ function parsePrimaryExpression(utkrisht, parser) {
165
+ let expression;
166
+
167
+ if (isCurrentTokenType(parser, "right")) {
168
+ expression = { type: "LiteralExpression", value: { type: "BooleanExpression", value: true }};
169
+ parser.position++;
170
+ } else if (isCurrentTokenType(parser, "wrong")) {
171
+ expression = { type: "LiteralExpression", value: { type: "BooleanExpression", value: false }};
172
+ parser.position++;
173
+ } else if (isCurrentTokenType(parser, "StringLiteral")) {
174
+ expression = { type: "LiteralExpression", value: { type: "StringLiteral", value: getCurrentToken(parser).lexeme }};
175
+ parser.position++;
176
+ } else if (isCurrentTokenType(parser, "NumericLiteral")) {
177
+ expression = { type: "LiteralExpression", value: { type: "NumericLiteral", value: Number(getCurrentToken(parser).lexeme) }};
178
+ parser.position++;
179
+ } else if (isCurrentTokenType(parser, "LeftRoundBracket")) {
180
+ parser.position++;
181
+ expression = { type: "GroupingExpression", expression: parseExpression(utkrisht, parser) };
182
+ expectToken(utkrisht, parser, "RightRoundBracket");
183
+ parser.position++;
184
+ } else if (isCurrentTokenType(parser, "Identifier")) {
185
+ expression = parseVariableExpression(utkrisht, parser);
186
+ } else {
187
+ throw error(
188
+ utkrisht,
189
+ isCurrentTokenType(parser, "EndOfFile")
190
+ ? "Expected an expression but reached end of code"
191
+ : "Expected an expression but got " + getCurrentToken(parser).type
192
+ ,
193
+ getCurrentToken(parser)
194
+ );
195
+ }
196
+
197
+ return expression;
198
+ }
199
+
200
+ function parseUnaryExpression(utkrisht, parser) {
201
+ if (isCurrentTokenType(parser, "ExclamationMark", "Minus")) {
202
+ const operator = getCurrentToken(parser);
203
+ parser.position++
204
+ const right = parseUnaryExpression(utkrisht, parser);
205
+ return { type: "UnaryExpression", operator, right };
206
+ }
207
+
208
+ return parsePrimaryExpression(utkrisht, parser);
209
+ }
210
+
211
+
212
+ function parseMultiplicationAndDivisionExpression(utkrisht, parser) {
213
+ let expression = parseUnaryExpression(utkrisht, parser);
214
+
215
+ while (isCurrentTokenType(parser, "Asterisk", "Slash")) {
216
+ const operator = getCurrentToken(parser);
217
+ parser.position++;
218
+ const right = parseUnaryExpression(utkrisht, parser)
219
+ expression = { left: expression, operator, right }
220
+ }
221
+
222
+ return expression;
223
+ }
224
+
225
+ function parseAdditionAndSubstractionExpression(utkrisht, parser) {
226
+ let expression = parseMultiplicationAndDivisionExpression(utkrisht, parser);
227
+
228
+ while (isCurrentTokenType(parser, "Plus", "Minus")) {
229
+ const operator = getCurrentToken(parser);
230
+ parser.position++;
231
+ const right = parseMultiplicationAndDivisionExpression(utkrisht, parser);
232
+ expression = { left: expression, operator, right }
233
+ }
234
+
235
+ return expression;
236
+ }
237
+
238
+
239
+ function parseComparisonExpression(utkrisht, parser) {
240
+ let expression = parseAdditionAndSubstractionExpression(utkrisht, parser);
241
+
242
+ while (isCurrentTokenType(parser, "MoreThan", "LessThan", "ExclamationMarkMoreThan", "ExclamationMarkLessThan")) {
243
+ const operator = getCurrentToken(parser);
244
+ parser.position++;
245
+ const right = parseAdditionAndSubstractionExpression(utkrisht, parser);
246
+ expression = { left: expression, operator, right }
247
+ }
248
+
249
+ return expression;
250
+ }
251
+
252
+ function parseEqualityAndInequalityExpression(utkrisht, parser) {
253
+ let expression = parseComparisonExpression(utkrisht, parser);
254
+
255
+ while (isCurrentTokenType(parser, "Equal", "ExclamationMarkEqual")) {
256
+ const operator = getCurrentToken(parser);
257
+ parser.position++;
258
+ const right = parseComparisonExpression(utkrisht, parser);
259
+ expression = { left: expression, operator, right };
260
+ }
261
+ return expression;
262
+ }
263
+
264
+ function parseExpression(utkrisht, parser) {
265
+ return parseEqualityAndInequalityExpression(utkrisht, parser);
266
+ }
267
+
268
+ function parseExpressionStatement(utkrisht, parser) {
269
+ const expressionStatement = parseExpression(utkrisht, parser);
270
+ expectToken(utkrisht, parser, "NewLine", "Dedent", "EndOfFile");
271
+ ignoreToken(parser, "NewLine")
272
+ return expressionStatement;
273
+ }
274
+
275
+
276
+ function parseWhenStatement(utkrisht, parser) {
277
+
278
+ }
279
+ function parseLoopStatement(utkrisht, parser) {
280
+
281
+ }
282
+ function parseTryStatement(utkrisht, parser) {
283
+
284
+ }
285
+ function parseExitStatement(utkrisht, parser) {
286
+
287
+ }
288
+ function parseStopOrSkipStatement(utkrisht, parser) {
289
+
290
+ }
291
+
292
+ function parseVariableAssignmentStatement(utkrisht, parser) {
293
+
294
+ }
295
+
296
+ function parseVariableDeclaration(utkrisht, parser) {
297
+ const name = getCurrentToken(parser);
298
+
299
+ const parametersOrArguments = [];
300
+ while (isCurrentTokenType(parser, "Identifier")) {
301
+ const name = getCurrentToken(parser);
302
+ parser.position++
303
+
304
+
305
+ }
306
+ }
307
+
308
+
309
+ function parseStatement(utkrisht, parser) {
310
+ if (isCurrentTokenType(parser, "When")) {
311
+ return parseWhenStatement(utkrisht, parser);
312
+ }
313
+ else if (isCurrentTokenType(parser, "Loop")) {
314
+ return parseLoopStatement(utkrisht, parser);
315
+ }
316
+ else if (isCurrentTokenType(parser, "Try")) {
317
+ return parseTryStatement(utkrisht, parser);
318
+ }
319
+ else if (isCurrentTokenType(parser, "Exit")) {
320
+ return parseExitStatement(utkrisht, parser);
321
+ }
322
+ else if (isCurrentTokenType(parser, "Stop", "Skip")) {
323
+ return parseStopOrSkipStatement(utkrisht, parser);
324
+ }
325
+ else if (isCurrentTokenType(parser, "Identifier") && isVariableAssignment(parser)) {
326
+ return parseVariableAssignmentStatement(utkrisht, parser);
327
+ }
328
+ else {
329
+ if (isCurrentTokenType(parser, "Else")) {
330
+ throw error(utkrisht, "Can not use `else` statement without `when` statement", getCurrentToken(parser));
331
+ } else if (isCurrentTokenType(parser, "Fix")) {
332
+ throw error(utkrisht, "Can not use `fix` statement without `try` statement", getCurrentToken(parser));
333
+ } else if (isCurrentTokenType(parser, "With")) {
334
+ throw error(utkrisht, "Can not use `with` statement without `loop` statement", getCurrentToken(parser))
335
+ } else {
336
+ return parseExpressionStatement(utkrisht, parser);
337
+ }
338
+ }
339
+ }
340
+
341
+
342
+
343
+
344
+
345
+ function parseDeclaration(utkrisht, parser) {
346
+ try {
347
+ if (isCurrentTokenType(parser, "Identifier") && isVariableDeclaration(parser)) {
348
+ parseVariableDeclaration(utkrisht, parser);
349
+ } else {
350
+ return parseStatement(utkrisht, parser);
351
+ }
352
+ } catch (error) {
353
+ // We are only concerned about parser errors, not bugs in this file.
354
+ if (error instanceof ParseError) {
355
+ synchronise(parser);
356
+ return undefined;
357
+ }
358
+
359
+ // If it is a different error, let the developer handle it
360
+ throw error;
361
+ }
362
+ }
363
+
364
+ export function parse(utkrisht, parser) {
365
+ const statements = [];
366
+
367
+ while (!isAtEnd(parser)) {
368
+ statements.push(parseDeclaration(utkrisht, parser));
369
+ }
370
+
371
+ return statements;
372
+ }
373
+
374
+
375
+
@@ -0,0 +1,53 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { createLexer, lex } from "./lexer.js";
3
+ import { createParser, parse } from "./parser.js";
4
+
5
+ export function createUtkrisht() {
6
+ return {
7
+ hadError: false
8
+ };
9
+ }
10
+
11
+
12
+ function run(utkrisht, source) {
13
+ const lexer = createLexer(source);
14
+ const tokens = lex(utkrisht, lexer);
15
+
16
+ console.log(JSON.stringify(tokens, null, 4))
17
+ if (utkrisht.hadError) {
18
+ return;
19
+ }
20
+ const parser = createParser(tokens);
21
+ const statements = parse(utkrisht, parser);
22
+
23
+ console.log(JSON.stringify(statements, null, 4));
24
+ }
25
+
26
+
27
+ function runFile(path) {
28
+ let data;
29
+ try {
30
+ data = readFileSync(path, "utf8");
31
+ } catch (err) {
32
+ console.error("Error reading file: ", err.message);
33
+ process.exit(0);
34
+ }
35
+
36
+ const utkrisht = createUtkrisht();
37
+
38
+ run(utkrisht, data);
39
+ }
40
+
41
+ export function main() {
42
+ const args = process.argv.slice(2);
43
+
44
+ if (args.length > 1) {
45
+ console.error("Usage node uki <input.uki>");
46
+ process.exit(0);
47
+ }
48
+
49
+ runFile(args[0]);
50
+ }
51
+
52
+ main();
53
+
@@ -0,0 +1,3 @@
1
+
2
+
3
+ # Utkrisht
@@ -0,0 +1,8 @@
1
+ {
2
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
3
+ // for the documentation about the extensions.json format
4
+ "recommendations": [
5
+ "dbaeumer.vscode-eslint",
6
+ "ms-vscode.extension-test-runner"
7
+ ]
8
+ }
@@ -0,0 +1,17 @@
1
+ // A launch configuration that launches the extension inside a new window
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ {
6
+ "version": "0.2.0",
7
+ "configurations": [
8
+ {
9
+ "name": "Run Extension",
10
+ "type": "extensionHost",
11
+ "request": "launch",
12
+ "args": [
13
+ "--extensionDevelopmentPath=${workspaceFolder}"
14
+ ]
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,5 @@
1
+ import { defineConfig } from '@vscode/test-cli';
2
+
3
+ export default defineConfig({
4
+ files: 'test/**/*.test.js',
5
+ });
@@ -0,0 +1,10 @@
1
+ .vscode/**
2
+ .vscode-test/**
3
+ test/**
4
+ .gitignore
5
+ .yarnrc
6
+ vsc-extension-quickstart.md
7
+ **/jsconfig.json
8
+ **/*.map
9
+ **/eslint.config.mjs
10
+ **/.vscode-test.*
@@ -0,0 +1,9 @@
1
+ # Change Log
2
+
3
+ All notable changes to the "utkrisht" extension will be documented in this file.
4
+
5
+ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
6
+
7
+ ## [Unreleased]
8
+
9
+ - Initial release
@@ -0,0 +1,65 @@
1
+ # utkrisht README
2
+
3
+ This is the README for your extension "utkrisht". After writing up a brief description, we recommend including the following sections.
4
+
5
+ ## Features
6
+
7
+ Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file.
8
+
9
+ For example if there is an image subfolder under your extension project workspace:
10
+
11
+ \!\[feature X\]\(images/feature-x.png\)
12
+
13
+ > Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow.
14
+
15
+ ## Requirements
16
+
17
+ If you have any requirements or dependencies, add a section describing those and how to install and configure them.
18
+
19
+ ## Extension Settings
20
+
21
+ Include if your extension adds any VS Code settings through the `contributes.configuration` extension point.
22
+
23
+ For example:
24
+
25
+ This extension contributes the following settings:
26
+
27
+ * `myExtension.enable`: Enable/disable this extension.
28
+ * `myExtension.thing`: Set to `blah` to do something.
29
+
30
+ ## Known Issues
31
+
32
+ Calling out known issues can help limit users opening duplicate issues against your extension.
33
+
34
+ ## Release Notes
35
+
36
+ Users appreciate release notes as you update your extension.
37
+
38
+ ### 1.0.0
39
+
40
+ Initial release of ...
41
+
42
+ ### 1.0.1
43
+
44
+ Fixed issue #.
45
+
46
+ ### 1.1.0
47
+
48
+ Added features X, Y, and Z.
49
+
50
+ ---
51
+
52
+ ## Working with Markdown
53
+
54
+ You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts:
55
+
56
+ * Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux)
57
+ * Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux)
58
+ * Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets
59
+
60
+ ## For more information
61
+
62
+ * [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown)
63
+ * [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/)
64
+
65
+ **Enjoy!**
@@ -0,0 +1,25 @@
1
+ import globals from "globals";
2
+
3
+ export default [{
4
+ files: ["**/*.js"],
5
+ languageOptions: {
6
+ globals: {
7
+ ...globals.commonjs,
8
+ ...globals.node,
9
+ ...globals.mocha,
10
+ },
11
+
12
+ ecmaVersion: 2022,
13
+ sourceType: "module",
14
+ },
15
+
16
+ rules: {
17
+ "no-const-assign": "warn",
18
+ "no-this-before-super": "warn",
19
+ "no-undef": "warn",
20
+ "no-unreachable": "warn",
21
+ "no-unused-vars": "warn",
22
+ "constructor-super": "warn",
23
+ "valid-typeof": "warn",
24
+ },
25
+ }];
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "Node16",
4
+ "target": "ES2022",
5
+ "checkJs": false, /* Typecheck .js files. */
6
+ "lib": [
7
+ "ES2022"
8
+ ]
9
+ },
10
+ "exclude": [
11
+ "node_modules"
12
+ ]
13
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "comments": {
3
+ "lineComment": "#",
4
+ },
5
+ "brackets": [
6
+ [
7
+ "[",
8
+ "]"
9
+ ],
10
+ [
11
+ "{",
12
+ "}"
13
+ ],
14
+ [
15
+ "(",
16
+ ")"
17
+ ]
18
+ ],
19
+ "autoClosingPairs": [
20
+ [
21
+ "(",
22
+ ")"
23
+ ],
24
+ [
25
+ "{",
26
+ "}"
27
+ ],
28
+ [
29
+ "[",
30
+ "]"
31
+ ],
32
+ {
33
+ "open": "\"",
34
+ "close": "\"",
35
+ "notIn": ["string"]
36
+ }
37
+ ],
38
+ "surroundingPairs": [
39
+ [
40
+ "[",
41
+ "]"
42
+ ],
43
+ [
44
+ "(",
45
+ ")"
46
+ ],
47
+ [
48
+ "\"",
49
+ "\""
50
+ ],
51
+ [
52
+ "{", "}"
53
+ ]
54
+ ],
55
+ "folding": {
56
+ "offSide": true,
57
+ "markers": {
58
+ "start": "^\\s*#region",
59
+ "end": "^\\s*#endregion"
60
+ }
61
+ }
62
+ }
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg"
2
+ width="24" height="24"
3
+ viewBox="0 -960 960 960"
4
+ fill="#e3e3e3">
5
+ <g transform="rotate(180 480 -480)">
6
+ <path d="m256-120-56-56 193-194q23-23 35-52t12-61v-204l-64 63-56-56 160-160 160 160-56 56-64-63v204q0 32 12 61t35 52l193 194-56 56-224-224-224 224Z"/>
7
+ </g>
8
+ </svg>