• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

source-academy / py-slang / 25385938634

05 May 2026 03:32PM UTC coverage: 72.848% (-1.0%) from 73.8%
25385938634

Pull #117

github

web-flow
Merge 2c0d79a8d into 78872e791
Pull Request #117: Add Pyodide implementation

1573 of 2394 branches covered (65.71%)

Branch coverage included in aggregate %.

43 of 43 new or added lines in 2 files covered. (100.0%)

12 existing lines in 1 file now uncovered.

4257 of 5609 relevant lines covered (75.9%)

11639.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.85
/src/parser/python-grammar.ts
1
// @ts-nocheck
2
// Generated automatically by nearley, version 2.20.1
3
// http://github.com/Hardmath123/nearley
4
function id(x: unknown[]) {
5
  return x[0];
3,466,614✔
6
}
7

8
import { ExprNS, FunctionParam, StmtNS } from "../ast-types";
9
import { Token } from "../tokenizer";
10
import pythonLexer from "./lexer";
11
import { toAstToken, toFunctionParam } from "./token-bridge";
12

13
const list = <T>([x]: [T]) => [x];
14✔
14
const drop = () => [];
100✔
15

16
/** Strip surrounding quotes and process escape sequences. */
17
function stripQuotes(s: string) {
18
  let inner;
19
  if (s.startsWith('"""') || s.startsWith("'''")) inner = s.slice(3, -3);
17,130✔
20
  else if (s.startsWith('"') || s.startsWith("'")) inner = s.slice(1, -1);
4,814!
UNCOV
21
  else return s;
×
22
  return inner.replace(/\\(["'\\\/bfnrtav0]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|.)/g, (_, ch) => {
17,130✔
23
    switch (ch[0]) {
128!
24
      case "n":
25
        return "\n";
81✔
26
      case "t":
27
        return "\t";
3✔
28
      case "r":
UNCOV
29
        return "\r";
×
30
      case "\\":
31
        return "\\";
21✔
32
      case "'":
33
        return "'";
16✔
34
      case '"':
35
        return '"';
4✔
36
      case "/":
UNCOV
37
        return "/";
×
38
      case "b":
UNCOV
39
        return "\b";
×
40
      case "f":
UNCOV
41
        return "\f";
×
42
      case "a":
UNCOV
43
        return "\x07";
×
44
      case "v":
UNCOV
45
        return "\x0B";
×
46
      case "0":
47
        return "\0";
1✔
48
      case "x":
49
        return String.fromCharCode(parseInt(ch.slice(1), 16));
1✔
50
      case "u":
UNCOV
51
        return String.fromCharCode(parseInt(ch.slice(1), 16));
×
52
      default:
53
        return "\\" + ch; // unrecognized escapes kept literally
1✔
54
    }
55
  });
56
}
57

58
// ── Leaf AST constructors (token → node) ────────────────────────────────
59
const astVariable = ([t]: [moo.Token]) => {
14✔
60
  const k = toAstToken(t);
190,740✔
61
  return new ExprNS.Variable(k, k, k);
190,740✔
62
};
63
const astBigInt = ([t]: [moo.Token]) => {
14✔
64
  const k = toAstToken(t);
11,011✔
65
  return new ExprNS.BigIntLiteral(k, k, t.value);
11,011✔
66
};
67
const astComplex = ([t]: [moo.Token]) => {
14✔
68
  const k = toAstToken(t);
288✔
69
  return new ExprNS.Complex(k, k, t.value);
288✔
70
};
71
const astNone = ([t]: [moo.Token]) => {
14✔
72
  const k = toAstToken(t);
6,845✔
73
  return new ExprNS.None(k, k);
6,845✔
74
};
75
const astString = ([t]: [moo.Token]) => {
14✔
76
  const k = toAstToken(t);
17,130✔
77
  return new ExprNS.Literal(k, k, stripQuotes(t.value));
17,130✔
78
};
79
const astTrue = ([t]: [moo.Token]) => {
14✔
80
  const k = toAstToken(t);
1,528✔
81
  return new ExprNS.Literal(k, k, true);
1,528✔
82
};
83
const astFalse = ([t]: [moo.Token]) => {
14✔
84
  const k = toAstToken(t);
1,502✔
85
  return new ExprNS.Literal(k, k, false);
1,502✔
86
};
87

88
// ── Operator AST constructors (children → node) ────────────────────────
89
const astBinary = ([l, op, r]: [ExprNS.Expr, Token, ExprNS.Expr]) =>
14✔
90
  new ExprNS.Binary(l.startToken, r.endToken, l, op, r);
8,032✔
91
const astBinaryTok = ([l, op, r]: [ExprNS.Expr, moo.Token, ExprNS.Expr]) =>
14✔
92
  new ExprNS.Binary(l.startToken, r.endToken, l, toAstToken(op), r);
56✔
93
const astBoolOp = ([l, op, r]: [ExprNS.Expr, moo.Token, ExprNS.Expr]) =>
14✔
94
  new ExprNS.BoolOp(l.startToken, r.endToken, l, toAstToken(op), r);
15,375✔
95
const astUnary = ([op, arg]: [moo.Token, ExprNS.Expr]) =>
14✔
96
  new ExprNS.Unary(toAstToken(op), arg.endToken, toAstToken(op), arg);
2,172✔
97
const astCompare = ([l, op, r]: [ExprNS.Expr, Token, ExprNS.Expr]) =>
14✔
98
  new ExprNS.Compare(l.startToken, r.endToken, l, op, r);
10,327✔
99

100
// ── Token / list helpers ────────────────────────────────────────────────
101
const tok = ([t]: [moo.Token]) => toAstToken(t);
15,692✔
102
const flatList = <T>([first, rest]: [T, [unknown, T][]]): T[] => [first, ...rest.map(d => d[1])];
204,570✔
103
const tokList = ([first, rest]: [moo.Token, [unknown, moo.Token][]]) => [
14✔
104
  toAstToken(first),
UNCOV
105
  ...rest.map(d => toAstToken(d[1])),
×
106
];
107
const Lexer = pythonLexer;
14✔
108
const ParserRules = [
14✔
109
  { name: "program$ebnf$1", symbols: [] },
110
  { name: "program$ebnf$1$subexpression$1", symbols: ["import_stmt", { type: "newline" }] },
111
  {
112
    name: "program$ebnf$1",
113
    symbols: ["program$ebnf$1", "program$ebnf$1$subexpression$1"],
114
    postprocess: function arrpush<T>(d: [T[], T]) {
115
      return d[0].concat([d[1]]);
9✔
116
    },
117
  },
118
  { name: "program$ebnf$2", symbols: [] },
119
  { name: "program$ebnf$2$subexpression$1", symbols: ["statement"] },
120
  { name: "program$ebnf$2$subexpression$1", symbols: [{ type: "newline" }] },
121
  {
122
    name: "program$ebnf$2",
123
    symbols: ["program$ebnf$2", "program$ebnf$2$subexpression$1"],
124
    postprocess: function arrpush<T>(d: [T[], T]) {
125
      return d[0].concat([d[1]]);
20,590✔
126
    },
127
  },
128
  {
129
    name: "program",
130
    symbols: ["program$ebnf$1", "program$ebnf$2"],
131
    postprocess: ([imports, stmts]: [
132
      [StmtNS.FromImport, moo.Token][],
133
      ([StmtNS.Stmt] | [moo.Token])[],
134
    ]) => {
135
      const importNodes = imports.map(d => d[0]);
23,262✔
136
      const stmtNodes = stmts.map(d => d[0]).filter(s => "startToken" in s);
398,391✔
137
      const filtered = [...importNodes, ...stmtNodes];
23,262✔
138
      const start = filtered[0]
23,262✔
139
        ? filtered[0].startToken
140
        : toAstToken({ type: "newline", value: "", line: 1, col: 1, offset: 0 });
141
      const end = filtered.length > 0 ? filtered[filtered.length - 1].endToken : start;
23,262✔
142
      return new StmtNS.FileInput(start, end, filtered, []);
23,262✔
143
    },
144
  },
145
  {
146
    name: "import_stmt",
147
    symbols: [{ literal: "from" }, "dotted_name", { literal: "import" }, "import_clause"],
148
    postprocess: ([kw, mod, , names]: [
149
      moo.Token,
150
      Token,
151
      moo.Token,
152
      StmtNS.FromImport["names"],
153
    ]) => {
154
      const last = names[names.length - 1];
11✔
155
      const endTok = last.alias || last.name;
11✔
156
      return new StmtNS.FromImport(toAstToken(kw), endTok, mod, names);
11✔
157
    },
158
  },
159
  { name: "dotted_name$ebnf$1", symbols: [] },
160
  { name: "dotted_name$ebnf$1$subexpression$1", symbols: [{ literal: "." }, { type: "name" }] },
161
  {
162
    name: "dotted_name$ebnf$1",
163
    symbols: ["dotted_name$ebnf$1", "dotted_name$ebnf$1$subexpression$1"],
164
    postprocess: function arrpush<T>(d: [T[], T]) {
165
      return d[0].concat([d[1]]);
2✔
166
    },
167
  },
168
  {
169
    name: "dotted_name",
170
    symbols: [{ type: "name" }, "dotted_name$ebnf$1"],
171
    postprocess: ([first, rest]: [moo.Token, [moo.Token, moo.Token][]]) => {
172
      const tok = toAstToken(first);
11✔
173
      for (const [, n] of rest) {
11✔
174
        const right = toAstToken(n);
2✔
175
        tok.lexeme = tok.lexeme + "." + right.lexeme;
2✔
176
      }
177
      return tok;
11✔
178
    },
179
  },
180
  { name: "import_clause", symbols: ["import_as_names"], postprocess: id },
181
  {
182
    name: "import_clause",
183
    symbols: [{ literal: "(" }, "import_as_names", { literal: ")" }],
184
    postprocess: ([, ns]: [moo.Token, StmtNS.FromImport["names"][number], moo.Token]) => ns,
3✔
185
  },
186
  { name: "import_as_names$ebnf$1", symbols: [] },
187
  { name: "import_as_names$ebnf$1$subexpression$1", symbols: [{ literal: "," }, "import_as_name"] },
188
  {
189
    name: "import_as_names$ebnf$1",
190
    symbols: ["import_as_names$ebnf$1", "import_as_names$ebnf$1$subexpression$1"],
191
    postprocess: function arrpush<T>(d: [T[], T]) {
192
      return d[0].concat([d[1]]);
4✔
193
    },
194
  },
195
  {
196
    name: "import_as_names",
197
    symbols: ["import_as_name", "import_as_names$ebnf$1"],
198
    postprocess: flatList,
199
  },
200
  {
201
    name: "import_as_name",
202
    symbols: [{ type: "name" }],
203
    postprocess: ([t]: [moo.Token]) => ({ name: toAstToken(t), alias: null }),
13✔
204
  },
205
  {
206
    name: "import_as_name",
207
    symbols: [{ type: "name" }, { literal: "as" }, { type: "name" }],
208
    postprocess: ([t, , a]: [moo.Token, moo.Token, moo.Token]) => ({
1✔
209
      name: toAstToken(t),
210
      alias: toAstToken(a),
211
    }),
212
  },
213
  { name: "statement", symbols: ["statementAssign", { type: "newline" }], postprocess: id },
214
  { name: "statement", symbols: ["statementAnnAssign", { type: "newline" }], postprocess: id },
215
  {
216
    name: "statement",
217
    symbols: ["statementSubscriptAssign", { type: "newline" }],
218
    postprocess: id,
219
  },
220
  { name: "statement", symbols: ["statementReturn", { type: "newline" }], postprocess: id },
221
  { name: "statement", symbols: ["statementPass", { type: "newline" }], postprocess: id },
222
  { name: "statement", symbols: ["statementBreak", { type: "newline" }], postprocess: id },
223
  { name: "statement", symbols: ["statementContinue", { type: "newline" }], postprocess: id },
224
  { name: "statement", symbols: ["statementGlobal", { type: "newline" }], postprocess: id },
225
  { name: "statement", symbols: ["statementNonlocal", { type: "newline" }], postprocess: id },
226
  { name: "statement", symbols: ["statementAssert", { type: "newline" }], postprocess: id },
227
  { name: "statement", symbols: ["statementExpr", { type: "newline" }], postprocess: id },
228
  { name: "statement", symbols: ["if_statement"], postprocess: id },
229
  { name: "statement", symbols: ["statementWhile"], postprocess: id },
230
  { name: "statement", symbols: ["statementFor"], postprocess: id },
231
  { name: "statement", symbols: ["statementDef"], postprocess: id },
232
  {
233
    name: "statementAssign",
234
    symbols: [{ type: "name" }, { literal: "=" }, "expression"],
235
    postprocess: ([n, , v]: [moo.Token, moo.Token, ExprNS.Expr]) => {
236
      const tok = toAstToken(n);
2,977✔
237
      return new StmtNS.Assign(tok, v.endToken, new ExprNS.Variable(tok, tok, tok), v);
2,977✔
238
    },
239
  },
240
  {
241
    name: "statementAnnAssign",
242
    symbols: [{ type: "name" }, { literal: ":" }, "expression", { literal: "=" }, "expression"],
243
    postprocess: ([n, , ann, , v]: [moo.Token, moo.Token, ExprNS.Expr, moo.Token, ExprNS.Expr]) => {
244
      const tok = toAstToken(n);
8✔
245
      return new StmtNS.AnnAssign(tok, v.endToken, new ExprNS.Variable(tok, tok, tok), v, ann);
8✔
246
    },
247
  },
248
  {
249
    name: "statementAnnAssign",
250
    symbols: [{ type: "name" }, { literal: ":" }, "expression"],
251
    postprocess: ([n, , ann]: [moo.Token, moo.Token, ExprNS.Expr]) => {
252
      const nameTok = toAstToken(n);
9✔
253
      const dummyVal = new ExprNS.None(ann.endToken, ann.endToken);
9✔
254
      return new StmtNS.AnnAssign(
9✔
255
        nameTok,
256
        ann.endToken,
257
        new ExprNS.Variable(nameTok, nameTok, nameTok),
258
        dummyVal,
259
        ann,
260
      );
261
    },
262
  },
263
  {
264
    name: "statementSubscriptAssign",
265
    symbols: [
266
      "expressionPost",
267
      { type: "lsqb" },
268
      "expression",
269
      { type: "rsqb" },
270
      { literal: "=" },
271
      "expression",
272
    ],
273
    postprocess: function (
274
      d: [ExprNS.Expr, moo.Token, ExprNS.Expr, moo.Token, moo.Token, ExprNS.Expr],
275
    ) {
276
      const obj = d[0],
440✔
277
        idx = d[2],
440✔
278
        rsqb = d[3],
440✔
279
        val = d[5];
440✔
280
      const sub = new ExprNS.Subscript(obj.startToken, toAstToken(rsqb), obj, idx);
440✔
281
      return new StmtNS.Assign(obj.startToken, val.endToken, sub, val);
440✔
282
    },
283
  },
284
  {
285
    name: "statementReturn",
286
    symbols: [{ literal: "return" }, "expression"],
287
    postprocess: ([kw, expr]: [moo.Token, ExprNS.Expr]) =>
288
      new StmtNS.Return(toAstToken(kw), expr.endToken, expr),
52,783✔
289
  },
290
  {
291
    name: "statementReturn",
292
    symbols: [{ literal: "return" }],
293
    postprocess: ([t]: [moo.Token]) => {
294
      const tok = toAstToken(t);
28,663✔
295
      return new StmtNS.Return(tok, tok, null);
28,663✔
296
    },
297
  },
298
  {
299
    name: "statementPass",
300
    symbols: [{ literal: "pass" }],
301
    postprocess: ([t]: [moo.Token]) => {
302
      const tok = toAstToken(t);
102✔
303
      return new StmtNS.Pass(tok, tok);
102✔
304
    },
305
  },
306
  {
307
    name: "statementBreak",
308
    symbols: [{ literal: "break" }],
309
    postprocess: ([t]: [moo.Token]) => {
310
      const tok = toAstToken(t);
22✔
311
      return new StmtNS.Break(tok, tok);
22✔
312
    },
313
  },
314
  {
315
    name: "statementContinue",
316
    symbols: [{ literal: "continue" }],
317
    postprocess: ([t]: [moo.Token]) => {
318
      const tok = toAstToken(t);
18✔
319
      return new StmtNS.Continue(tok, tok);
18✔
320
    },
321
  },
322
  {
323
    name: "statementGlobal",
324
    symbols: [{ literal: "global" }, { type: "name" }],
325
    postprocess: ([kw, n]: [moo.Token, moo.Token]) =>
326
      new StmtNS.Global(toAstToken(kw), toAstToken(n), toAstToken(n)),
2✔
327
  },
328
  {
329
    name: "statementNonlocal",
330
    symbols: [{ literal: "nonlocal" }, { type: "name" }],
331
    postprocess: ([kw, n]: [moo.Token, moo.Token]) =>
332
      new StmtNS.NonLocal(toAstToken(kw), toAstToken(n), toAstToken(n)),
20✔
333
  },
334
  {
335
    name: "statementAssert",
336
    symbols: [{ literal: "assert" }, "expression"],
337
    postprocess: ([kw, e]: [moo.Token, ExprNS.Expr]) =>
338
      new StmtNS.Assert(toAstToken(kw), e.endToken, e),
8✔
339
  },
340
  {
341
    name: "statementExpr",
342
    symbols: ["expression"],
343
    postprocess: ([e]: [ExprNS.Expr]) => new StmtNS.SimpleExpr(e.startToken, e.endToken, e),
23,535✔
344
  },
345
  {
346
    name: "statementWhile",
347
    symbols: [{ literal: "while" }, "expression", { literal: ":" }, "block"],
348
    postprocess: ([kw, test, , body]: [moo.Token, ExprNS.Expr, moo.Token, StmtNS.Stmt[]]) =>
349
      new StmtNS.While(toAstToken(kw), body[body.length - 1].endToken, test, body),
453✔
350
  },
351
  {
352
    name: "statementFor",
353
    symbols: [
354
      { literal: "for" },
355
      { type: "name" },
356
      { literal: "in" },
357
      "expression",
358
      { literal: ":" },
359
      "block",
360
    ],
361
    postprocess: ([kw, target, , iter, , body]: [
362
      moo.Token,
363
      moo.Token,
364
      moo.Token,
365
      ExprNS.Expr,
366
      moo.Token,
367
      StmtNS.Stmt[],
368
    ]) =>
369
      new StmtNS.For(
102✔
370
        toAstToken(kw),
371
        body[body.length - 1].endToken,
372
        toAstToken(target),
373
        iter,
374
        body,
375
      ),
376
  },
377
  {
378
    name: "statementDef",
379
    symbols: [{ literal: "def" }, { type: "name" }, "params", { literal: ":" }, "block"],
380
    postprocess: ([kw, name, params, , body]: [
381
      moo.Token,
382
      moo.Token,
383
      FunctionParam[],
384
      moo.Token,
385
      StmtNS.Stmt[],
386
    ]) =>
387
      new StmtNS.FunctionDef(
18,227✔
388
        toAstToken(kw),
389
        body[body.length - 1].endToken,
390
        toAstToken(name),
391
        params,
392
        body,
393
        [],
394
      ),
395
  },
396
  { name: "if_statement$ebnf$1", symbols: [] },
397
  {
398
    name: "if_statement$ebnf$1$subexpression$1",
399
    symbols: [{ literal: "elif" }, "expression", { literal: ":" }, "block"],
400
  },
401
  {
402
    name: "if_statement$ebnf$1",
403
    symbols: ["if_statement$ebnf$1", "if_statement$ebnf$1$subexpression$1"],
404
    postprocess: function arrpush<T>(d: [T[], T]) {
405
      return d[0].concat([d[1]]);
4,981✔
406
    },
407
  },
408
  {
409
    name: "if_statement$ebnf$2$subexpression$1",
410
    symbols: [{ literal: "else" }, { literal: ":" }, "block"],
411
  },
412
  {
413
    name: "if_statement$ebnf$2",
414
    symbols: ["if_statement$ebnf$2$subexpression$1"],
415
    postprocess: id,
416
  },
417
  {
418
    name: "if_statement$ebnf$2",
419
    symbols: [],
420
    postprocess: () => null,
12,233✔
421
  },
422
  {
423
    name: "if_statement",
424
    symbols: [
425
      { literal: "if" },
426
      "expression",
427
      { literal: ":" },
428
      "block",
429
      "if_statement$ebnf$1",
430
      "if_statement$ebnf$2",
431
    ],
432
    postprocess: ([kw, test, , body, elifs, elseBlock]: [
433
      moo.Token,
434
      ExprNS.Expr,
435
      moo.Token,
436
      StmtNS.Stmt[],
437
      [moo.Token, ExprNS.Expr, moo.Token, StmtNS.Stmt[]][],
438
      [moo.Token, moo.Token, StmtNS.Stmt[]],
439
    ]) => {
440
      let else_ = elseBlock ? elseBlock[2] : null;
17,984✔
441
      for (let i = elifs.length - 1; i >= 0; i--) {
17,984✔
442
        const [ekw, etest, , ebody] = elifs[i];
15,583✔
443
        const endTok =
444
          else_ && else_.length > 0
15,583✔
445
            ? else_[else_.length - 1].endToken
446
            : ebody[ebody.length - 1].endToken;
447
        else_ = [new StmtNS.If(toAstToken(ekw), endTok, etest, ebody, else_)];
15,583✔
448
      }
449
      const endTok =
450
        else_ && else_.length > 0
17,984✔
451
          ? else_[else_.length - 1].endToken
452
          : body[body.length - 1].endToken;
453
      return new StmtNS.If(toAstToken(kw), endTok, test, body, else_);
17,984✔
454
    },
455
  },
456
  { name: "names$ebnf$1", symbols: [] },
457
  { name: "names$ebnf$1$subexpression$1", symbols: [{ literal: "," }, { type: "name" }] },
458
  {
459
    name: "names$ebnf$1",
460
    symbols: ["names$ebnf$1", "names$ebnf$1$subexpression$1"],
461
    postprocess: function arrpush<T>(d: [T[], T]) {
UNCOV
462
      return d[0].concat([d[1]]);
×
463
    },
464
  },
465
  { name: "names", symbols: [{ type: "name" }, "names$ebnf$1"], postprocess: tokList },
466
  { name: "block", symbols: ["blockInline", { type: "newline" }], postprocess: list },
467
  { name: "block$ebnf$1$subexpression$1", symbols: ["statement"] },
468
  { name: "block$ebnf$1$subexpression$1", symbols: [{ type: "newline" }] },
469
  { name: "block$ebnf$1", symbols: ["block$ebnf$1$subexpression$1"] },
470
  { name: "block$ebnf$1$subexpression$2", symbols: ["statement"] },
471
  { name: "block$ebnf$1$subexpression$2", symbols: [{ type: "newline" }] },
472
  {
473
    name: "block$ebnf$1",
474
    symbols: ["block$ebnf$1", "block$ebnf$1$subexpression$2"],
475
    postprocess: function arrpush<T>(d: [T[], T]) {
476
      return d[0].concat([d[1]]);
22,586✔
477
    },
478
  },
479
  {
480
    name: "block",
481
    symbols: [{ type: "newline" }, { type: "indent" }, "block$ebnf$1", { type: "dedent" }],
482
    postprocess: ([, , stmts]: [moo.Token, moo.Token, ([StmtNS.Stmt] | [moo.Token])[]]) =>
483
      stmts.map(d => d[0]).filter(s => s && "startToken" in s),
53,899✔
484
  },
485
  { name: "blockInline", symbols: ["statementAssign"], postprocess: id },
486
  { name: "blockInline", symbols: ["statementAnnAssign"], postprocess: id },
487
  { name: "blockInline", symbols: ["statementSubscriptAssign"], postprocess: id },
488
  { name: "blockInline", symbols: ["statementReturn"], postprocess: id },
489
  { name: "blockInline", symbols: ["statementPass"], postprocess: id },
490
  { name: "blockInline", symbols: ["statementBreak"], postprocess: id },
491
  { name: "blockInline", symbols: ["statementContinue"], postprocess: id },
492
  { name: "blockInline", symbols: ["statementGlobal"], postprocess: id },
493
  { name: "blockInline", symbols: ["statementNonlocal"], postprocess: id },
494
  { name: "blockInline", symbols: ["statementAssert"], postprocess: id },
495
  { name: "blockInline", symbols: ["statementExpr"], postprocess: id },
496
  {
497
    name: "rest_names",
498
    symbols: [{ type: "name" }],
499
    postprocess: ([t]: [moo.Token]) => {
500
      const tok = toFunctionParam(t, false);
21,137✔
501
      return [tok];
21,137✔
502
    },
503
  },
504
  {
505
    name: "rest_names",
506
    symbols: [{ literal: "*" }, { type: "name" }],
507
    postprocess: ([, t]: [moo.Token, moo.Token]) => {
508
      const tok = toFunctionParam(t, true);
38✔
509
      return [tok];
38✔
510
    },
511
  },
512
  {
513
    name: "rest_names",
514
    symbols: ["rest_names", { literal: "," }, { type: "name" }],
515
    postprocess: ([params, , t]: [FunctionParam[], moo.Token, moo.Token]) => {
516
      const tok = toFunctionParam(t, false);
18,074✔
517
      return [...params, tok];
18,074✔
518
    },
519
  },
520
  {
521
    name: "rest_names",
522
    symbols: ["rest_names", { literal: "," }, { literal: "*" }, { type: "name" }],
523
    postprocess: ([params, , , t]: [FunctionParam[], moo.Token, moo.Token, moo.Token]) => {
524
      const tok = toFunctionParam(t, true);
16✔
525
      return [...params, tok];
16✔
526
    },
527
  },
528
  { name: "params", symbols: [{ literal: "(" }, { literal: ")" }], postprocess: drop },
529
  {
530
    name: "params",
531
    symbols: [{ literal: "(" }, "rest_names", { literal: ")" }],
532
    postprocess: ([, ps]: [moo.Token, FunctionParam[], moo.Token]) => ps,
18,129✔
533
  },
534
  {
535
    name: "expression",
536
    symbols: ["expressionOr", { literal: "if" }, "expressionOr", { literal: "else" }, "expression"],
537
    postprocess: ([cons, , test, , alt]: [
538
      ExprNS.Expr,
539
      moo.Token,
540
      ExprNS.Expr,
541
      moo.Token,
542
      ExprNS.Expr,
543
    ]) => new ExprNS.Ternary(cons.startToken, alt.endToken, test, cons, alt),
19,042✔
544
  },
545
  { name: "expression", symbols: ["expressionOr"], postprocess: id },
546
  { name: "expression", symbols: ["lambda_expr"], postprocess: id },
547
  {
548
    name: "expressionOr",
549
    symbols: ["expressionOr", { literal: "or" }, "expressionAnd"],
550
    postprocess: astBoolOp,
551
  },
552
  { name: "expressionOr", symbols: ["expressionAnd"], postprocess: id },
553
  {
554
    name: "expressionAnd",
555
    symbols: ["expressionAnd", { literal: "and" }, "expressionNot"],
556
    postprocess: astBoolOp,
557
  },
558
  { name: "expressionAnd", symbols: ["expressionNot"], postprocess: id },
559
  { name: "expressionNot", symbols: [{ literal: "not" }, "expressionNot"], postprocess: astUnary },
560
  { name: "expressionNot", symbols: ["expressionCmp"], postprocess: id },
561
  {
562
    name: "expressionCmp",
563
    symbols: ["expressionCmp", "expressionCmpOp", "expressionAdd"],
564
    postprocess: astCompare,
565
  },
566
  { name: "expressionCmp", symbols: ["expressionAdd"], postprocess: id },
567
  { name: "expressionCmpOp", symbols: [{ type: "less" }], postprocess: tok },
568
  { name: "expressionCmpOp", symbols: [{ type: "greater" }], postprocess: tok },
569
  { name: "expressionCmpOp", symbols: [{ type: "doubleequal" }], postprocess: tok },
570
  { name: "expressionCmpOp", symbols: [{ type: "greaterequal" }], postprocess: tok },
571
  { name: "expressionCmpOp", symbols: [{ type: "lessequal" }], postprocess: tok },
572
  { name: "expressionCmpOp", symbols: [{ type: "notequal" }], postprocess: tok },
573
  { name: "expressionCmpOp", symbols: [{ literal: "in" }], postprocess: tok },
574
  {
575
    name: "expressionCmpOp",
576
    symbols: [{ literal: "not" }, { literal: "in" }],
577
    postprocess: ([t]: [moo.Token]) => {
578
      const tok = toAstToken(t);
3✔
579
      tok.lexeme = "not in";
3✔
580
      return tok;
3✔
581
    },
582
  },
583
  { name: "expressionCmpOp", symbols: [{ literal: "is" }], postprocess: tok },
584
  {
585
    name: "expressionCmpOp",
586
    symbols: [{ literal: "is" }, { literal: "not" }],
587
    postprocess: ([t]: [moo.Token]) => {
588
      const tok = toAstToken(t);
3✔
589
      tok.lexeme = "is not";
3✔
590
      return tok;
3✔
591
    },
592
  },
593
  {
594
    name: "expressionAdd",
595
    symbols: ["expressionAdd", "expressionAddOp", "expressionMul"],
596
    postprocess: astBinary,
597
  },
598
  { name: "expressionAdd", symbols: ["expressionMul"], postprocess: id },
599
  { name: "expressionAddOp", symbols: [{ type: "plus" }], postprocess: tok },
600
  { name: "expressionAddOp", symbols: [{ type: "minus" }], postprocess: tok },
601
  {
602
    name: "expressionMul",
603
    symbols: ["expressionMul", "expressionMulOp", "expressionUnary"],
604
    postprocess: astBinary,
605
  },
606
  { name: "expressionMul", symbols: ["expressionUnary"], postprocess: id },
607
  { name: "expressionMulOp", symbols: [{ type: "star" }], postprocess: tok },
608
  { name: "expressionMulOp", symbols: [{ type: "slash" }], postprocess: tok },
609
  { name: "expressionMulOp", symbols: [{ type: "percent" }], postprocess: tok },
610
  { name: "expressionMulOp", symbols: [{ type: "doubleslash" }], postprocess: tok },
611
  {
612
    name: "expressionUnary",
613
    symbols: [{ type: "plus" }, "expressionUnary"],
614
    postprocess: astUnary,
615
  },
616
  {
617
    name: "expressionUnary",
618
    symbols: [{ type: "minus" }, "expressionUnary"],
619
    postprocess: astUnary,
620
  },
621
  { name: "expressionUnary", symbols: ["expressionPow"], postprocess: id },
622
  {
623
    name: "expressionPow",
624
    symbols: ["expressionPost", { type: "doublestar" }, "expressionUnary"],
625
    postprocess: astBinaryTok,
626
  },
627
  { name: "expressionPow", symbols: ["expressionPost"], postprocess: id },
628
  {
629
    name: "expressionPost",
630
    symbols: ["expressionPost", { type: "lsqb" }, "expression", { type: "rsqb" }],
631
    postprocess: ([obj, , idx, rsqb]: [ExprNS.Expr, moo.Token, ExprNS.Expr, moo.Token]) =>
632
      new ExprNS.Subscript(obj.startToken, toAstToken(rsqb), obj, idx),
712✔
633
  },
634
  {
635
    name: "expressionPost",
636
    symbols: ["expressionPost", { literal: "(" }, "spread_expressions", { literal: ")" }],
637
    postprocess: ([callee, , args, rparen]: [ExprNS.Expr, moo.Token, ExprNS.Expr[], moo.Token]) =>
638
      new ExprNS.Call(callee.startToken, toAstToken(rparen), callee, args),
88,843✔
639
  },
640
  {
641
    name: "expressionPost",
642
    symbols: ["expressionPost", { literal: "(" }, { literal: ")" }],
643
    postprocess: ([callee, , rparen]: [ExprNS.Expr, moo.Token, moo.Token]) =>
644
      new ExprNS.Call(callee.startToken, toAstToken(rparen), callee, []),
392✔
645
  },
646
  { name: "expressionPost", symbols: ["atom"], postprocess: id },
647
  {
648
    name: "atom",
649
    symbols: [{ literal: "(" }, "expression", { literal: ")" }],
650
    postprocess: ([, e]: [moo.Token, ExprNS.Expr, moo.Token]) =>
651
      new ExprNS.Grouping(e.startToken, e.endToken, e),
9,063✔
652
  },
653
  {
654
    name: "atom",
655
    symbols: [{ type: "lsqb" }, { type: "rsqb" }],
656
    postprocess: ([l, r]: [moo.Token, moo.Token]) =>
657
      new ExprNS.List(toAstToken(l), toAstToken(r), []),
15✔
658
  },
659
  {
660
    name: "atom",
661
    symbols: [{ type: "lsqb" }, "expressions", { type: "rsqb" }],
662
    postprocess: ([l, elems, r]: [moo.Token, ExprNS.Expr[], moo.Token]) =>
663
      new ExprNS.List(toAstToken(l), toAstToken(r), elems),
152✔
664
  },
665
  { name: "atom", symbols: [{ type: "name" }], postprocess: astVariable },
666
  {
667
    name: "atom",
668
    symbols: [{ type: "number_float" }],
669
    postprocess: ([t]: [moo.Token]) => {
670
      const tok = toAstToken(t);
344✔
671
      return new ExprNS.Literal(tok, tok, parseFloat(t.value));
344✔
672
    },
673
  },
674
  { name: "atom", symbols: [{ type: "number_int" }], postprocess: astBigInt },
675
  { name: "atom", symbols: [{ type: "number_hex" }], postprocess: astBigInt },
676
  { name: "atom", symbols: [{ type: "number_oct" }], postprocess: astBigInt },
677
  { name: "atom", symbols: [{ type: "number_bin" }], postprocess: astBigInt },
678
  { name: "atom", symbols: [{ type: "number_complex" }], postprocess: astComplex },
679
  { name: "atom", symbols: ["stringLit"], postprocess: id },
680
  { name: "atom", symbols: [{ literal: "None" }], postprocess: astNone },
681
  { name: "atom", symbols: [{ literal: "True" }], postprocess: astTrue },
682
  { name: "atom", symbols: [{ literal: "False" }], postprocess: astFalse },
683
  {
684
    name: "lambda_expr",
685
    symbols: [{ literal: "lambda" }, "rest_names", { literal: ":" }, "expression"],
686
    postprocess: ([kw, params, , body]: [moo.Token, FunctionParam[], moo.Token, ExprNS.Expr]) =>
687
      new ExprNS.Lambda(toAstToken(kw), body.endToken, params, body),
4,750✔
688
  },
689
  {
690
    name: "lambda_expr",
691
    symbols: [{ literal: "lambda" }, "rest_names", { type: "doublecolon" }, "block"],
692
    postprocess: ([kw, params, , body]: [moo.Token, FunctionParam[], moo.Token, StmtNS.Stmt[]]) =>
UNCOV
693
      new ExprNS.MultiLambda(toAstToken(kw), body[body.length - 1].endToken, params, body, []),
×
694
  },
695
  {
696
    name: "lambda_expr",
697
    symbols: [{ literal: "lambda" }, { literal: ":" }, "expression"],
698
    postprocess: ([kw, , body]: [moo.Token, moo.Token, ExprNS.Expr]) =>
699
      new ExprNS.Lambda(toAstToken(kw), body.endToken, [], body),
5,849✔
700
  },
701
  {
702
    name: "lambda_expr",
703
    symbols: [{ literal: "lambda" }, { type: "doublecolon" }, "block"],
704
    postprocess: ([kw, , body]: [moo.Token, moo.Token, StmtNS.Stmt[]]) =>
UNCOV
705
      new ExprNS.MultiLambda(toAstToken(kw), body[body.length - 1].endToken, [], body, []),
×
706
  },
707
  { name: "expressions$ebnf$1", symbols: [] },
708
  { name: "expressions$ebnf$1$subexpression$1", symbols: [{ literal: "," }, "expression"] },
709
  {
710
    name: "expressions$ebnf$1",
711
    symbols: ["expressions$ebnf$1", "expressions$ebnf$1$subexpression$1"],
712
    postprocess: function arrpush<T>(d: [T[], T]) {
713
      return d[0].concat([d[1]]);
243✔
714
    },
715
  },
716
  { name: "expressions$ebnf$2$subexpression$1", symbols: [{ type: "comma" }] },
717
  { name: "expressions$ebnf$2", symbols: ["expressions$ebnf$2$subexpression$1"], postprocess: id },
718
  {
719
    name: "expressions$ebnf$2",
720
    symbols: [],
721
    postprocess: () => null,
397✔
722
  },
723
  {
724
    name: "expressions",
725
    symbols: ["expression", "expressions$ebnf$1", "expressions$ebnf$2"],
726
    postprocess: flatList,
727
  },
728
  { name: "spread_expressions$ebnf$1", symbols: [] },
729
  {
730
    name: "spread_expressions$ebnf$1$subexpression$1",
731
    symbols: [{ literal: "," }, "spread_expression"],
732
  },
733
  {
734
    name: "spread_expressions$ebnf$1",
735
    symbols: ["spread_expressions$ebnf$1", "spread_expressions$ebnf$1$subexpression$1"],
736
    postprocess: function arrpush<T>(d: [T[], T]) {
737
      return d[0].concat([d[1]]);
54,765✔
738
    },
739
  },
740
  { name: "spread_expressions$ebnf$2$subexpression$1", symbols: [{ type: "comma" }] },
741
  {
742
    name: "spread_expressions$ebnf$2",
743
    symbols: ["spread_expressions$ebnf$2$subexpression$1"],
744
    postprocess: id,
745
  },
746
  {
747
    name: "spread_expressions$ebnf$2",
748
    symbols: [],
749
    postprocess: () => null,
166,468✔
750
  },
751
  {
752
    name: "spread_expressions",
753
    symbols: ["spread_expression", "spread_expressions$ebnf$1", "spread_expressions$ebnf$2"],
754
    postprocess: flatList,
755
  },
756
  { name: "spread_expression", symbols: ["expression"], postprocess: id },
757
  {
758
    name: "spread_expression",
759
    symbols: [{ type: "star" }, "expression"],
760
    postprocess: ([star, expr]: [moo.Token, ExprNS.Expr]) =>
761
      new ExprNS.Starred(toAstToken(star), expr.endToken, expr),
62✔
762
  },
763
  { name: "stringLit", symbols: [{ type: "string_triple_double" }], postprocess: astString },
764
  { name: "stringLit", symbols: [{ type: "string_triple_single" }], postprocess: astString },
765
  { name: "stringLit", symbols: [{ type: "string_double" }], postprocess: astString },
766
  { name: "stringLit", symbols: [{ type: "string_single" }], postprocess: astString },
767
];
768
const ParserStart = "program";
14✔
769
export default { Lexer, ParserRules, ParserStart };
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc