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.ModuleDeclaration:
{
for (const element of node.elements) {
visit(element, source);

View file

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

View file

@ -182,14 +182,14 @@ export const enum SyntaxKind {
Initializer,
TypeAssert,
Param,
Module,
ModuleDeclaration,
SourceFile,
}
export type Syntax
= SourceFile
| Module
| ModuleDeclaration
| Token
| Param
| Body
@ -220,7 +220,8 @@ function isNodeWithScope(node: Syntax): node is NodeWithScope {
export const enum Symkind {
Var = 1,
Type = 2,
Any = Var | Type
Module = 4,
Any = Var | Type | Module
}
export class Scope {
@ -267,6 +268,14 @@ export class Scope {
}
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.ReturnStatement:
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 pubKeyword: PubKeyword | null,
public modKeyword: ModKeyword,
public name: Identifier,
public body: Body,
public name: IdentifierAlt,
public blockStart: BlockStart,
public elements: SourceFileElement[],
) {
super();
}
@ -2215,7 +2227,10 @@ export class Module extends SyntaxBase {
}
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
= Statement
| Declaration
| Module
| ModuleDeclaration
export class SourceFile extends SyntaxBase {

View file

@ -59,6 +59,7 @@ import {
LiteralPattern,
DisjunctivePattern,
TupleTypeExpression,
ModuleDeclaration,
} from "./cst"
import { Stream } from "./util";
@ -954,11 +955,38 @@ export class Parser {
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 {
const t0 = this.peekTokenAfterModifiers();
switch (t0.kind) {
case SyntaxKind.LetKeyword:
return this.parseLetDeclaration();
case SyntaxKind.ModKeyword:
return this.parseModuleDeclaration();
case SyntaxKind.ImportKeyword:
return this.parseImportDeclaration();
case SyntaxKind.StructKeyword:

View file

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