parsing lambdas

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

@ -154,6 +154,10 @@ export function prettyPrint(ast: AST, indent = 0): string {
.join(', '); .join(', ');
return `${i}{${fields}}`; return `${i}{${fields}}`;
case 'lambda':
const params = ast.params.join(', ')
return `${i}(${params}) => ${prettyPrint(ast.body)}`
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('x = (y = 1; y + 1); x * 2'); const tokens2 = tokenize(`a b \\ a + b`);
const p2 = new Parser(tokens2); const p2 = new Parser(tokens2);
const ast3 = p2.parse(); const ast3 = p2.parse();
console.log(ast3); console.log(ast3);

@ -68,11 +68,35 @@ export class Parser {
kind === 'open-brace'; kind === 'open-brace';
} }
private isLambdaStart(): boolean {
const kind = this.current().kind;
if (kind === 'backslash') {
return true;
}
if (kind !== 'ident') {
return false;
}
let offset = 1;
while (true) {
const token = this.peek(offset);
if (token.kind === 'backslash') return true;
if (token.kind !== 'ident') return false;
offset++;
}
}
parse(): AST { parse(): AST {
return this.parseExpression(); return this.parseExpression();
} }
private parseExpression(): AST { private parseExpression(): AST {
if (this.isLambdaStart()) {
return this.parseLambda();
}
if (this.current().kind === 'ident' && this.peek().kind === 'equals') { if (this.current().kind === 'ident' && this.peek().kind === 'equals') {
return this.parseLet(); return this.parseLet();
} }
@ -80,6 +104,20 @@ export class Parser {
return this.parseInfix(); return this.parseInfix();
} }
private parseLambda(): AST {
const params: string[] = [];
while (this.current().kind === 'ident') {
const param = this.advance();
params.push((param as { value: string }).value);
}
this.expect('backslash');
const body = this.parseExpression();
return { kind: 'lambda', params, body };
}
private parseLet(): AST { private parseLet(): AST {
const nameToken = this.expect('ident'); const nameToken = this.expect('ident');
const name = (nameToken as { value: string }).value; const name = (nameToken as { value: string }).value;
@ -198,55 +236,4 @@ export class Parser {
throw new Error(`Unexpected token: ${token.kind}`); throw new Error(`Unexpected token: ${token.kind}`);
} }
/*
private parseLambda(): AST {
this.expect('open-paren');
const params: string[] = [];
if (this.current().kind !== 'close-paren') {
const first = this.expect('ident');
params.push((first as { value: string }).value);
while (this.current().kind === 'comma') {
this.advance();
const param = this.expect('ident');
params.push((param as { value: string }).value);
}
}
this.expect('close-paren');
this.expect('arrow');
const body = this.parseExpression();
return { kind: 'lambda', params, body }
}
private parsePostfix(): AST {
let expr = this.parsePrimary();
while (this.current().kind === 'open-paren') {
this.advance();
const args: AST[] = [];
if (this.current().kind !== 'close-paren') {
args.push(this.parseExpression());
while (this.current().kind === 'comma') {
this.advance();
args.push(this.parseExpression());
}
}
this.expect('close-paren');
expr = { kind: 'apply', func: expr, args };
}
return expr;
}
*/
} }

Loading…
Cancel
Save