Sikau

Build an interpreter · Day 5 · about 45 min

Project: The complete parser

Functions, calls, arrays and indexing — the whole Chiya grammar.

The rest of the grammar

After today, every Chiya program has a syntax tree, and the parser never needs to change again until you add new syntax yourself.

Chiya still can't express functions or lists. Today you finish the parser: function literals fn(a, b) { … }, calls f(1, 2), array literals [1, 2, 3] and indexing xs[0]. Calls and indexing look like infix operators — they come after a value — so they slot into the Pratt loop with the highest binding power, 6.

let add = fn(a, b) { a + b };
let xs = [add(1, 2), 4];
xs[0] * 10

Calls and indexing in the loop

Give ( and [ binding power 6 in the table. When the loop meets ( after a value, the value is being called: parse a comma-separated list of arguments up to ). When it meets [, parse one expression and expect ]. Because they bind tightest, a + f(x)[0] becomes (a + (f(x)[0])).

while ((PRECEDENCE[peek().type] ?? 0) > min) {
  const op = next();
  if (op.type === "(") left = { type: "Call", callee: left, args: list(")") };
  else if (op.type === "[") {
    const index = expression(0);
    expect("]");
    left = { type: "Index", target: left, index };
  } else left = { type: "Infix", op: op.type, left, right: expression(PRECEDENCE[op.type]) };
}

One list(close) helper parses expr, expr, … up to a closing token. Calls use it with ) and array literals with ].

The rest of this lesson

  • Function literals and arraysexplain
  • Read the callpredict
  • Same token, two jobsmatch
  • Parsing add(1, 2)[0]order
  • Finish the parserchallenge
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 10 lessons of Build an interpreter