|
|
|
|
@ -52,17 +52,29 @@ export class Parser {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private canStartPrimary(): boolean {
|
|
|
|
|
const kind = this.current().kind;
|
|
|
|
|
return kind === 'ident' || kind === 'type-ident' ||
|
|
|
|
|
kind === 'int' || kind === 'float' || kind === 'string' ||
|
|
|
|
|
kind === 'open-paren' || kind === 'open-bracket' ||
|
|
|
|
|
kind === 'open-brace';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parse(): AST {
|
|
|
|
|
return this.parseExpression();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private parseExpression(): AST {
|
|
|
|
|
let left = this.parsePrimary();
|
|
|
|
|
return this.parseInfix();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private parseInfix(): AST {
|
|
|
|
|
let left = this.parseApplication();
|
|
|
|
|
|
|
|
|
|
while (this.isInfixOp()) {
|
|
|
|
|
const opToken = this.advance();
|
|
|
|
|
const opName = this.tokenToOpName(opToken);
|
|
|
|
|
const right = this.parsePrimary();
|
|
|
|
|
const right = this.parseApplication();
|
|
|
|
|
|
|
|
|
|
left = {
|
|
|
|
|
kind: 'apply',
|
|
|
|
|
@ -74,6 +86,17 @@ export class Parser {
|
|
|
|
|
return left;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private parseApplication(): AST {
|
|
|
|
|
let func = this.parsePrimary();
|
|
|
|
|
|
|
|
|
|
while (this.canStartPrimary()) {
|
|
|
|
|
const arg = this.parsePrimary();
|
|
|
|
|
func = { kind: 'apply', func, args: [arg] };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return func;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private parsePrimary(): AST {
|
|
|
|
|
const token = this.current();
|
|
|
|
|
|
|
|
|
|
@ -145,6 +168,11 @@ export class Parser {
|
|
|
|
|
return { kind: 'variable', name: token.value };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (token.kind === 'type-ident') {
|
|
|
|
|
this.advance();
|
|
|
|
|
return { kind: 'constructor', name: token.value };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new Error(`Unexpected token: ${token.kind}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|