Add support for parsing module declarations

This commit is contained in:
Sam Vervaeck 2022-09-17 13:20:49 +02:00
parent 117f49f343
commit cea177e4a6
5 changed files with 57 additions and 9 deletions

View file

@ -37,6 +37,7 @@ export class Analyser {
} }
case SyntaxKind.SourceFile: case SyntaxKind.SourceFile:
case SyntaxKind.ModuleDeclaration:
{ {
for (const element of node.elements) { for (const element of node.elements) {
visit(element, source); visit(element, source);

View file

@ -1103,6 +1103,7 @@ export class Checker {
switch (node.kind) { switch (node.kind) {
case SyntaxKind.SourceFile: case SyntaxKind.SourceFile:
case SyntaxKind.ModuleDeclaration:
{ {
for (const element of node.elements) { for (const element of node.elements) {
this.infer(element); this.infer(element);
@ -1588,6 +1589,7 @@ export class Checker {
switch (node.kind) { switch (node.kind) {
case SyntaxKind.SourceFile: case SyntaxKind.SourceFile:
case SyntaxKind.ModuleDeclaration:
{ {
const env = node.typeEnv = new TypeEnv(parentEnv); const env = node.typeEnv = new TypeEnv(parentEnv);
for (const element of node.elements) { for (const element of node.elements) {

View file

@ -182,14 +182,14 @@ export const enum SyntaxKind {
Initializer, Initializer,
TypeAssert, TypeAssert,
Param, Param,
Module, ModuleDeclaration,
SourceFile, SourceFile,
} }
export type Syntax export type Syntax
= SourceFile = SourceFile
| Module | ModuleDeclaration
| Token | Token
| Param | Param
| Body | Body
@ -220,7 +220,8 @@ function isNodeWithScope(node: Syntax): node is NodeWithScope {
export const enum Symkind { export const enum Symkind {
Var = 1, Var = 1,
Type = 2, Type = 2,
Any = Var | Type Module = 4,
Any = Var | Type | Module
} }
export class Scope { export class Scope {
@ -267,6 +268,14 @@ export class Scope {
} }
break; break;
} }
case SyntaxKind.ModuleDeclaration:
{
this.add(node.name.text, node, Symkind.Module);
for (const element of node.elements) {
this.scan(element);
}
break;
}
case SyntaxKind.ExpressionStatement: case SyntaxKind.ExpressionStatement:
case SyntaxKind.ReturnStatement: case SyntaxKind.ReturnStatement:
case SyntaxKind.IfStatement: case SyntaxKind.IfStatement:
@ -2194,15 +2203,18 @@ export class Initializer extends SyntaxBase {
} }
export class Module extends SyntaxBase { export class ModuleDeclaration extends SyntaxBase {
public readonly kind = SyntaxKind.Module; public readonly kind = SyntaxKind.ModuleDeclaration;
public typeEnv?: TypeEnv;
public constructor( public constructor(
public pubKeyword: PubKeyword | null, public pubKeyword: PubKeyword | null,
public modKeyword: ModKeyword, public modKeyword: ModKeyword,
public name: Identifier, public name: IdentifierAlt,
public body: Body, public blockStart: BlockStart,
public elements: SourceFileElement[],
) { ) {
super(); super();
} }
@ -2215,7 +2227,10 @@ export class Module extends SyntaxBase {
} }
public getLastToken(): Token { public getLastToken(): Token {
return this.body.getLastToken(); if (this.elements.length > 0) {
return this.elements[this.elements.length-1].getLastToken();
}
return this.blockStart;
} }
} }
@ -2223,7 +2238,7 @@ export class Module extends SyntaxBase {
export type SourceFileElement export type SourceFileElement
= Statement = Statement
| Declaration | Declaration
| Module | ModuleDeclaration
export class SourceFile extends SyntaxBase { export class SourceFile extends SyntaxBase {

View file

@ -59,6 +59,7 @@ import {
LiteralPattern, LiteralPattern,
DisjunctivePattern, DisjunctivePattern,
TupleTypeExpression, TupleTypeExpression,
ModuleDeclaration,
} from "./cst" } from "./cst"
import { Stream } from "./util"; import { Stream } from "./util";
@ -954,11 +955,38 @@ export class Parser {
return new ImportDeclaration(importKeyword, importSource); return new ImportDeclaration(importKeyword, importSource);
} }
public parseModuleDeclaration(): ModuleDeclaration {
let pubKeyword = null;
let t0 = this.getToken();
if (t0.kind === SyntaxKind.PubKeyword) {
pubKeyword = t0;
t0 = this.getToken();
}
if (t0.kind !== SyntaxKind.ModKeyword) {
this.raiseParseError(t0, [ SyntaxKind.ModKeyword ]);
}
const name = this.expectToken(SyntaxKind.IdentifierAlt);
const blockStart = this.expectToken(SyntaxKind.BlockStart);
const elements = [];
for (;;) {
const t1 = this.peekToken();
if (t1.kind === SyntaxKind.BlockEnd) {
this.getToken();
break;
}
elements.push(this.parseSourceFileElement());
}
this.expectToken(SyntaxKind.LineFoldEnd);
return new ModuleDeclaration(pubKeyword, t0, name, blockStart, elements);
}
public parseSourceFileElement(): SourceFileElement { public parseSourceFileElement(): SourceFileElement {
const t0 = this.peekTokenAfterModifiers(); const t0 = this.peekTokenAfterModifiers();
switch (t0.kind) { switch (t0.kind) {
case SyntaxKind.LetKeyword: case SyntaxKind.LetKeyword:
return this.parseLetDeclaration(); return this.parseLetDeclaration();
case SyntaxKind.ModKeyword:
return this.parseModuleDeclaration();
case SyntaxKind.ImportKeyword: case SyntaxKind.ImportKeyword:
return this.parseImportDeclaration(); return this.parseImportDeclaration();
case SyntaxKind.StructKeyword: case SyntaxKind.StructKeyword:

View file

@ -41,6 +41,7 @@ import {
RArrowAlt, RArrowAlt,
VBar, VBar,
ForeignKeyword, ForeignKeyword,
ModKeyword,
} from "./cst" } from "./cst"
import { Diagnostics, UnexpectedCharDiagnostic } from "./diagnostics" import { Diagnostics, UnexpectedCharDiagnostic } from "./diagnostics"
import { Stream, BufferedStream, assert } from "./util"; import { Stream, BufferedStream, assert } from "./util";
@ -368,6 +369,7 @@ export class Scanner extends BufferedStream<Token> {
case 'enum': return new EnumKeyword(startPos); case 'enum': return new EnumKeyword(startPos);
case 'match': return new MatchKeyword(startPos); case 'match': return new MatchKeyword(startPos);
case 'foreign': return new ForeignKeyword(startPos); case 'foreign': return new ForeignKeyword(startPos);
case 'mod': return new ModKeyword(startPos);
default: default:
if (isUpper(text[0])) { if (isUpper(text[0])) {
return new IdentifierAlt(text, startPos); return new IdentifierAlt(text, startPos);