Split Punctuated into subclasses for parser

This commit is contained in:
Sam Vervaeck 2020-02-24 20:47:07 +01:00
parent 96aa6b6991
commit 365de4e3f7
2 changed files with 227 additions and 28 deletions

View file

@ -1,9 +1,13 @@
import "reflect-metadata"
import { Stream } from "./util"
interface JsonArray extends Array<Json> { };
interface JsonObject { [key: string]: Json }
type Json = string | boolean | number | JsonArray | JsonObject;
type Json = null | string | boolean | number | JsonArray | JsonObject;
export type TokenStream = Stream<Token>;
export enum SyntaxKind {
@ -12,10 +16,15 @@ export enum SyntaxKind {
Literal,
Identifier,
Operator,
Punctuated,
Parenthesized,
Braced,
Bracketed,
Semi,
Comma,
Colon,
Dot,
RArrow,
EqSign,
// Special nodes
@ -25,9 +34,16 @@ export enum SyntaxKind {
Sentence,
Param,
// Patterns
BindPatt,
ExprPatt,
// Expressions
ConstantExpr,
ConstExpr,
ReferenceExpr,
// Statements
@ -144,17 +160,15 @@ export enum PunctType {
Brace,
}
export class Punctuated extends SyntaxBase {
export class Parenthesized extends SyntaxBase {
kind: SyntaxKind.Punctuated = SyntaxKind.Punctuated
kind: SyntaxKind.Parenthesized = SyntaxKind.Parenthesized;
static META = {
punctuator: EdgeType.Primitive,
elements: EdgeType.Node | EdgeType.List
}
constructor(
public punctuator: PunctType,
public elements: Token[],
public span: TextSpan,
public parentNode: Syntax | null = null
@ -164,8 +178,58 @@ export class Punctuated extends SyntaxBase {
toJSON(): Json {
return {
kind: 'Punctuated',
punctuator: this.punctuator,
kind: 'Parenthesized',
elements: this.elements.map(element => element.toJSON()),
}
}
}
export class Braced extends SyntaxBase {
kind: SyntaxKind.Braced = SyntaxKind.Braced;
static META = {
elements: EdgeType.Node | EdgeType.List
}
constructor(
public elements: Token[],
public span: TextSpan,
public parentNode: Syntax | null = null
) {
super();
}
toJSON(): Json {
return {
kind: 'Braced',
elements: this.elements.map(element => element.toJSON()),
}
}
}
export class Bracketed extends SyntaxBase {
kind: SyntaxKind.Bracketed = SyntaxKind.Bracketed;
static META = {
elements: EdgeType.Node | EdgeType.List
}
constructor(
public elements: Token[],
public span: TextSpan,
public parentNode: Syntax | null = null
) {
super();
}
toJSON(): Json {
return {
kind: 'Bracketed',
elements: this.elements.map(element => element.toJSON()),
}
}
@ -209,6 +273,7 @@ export class Operator extends SyntaxBase {
constructor(
public text: string,
public span: TextSpan,
public origNode: Syntax | null = null,
public parentNode: Syntax | null = null
) {
super();
@ -218,7 +283,7 @@ export class Operator extends SyntaxBase {
return {
kind: 'Operator',
text: this.text,
span: this.span.toJSON(),
span: this.span !== null ? this.span.toJSON() : null,
}
}
@ -229,16 +294,17 @@ export class Semi extends SyntaxBase {
kind: SyntaxKind.Semi = SyntaxKind.Semi;
constructor(
public span: TextSpan,
public span: TextSpan | null = null,
public origNode: Syntax | null = null,
public parentNode: Syntax | null = null
) {
super();
}
toJSON() {
toJSON(): Json {
return {
kind: 'Semi',
span: this.span.toJSON(),
span: this.span !== null ? this.span.toJSON() : null,
}
}
@ -250,15 +316,16 @@ export class Colon extends SyntaxBase {
constructor(
public span: TextSpan,
public origNode: Syntax | null = null,
public parentNode: Syntax | null = null
) {
super();
}
toJSON() {
toJSON(): Json {
return {
kind: 'Colon',
span: this.span.toJSON(),
span: this.span !== null ? this.span.toJSON() : null,
}
}
@ -269,7 +336,74 @@ export class Comma extends SyntaxBase {
kind: SyntaxKind.Comma = SyntaxKind.Comma;
constructor(
public span: TextSpan,
public span: TextSpan | null = null,
public origNode: Syntax | null = null,
public parentNode: Syntax | null = null
) {
super();
}
toJSON(): Json {
return {
kind: 'Comma',
span: this.span !== null ? this.span.toJSON() : null,
}
}
}
export class RArrow extends SyntaxBase {
kind: SyntaxKind.RArrow = SyntaxKind.RArrow;
constructor(
public span: TextSpan | null = null,
public origNode: Syntax | null = null,
public parentNode: Syntax | null = null
) {
super();
}
toJSON(): Json {
return {
kind: 'RArrow',
span: this.span !== null ? this.span.toJSON() : null,
}
}
}
export class EqSign extends SyntaxBase {
kind: SyntaxKind.EqSign = SyntaxKind.EqSign;
constructor(
public span: TextSpan | null = null,
public origNode: Syntax | null = null,
public parentNode: Syntax | null = null
) {
super();
}
toJSON(): Json {
return {
kind: 'EqSign',
span: this.span !== null ? this.span.toJSON() : null,
}
}
}
export class Dot extends SyntaxBase {
kind: SyntaxKind.Dot = SyntaxKind.Dot;
constructor(
public span: TextSpan | null = null,
public origNode: Syntax | null = null,
public parentNode: Syntax | null = null
) {
super();
@ -277,8 +411,8 @@ export class Comma extends SyntaxBase {
toJSON() {
return {
kind: 'Comma',
span: this.span.toJSON(),
kind: 'Dot',
span: this.span !== null ? this.span.toJSON() : null,
}
}
@ -286,10 +420,17 @@ export class Comma extends SyntaxBase {
export type Token
= Semi
| Comma
| Colon
| EqSign
| Dot
| RArrow
| Identifier
| Operator
| Literal
| Punctuated
| Parenthesized
| Braced
| Bracketed
export class Sentence extends SyntaxBase {
@ -323,7 +464,7 @@ export class QualName {
}
constructor(
public name: string,
public name: Identifier | Operator,
public path: Identifier[],
public span: TextSpan,
public parentNode: Syntax | null = null
@ -333,9 +474,48 @@ export class QualName {
}
export class ConstantExpr {
export class Param extends SyntaxBase {
kind = SyntaxKind.ConstantExpr;
kind: SyntaxKind.Param = SyntaxKind.Param;
constructor(
public bindings: Pattern,
public typeDecl: TypeDecl | null,
public defaultValue: Expr | null,
public span: TextSpan | null = null,
public parentNode: Syntax | null = null,
) {
super();
}
}
export class BindPatt extends SyntaxBase {
kind: SyntaxKind.BindPatt = SyntaxKind.BindPatt;
constructor(
public name: Identifier,
public span: TextSpan | null = null,
public origNode: Syntax | null = null,
public parentNode: Syntax | null = null
) {
super();
}
toJSON() {
return {
kind: 'BindPatt',
name: this.name.toJSON(),
span: this.span !== null ? this.span.toJSON() : null,
}
}
}
export class ConstExpr {
kind = SyntaxKind.ConstExpr;
static META = {
value: EdgeType.Primitive,
@ -352,7 +532,7 @@ export class ConstantExpr {
}
export type Expr
= ConstantExpr
= ConstExpr
class ReturnStatement extends SyntaxBase {
@ -463,6 +643,7 @@ export type Decl
export type Syntax
= Decl
| Expr
| Token
| SourceFile
| QualName

View file

@ -7,11 +7,14 @@ import {
TextPos,
TextSpan,
Identifier,
RArrow,
Operator,
PunctType,
Token,
Decl,
Punctuated,
Parenthesized,
Braced,
Bracketed,
Sentence,
SourceFile,
Semi,
@ -192,6 +195,7 @@ export class Scanner {
const startPos = this.currPos.clone()
switch (c0) {
case ';':
this.getChar();
@ -202,7 +206,6 @@ export class Scanner {
case ':':
this.getChar();
return new Colon(new TextSpan(this.file, startPos, this.currPos.clone()));
}
if (isOpenPunct(c0)) {
@ -244,7 +247,16 @@ export class Scanner {
const endPos = this.currPos.clone();
return new Punctuated(punctType, elements, new TextSpan(this.file, startPos, endPos));
switch (punctType) {
case PunctType.Brace:
return new Braced(elements, new TextSpan(this.file, startPos, endPos));
case PunctType.Paren:
return new Parenthesized(elements, new TextSpan(this.file, startPos, endPos));
case PunctType.Bracket:
return new Bracketed(elements, new TextSpan(this.file, startPos, endPos));
default:
throw new Error("Got an invalid state.")
}
} else if (isIdentStart(c0)) {
@ -256,7 +268,13 @@ export class Scanner {
const text = this.takeWhile(isOperatorPart)
const endPos = this.currPos.clone()
return new Operator(text, new TextSpan(this.file, startPos, endPos));
const span = new TextSpan(this.file, startPos, endPos);
if (text === '->') {
return new RArrow(span);
} else {
return new Operator(text, span);
}
} else {
@ -290,7 +308,7 @@ export class Scanner {
break;
}
tokens.push(token)
if (token.kind === SyntaxKind.Punctuated && token.punctuator === PunctType.Brace) {
if (token.kind === SyntaxKind.Braced) {
break;
}
}