Enable parsing enum-declarations

This commit is contained in:
Sam Vervaeck 2022-09-10 14:11:04 +02:00
parent 7b3f1948bb
commit 3611dedf24
4 changed files with 182 additions and 2 deletions

View file

@ -92,6 +92,7 @@ export const enum SyntaxKind {
ModKeyword,
ImportKeyword,
StructKeyword,
EnumKeyword,
TypeKeyword,
ReturnKeyword,
MatchKeyword,
@ -150,6 +151,7 @@ export const enum SyntaxKind {
SuffixFuncDecl,
LetDeclaration,
StructDeclaration,
EnumDeclaration,
ImportDeclaration,
TypeAliasDeclaration,
@ -160,6 +162,10 @@ export const enum SyntaxKind {
// Structure declaration members
StructDeclarationField,
// Enum declaration elements
EnumDeclarationStructElement,
EnumDeclarationTupleElement,
// Other nodes
WrappedOperator,
Initializer,
@ -745,6 +751,16 @@ export class StructKeyword extends TokenBase {
}
export class EnumKeyword extends TokenBase {
public readonly kind = SyntaxKind.EnumKeyword;
public get text(): string {
return 'enum';
}
}
export class ReturnKeyword extends TokenBase {
public readonly kind = SyntaxKind.ReturnKeyword;
@ -870,6 +886,7 @@ export type Token
| IfKeyword
| ElseKeyword
| ElifKeyword
| EnumKeyword
export type TokenKind
= Token['kind']
@ -1557,6 +1574,88 @@ export class Param extends SyntaxBase {
}
export class EnumDeclarationStructElement extends SyntaxBase {
public readonly kind = SyntaxKind.EnumDeclarationStructElement;
public constructor(
public name: IdentifierAlt,
public blockStart: BlockStart,
public members: StructDeclarationField[],
) {
super();
}
public getFirstToken(): Token {
return this.name;
}
public getLastToken(): Token {
if (this.members.length > 0) {
return this.members[this.members.length-1].getLastToken();
}
return this.blockStart;
}
}
export class EnumDeclarationTupleElement extends SyntaxBase {
public readonly kind = SyntaxKind.EnumDeclarationTupleElement;
public constructor(
public name: IdentifierAlt,
public elements: TypeExpression[],
) {
super();
}
public getFirstToken(): Token {
return this.name;
}
public getLastToken(): Token {
if (this.elements.length > 0) {
return this.elements[this.elements.length-1].getLastToken();
}
return this.name;
}
}
export type EnumDeclarationElement
= EnumDeclarationStructElement
| EnumDeclarationTupleElement
export class EnumDeclaration extends SyntaxBase {
public readonly kind = SyntaxKind.EnumDeclaration;
public constructor(
public pubKeyword: PubKeyword | null,
public enumKeyword: EnumKeyword,
public name: IdentifierAlt,
public members: EnumDeclarationElement[] | null,
) {
super();
}
public getFirstToken(): Token {
if (this.pubKeyword !== null) {
return this.pubKeyword;
}
return this.enumKeyword;
}
public getLastToken(): Token {
if (this.members !== null && this.members.length > 0) {
return this.members[this.members.length-1].getLastToken();
}
return this.name;
}
}
export class StructDeclarationField extends SyntaxBase {
public readonly kind = SyntaxKind.StructDeclarationField;
@ -1584,6 +1683,7 @@ export class StructDeclaration extends SyntaxBase {
public readonly kind = SyntaxKind.StructDeclaration;
public constructor(
public pubKeyword: PubKeyword | null,
public structKeyword: StructKeyword,
public name: IdentifierAlt,
public members: StructDeclarationField[] | null,
@ -1592,6 +1692,9 @@ export class StructDeclaration extends SyntaxBase {
}
public getFirstToken(): Token {
if (this.pubKeyword !== null) {
return this.pubKeyword;
}
return this.structKeyword;
}
@ -1769,6 +1872,7 @@ export type Declaration
= LetDeclaration
| ImportDeclaration
| StructDeclaration
| EnumDeclaration
export class Initializer extends SyntaxBase {

View file

@ -70,6 +70,7 @@ const DESCRIPTIONS: Partial<Record<SyntaxKind, string>> = {
[SyntaxKind.RBrace]: "'}'",
[SyntaxKind.LBracket]: "'['",
[SyntaxKind.RBracket]: "']'",
[SyntaxKind.IdentifierAlt]: 'an identifier starting with an uppercase letter',
[SyntaxKind.ConstantExpression]: 'a constant expression',
[SyntaxKind.ReferenceExpression]: 'a reference expression',
[SyntaxKind.LineFoldEnd]: 'the end of the current line-fold',

View file

@ -48,6 +48,9 @@ import {
IdentifierAlt,
WrappedOperator,
ArrowTypeExpression,
EnumDeclarationStructElement,
EnumDeclaration,
EnumDeclarationTupleElement,
} from "./cst"
import { Stream } from "./util";
@ -407,8 +410,76 @@ export class Parser {
return this.parseBinaryOperatorAfterExpr(lhs, 0);
}
public parseEnumDeclaration(): EnumDeclaration {
let pubKeyword = null;
let t0 = this.getToken();
if (t0.kind == SyntaxKind.PubKeyword) {
pubKeyword = t0;
t0 = this.getToken();
}
if (t0.kind !== SyntaxKind.EnumKeyword) {
this.raiseParseError(t0, [ SyntaxKind.EnumKeyword ]);
}
const name = this.expectToken(SyntaxKind.IdentifierAlt);
const t1 = this.peekToken();
let members = null;
if (t1.kind === SyntaxKind.BlockStart) {
members = [];
this.getToken();
for (;;) {
const t2 = this.peekToken();
if (t2.kind === SyntaxKind.BlockEnd) {
this.getToken();
break;
}
const name = this.expectToken(SyntaxKind.IdentifierAlt);
const t3 = this.peekToken();
let member;
if (t3.kind === SyntaxKind.BlockStart) {
this.getToken();
const members = [];
for (;;) {
const name = this.expectToken(SyntaxKind.Identifier);
const colon = this.expectToken(SyntaxKind.Colon);
const typeExpr = this.parseTypeExpression();
members.push(new StructDeclarationField(name, colon, typeExpr));
const t4 = this.peekToken();
if (t4.kind === SyntaxKind.BlockEnd) {
this.getToken();
break;
}
}
member = new EnumDeclarationStructElement(name, t3, members);
} else {
const typeExps = [];
for (;;) {
const t3 = this.peekToken();
if (t3.kind === SyntaxKind.LineFoldEnd) {
break;
}
const typeExpr = this.parsePrimitiveTypeExpression();
typeExps.push(typeExpr);
}
member = new EnumDeclarationTupleElement(name, typeExps);
}
members.push(member);
this.expectToken(SyntaxKind.LineFoldEnd);
}
}
this.expectToken(SyntaxKind.LineFoldEnd);
return new EnumDeclaration(pubKeyword, t0, name, members);
}
public parseStructDeclaration(): StructDeclaration {
const structKeyword = this.expectToken(SyntaxKind.StructKeyword);
let pubKeyword = null;
let t0 = this.getToken();
if (t0.kind === SyntaxKind.PubKeyword) {
pubKeyword = t0;
t0 = this.getToken();
}
if (t0.kind !== SyntaxKind.StructKeyword) {
this.raiseParseError(t0, [ SyntaxKind.StructKeyword ]);
}
const name = this.expectToken(SyntaxKind.IdentifierAlt);
const t2 = this.peekToken()
let members = null;
@ -430,7 +501,7 @@ export class Parser {
}
}
this.expectToken(SyntaxKind.LineFoldEnd);
return new StructDeclaration(structKeyword, name, members);
return new StructDeclaration(pubKeyword, t0, name, members);
}
private parsePatternStartingWithConstructor() {
@ -731,6 +802,8 @@ export class Parser {
return this.parseImportDeclaration();
case SyntaxKind.StructKeyword:
return this.parseStructDeclaration();
case SyntaxKind.EnumKeyword:
return this.parseEnumDeclaration();
case SyntaxKind.IfKeyword:
return this.parseIfStatement();
default:

View file

@ -36,6 +36,7 @@ import {
IfKeyword,
StructKeyword,
RArrow,
EnumKeyword,
} from "./cst"
import { Diagnostics, UnexpectedCharDiagnostic } from "./diagnostics"
import { Stream, BufferedStream, assert } from "./util";
@ -356,6 +357,7 @@ export class Scanner extends BufferedStream<Token> {
case 'else': return new ElseKeyword(startPos);
case 'elif': return new ElifKeyword(startPos);
case 'struct': return new StructKeyword(startPos);
case 'enum': return new EnumKeyword(startPos);
default:
if (isUpper(text[0])) {
return new IdentifierAlt(text, startPos);