Typeclasses
This commit is contained in:
parent
a4daf88085
commit
8020f9d1a0
6 changed files with 123 additions and 19 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import type { Token } from './lexer'
|
||||
import type { AST, MatchCase, Pattern, Definition, TypeAST, TypeDefinition, TypeConstructor, Annotation } from './ast'
|
||||
import type { AST, MatchCase, Pattern, Definition, TypeAST, TypeDefinition, TypeConstructor, Annotation, ClassDefinition, InstanceDeclaration } from './ast'
|
||||
import { ParseError } from './error'
|
||||
|
||||
export class Parser {
|
||||
|
|
@ -150,20 +150,32 @@ export class Parser {
|
|||
}
|
||||
}
|
||||
|
||||
parse(): { definitions: Definition[], typeDefinitions: TypeDefinition[] } {
|
||||
parse(): { definitions: Definition[], typeDefinitions: TypeDefinition[], classDefinitions: ClassDefinition[], instanceDeclarations: InstanceDeclaration[] } {
|
||||
const definitions: Definition[] = [];
|
||||
const typeDefinitions: TypeDefinition[] = [];
|
||||
const classDefinitions: ClassDefinition[] = [];
|
||||
const instanceDeclarations: InstanceDeclaration[] = [];
|
||||
|
||||
while (this.current().kind !== 'eof') {
|
||||
if (this.current().kind === 'type-ident') {
|
||||
typeDefinitions.push(this.parseTypeDefinition());
|
||||
let offset = 1;
|
||||
while (this.peek(offset).kind === 'ident') offset++;
|
||||
const after = this.peek(offset);
|
||||
|
||||
if (after.kind === 'open-brace') {
|
||||
classDefinitions.push(this.parseClassDefinition());
|
||||
} else if (after.kind === 'colon') {
|
||||
instanceDeclarations.push(this.parseInstanceDeclaration());
|
||||
} else {
|
||||
typeDefinitions.push(this.parseTypeDefinition());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
definitions.push(this.parseDefinition());
|
||||
}
|
||||
|
||||
return { definitions, typeDefinitions };
|
||||
return { definitions, typeDefinitions, classDefinitions, instanceDeclarations };
|
||||
}
|
||||
|
||||
private parseDefinition(): Definition {
|
||||
|
|
@ -662,4 +674,32 @@ export class Parser {
|
|||
}
|
||||
return { name, args };
|
||||
}
|
||||
|
||||
private parseClassDefinition(): ClassDefinition {
|
||||
const nameToken = this.advance();
|
||||
const param = (this.expect('ident') as { value: string }).value;
|
||||
|
||||
this.expect('open-brace');
|
||||
const methods: { name: string, type: TypeAST }[] = [];
|
||||
while (this.current().kind !== 'close-brace') {
|
||||
const methodName = (this.expect('ident') as { value: string }).value;
|
||||
this.expect('colon');
|
||||
const type = this.parseType();
|
||||
methods.push({ name: methodName, type });
|
||||
if (this.current().kind === 'semicolon') this.advance();
|
||||
}
|
||||
this.expect('close-brace');
|
||||
if (this.current().kind === 'semicolon') this.advance();
|
||||
|
||||
return { kind: 'class-definition', name: (nameToken as { value: string }).value, param, methods, ...this.getPos(nameToken) };
|
||||
}
|
||||
|
||||
private parseInstanceDeclaration(): InstanceDeclaration {
|
||||
const typeToken = this.advance();
|
||||
this.expect('colon');
|
||||
const classToken = this.expect('type-ident');
|
||||
if (this.current().kind === 'semicolon') this.advance();
|
||||
|
||||
return { kind: 'instance-declaration', typeName: (typeToken as { value: string }).value, className: (classToken as { value: string }).value, ...this.getPos(typeToken) };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue