Add support for parsing module declarations
This commit is contained in:
parent
117f49f343
commit
cea177e4a6
5 changed files with 57 additions and 9 deletions
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
33
src/cst.ts
33
src/cst.ts
|
@ -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 {
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue