Parse the whole query
# grade this stage (from your course directory)
npx theinference test --stage parse-query --watchAssemble 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.
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.
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();
}
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"
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.
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).