parsing record access and update
This commit is contained in:
parent
6e8b5afd3b
commit
b6f7e63e49
3 changed files with 48 additions and 3 deletions
|
|
@ -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…
Add table
Add a link
Reference in a new issue