Build your own knowledge graph database
Cypher-lite front-end: tokenize then parse·16 min

Parse the whole query

0 / 1
# grade this stage (from your course directory)
npx theinference test --stage parse-query --watch

Assemble the top-level parser: MATCH <path> [WHERE <pred>] RETURN [DISTINCT] <items> [ORDER BY ...] [LIMIT n] → Query. Tokenize, then drive the clause parsers in order. This is where everything from the chapter clicks together.

Your task

Implement parseQuery

Parse WHERE predicates (a.prop OP literal, chained by AND into a left-associative tree), RETURN items (a, a.prop, a.prop AS alias, with optional DISTINCT), optional ORDER BY key [ASC|DESC], and LIMIT int. Throw if any token remains before EOF.

src/parser.ts
export function parseQuery(query: string): Query {
  const p = new Parser(tokenize(query));
  // MATCH <path>
  // [WHERE <comparison> (AND <comparison>)*]
  // RETURN [DISTINCT] <item> (, <item>)*
  // [ORDER BY <key> [ASC|DESC] (, ...)*]
  // [LIMIT <int>]
  // assert peek().kind === 'EOF'  // else throw on trailing tokens
  return p.parseQuery();
}
Process command (the capstone shape)
your_program.sh parse "MATCH (bacon:Person {name:'Kevin Bacon'})-[:ACTED_IN]->(m)<-[:ACTED_IN]-(coStar) WHERE coStar.name <> 'Kevin Bacon' RETURN DISTINCT coStar.name AS name ORDER BY name"
Fail loudly on garbage

After parsing the RETURN items (and any ORDER BY / LIMIT), assert the next token is EOF. Silently ignoring trailing tokens hides bugs and will diverge from the reference AST. A real parser rejects malformed input rather than guessing.

How it's graded

Process mode, stdout_json_match against the full Query AST. Note distinct:true, the <> comparison in where, and the orderBy entry. The ORDER BY key here is the RETURN alias name, parsed as a bare variable (property:null).