parsing record access and update

master
Dustin Swan 6 days ago
parent 6e8b5afd3b
commit b6f7e63e49
Signed by: dustinswan
GPG Key ID: 30D46587E2100467

@ -158,6 +158,13 @@ export function prettyPrint(ast: AST, indent = 0): string {
const params = ast.params.join(', ') const params = ast.params.join(', ')
return `${i}(${params}) => ${prettyPrint(ast.body)}` return `${i}(${params}) => ${prettyPrint(ast.body)}`
case 'record-access':
return `${i}${prettyPrint(ast.record)}.${ast.field}`
case 'record-update':
const updates = Object.entries(ast.updates).map(([k, v]) => `${k} = ${prettyPrint(v, 0)}`).join(', ');
return `${i}${prettyPrint(ast.record)} { ${updates} }`
default: default:
return `${i}${ast.kind}` return `${i}${ast.kind}`
} }

@ -25,7 +25,7 @@ console.log(tokenize(str));
// const tokens2 = tokenize("let x = (y) => 5 + y in x(3)"); // const tokens2 = tokenize("let x = (y) => 5 + y in x(3)");
// const tokens2 = tokenize("let x = 5 in x * 4"); // const tokens2 = tokenize("let x = 5 in x * 4");
// const tokens2 = tokenize("(x, y) => x + y"); // const tokens2 = tokenize("(x, y) => x + y");
const tokens2 = tokenize(`a b \\ a + b`); const tokens2 = tokenize('point { x = 3 }');
const p2 = new Parser(tokens2); const p2 = new Parser(tokens2);
const ast3 = p2.parse(); const ast3 = p2.parse();
console.log(ast3); console.log(ast3);

@ -148,16 +148,54 @@ export class Parser {
} }
private parseApplication(): AST { private parseApplication(): AST {
let func = this.parsePrimary(); let func = this.parsePostfix();
while (this.canStartPrimary()) { while (this.canStartPrimary()) {
const arg = this.parsePrimary(); const arg = this.parsePostfix();
func = { kind: 'apply', func, args: [arg] }; func = { kind: 'apply', func, args: [arg] };
} }
return func; return func;
} }
private parsePostfix(): AST {
let expr = this.parsePrimary();
while (true) {
if (this.current().kind === 'dot') {
// Record access
this.advance();
const fieldToken = this.expect('ident');
const field = (fieldToken as { value: string }).value;
expr = { kind: 'record-access', record: expr, field };
} else if (this.current().kind === 'open-brace') {
// Record update
this.advance();
const updates: { [key: string]: AST } = {};
let first = true;
while (this.current().kind !== 'close-brace') {
if (!first) {
this.expect('comma');
}
first = false;
const keyToken = this.expect('ident');
const key = (keyToken as { value: string }).value;
this.expect('equals');
updates[key] = this.parseExpression();
}
this.expect('close-brace');
expr = { kind: 'record-update', record: expr, updates }
} else {
break;
}
}
return expr;
}
private parsePrimary(): AST { private parsePrimary(): AST {
const token = this.current(); const token = this.current();

Loading…
Cancel
Save