@lewin671/python-vm 0.1.0 → 0.1.1

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 (142) hide show
  1. package/dist/compiler.d.ts.map +1 -0
  2. package/dist/compiler.js.map +1 -0
  3. package/dist/compiler_module/compiler.d.ts.map +1 -0
  4. package/dist/compiler_module/compiler.js.map +1 -0
  5. package/dist/compiler_module/index.d.ts.map +1 -0
  6. package/dist/compiler_module/index.js.map +1 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/lexer/index.d.ts.map +1 -0
  10. package/dist/lexer/index.js.map +1 -0
  11. package/dist/lexer/lexer.d.ts.map +1 -0
  12. package/dist/lexer/lexer.js.map +1 -0
  13. package/dist/parser/expressions.d.ts.map +1 -0
  14. package/dist/parser/expressions.js.map +1 -0
  15. package/dist/parser/index.d.ts.map +1 -0
  16. package/dist/parser/index.js.map +1 -0
  17. package/dist/parser/parser.d.ts.map +1 -0
  18. package/dist/parser/parser.js.map +1 -0
  19. package/dist/parser/statements.d.ts.map +1 -0
  20. package/dist/parser/statements.js.map +1 -0
  21. package/dist/parser/targets.d.ts.map +1 -0
  22. package/dist/parser/targets.js.map +1 -0
  23. package/dist/types/ast.d.ts.map +1 -0
  24. package/dist/types/ast.js.map +1 -0
  25. package/dist/types/bytecode.d.ts.map +1 -0
  26. package/dist/types/bytecode.js.map +1 -0
  27. package/dist/types/index.d.ts.map +1 -0
  28. package/dist/types/index.js.map +1 -0
  29. package/dist/types/token.d.ts.map +1 -0
  30. package/dist/types/token.js.map +1 -0
  31. package/dist/vm/builtins.d.ts.map +1 -0
  32. package/dist/vm/builtins.js.map +1 -0
  33. package/dist/vm/callable.d.ts.map +1 -0
  34. package/dist/vm/callable.js.map +1 -0
  35. package/dist/vm/execution.d.ts.map +1 -0
  36. package/dist/vm/execution.js.map +1 -0
  37. package/dist/vm/expression-generator.d.ts.map +1 -0
  38. package/dist/vm/expression-generator.js.map +1 -0
  39. package/dist/vm/expressions.d.ts.map +1 -0
  40. package/dist/vm/expressions.js.map +1 -0
  41. package/dist/vm/imports.d.ts.map +1 -0
  42. package/dist/vm/imports.js.map +1 -0
  43. package/dist/vm/index.d.ts.map +1 -0
  44. package/dist/vm/index.js.map +1 -0
  45. package/dist/vm/operations.d.ts.map +1 -0
  46. package/dist/vm/operations.js.map +1 -0
  47. package/dist/vm/runtime-types.d.ts.map +1 -0
  48. package/dist/vm/runtime-types.js.map +1 -0
  49. package/dist/vm/statements.d.ts.map +1 -0
  50. package/dist/vm/statements.js.map +1 -0
  51. package/dist/vm/truthy.d.ts.map +1 -0
  52. package/dist/vm/truthy.js.map +1 -0
  53. package/dist/vm/value-utils.d.ts.map +1 -0
  54. package/dist/vm/value-utils.js.map +1 -0
  55. package/dist/vm/vm.d.ts.map +1 -0
  56. package/dist/vm/vm.js.map +1 -0
  57. package/package.json +7 -1
  58. package/.claude/settings.local.json +0 -3
  59. package/.prettierrc +0 -7
  60. package/Agents.md +0 -66
  61. package/SETUP.md +0 -171
  62. package/examples/assert_testing.py +0 -38
  63. package/examples/big_int_precision.py +0 -2
  64. package/examples/boolean_logic.py +0 -35
  65. package/examples/break_continue.py +0 -43
  66. package/examples/classes_objects.py +0 -43
  67. package/examples/compiler_killer_async.py +0 -6
  68. package/examples/compiler_killer_bigint.py +0 -3
  69. package/examples/compiler_killer_bool_int_dict_key.py +0 -5
  70. package/examples/compiler_killer_bool_len.py +0 -9
  71. package/examples/compiler_killer_floor_division.py +0 -4
  72. package/examples/compiler_killer_is_identity.py +0 -3
  73. package/examples/compiler_killer_list_sort_return.py +0 -3
  74. package/examples/compiler_killer_match.py +0 -13
  75. package/examples/compiler_killer_negative_repeat.py +0 -3
  76. package/examples/compiler_killer_negative_zero_repr.py +0 -3
  77. package/examples/compiler_killer_rounding.py +0 -4
  78. package/examples/compiler_killer_slice_assign.py +0 -3
  79. package/examples/comprehensions.py +0 -28
  80. package/examples/conditions.py +0 -13
  81. package/examples/context_manager.py +0 -35
  82. package/examples/decorators.py +0 -50
  83. package/examples/exceptions.py +0 -40
  84. package/examples/fibonacci.py +0 -10
  85. package/examples/functions.py +0 -38
  86. package/examples/generator.py +0 -51
  87. package/examples/global_nonlocal.py +0 -48
  88. package/examples/hello.py +0 -3
  89. package/examples/itertools_example.py +0 -33
  90. package/examples/lists_dicts.py +0 -29
  91. package/examples/loops.py +0 -19
  92. package/examples/math_ops.py +0 -15
  93. package/examples/nan_set.py +0 -6
  94. package/examples/numbers_operators.py +0 -51
  95. package/examples/sets.py +0 -36
  96. package/examples/slicing.py +0 -29
  97. package/examples/starred_unpacking.py +0 -3
  98. package/examples/string_formatting.py +0 -36
  99. package/examples/strings.py +0 -22
  100. package/examples/tuples.py +0 -45
  101. package/examples/type_conversion.py +0 -41
  102. package/jest.config.js +0 -15
  103. package/notes/iterations/compiler-runtime/compiler-runtime_2025-09-16.md +0 -25
  104. package/notes/iterations/compiler-runtime/compiler-runtime_2026-01-16.md +0 -24
  105. package/notes/iterations/compiler-runtime/compiler-runtime_test_2026-01-16.md +0 -21
  106. package/notes/iterations/floor-division/floor-division_2026-01-16.md +0 -29
  107. package/prompts/commit.txt +0 -9
  108. package/prompts/task.txt +0 -21
  109. package/prompts/test.txt +0 -23
  110. package/scripts/codex-loop.js +0 -215
  111. package/scripts/verify.sh +0 -12
  112. package/src/compiler.ts +0 -58
  113. package/src/compiler_module/compiler.ts +0 -19
  114. package/src/compiler_module/index.ts +0 -1
  115. package/src/index.ts +0 -39
  116. package/src/lexer/index.ts +0 -1
  117. package/src/lexer/lexer.ts +0 -402
  118. package/src/parser/expressions.ts +0 -462
  119. package/src/parser/index.ts +0 -1
  120. package/src/parser/parser.ts +0 -102
  121. package/src/parser/statements.ts +0 -366
  122. package/src/parser/targets.ts +0 -71
  123. package/src/types/ast.ts +0 -64
  124. package/src/types/bytecode.ts +0 -50
  125. package/src/types/index.ts +0 -3
  126. package/src/types/token.ts +0 -44
  127. package/src/vm/builtins.ts +0 -237
  128. package/src/vm/callable.ts +0 -154
  129. package/src/vm/execution.ts +0 -251
  130. package/src/vm/expression-generator.ts +0 -65
  131. package/src/vm/expressions.ts +0 -373
  132. package/src/vm/imports.ts +0 -61
  133. package/src/vm/index.ts +0 -2
  134. package/src/vm/operations.ts +0 -414
  135. package/src/vm/runtime-types.ts +0 -292
  136. package/src/vm/statements.ts +0 -358
  137. package/src/vm/truthy.ts +0 -36
  138. package/src/vm/value-utils.ts +0 -173
  139. package/src/vm/vm.ts +0 -80
  140. package/tests/compiler.test.ts +0 -111
  141. package/tsconfig.json +0 -20
  142. package/vitest.config.ts +0 -16
@@ -1,462 +0,0 @@
1
- import type { Parser } from './parser';
2
- import { ASTNode, ASTNodeType, TokenType } from '../types';
3
-
4
- export function parseStringLiteral(this: Parser): ASTNode {
5
- let value = '';
6
- while (this.match(TokenType.STRING)) value += this.consume().value;
7
- return { type: ASTNodeType.STRING_LITERAL, value };
8
- }
9
-
10
- export function parseLiteral(this: Parser): ASTNode {
11
- const token = this.peek();
12
- if (!token) throw new Error('Expected literal');
13
- if (token.type === TokenType.NUMBER) {
14
- this.consume();
15
- return { type: ASTNodeType.NUMBER_LITERAL, value: token.value };
16
- }
17
- if (token.type === TokenType.STRING) return this.parseStringLiteral();
18
- if (token.type === TokenType.BOOLEAN) {
19
- this.consume();
20
- return { type: ASTNodeType.BOOLEAN_LITERAL, value: token.value === 'True' };
21
- }
22
- if (token.type === TokenType.NONE) {
23
- this.consume();
24
- return { type: ASTNodeType.NONE_LITERAL, value: null };
25
- }
26
- throw new Error(`Unexpected token type for literal: ${TokenType[token.type]}`);
27
- }
28
-
29
- export function parseIdentifier(this: Parser): ASTNode {
30
- const token = this.expect(TokenType.IDENTIFIER);
31
- return { type: ASTNodeType.IDENTIFIER, name: token.value };
32
- }
33
-
34
- export function parseArguments(this: Parser): ASTNode[] {
35
- const args: ASTNode[] = [];
36
- if (!this.match(TokenType.RPAREN)) {
37
- while (true) {
38
- if (this.match(TokenType.OPERATOR, '*') || this.match(TokenType.OPERATOR, '**')) {
39
- const op = this.consume().value;
40
- const value = this.parseExpression();
41
- args.push({ type: op === '*' ? 'StarArg' : 'KwArg', value } as any);
42
- } else if (this.match(TokenType.IDENTIFIER) && this.peek(1)?.type === TokenType.ASSIGN) {
43
- const name = this.consume().value;
44
- this.consume();
45
- const value = this.parseExpression();
46
- args.push({ type: 'KeywordArg', name, value } as any);
47
- } else {
48
- args.push(this.parseExpression());
49
- }
50
- if (!this.match(TokenType.COMMA)) break;
51
- this.consume();
52
- if (this.match(TokenType.RPAREN)) break;
53
- }
54
- }
55
- return args;
56
- }
57
-
58
- export function parseSlice(this: Parser): ASTNode {
59
- let start: ASTNode | null = null;
60
- let end: ASTNode | null = null;
61
- let step: ASTNode | null = null;
62
- if (!this.match(TokenType.COLON)) start = this.parseExpression();
63
- if (this.match(TokenType.COLON)) {
64
- this.consume();
65
- if (!this.match(TokenType.COLON) && !this.match(TokenType.RBRACKET)) end = this.parseExpression();
66
- if (this.match(TokenType.COLON)) {
67
- this.consume();
68
- if (!this.match(TokenType.RBRACKET)) step = this.parseExpression();
69
- }
70
- return { type: ASTNodeType.SLICE, start, end, step };
71
- }
72
- return start as ASTNode;
73
- }
74
-
75
- export function parsePatternAtom(this: Parser): ASTNode {
76
- if (this.match(TokenType.NUMBER) || this.match(TokenType.STRING) || this.match(TokenType.BOOLEAN) || this.match(TokenType.NONE)) {
77
- return { type: ASTNodeType.MATCH_PATTERN_VALUE, value: this.parseLiteral() } as any;
78
- }
79
- if (this.match(TokenType.IDENTIFIER)) {
80
- const name = this.consume().value;
81
- if (name === '_') return { type: ASTNodeType.MATCH_PATTERN_WILDCARD } as any;
82
- return { type: ASTNodeType.MATCH_PATTERN_CAPTURE, name } as any;
83
- }
84
- if (this.match(TokenType.LBRACKET)) {
85
- this.consume();
86
- const elements: ASTNode[] = [];
87
- if (!this.match(TokenType.RBRACKET)) {
88
- elements.push(this.parsePattern());
89
- while (this.match(TokenType.COMMA)) {
90
- this.consume();
91
- if (this.match(TokenType.RBRACKET)) break;
92
- elements.push(this.parsePattern());
93
- }
94
- }
95
- this.expect(TokenType.RBRACKET);
96
- return { type: ASTNodeType.MATCH_PATTERN_SEQUENCE, elements } as any;
97
- }
98
- throw new Error(`Unexpected token in pattern: ${this.peek()?.value}`);
99
- }
100
-
101
- export function parsePattern(this: Parser): ASTNode {
102
- let pattern = this.parsePatternAtom();
103
- if (this.match(TokenType.OPERATOR, '|')) {
104
- const patterns: ASTNode[] = [pattern];
105
- while (this.match(TokenType.OPERATOR, '|')) {
106
- this.consume();
107
- patterns.push(this.parsePatternAtom());
108
- }
109
- pattern = { type: ASTNodeType.MATCH_PATTERN_OR, patterns } as any;
110
- }
111
- return pattern;
112
- }
113
-
114
- export function parseLambdaParameters(this: Parser): string[] {
115
- const params: string[] = [];
116
- if (this.match(TokenType.COLON)) return params;
117
- while (true) {
118
- if (this.match(TokenType.OPERATOR, '*')) {
119
- this.consume();
120
- params.push(`*${this.expect(TokenType.IDENTIFIER).value}`);
121
- } else if (this.match(TokenType.OPERATOR, '**')) {
122
- this.consume();
123
- params.push(`**${this.expect(TokenType.IDENTIFIER).value}`);
124
- } else {
125
- const name = this.expect(TokenType.IDENTIFIER).value;
126
- if (this.match(TokenType.ASSIGN)) {
127
- this.consume();
128
- this.parseExpression();
129
- }
130
- params.push(name);
131
- }
132
- if (!this.match(TokenType.COMMA)) break;
133
- this.consume();
134
- }
135
- return params;
136
- }
137
-
138
- export function parseLambda(this: Parser): ASTNode {
139
- this.consume(); // lambda
140
- const params = this.parseLambdaParameters();
141
- this.expect(TokenType.COLON);
142
- const body = this.parseExpression();
143
- return { type: ASTNodeType.LAMBDA, params, body };
144
- }
145
-
146
- export function parseAtom(this: Parser): ASTNode {
147
- if (this.match(TokenType.LPAREN)) {
148
- this.consume();
149
- if (this.match(TokenType.RPAREN)) {
150
- this.consume();
151
- return { type: ASTNodeType.TUPLE_LITERAL, elements: [] };
152
- }
153
- const expr = this.parseExpression();
154
- if (this.match(TokenType.KEYWORD, 'for')) {
155
- const comprehension = this.parseComprehension(expr);
156
- this.expect(TokenType.RPAREN);
157
- return { type: ASTNodeType.GENERATOR_EXPR, expression: expr, comprehension };
158
- }
159
- if (this.match(TokenType.COMMA)) {
160
- const elements = [expr];
161
- while (this.match(TokenType.COMMA)) {
162
- this.consume();
163
- if (this.match(TokenType.RPAREN)) break;
164
- elements.push(this.parseExpression());
165
- }
166
- this.expect(TokenType.RPAREN);
167
- return { type: ASTNodeType.TUPLE_LITERAL, elements };
168
- }
169
- this.expect(TokenType.RPAREN);
170
- return expr;
171
- }
172
- if (this.match(TokenType.KEYWORD, 'yield')) {
173
- this.consume();
174
- const value = this.match(TokenType.NEWLINE) || this.match(TokenType.COMMA) || this.match(TokenType.RPAREN) ? null : this.parseExpression();
175
- return { type: ASTNodeType.YIELD, value };
176
- }
177
- if (this.match(TokenType.KEYWORD, 'lambda')) {
178
- return this.parseLambda();
179
- }
180
- if (this.match(TokenType.LBRACKET)) {
181
- this.consume();
182
- if (this.match(TokenType.RBRACKET)) {
183
- this.consume();
184
- return { type: ASTNodeType.LIST_LITERAL, elements: [] };
185
- }
186
- const first = this.parseExpression();
187
- if (this.match(TokenType.KEYWORD, 'for')) {
188
- const comprehension = this.parseComprehension(first);
189
- this.expect(TokenType.RBRACKET);
190
- return { type: ASTNodeType.LIST_COMP, expression: first, comprehension };
191
- }
192
- const elements = [first];
193
- while (this.match(TokenType.COMMA)) {
194
- this.consume();
195
- if (this.match(TokenType.RBRACKET)) break;
196
- elements.push(this.parseExpression());
197
- }
198
- this.expect(TokenType.RBRACKET);
199
- return { type: ASTNodeType.LIST_LITERAL, elements };
200
- }
201
- if (this.match(TokenType.LBRACE)) {
202
- this.consume();
203
- if (this.match(TokenType.RBRACE)) {
204
- this.consume();
205
- return { type: ASTNodeType.DICT_LITERAL, entries: [] };
206
- }
207
- const key = this.parseExpression();
208
- if (this.match(TokenType.COLON)) {
209
- this.consume();
210
- const value = this.parseExpression();
211
- if (this.match(TokenType.KEYWORD, 'for')) {
212
- const comprehension = this.parseComprehension({ type: 'KeyValue', key, value } as any);
213
- this.expect(TokenType.RBRACE);
214
- return { type: ASTNodeType.DICT_COMP, key, value, comprehension };
215
- }
216
- const entries = [{ key, value }];
217
- while (this.match(TokenType.COMMA)) {
218
- this.consume();
219
- if (this.match(TokenType.RBRACE)) break;
220
- const k = this.parseExpression();
221
- this.expect(TokenType.COLON);
222
- const v = this.parseExpression();
223
- entries.push({ key: k, value: v });
224
- }
225
- this.expect(TokenType.RBRACE);
226
- return { type: ASTNodeType.DICT_LITERAL, entries };
227
- }
228
- if (this.match(TokenType.KEYWORD, 'for')) {
229
- const comprehension = this.parseComprehension(key);
230
- this.expect(TokenType.RBRACE);
231
- return { type: ASTNodeType.SET_COMP, expression: key, comprehension };
232
- }
233
- const elements = [key];
234
- while (this.match(TokenType.COMMA)) {
235
- this.consume();
236
- if (this.match(TokenType.RBRACE)) break;
237
- elements.push(this.parseExpression());
238
- }
239
- this.expect(TokenType.RBRACE);
240
- return { type: ASTNodeType.SET_LITERAL, elements };
241
- }
242
- if (this.match(TokenType.IDENTIFIER)) {
243
- const name = this.consume().value;
244
- return { type: ASTNodeType.IDENTIFIER, name };
245
- }
246
- return this.parseLiteral();
247
- }
248
-
249
- export function parsePostfix(this: Parser): ASTNode {
250
- let expr = this.parseAtom();
251
- while (
252
- this.match(TokenType.LPAREN) ||
253
- this.match(TokenType.LBRACKET) ||
254
- (this.match(TokenType.DOT) && this.peek(1)?.type === TokenType.IDENTIFIER)
255
- ) {
256
- if (this.match(TokenType.LPAREN)) {
257
- this.consume();
258
- const args = this.parseArguments();
259
- this.expect(TokenType.RPAREN);
260
- expr = { type: ASTNodeType.CALL, callee: expr, args };
261
- } else if (this.match(TokenType.LBRACKET)) {
262
- this.consume();
263
- const index = this.parseSlice();
264
- this.expect(TokenType.RBRACKET);
265
- expr = { type: ASTNodeType.SUBSCRIPT, object: expr, index };
266
- } else if (this.match(TokenType.DOT)) {
267
- this.consume();
268
- const name = this.expect(TokenType.IDENTIFIER).value;
269
- expr = { type: ASTNodeType.ATTRIBUTE, object: expr, name };
270
- }
271
- }
272
- return expr;
273
- }
274
-
275
- export function parseUnary(this: Parser): ASTNode {
276
- if (this.match(TokenType.OPERATOR, '+') || this.match(TokenType.OPERATOR, '-') || this.match(TokenType.OPERATOR, '~')) {
277
- const operator = this.consume().value;
278
- const operand = this.parseUnary();
279
- return { type: ASTNodeType.UNARY_OPERATION, operator, operand };
280
- }
281
- if (this.match(TokenType.KEYWORD) && this.peek()?.value === 'not') {
282
- this.consume();
283
- const operand = this.parseUnary();
284
- return { type: ASTNodeType.UNARY_OPERATION, operator: 'not', operand };
285
- }
286
- return this.parsePostfix();
287
- }
288
-
289
- export function parsePower(this: Parser): ASTNode {
290
- let left = this.parseUnary();
291
- if (this.match(TokenType.OPERATOR, '**')) {
292
- this.consume();
293
- const right = this.parsePower();
294
- left = { type: ASTNodeType.BINARY_OPERATION, operator: '**', left, right };
295
- }
296
- return left;
297
- }
298
-
299
- export function parseFactor(this: Parser): ASTNode {
300
- let left = this.parsePower();
301
- while (this.match(TokenType.OPERATOR, '*') || this.match(TokenType.OPERATOR, '/') || this.match(TokenType.OPERATOR, '//') || this.match(TokenType.OPERATOR, '%')) {
302
- const operator = this.consume().value;
303
- const right = this.parsePower();
304
- left = { type: ASTNodeType.BINARY_OPERATION, operator, left, right };
305
- }
306
- return left;
307
- }
308
-
309
- export function parseTerm(this: Parser): ASTNode {
310
- let left = this.parseFactor();
311
- while (this.match(TokenType.OPERATOR, '+') || this.match(TokenType.OPERATOR, '-')) {
312
- const operator = this.consume().value;
313
- const right = this.parseFactor();
314
- left = { type: ASTNodeType.BINARY_OPERATION, operator, left, right };
315
- }
316
- return left;
317
- }
318
-
319
- export function parseShift(this: Parser): ASTNode {
320
- let left = this.parseTerm();
321
- while (this.match(TokenType.OPERATOR, '<<') || this.match(TokenType.OPERATOR, '>>')) {
322
- const operator = this.consume().value;
323
- const right = this.parseTerm();
324
- left = { type: ASTNodeType.BINARY_OPERATION, operator, left, right };
325
- }
326
- return left;
327
- }
328
-
329
- export function parseBitAnd(this: Parser): ASTNode {
330
- let left = this.parseShift();
331
- while (this.match(TokenType.OPERATOR, '&')) {
332
- this.consume();
333
- const right = this.parseShift();
334
- left = { type: ASTNodeType.BINARY_OPERATION, operator: '&', left, right };
335
- }
336
- return left;
337
- }
338
-
339
- export function parseBitXor(this: Parser): ASTNode {
340
- let left = this.parseBitAnd();
341
- while (this.match(TokenType.OPERATOR, '^')) {
342
- this.consume();
343
- const right = this.parseBitAnd();
344
- left = { type: ASTNodeType.BINARY_OPERATION, operator: '^', left, right };
345
- }
346
- return left;
347
- }
348
-
349
- export function parseBitOr(this: Parser): ASTNode {
350
- let left = this.parseBitXor();
351
- while (this.match(TokenType.OPERATOR, '|')) {
352
- this.consume();
353
- const right = this.parseBitXor();
354
- left = { type: ASTNodeType.BINARY_OPERATION, operator: '|', left, right };
355
- }
356
- return left;
357
- }
358
-
359
- export function parseComparison(this: Parser): ASTNode {
360
- let left = this.parseBitOr();
361
- const operators: string[] = [];
362
- const comparators: ASTNode[] = [];
363
- while (true) {
364
- if (this.match(TokenType.KEYWORD, 'not') && this.peek(1)?.type === TokenType.KEYWORD && this.peek(1)?.value === 'in') {
365
- this.consume();
366
- this.consume();
367
- operators.push('not in');
368
- comparators.push(this.parseBitOr());
369
- continue;
370
- }
371
- if (this.match(TokenType.KEYWORD, 'is') && this.peek(1)?.type === TokenType.KEYWORD && this.peek(1)?.value === 'not') {
372
- this.consume();
373
- this.consume();
374
- operators.push('is not');
375
- comparators.push(this.parseBitOr());
376
- continue;
377
- }
378
- if (
379
- this.match(TokenType.OPERATOR, '==') ||
380
- this.match(TokenType.OPERATOR, '!=') ||
381
- this.match(TokenType.OPERATOR, '<') ||
382
- this.match(TokenType.OPERATOR, '>') ||
383
- this.match(TokenType.OPERATOR, '<=') ||
384
- this.match(TokenType.OPERATOR, '>=') ||
385
- this.match(TokenType.KEYWORD, 'in') ||
386
- this.match(TokenType.KEYWORD, 'is')
387
- ) {
388
- operators.push(this.consume().value);
389
- comparators.push(this.parseBitOr());
390
- continue;
391
- }
392
- break;
393
- }
394
- if (operators.length === 0) return left;
395
- return { type: ASTNodeType.COMPARE, left, ops: operators, comparators };
396
- }
397
-
398
- export function parseNot(this: Parser): ASTNode {
399
- if (this.match(TokenType.KEYWORD, 'not')) {
400
- this.consume();
401
- const operand = this.parseNot();
402
- return { type: ASTNodeType.UNARY_OPERATION, operator: 'not', operand };
403
- }
404
- return this.parseComparison();
405
- }
406
-
407
- export function parseAnd(this: Parser): ASTNode {
408
- let left = this.parseNot();
409
- while (this.match(TokenType.KEYWORD, 'and')) {
410
- this.consume();
411
- const right = this.parseNot();
412
- left = { type: ASTNodeType.BOOL_OPERATION, operator: 'and', values: [left, right] };
413
- }
414
- return left;
415
- }
416
-
417
- export function parseOr(this: Parser): ASTNode {
418
- let left = this.parseAnd();
419
- while (this.match(TokenType.KEYWORD, 'or')) {
420
- this.consume();
421
- const right = this.parseAnd();
422
- left = { type: ASTNodeType.BOOL_OPERATION, operator: 'or', values: [left, right] };
423
- }
424
- return left;
425
- }
426
-
427
- export function parseIfExpression(this: Parser): ASTNode {
428
- const expr = this.parseOr();
429
- if (this.match(TokenType.KEYWORD, 'if')) {
430
- this.consume();
431
- const test = this.parseOr();
432
- this.expect(TokenType.KEYWORD, 'else');
433
- const alternate = this.parseIfExpression();
434
- return { type: ASTNodeType.IF_EXPRESSION, test, consequent: expr, alternate };
435
- }
436
- return expr;
437
- }
438
-
439
- export function parseExpression(this: Parser): ASTNode {
440
- return this.parseIfExpression();
441
- }
442
-
443
- export function parseExpressionNoIf(this: Parser): ASTNode {
444
- return this.parseOr();
445
- }
446
-
447
- export function parseComprehension(this: Parser, expression: ASTNode): ASTNode {
448
- const clauses: any[] = [];
449
- while (this.match(TokenType.KEYWORD, 'for')) {
450
- this.consume();
451
- const target = this.parseTarget();
452
- this.expect(TokenType.KEYWORD, 'in');
453
- const iter = this.parseExpressionNoIf();
454
- const ifs: ASTNode[] = [];
455
- while (this.match(TokenType.KEYWORD, 'if')) {
456
- this.consume();
457
- ifs.push(this.parseExpression());
458
- }
459
- clauses.push({ target, iter, ifs });
460
- }
461
- return { clauses, expression } as any;
462
- }
@@ -1 +0,0 @@
1
- export { Parser } from './parser';
@@ -1,102 +0,0 @@
1
- import { Token, TokenType, ASTNode } from '../types';
2
- import * as Expr from './expressions';
3
- import * as Target from './targets';
4
- import * as Stmt from './statements';
5
-
6
- export class Parser {
7
- tokens: Token[];
8
- pos = 0;
9
-
10
- constructor(tokens: Token[]) {
11
- this.tokens = tokens;
12
- }
13
-
14
- peek(offset: number = 0): Token | null {
15
- return this.pos + offset < this.tokens.length ? this.tokens[this.pos + offset] : null;
16
- }
17
-
18
- consume(): Token {
19
- if (this.pos >= this.tokens.length) throw new Error('Unexpected end of input');
20
- return this.tokens[this.pos++];
21
- }
22
-
23
- match(type: TokenType, value?: string): boolean {
24
- const token = this.peek();
25
- return !!token && token.type === type && (value === undefined || token.value === value);
26
- }
27
-
28
- expect(type: TokenType, value?: string): Token {
29
- const token = this.peek();
30
- if (!token) throw new Error(`Expected ${TokenType[type]}${value ? ` \"${value}\"` : ''}, but got end of input`);
31
- if (token.type !== type) {
32
- throw new Error(
33
- `Expected ${TokenType[type]}${value ? ` \"${value}\"` : ''}, but got ${TokenType[token.type]} \"${token.value}\" at line ${token.line}`
34
- );
35
- }
36
- if (value !== undefined && token.value !== value) {
37
- throw new Error(`Expected \"${value}\", but got \"${token.value}\" at line ${token.line}`);
38
- }
39
- return this.consume();
40
- }
41
-
42
- skipNewlines(): void {
43
- while (this.match(TokenType.NEWLINE)) {
44
- this.consume();
45
- }
46
- }
47
-
48
- // Expression parsing
49
- parseStringLiteral = Expr.parseStringLiteral;
50
- parseLiteral = Expr.parseLiteral;
51
- parseIdentifier = Expr.parseIdentifier;
52
- parseArguments = Expr.parseArguments;
53
- parseSlice = Expr.parseSlice;
54
- parsePatternAtom = Expr.parsePatternAtom;
55
- parsePattern = Expr.parsePattern;
56
- parseLambdaParameters = Expr.parseLambdaParameters;
57
- parseLambda = Expr.parseLambda;
58
- parseAtom = Expr.parseAtom;
59
- parsePostfix = Expr.parsePostfix;
60
- parsePostfixTarget = Target.parsePostfixTarget;
61
- parseTargetElement = Target.parseTargetElement;
62
- parseTarget = Target.parseTarget;
63
- parseUnary = Expr.parseUnary;
64
- parsePower = Expr.parsePower;
65
- parseFactor = Expr.parseFactor;
66
- parseTerm = Expr.parseTerm;
67
- parseShift = Expr.parseShift;
68
- parseBitAnd = Expr.parseBitAnd;
69
- parseBitXor = Expr.parseBitXor;
70
- parseBitOr = Expr.parseBitOr;
71
- parseComparison = Expr.parseComparison;
72
- parseNot = Expr.parseNot;
73
- parseAnd = Expr.parseAnd;
74
- parseOr = Expr.parseOr;
75
- parseIfExpression = Expr.parseIfExpression;
76
- parseExpression = Expr.parseExpression;
77
- parseExpressionNoIf = Expr.parseExpressionNoIf;
78
- parseComprehension = Expr.parseComprehension;
79
-
80
- // Statement parsing
81
- parseExpressionStatement = Stmt.parseExpressionStatement;
82
- parseExpressionList = Stmt.parseExpressionList;
83
- parseAssignmentOrExpression = Stmt.parseAssignmentOrExpression;
84
- parseBlock = Stmt.parseBlock;
85
- parseIfStatement = Stmt.parseIfStatement;
86
- parseWhileStatement = Stmt.parseWhileStatement;
87
- parseForStatement = Stmt.parseForStatement;
88
- parseFunctionParameters = Stmt.parseFunctionParameters;
89
- parseFunctionDef = Stmt.parseFunctionDef;
90
- parseClassDef = Stmt.parseClassDef;
91
- parseDecorators = Stmt.parseDecorators;
92
- parseTryStatement = Stmt.parseTryStatement;
93
- parseWithStatement = Stmt.parseWithStatement;
94
- parseMatchStatement = Stmt.parseMatchStatement;
95
- parseImportStatement = Stmt.parseImportStatement;
96
- parseStatement = Stmt.parseStatement;
97
- parseProgram = Stmt.parseProgram;
98
-
99
- parse(): ASTNode {
100
- return this.parseProgram();
101
- }
102
- }