@lewin671/python-vm 0.1.0 → 0.1.2

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 (143) hide show
  1. package/README.md +1 -2
  2. package/dist/compiler.d.ts.map +1 -0
  3. package/dist/compiler.js.map +1 -0
  4. package/dist/compiler_module/compiler.d.ts.map +1 -0
  5. package/dist/compiler_module/compiler.js.map +1 -0
  6. package/dist/compiler_module/index.d.ts.map +1 -0
  7. package/dist/compiler_module/index.js.map +1 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/lexer/index.d.ts.map +1 -0
  11. package/dist/lexer/index.js.map +1 -0
  12. package/dist/lexer/lexer.d.ts.map +1 -0
  13. package/dist/lexer/lexer.js.map +1 -0
  14. package/dist/parser/expressions.d.ts.map +1 -0
  15. package/dist/parser/expressions.js.map +1 -0
  16. package/dist/parser/index.d.ts.map +1 -0
  17. package/dist/parser/index.js.map +1 -0
  18. package/dist/parser/parser.d.ts.map +1 -0
  19. package/dist/parser/parser.js.map +1 -0
  20. package/dist/parser/statements.d.ts.map +1 -0
  21. package/dist/parser/statements.js.map +1 -0
  22. package/dist/parser/targets.d.ts.map +1 -0
  23. package/dist/parser/targets.js.map +1 -0
  24. package/dist/types/ast.d.ts.map +1 -0
  25. package/dist/types/ast.js.map +1 -0
  26. package/dist/types/bytecode.d.ts.map +1 -0
  27. package/dist/types/bytecode.js.map +1 -0
  28. package/dist/types/index.d.ts.map +1 -0
  29. package/dist/types/index.js.map +1 -0
  30. package/dist/types/token.d.ts.map +1 -0
  31. package/dist/types/token.js.map +1 -0
  32. package/dist/vm/builtins.d.ts.map +1 -0
  33. package/dist/vm/builtins.js.map +1 -0
  34. package/dist/vm/callable.d.ts.map +1 -0
  35. package/dist/vm/callable.js.map +1 -0
  36. package/dist/vm/execution.d.ts.map +1 -0
  37. package/dist/vm/execution.js.map +1 -0
  38. package/dist/vm/expression-generator.d.ts.map +1 -0
  39. package/dist/vm/expression-generator.js.map +1 -0
  40. package/dist/vm/expressions.d.ts.map +1 -0
  41. package/dist/vm/expressions.js.map +1 -0
  42. package/dist/vm/imports.d.ts.map +1 -0
  43. package/dist/vm/imports.js.map +1 -0
  44. package/dist/vm/index.d.ts.map +1 -0
  45. package/dist/vm/index.js.map +1 -0
  46. package/dist/vm/operations.d.ts.map +1 -0
  47. package/dist/vm/operations.js.map +1 -0
  48. package/dist/vm/runtime-types.d.ts.map +1 -0
  49. package/dist/vm/runtime-types.js.map +1 -0
  50. package/dist/vm/statements.d.ts.map +1 -0
  51. package/dist/vm/statements.js.map +1 -0
  52. package/dist/vm/truthy.d.ts.map +1 -0
  53. package/dist/vm/truthy.js.map +1 -0
  54. package/dist/vm/value-utils.d.ts.map +1 -0
  55. package/dist/vm/value-utils.js.map +1 -0
  56. package/dist/vm/vm.d.ts.map +1 -0
  57. package/dist/vm/vm.js.map +1 -0
  58. package/package.json +7 -1
  59. package/.claude/settings.local.json +0 -3
  60. package/.prettierrc +0 -7
  61. package/Agents.md +0 -66
  62. package/SETUP.md +0 -171
  63. package/examples/assert_testing.py +0 -38
  64. package/examples/big_int_precision.py +0 -2
  65. package/examples/boolean_logic.py +0 -35
  66. package/examples/break_continue.py +0 -43
  67. package/examples/classes_objects.py +0 -43
  68. package/examples/compiler_killer_async.py +0 -6
  69. package/examples/compiler_killer_bigint.py +0 -3
  70. package/examples/compiler_killer_bool_int_dict_key.py +0 -5
  71. package/examples/compiler_killer_bool_len.py +0 -9
  72. package/examples/compiler_killer_floor_division.py +0 -4
  73. package/examples/compiler_killer_is_identity.py +0 -3
  74. package/examples/compiler_killer_list_sort_return.py +0 -3
  75. package/examples/compiler_killer_match.py +0 -13
  76. package/examples/compiler_killer_negative_repeat.py +0 -3
  77. package/examples/compiler_killer_negative_zero_repr.py +0 -3
  78. package/examples/compiler_killer_rounding.py +0 -4
  79. package/examples/compiler_killer_slice_assign.py +0 -3
  80. package/examples/comprehensions.py +0 -28
  81. package/examples/conditions.py +0 -13
  82. package/examples/context_manager.py +0 -35
  83. package/examples/decorators.py +0 -50
  84. package/examples/exceptions.py +0 -40
  85. package/examples/fibonacci.py +0 -10
  86. package/examples/functions.py +0 -38
  87. package/examples/generator.py +0 -51
  88. package/examples/global_nonlocal.py +0 -48
  89. package/examples/hello.py +0 -3
  90. package/examples/itertools_example.py +0 -33
  91. package/examples/lists_dicts.py +0 -29
  92. package/examples/loops.py +0 -19
  93. package/examples/math_ops.py +0 -15
  94. package/examples/nan_set.py +0 -6
  95. package/examples/numbers_operators.py +0 -51
  96. package/examples/sets.py +0 -36
  97. package/examples/slicing.py +0 -29
  98. package/examples/starred_unpacking.py +0 -3
  99. package/examples/string_formatting.py +0 -36
  100. package/examples/strings.py +0 -22
  101. package/examples/tuples.py +0 -45
  102. package/examples/type_conversion.py +0 -41
  103. package/jest.config.js +0 -15
  104. package/notes/iterations/compiler-runtime/compiler-runtime_2025-09-16.md +0 -25
  105. package/notes/iterations/compiler-runtime/compiler-runtime_2026-01-16.md +0 -24
  106. package/notes/iterations/compiler-runtime/compiler-runtime_test_2026-01-16.md +0 -21
  107. package/notes/iterations/floor-division/floor-division_2026-01-16.md +0 -29
  108. package/prompts/commit.txt +0 -9
  109. package/prompts/task.txt +0 -21
  110. package/prompts/test.txt +0 -23
  111. package/scripts/codex-loop.js +0 -215
  112. package/scripts/verify.sh +0 -12
  113. package/src/compiler.ts +0 -58
  114. package/src/compiler_module/compiler.ts +0 -19
  115. package/src/compiler_module/index.ts +0 -1
  116. package/src/index.ts +0 -39
  117. package/src/lexer/index.ts +0 -1
  118. package/src/lexer/lexer.ts +0 -402
  119. package/src/parser/expressions.ts +0 -462
  120. package/src/parser/index.ts +0 -1
  121. package/src/parser/parser.ts +0 -102
  122. package/src/parser/statements.ts +0 -366
  123. package/src/parser/targets.ts +0 -71
  124. package/src/types/ast.ts +0 -64
  125. package/src/types/bytecode.ts +0 -50
  126. package/src/types/index.ts +0 -3
  127. package/src/types/token.ts +0 -44
  128. package/src/vm/builtins.ts +0 -237
  129. package/src/vm/callable.ts +0 -154
  130. package/src/vm/execution.ts +0 -251
  131. package/src/vm/expression-generator.ts +0 -65
  132. package/src/vm/expressions.ts +0 -373
  133. package/src/vm/imports.ts +0 -61
  134. package/src/vm/index.ts +0 -2
  135. package/src/vm/operations.ts +0 -414
  136. package/src/vm/runtime-types.ts +0 -292
  137. package/src/vm/statements.ts +0 -358
  138. package/src/vm/truthy.ts +0 -36
  139. package/src/vm/value-utils.ts +0 -173
  140. package/src/vm/vm.ts +0 -80
  141. package/tests/compiler.test.ts +0 -111
  142. package/tsconfig.json +0 -20
  143. 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
- }