|
|
|
@ -86,6 +86,33 @@ export class Parser {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private precOf(token: Token): number {
|
|
|
|
|
|
|
|
switch (token.kind) {
|
|
|
|
|
|
|
|
case 'ampersand':
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
case 'equals-equals':
|
|
|
|
|
|
|
|
case 'not-equals':
|
|
|
|
|
|
|
|
case 'greater-than':
|
|
|
|
|
|
|
|
case 'greater-equals':
|
|
|
|
|
|
|
|
case 'less-than':
|
|
|
|
|
|
|
|
case 'less-equals':
|
|
|
|
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
case 'plus':
|
|
|
|
|
|
|
|
case 'minus':
|
|
|
|
|
|
|
|
return 3;
|
|
|
|
|
|
|
|
case 'star':
|
|
|
|
|
|
|
|
case 'slash':
|
|
|
|
|
|
|
|
case 'percent':
|
|
|
|
|
|
|
|
return 4;
|
|
|
|
|
|
|
|
case 'caret':
|
|
|
|
|
|
|
|
return 5;
|
|
|
|
|
|
|
|
case 'tilde':
|
|
|
|
|
|
|
|
return 6;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private canStartPrimary(): boolean {
|
|
|
|
private canStartPrimary(): boolean {
|
|
|
|
const kind = this.current().kind;
|
|
|
|
const kind = this.current().kind;
|
|
|
|
return kind === 'ident' || kind === 'type-ident' ||
|
|
|
|
return kind === 'ident' || kind === 'type-ident' ||
|
|
|
|
@ -344,16 +371,17 @@ export class Parser {
|
|
|
|
return { kind: 'let', name, value, body, ...this.getPos(nameToken) };
|
|
|
|
return { kind: 'let', name, value, body, ...this.getPos(nameToken) };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private parseInfix(): AST {
|
|
|
|
private parseInfix(minPrec: number = 0): AST {
|
|
|
|
const token = this.current();
|
|
|
|
const token = this.current();
|
|
|
|
let left = this.parseApplication();
|
|
|
|
let left = this.parseApplication();
|
|
|
|
|
|
|
|
|
|
|
|
while (this.isInfixOp()) {
|
|
|
|
while (this.isInfixOp() && this.precOf(this.current()) >= minPrec) {
|
|
|
|
const opToken = this.advance();
|
|
|
|
const opToken = this.advance();
|
|
|
|
|
|
|
|
const prec = this.precOf(opToken);
|
|
|
|
|
|
|
|
|
|
|
|
if (opToken.kind === 'tilde') {
|
|
|
|
if (opToken.kind === 'tilde') {
|
|
|
|
// function application operator
|
|
|
|
// function application operator
|
|
|
|
const right = this.parseApplication();
|
|
|
|
const right = this.parseInfix(prec + 1);
|
|
|
|
|
|
|
|
|
|
|
|
left = {
|
|
|
|
left = {
|
|
|
|
kind: 'apply',
|
|
|
|
kind: 'apply',
|
|
|
|
@ -364,7 +392,7 @@ export class Parser {
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// operators desugar to function calls
|
|
|
|
// operators desugar to function calls
|
|
|
|
const opName = this.tokenToOpName(opToken);
|
|
|
|
const opName = this.tokenToOpName(opToken);
|
|
|
|
const right = this.parseApplication();
|
|
|
|
const right = this.parseInfix(prec + 1);
|
|
|
|
|
|
|
|
|
|
|
|
left = {
|
|
|
|
left = {
|
|
|
|
kind: 'apply',
|
|
|
|
kind: 'apply',
|
|
|
|
|