Update the parser and related files

- Extend the parser to support many more constructs
 - Add basic structure for parsing embedded JavaScript
 - Remove and update some AST definitions
 - Fix some bugs
This commit is contained in:
Sam Vervaeck 2020-05-22 19:50:47 +02:00
parent 9e139c40a9
commit 70b219d6df
9 changed files with 755 additions and 245 deletions

View file

@ -2,6 +2,8 @@
@language Bolt;
@language JS;
node EndOfFile > BoltToken, JSToken;
// Bolt language AST definitions
type BoltValue = Integer | bool | String;
@ -34,8 +36,6 @@ node BoltAssignment > BoltToken {
operator: Option<String>,
}
node BoltEOS > BoltToken;
node BoltComma > BoltToken;
node BoltSemi > BoltToken;
node BoltColon > BoltToken;
@ -62,7 +62,8 @@ node BoltModKeyword > BoltToken, BoltKeyword;
node BoltMutKeyword > BoltToken, BoltKeyword;
node BoltEnumKeyword > BoltToken, BoltKeyword;
node BoltStructKeyword > BoltToken, BoltKeyword;
node BoltNewTypeKeyword > BoltToken, BoltKeyword;
node BoltTypeKeyword > BoltToken, BoltKeyword;
node BoltTraitKeyworkd > BoltToken, BoltKeyword;
node BoltPunctuated > BoltToken {
text: String,
@ -85,11 +86,17 @@ node BoltSentence > BoltSourceElement {
tokens: Vec<BoltToken>,
}
node BoltTypeNode;
node BoltTypeExpression;
node BoltReferenceTypeNode > BoltTypeNode {
node BoltReferenceTypeExpression > BoltTypeExpression {
name: BoltQualName,
arguments: Option<Vec<BoltTypeNode>>,
arguments: Option<Vec<BoltTypeExpression>>,
}
node BoltTypeParameter {
index: usize,
name: BoltIdentifier,
defaultType: Option<BoltTypeExpression>,
}
node BoltPattern;
@ -99,7 +106,7 @@ node BoltBindPattern > BoltPattern {
}
node BoltTypePattern > BoltPattern {
type: BoltTypeNode,
type: BoltTypeExpression,
nestedPattern: BoltPattern,
}
@ -122,7 +129,7 @@ node BoltRecordPatternField {
}
node BoltRecordPattern > BoltPattern {
name: BoltTypeNode,
name: BoltTypeExpression,
fields: Vec<BoltRecordPatternField>,
}
@ -185,12 +192,14 @@ node BoltExpressionStatement > BoltStatement {
node BoltParameter {
index: usize,
bindings: BoltPattern,
type: Option<BoltTypeNode>,
type: Option<BoltTypeExpression>,
defaultValue: Option<BoltExpression>,
}
node BoltDeclaration > BoltSourceElement;
node BoltTypeDeclaration > BoltDeclaration;
enum BoltDeclarationModifiers {
Mutable = 0x1,
Public = 0x2,
@ -198,10 +207,6 @@ enum BoltDeclarationModifiers {
IsForeign = 0x8,
}
node BoltNewTypeDeclaration > BoltDeclaration {
modifiers: BoltDeclarationModifiers,
name: BoltIdentifier,
}
node BoltModule > BoltDeclaration {
modifiers: BoltDeclarationModifiers,
@ -214,14 +219,14 @@ node BoltFunctionDeclaration > BoltDeclaration {
target: String,
name: BoltSymbol,
params: Vec<BoltParameter>,
returnType: Option<BoltTypeNode>,
returnType: Option<BoltTypeExpression>,
body: Vec<BoltStatement>,
}
node BoltVariableDeclaration > BoltDeclaration {
modifiers: BoltDeclarationModifiers,
bindings: BoltPattern,
type: Option<BoltTypeNode>,
type: Option<BoltTypeExpression>,
value: Option<BoltExpression>,
}
@ -238,14 +243,22 @@ node BoltImportDeclaration > BoltDeclaration {
node BoltRecordDeclarationField {
name: BoltIdentifier,
type: BoltTypeNode,
type: BoltTypeExpression,
}
node BoltTypeAliasDeclaration > BoltTypeDeclaration {
modifiers: BoltDeclarationModifiers,
name: BoltIdentifier,
typeParams: Option<Vec<BoltTypeParameter>>,
typeExpr: BoltTypeExpression,
}
node BoltSourceElement;
node BoltRecordDeclaration > BoltDeclaration {
node BoltRecordDeclaration > BoltTypeDeclaration {
modifiers: BoltDeclarationModifiers,
name: BoltQualName,
typeParms: Option<Vec<BoltTypeParameter>>,
fields: Vec<BoltRecordDeclarationField>,
}
@ -263,6 +276,10 @@ node JSIdentifier > JSToken {
text: String,
}
node JSReturnKeyword > JSToken;
node JSTryKeyword > JSToken;
node JSCatchKeyword > JSToken;
node JSPattern;
node JSBindPattern > JSPattern {
@ -320,7 +337,9 @@ node JSReferenceExpression > JSExpression {
name: String,
}
node JSStatement;
node JSSourceElement;
node JSStatement > JSSourceElement;
node JSExpressionStatement > JSStatement {
expression: JSExpression,
@ -338,7 +357,7 @@ node JSParameter {
defaultValue: Option<JSExpression>,
}
node JSDeclaration;
node JSDeclaration > JSSourceElement;
enum JSDeclarationModifiers {
IsExported = 0x1,
@ -366,5 +385,3 @@ node JSSourceFile {
elements: Vec<JSSourceElement>,
}
node JSSourceElement > JSDeclaration, JSStatement;

318
src/ast.d.ts vendored
View file

@ -1,12 +1,12 @@
export const enum SyntaxKind {
FunctionBody = 3,
BoltStringLiteral = 5,
BoltIntegerLiteral = 6,
BoltIdentifier = 8,
BoltOperator = 9,
BoltAssignment = 10,
BoltEOS = 11,
EndOfFile = 2,
FunctionBody = 4,
BoltStringLiteral = 6,
BoltIntegerLiteral = 7,
BoltIdentifier = 9,
BoltOperator = 10,
BoltAssignment = 11,
BoltComma = 12,
BoltSemi = 13,
BoltColon = 14,
@ -30,62 +30,66 @@ export const enum SyntaxKind {
BoltMutKeyword = 33,
BoltEnumKeyword = 34,
BoltStructKeyword = 35,
BoltNewTypeKeyword = 36,
BoltParenthesized = 38,
BoltBraced = 39,
BoltBracketed = 40,
BoltSourceFile = 41,
BoltQualName = 42,
BoltSentence = 43,
BoltReferenceTypeNode = 45,
BoltBindPattern = 47,
BoltTypePattern = 48,
BoltExpressionPattern = 49,
BoltTuplePatternElement = 50,
BoltTuplePattern = 51,
BoltRecordPatternField = 52,
BoltRecordPattern = 53,
BoltReferenceExpression = 55,
BoltCallExpression = 56,
BoltYieldExpression = 57,
BoltMatchArm = 58,
BoltMatchExpression = 59,
BoltCase = 60,
BoltCaseExpression = 61,
BoltBlockExpression = 62,
BoltConstantExpression = 63,
BoltReturnStatement = 65,
BoltResumeStatement = 66,
BoltExpressionStatement = 67,
BoltParameter = 68,
BoltNewTypeDeclaration = 71,
BoltModule = 72,
BoltFunctionDeclaration = 73,
BoltVariableDeclaration = 74,
BoltPlainImportSymbol = 76,
BoltImportDeclaration = 77,
BoltRecordDeclarationField = 78,
BoltRecordDeclaration = 80,
JSOperator = 83,
JSIdentifier = 84,
JSBindPattern = 86,
JSConstantExpression = 88,
JSMemberExpression = 90,
JSCallExpression = 91,
JSBinaryExpression = 92,
JSUnaryExpression = 93,
JSNewExpression = 94,
JSSequenceExpression = 95,
JSConditionalExpression = 96,
JSReferenceExpression = 97,
JSExpressionStatement = 99,
JSConditionalStatement = 100,
JSParameter = 101,
JSFunctionDeclaration = 104,
JSArrowFunctionDeclaration = 105,
JSLetDeclaration = 106,
JSSourceFile = 107,
JSSourceElement = 108,
BoltTypeKeyword = 36,
BoltTraitKeyworkd = 37,
BoltParenthesized = 39,
BoltBraced = 40,
BoltBracketed = 41,
BoltSourceFile = 42,
BoltQualName = 43,
BoltSentence = 44,
BoltReferenceTypeExpression = 46,
BoltTypeParameter = 47,
BoltBindPattern = 49,
BoltTypePattern = 50,
BoltExpressionPattern = 51,
BoltTuplePatternElement = 52,
BoltTuplePattern = 53,
BoltRecordPatternField = 54,
BoltRecordPattern = 55,
BoltReferenceExpression = 57,
BoltCallExpression = 58,
BoltYieldExpression = 59,
BoltMatchArm = 60,
BoltMatchExpression = 61,
BoltCase = 62,
BoltCaseExpression = 63,
BoltBlockExpression = 64,
BoltConstantExpression = 65,
BoltReturnStatement = 67,
BoltResumeStatement = 68,
BoltExpressionStatement = 69,
BoltParameter = 70,
BoltModule = 74,
BoltFunctionDeclaration = 75,
BoltVariableDeclaration = 76,
BoltPlainImportSymbol = 78,
BoltImportDeclaration = 79,
BoltRecordDeclarationField = 80,
BoltTypeAliasDeclaration = 81,
BoltRecordDeclaration = 83,
JSOperator = 86,
JSIdentifier = 87,
JSReturnKeyword = 88,
JSTryKeyword = 89,
JSCatchKeyword = 90,
JSBindPattern = 92,
JSConstantExpression = 94,
JSMemberExpression = 96,
JSCallExpression = 97,
JSBinaryExpression = 98,
JSUnaryExpression = 99,
JSNewExpression = 100,
JSSequenceExpression = 101,
JSConditionalExpression = 102,
JSReferenceExpression = 103,
JSExpressionStatement = 106,
JSConditionalStatement = 107,
JSParameter = 108,
JSFunctionDeclaration = 111,
JSArrowFunctionDeclaration = 112,
JSLetDeclaration = 113,
JSSourceFile = 114,
}
@ -101,17 +105,21 @@ interface SyntaxBase {
parentNode: Syntax | null;
span: TextSpan | null;
}
export interface EndOfFile extends SyntaxBase {
kind: SyntaxKind.EndOfFile;
}
export interface FunctionBody extends SyntaxBase {
kind: SyntaxKind.FunctionBody;
}
export type BoltToken
= BoltStringLiteral
= EndOfFile
| BoltStringLiteral
| BoltIntegerLiteral
| BoltIdentifier
| BoltOperator
| BoltAssignment
| BoltEOS
| BoltComma
| BoltSemi
| BoltColon
@ -135,7 +143,8 @@ export type BoltToken
| BoltMutKeyword
| BoltEnumKeyword
| BoltStructKeyword
| BoltNewTypeKeyword
| BoltTypeKeyword
| BoltTraitKeyworkd
| BoltParenthesized
| BoltBraced
| BoltBracketed
@ -171,10 +180,6 @@ export interface BoltAssignment extends SyntaxBase {
operator: string | null;
}
export interface BoltEOS extends SyntaxBase {
kind: SyntaxKind.BoltEOS;
}
export interface BoltComma extends SyntaxBase {
kind: SyntaxKind.BoltComma;
}
@ -229,7 +234,8 @@ export type BoltKeyword
| BoltMutKeyword
| BoltEnumKeyword
| BoltStructKeyword
| BoltNewTypeKeyword
| BoltTypeKeyword
| BoltTraitKeyworkd
export interface BoltFnKeyword extends SyntaxBase {
@ -284,8 +290,12 @@ export interface BoltStructKeyword extends SyntaxBase {
kind: SyntaxKind.BoltStructKeyword;
}
export interface BoltNewTypeKeyword extends SyntaxBase {
kind: SyntaxKind.BoltNewTypeKeyword;
export interface BoltTypeKeyword extends SyntaxBase {
kind: SyntaxKind.BoltTypeKeyword;
}
export interface BoltTraitKeyworkd extends SyntaxBase {
kind: SyntaxKind.BoltTraitKeyworkd;
}
export type BoltPunctuated
@ -325,14 +335,21 @@ export interface BoltSentence extends SyntaxBase {
tokens: BoltToken[];
}
export type BoltTypeNode
= BoltReferenceTypeNode
export type BoltTypeExpression
= BoltReferenceTypeExpression
export interface BoltReferenceTypeNode extends SyntaxBase {
kind: SyntaxKind.BoltReferenceTypeNode;
export interface BoltReferenceTypeExpression extends SyntaxBase {
kind: SyntaxKind.BoltReferenceTypeExpression;
name: BoltQualName;
arguments: BoltTypeNode[] | null;
arguments: BoltTypeExpression[] | null;
}
export interface BoltTypeParameter extends SyntaxBase {
kind: SyntaxKind.BoltTypeParameter;
index: number;
name: BoltIdentifier;
defaultType: BoltTypeExpression | null;
}
export type BoltPattern
@ -350,7 +367,7 @@ export interface BoltBindPattern extends SyntaxBase {
export interface BoltTypePattern extends SyntaxBase {
kind: SyntaxKind.BoltTypePattern;
type: BoltTypeNode;
type: BoltTypeExpression;
nestedPattern: BoltPattern;
}
@ -378,7 +395,7 @@ export interface BoltRecordPatternField extends SyntaxBase {
export interface BoltRecordPattern extends SyntaxBase {
kind: SyntaxKind.BoltRecordPattern;
name: BoltTypeNode;
name: BoltTypeExpression;
fields: BoltRecordPatternField[];
}
@ -466,28 +483,27 @@ export interface BoltParameter extends SyntaxBase {
kind: SyntaxKind.BoltParameter;
index: number;
bindings: BoltPattern;
type: BoltTypeNode | null;
type: BoltTypeExpression | null;
defaultValue: BoltExpression | null;
}
export type BoltDeclaration
= BoltNewTypeDeclaration
= BoltTypeAliasDeclaration
| BoltRecordDeclaration
| BoltModule
| BoltFunctionDeclaration
| BoltVariableDeclaration
| BoltImportDeclaration
export type BoltTypeDeclaration
= BoltTypeAliasDeclaration
| BoltRecordDeclaration
export const enum BoltDeclarationModifiers {
Mutable = 1,Public = 2,IsType = 4,IsForeign = 8,}
export interface BoltNewTypeDeclaration extends SyntaxBase {
kind: SyntaxKind.BoltNewTypeDeclaration;
modifiers: BoltDeclarationModifiers;
name: BoltIdentifier;
}
export interface BoltModule extends SyntaxBase {
kind: SyntaxKind.BoltModule;
modifiers: BoltDeclarationModifiers;
@ -501,7 +517,7 @@ export interface BoltFunctionDeclaration extends SyntaxBase {
target: string;
name: BoltSymbol;
params: BoltParameter[];
returnType: BoltTypeNode | null;
returnType: BoltTypeExpression | null;
body: BoltStatement[];
}
@ -509,7 +525,7 @@ export interface BoltVariableDeclaration extends SyntaxBase {
kind: SyntaxKind.BoltVariableDeclaration;
modifiers: BoltDeclarationModifiers;
bindings: BoltPattern;
type: BoltTypeNode | null;
type: BoltTypeExpression | null;
value: BoltExpression | null;
}
@ -531,7 +547,15 @@ export interface BoltImportDeclaration extends SyntaxBase {
export interface BoltRecordDeclarationField extends SyntaxBase {
kind: SyntaxKind.BoltRecordDeclarationField;
name: BoltIdentifier;
type: BoltTypeNode;
type: BoltTypeExpression;
}
export interface BoltTypeAliasDeclaration extends SyntaxBase {
kind: SyntaxKind.BoltTypeAliasDeclaration;
modifiers: BoltDeclarationModifiers;
name: BoltIdentifier;
typeParams: BoltTypeParameter[] | null;
typeExpr: BoltTypeExpression;
}
export type BoltSourceElement
@ -539,24 +563,29 @@ export type BoltSourceElement
| BoltReturnStatement
| BoltResumeStatement
| BoltExpressionStatement
| BoltNewTypeDeclaration
| BoltTypeAliasDeclaration
| BoltRecordDeclaration
| BoltModule
| BoltFunctionDeclaration
| BoltVariableDeclaration
| BoltImportDeclaration
| BoltRecordDeclaration
export interface BoltRecordDeclaration extends SyntaxBase {
kind: SyntaxKind.BoltRecordDeclaration;
modifiers: BoltDeclarationModifiers;
name: BoltQualName;
typeParms: BoltTypeParameter[] | null;
fields: BoltRecordDeclarationField[];
}
export type JSToken
= JSOperator
= EndOfFile
| JSOperator
| JSIdentifier
| JSReturnKeyword
| JSTryKeyword
| JSCatchKeyword
export interface JSOperator extends SyntaxBase {
@ -569,6 +598,18 @@ export interface JSIdentifier extends SyntaxBase {
text: string;
}
export interface JSReturnKeyword extends SyntaxBase {
kind: SyntaxKind.JSReturnKeyword;
}
export interface JSTryKeyword extends SyntaxBase {
kind: SyntaxKind.JSTryKeyword;
}
export interface JSCatchKeyword extends SyntaxBase {
kind: SyntaxKind.JSCatchKeyword;
}
export type JSPattern
= JSBindPattern
@ -647,10 +688,17 @@ export interface JSReferenceExpression extends SyntaxBase {
name: string;
}
export type JSSourceElement
= JSExpressionStatement
| JSConditionalStatement
| JSFunctionDeclaration
| JSArrowFunctionDeclaration
| JSLetDeclaration
export type JSStatement
= JSExpressionStatement
| JSConditionalStatement
| JSSourceElement
export interface JSExpressionStatement extends SyntaxBase {
@ -676,7 +724,6 @@ export type JSDeclaration
= JSFunctionDeclaration
| JSArrowFunctionDeclaration
| JSLetDeclaration
| JSSourceElement
export const enum JSDeclarationModifiers {
@ -708,17 +755,12 @@ export interface JSSourceFile extends SyntaxBase {
elements: JSSourceElement[];
}
export interface JSSourceElement extends SyntaxBase {
kind: SyntaxKind.JSSourceElement;
}
export type BoltSyntax
= BoltStringLiteral
| BoltIntegerLiteral
| BoltIdentifier
| BoltOperator
| BoltAssignment
| BoltEOS
| BoltComma
| BoltSemi
| BoltColon
@ -742,14 +784,16 @@ export type BoltSyntax
| BoltMutKeyword
| BoltEnumKeyword
| BoltStructKeyword
| BoltNewTypeKeyword
| BoltTypeKeyword
| BoltTraitKeyworkd
| BoltParenthesized
| BoltBraced
| BoltBracketed
| BoltSourceFile
| BoltQualName
| BoltSentence
| BoltReferenceTypeNode
| BoltReferenceTypeExpression
| BoltTypeParameter
| BoltBindPattern
| BoltTypePattern
| BoltExpressionPattern
@ -770,19 +814,22 @@ export type BoltSyntax
| BoltResumeStatement
| BoltExpressionStatement
| BoltParameter
| BoltNewTypeDeclaration
| BoltModule
| BoltFunctionDeclaration
| BoltVariableDeclaration
| BoltPlainImportSymbol
| BoltImportDeclaration
| BoltRecordDeclarationField
| BoltTypeAliasDeclaration
| BoltRecordDeclaration
export type JSSyntax
= JSOperator
| JSIdentifier
| JSReturnKeyword
| JSTryKeyword
| JSCatchKeyword
| JSBindPattern
| JSConstantExpression
| JSMemberExpression
@ -800,17 +847,16 @@ export type JSSyntax
| JSArrowFunctionDeclaration
| JSLetDeclaration
| JSSourceFile
| JSSourceElement
export type Syntax
= FunctionBody
= EndOfFile
| FunctionBody
| BoltStringLiteral
| BoltIntegerLiteral
| BoltIdentifier
| BoltOperator
| BoltAssignment
| BoltEOS
| BoltComma
| BoltSemi
| BoltColon
@ -834,14 +880,16 @@ export type Syntax
| BoltMutKeyword
| BoltEnumKeyword
| BoltStructKeyword
| BoltNewTypeKeyword
| BoltTypeKeyword
| BoltTraitKeyworkd
| BoltParenthesized
| BoltBraced
| BoltBracketed
| BoltSourceFile
| BoltQualName
| BoltSentence
| BoltReferenceTypeNode
| BoltReferenceTypeExpression
| BoltTypeParameter
| BoltBindPattern
| BoltTypePattern
| BoltExpressionPattern
@ -862,16 +910,19 @@ export type Syntax
| BoltResumeStatement
| BoltExpressionStatement
| BoltParameter
| BoltNewTypeDeclaration
| BoltModule
| BoltFunctionDeclaration
| BoltVariableDeclaration
| BoltPlainImportSymbol
| BoltImportDeclaration
| BoltRecordDeclarationField
| BoltTypeAliasDeclaration
| BoltRecordDeclaration
| JSOperator
| JSIdentifier
| JSReturnKeyword
| JSTryKeyword
| JSCatchKeyword
| JSBindPattern
| JSConstantExpression
| JSMemberExpression
@ -889,18 +940,17 @@ export type Syntax
| JSArrowFunctionDeclaration
| JSLetDeclaration
| JSSourceFile
| JSSourceElement
export function kindToString(kind: SyntaxKind): string;
export function createEndOfFile(span?: TextSpan | null): EndOfFile;
export function createFunctionBody(span?: TextSpan | null): FunctionBody;
export function createBoltStringLiteral(value: string, span?: TextSpan | null): BoltStringLiteral;
export function createBoltIntegerLiteral(value: bigint, span?: TextSpan | null): BoltIntegerLiteral;
export function createBoltIdentifier(text: string, span?: TextSpan | null): BoltIdentifier;
export function createBoltOperator(text: string, span?: TextSpan | null): BoltOperator;
export function createBoltAssignment(operator: string | null, span?: TextSpan | null): BoltAssignment;
export function createBoltEOS(span?: TextSpan | null): BoltEOS;
export function createBoltComma(span?: TextSpan | null): BoltComma;
export function createBoltSemi(span?: TextSpan | null): BoltSemi;
export function createBoltColon(span?: TextSpan | null): BoltColon;
@ -924,21 +974,23 @@ export function createBoltModKeyword(span?: TextSpan | null): BoltModKeyword;
export function createBoltMutKeyword(span?: TextSpan | null): BoltMutKeyword;
export function createBoltEnumKeyword(span?: TextSpan | null): BoltEnumKeyword;
export function createBoltStructKeyword(span?: TextSpan | null): BoltStructKeyword;
export function createBoltNewTypeKeyword(span?: TextSpan | null): BoltNewTypeKeyword;
export function createBoltTypeKeyword(span?: TextSpan | null): BoltTypeKeyword;
export function createBoltTraitKeyworkd(span?: TextSpan | null): BoltTraitKeyworkd;
export function createBoltParenthesized(text: string, span?: TextSpan | null): BoltParenthesized;
export function createBoltBraced(text: string, span?: TextSpan | null): BoltBraced;
export function createBoltBracketed(text: string, span?: TextSpan | null): BoltBracketed;
export function createBoltSourceFile(elements: BoltSourceElement[], span?: TextSpan | null): BoltSourceFile;
export function createBoltQualName(modulePath: BoltIdentifier[], name: BoltSymbol, span?: TextSpan | null): BoltQualName;
export function createBoltSentence(tokens: BoltToken[], span?: TextSpan | null): BoltSentence;
export function createBoltReferenceTypeNode(name: BoltQualName, arguments: BoltTypeNode[] | null, span?: TextSpan | null): BoltReferenceTypeNode;
export function createBoltReferenceTypeExpression(name: BoltQualName, arguments: BoltTypeExpression[] | null, span?: TextSpan | null): BoltReferenceTypeExpression;
export function createBoltTypeParameter(index: number, name: BoltIdentifier, defaultType: BoltTypeExpression | null, span?: TextSpan | null): BoltTypeParameter;
export function createBoltBindPattern(name: BoltIdentifier, span?: TextSpan | null): BoltBindPattern;
export function createBoltTypePattern(type: BoltTypeNode, nestedPattern: BoltPattern, span?: TextSpan | null): BoltTypePattern;
export function createBoltTypePattern(type: BoltTypeExpression, nestedPattern: BoltPattern, span?: TextSpan | null): BoltTypePattern;
export function createBoltExpressionPattern(expression: BoltExpression, span?: TextSpan | null): BoltExpressionPattern;
export function createBoltTuplePatternElement(index: number, pattern: BoltPattern, span?: TextSpan | null): BoltTuplePatternElement;
export function createBoltTuplePattern(elements: BoltTuplePatternElement[], span?: TextSpan | null): BoltTuplePattern;
export function createBoltRecordPatternField(name: BoltIdentifier, pattern: BoltPattern, span?: TextSpan | null): BoltRecordPatternField;
export function createBoltRecordPattern(name: BoltTypeNode, fields: BoltRecordPatternField[], span?: TextSpan | null): BoltRecordPattern;
export function createBoltRecordPattern(name: BoltTypeExpression, fields: BoltRecordPatternField[], span?: TextSpan | null): BoltRecordPattern;
export function createBoltReferenceExpression(name: BoltQualName, span?: TextSpan | null): BoltReferenceExpression;
export function createBoltCallExpression(operator: BoltExpression, operands: BoltExpression[], span?: TextSpan | null): BoltCallExpression;
export function createBoltYieldExpression(value: BoltExpression, span?: TextSpan | null): BoltYieldExpression;
@ -951,17 +1003,20 @@ export function createBoltConstantExpression(value: BoltValue, span?: TextSpan |
export function createBoltReturnStatement(value: BoltExpression | null, span?: TextSpan | null): BoltReturnStatement;
export function createBoltResumeStatement(value: BoltExpression, span?: TextSpan | null): BoltResumeStatement;
export function createBoltExpressionStatement(expression: BoltExpression, span?: TextSpan | null): BoltExpressionStatement;
export function createBoltParameter(index: number, bindings: BoltPattern, type: BoltTypeNode | null, defaultValue: BoltExpression | null, span?: TextSpan | null): BoltParameter;
export function createBoltNewTypeDeclaration(modifiers: BoltDeclarationModifiers, name: BoltIdentifier, span?: TextSpan | null): BoltNewTypeDeclaration;
export function createBoltParameter(index: number, bindings: BoltPattern, type: BoltTypeExpression | null, defaultValue: BoltExpression | null, span?: TextSpan | null): BoltParameter;
export function createBoltModule(modifiers: BoltDeclarationModifiers, name: BoltQualName, elements: BoltSourceElement[], span?: TextSpan | null): BoltModule;
export function createBoltFunctionDeclaration(modifiers: BoltDeclarationModifiers, target: string, name: BoltSymbol, params: BoltParameter[], returnType: BoltTypeNode | null, body: BoltStatement[], span?: TextSpan | null): BoltFunctionDeclaration;
export function createBoltVariableDeclaration(modifiers: BoltDeclarationModifiers, bindings: BoltPattern, type: BoltTypeNode | null, value: BoltExpression | null, span?: TextSpan | null): BoltVariableDeclaration;
export function createBoltFunctionDeclaration(modifiers: BoltDeclarationModifiers, target: string, name: BoltSymbol, params: BoltParameter[], returnType: BoltTypeExpression | null, body: BoltStatement[], span?: TextSpan | null): BoltFunctionDeclaration;
export function createBoltVariableDeclaration(modifiers: BoltDeclarationModifiers, bindings: BoltPattern, type: BoltTypeExpression | null, value: BoltExpression | null, span?: TextSpan | null): BoltVariableDeclaration;
export function createBoltPlainImportSymbol(name: BoltQualName, span?: TextSpan | null): BoltPlainImportSymbol;
export function createBoltImportDeclaration(file: string, symbols: BoltImportSymbol[], span?: TextSpan | null): BoltImportDeclaration;
export function createBoltRecordDeclarationField(name: BoltIdentifier, type: BoltTypeNode, span?: TextSpan | null): BoltRecordDeclarationField;
export function createBoltRecordDeclaration(modifiers: BoltDeclarationModifiers, name: BoltQualName, fields: BoltRecordDeclarationField[], span?: TextSpan | null): BoltRecordDeclaration;
export function createBoltRecordDeclarationField(name: BoltIdentifier, type: BoltTypeExpression, span?: TextSpan | null): BoltRecordDeclarationField;
export function createBoltTypeAliasDeclaration(modifiers: BoltDeclarationModifiers, name: BoltIdentifier, typeParams: BoltTypeParameter[] | null, typeExpr: BoltTypeExpression, span?: TextSpan | null): BoltTypeAliasDeclaration;
export function createBoltRecordDeclaration(modifiers: BoltDeclarationModifiers, name: BoltQualName, typeParms: BoltTypeParameter[] | null, fields: BoltRecordDeclarationField[], span?: TextSpan | null): BoltRecordDeclaration;
export function createJSOperator(text: string, span?: TextSpan | null): JSOperator;
export function createJSIdentifier(text: string, span?: TextSpan | null): JSIdentifier;
export function createJSReturnKeyword(span?: TextSpan | null): JSReturnKeyword;
export function createJSTryKeyword(span?: TextSpan | null): JSTryKeyword;
export function createJSCatchKeyword(span?: TextSpan | null): JSCatchKeyword;
export function createJSBindPattern(name: JSIdentifier, span?: TextSpan | null): JSBindPattern;
export function createJSConstantExpression(value: BoltValue, span?: TextSpan | null): JSConstantExpression;
export function createJSMemberExpression(value: JSExpression, property: JSExpression, modifiers: JSMemberExpressionModifiers, span?: TextSpan | null): JSMemberExpression;
@ -979,8 +1034,8 @@ export function createJSFunctionDeclaration(modifiers: JSDeclarationModifiers, n
export function createJSArrowFunctionDeclaration(name: JSIdentifier, params: JSParameter[], body: JSExpression, span?: TextSpan | null): JSArrowFunctionDeclaration;
export function createJSLetDeclaration(bindings: JSPattern, value: JSExpression | null, span?: TextSpan | null): JSLetDeclaration;
export function createJSSourceFile(elements: JSSourceElement[], span?: TextSpan | null): JSSourceFile;
export function createJSSourceElement(span?: TextSpan | null): JSSourceElement;
export function isEndOfFile(value: any): value is EndOfFile;
export function isFunctionBody(value: any): value is FunctionBody;
export function isBoltToken(value: any): value is BoltToken;
export function isBoltStringLiteral(value: any): value is BoltStringLiteral;
@ -989,7 +1044,6 @@ export function isBoltSymbol(value: any): value is BoltSymbol;
export function isBoltIdentifier(value: any): value is BoltIdentifier;
export function isBoltOperator(value: any): value is BoltOperator;
export function isBoltAssignment(value: any): value is BoltAssignment;
export function isBoltEOS(value: any): value is BoltEOS;
export function isBoltComma(value: any): value is BoltComma;
export function isBoltSemi(value: any): value is BoltSemi;
export function isBoltColon(value: any): value is BoltColon;
@ -1014,7 +1068,8 @@ export function isBoltModKeyword(value: any): value is BoltModKeyword;
export function isBoltMutKeyword(value: any): value is BoltMutKeyword;
export function isBoltEnumKeyword(value: any): value is BoltEnumKeyword;
export function isBoltStructKeyword(value: any): value is BoltStructKeyword;
export function isBoltNewTypeKeyword(value: any): value is BoltNewTypeKeyword;
export function isBoltTypeKeyword(value: any): value is BoltTypeKeyword;
export function isBoltTraitKeyworkd(value: any): value is BoltTraitKeyworkd;
export function isBoltPunctuated(value: any): value is BoltPunctuated;
export function isBoltParenthesized(value: any): value is BoltParenthesized;
export function isBoltBraced(value: any): value is BoltBraced;
@ -1022,8 +1077,9 @@ export function isBoltBracketed(value: any): value is BoltBracketed;
export function isBoltSourceFile(value: any): value is BoltSourceFile;
export function isBoltQualName(value: any): value is BoltQualName;
export function isBoltSentence(value: any): value is BoltSentence;
export function isBoltTypeNode(value: any): value is BoltTypeNode;
export function isBoltReferenceTypeNode(value: any): value is BoltReferenceTypeNode;
export function isBoltTypeExpression(value: any): value is BoltTypeExpression;
export function isBoltReferenceTypeExpression(value: any): value is BoltReferenceTypeExpression;
export function isBoltTypeParameter(value: any): value is BoltTypeParameter;
export function isBoltPattern(value: any): value is BoltPattern;
export function isBoltBindPattern(value: any): value is BoltBindPattern;
export function isBoltTypePattern(value: any): value is BoltTypePattern;
@ -1048,7 +1104,7 @@ export function isBoltResumeStatement(value: any): value is BoltResumeStatement;
export function isBoltExpressionStatement(value: any): value is BoltExpressionStatement;
export function isBoltParameter(value: any): value is BoltParameter;
export function isBoltDeclaration(value: any): value is BoltDeclaration;
export function isBoltNewTypeDeclaration(value: any): value is BoltNewTypeDeclaration;
export function isBoltTypeDeclaration(value: any): value is BoltTypeDeclaration;
export function isBoltModule(value: any): value is BoltModule;
export function isBoltFunctionDeclaration(value: any): value is BoltFunctionDeclaration;
export function isBoltVariableDeclaration(value: any): value is BoltVariableDeclaration;
@ -1056,11 +1112,15 @@ export function isBoltImportSymbol(value: any): value is BoltImportSymbol;
export function isBoltPlainImportSymbol(value: any): value is BoltPlainImportSymbol;
export function isBoltImportDeclaration(value: any): value is BoltImportDeclaration;
export function isBoltRecordDeclarationField(value: any): value is BoltRecordDeclarationField;
export function isBoltTypeAliasDeclaration(value: any): value is BoltTypeAliasDeclaration;
export function isBoltSourceElement(value: any): value is BoltSourceElement;
export function isBoltRecordDeclaration(value: any): value is BoltRecordDeclaration;
export function isJSToken(value: any): value is JSToken;
export function isJSOperator(value: any): value is JSOperator;
export function isJSIdentifier(value: any): value is JSIdentifier;
export function isJSReturnKeyword(value: any): value is JSReturnKeyword;
export function isJSTryKeyword(value: any): value is JSTryKeyword;
export function isJSCatchKeyword(value: any): value is JSCatchKeyword;
export function isJSPattern(value: any): value is JSPattern;
export function isJSBindPattern(value: any): value is JSBindPattern;
export function isJSExpression(value: any): value is JSExpression;
@ -1073,6 +1133,7 @@ export function isJSNewExpression(value: any): value is JSNewExpression;
export function isJSSequenceExpression(value: any): value is JSSequenceExpression;
export function isJSConditionalExpression(value: any): value is JSConditionalExpression;
export function isJSReferenceExpression(value: any): value is JSReferenceExpression;
export function isJSSourceElement(value: any): value is JSSourceElement;
export function isJSStatement(value: any): value is JSStatement;
export function isJSExpressionStatement(value: any): value is JSExpressionStatement;
export function isJSConditionalStatement(value: any): value is JSConditionalStatement;
@ -1082,4 +1143,3 @@ export function isJSFunctionDeclaration(value: any): value is JSFunctionDeclarat
export function isJSArrowFunctionDeclaration(value: any): value is JSArrowFunctionDeclaration;
export function isJSLetDeclaration(value: any): value is JSLetDeclaration;
export function isJSSourceFile(value: any): value is JSSourceFile;
export function isJSSourceElement(value: any): value is JSSourceElement;

View file

@ -125,7 +125,7 @@ export class Compiler {
// TODO
break;
case SyntaxKind.BoltNewTypeDeclaration:
case SyntaxKind.BoltTypeAliasDeclaration:
break;
case SyntaxKind.BoltVariableDeclaration:

5
src/debugServer.ts Normal file
View file

@ -0,0 +1,5 @@
export function connectToInspector(address: string) {
}

View file

@ -228,7 +228,7 @@ export class Expander {
} else {
this.checker.check(node);
//this.checker.check(node);
return node;

View file

@ -1,4 +1,4 @@
)
import * as acorn from "acorn"
import {
@ -19,8 +19,8 @@ import {
BoltPattern,
createBoltBindPattern,
BoltImportDeclaration,
BoltTypeNode,
createBoltReferenceTypeNode,
BoltTypeExpression,
createBoltReferenceTypeExpression,
createBoltConstantExpression,
createBoltReferenceExpression,
createBoltParameter,
@ -42,18 +42,27 @@ import {
BoltRecordDeclarationField,
BoltModule,
createBoltModule,
BoltNewTypeDeclaration,
createBoltNewTypeDeclaration,
BoltTypeAliasDeclaration,
createBoltTypeAliasDeclaration,
BoltFunctionDeclaration,
createBoltFunctionDeclaration,
createBoltCallExpression,
BoltSymbol,
JSSourceElement,
JSStatement,
BoltTypeParameter,
createBoltTypePattern,
createBoltTypeParameter,
} from "./ast"
import { Stream, setOrigNodeRange, createTokenStream, uniq } from "./util"
import { Scanner } from "./scanner"
import { Stream, setOrigNodeRange, createTokenStream, uniq, FastStringMap } from "./util"
export type BoltTokenStream = Stream<BoltToken>;
export type JSTokenStream = Stream<JSToken>;
function describeKind(kind: SyntaxKind): string {
switch (kind) {
case SyntaxKind.BoltIdentifier:
@ -94,16 +103,22 @@ function describeKind(kind: SyntaxKind): string {
return "'struct'"
case SyntaxKind.BoltEnumKeyword:
return "'enum'"
case SyntaxKind.BoltNewTypeKeyword:
return "'newtype'";
case SyntaxKind.BoltTypeKeyword:
return "'type'";
case SyntaxKind.BoltBraced:
return "'{' .. '}'"
case SyntaxKind.BoltBracketed:
return "'[' .. ']'"
case SyntaxKind.BoltParenthesized:
return "'(' .. ')'"
case SyntaxKind.BoltEOS:
case SyntaxKind.EndOfFile:
return "'}', ')', ']' or end-of-file"
case SyntaxKind.BoltLtSign:
return "'<'";
case SyntaxKind.BoltGtSign:
return "'<'";
case SyntaxKind.BoltEqSign:
return "'='";
default:
throw new Error(`failed to describe ${kindToString(kind)}`)
}
@ -117,7 +132,6 @@ function enumerate(elements: string[]) {
}
}
export class ParseError extends Error {
constructor(public actual: BoltToken, public expected: SyntaxKind[]) {
super(`${actual.span!.file.origPath}:${actual.span!.start.line}:${actual.span!.start.column}: expected ${enumerate(expected.map(e => describeKind(e)))} but got ${describeKind(actual.kind)}`)
@ -131,6 +145,10 @@ enum OperatorKind {
Suffix,
}
function isRightAssoc(kind: OperatorKind) {
return kind === OperatorKind.InfixR;
}
interface OperatorInfo {
kind: OperatorKind;
arity: number;
@ -162,9 +180,9 @@ const KIND_DECLARATION_KEYWORD = [
SyntaxKind.BoltFnKeyword,
SyntaxKind.BoltEnumKeyword,
SyntaxKind.BoltLetKeyword,
SyntaxKind.BoltNewTypeKeyword,
SyntaxKind.BoltModKeyword,
SyntaxKind.BoltStructKeyword,
SyntaxKind.BoltTypeKeyword,
]
const KIND_DECLARATION_T0 = uniq([
@ -180,9 +198,37 @@ const KIND_SOURCEELEMENT_T0 = uniq([
...KIND_DECLARATION_T0,
])
type OperatorTableMatrix = [OperatorKind, number, string][][];
class OperatorTable {
private operatorsByName = new FastStringMap<string, OperatorInfo>();
//private operatorsByPrecedence = FastStringMap<number, OperatorInfo>();
constructor(definitions: OperatorTableMatrix) {
let i = 0;
for (const group of definitions) {
for (const [kind, arity, name] of group) {
const info = { kind, arity, name, precedence: i }
this.operatorsByName.set(name, info);
//this.operatorsByPrecedence[i] = info;
}
i++;
}
}
public lookup(name: string): OperatorInfo | null {
if (!this.operatorsByName.has(name)) {
return null;
}
return this.operatorsByName.get(name);
}
}
export class Parser {
operatorTable = [
exprOperatorTable = new OperatorTable([
[
[OperatorKind.InfixL, 2, '&&'],
[OperatorKind.InfixL, 2, '||']
@ -207,14 +253,20 @@ export class Parser {
[OperatorKind.InfixL, 2, '%'],
],
[
[OperatorKind.Prefix, '!']
[OperatorKind.Prefix, 1, '!']
],
];
]);
typeOperatorTable = new OperatorTable([
[
[OperatorKind.InfixL, 2, '|'],
]
]);
protected assertEmpty(tokens: BoltTokenStream) {
const t0 = tokens.peek(1);
if (t0.kind !== SyntaxKind.BoltEOS) {
throw new ParseError(t0, [SyntaxKind.BoltEOS]);
if (t0.kind !== SyntaxKind.EndOfFile) {
throw new ParseError(t0, [SyntaxKind.EndOfFile]);
}
}
@ -280,15 +332,16 @@ export class Parser {
return node;
}
public parseReferenceTypeNode(tokens: BoltTokenStream) {
public parseReferenceTypeExpression(tokens: BoltTokenStream) {
const name = this.parseQualName(tokens)
const t1 = tokens.peek();
let typeArgs: BoltTypeNode[] | null = null;
let typeArgs: BoltTypeExpression[] | null = null;
if (t1.kind === SyntaxKind.BoltLtSign) {
typeArgs = [];
tokens.get();
let first = true;
while (true) {
@ -302,26 +355,63 @@ export class Parser {
assertToken(t2, SyntaxKind.BoltComma);
tokens.get();
}
typeArgs!.push(this.parseTypeNode(tokens));
typeArgs!.push(this.parseTypeExpression(tokens));
}
const t4 = tokens.get();
assertToken(t4, SyntaxKind.BoltGtSign);
}
const node = createBoltReferenceTypeNode(name, typeArgs);
const node = createBoltReferenceTypeExpression(name, typeArgs);
setOrigNodeRange(node, name, name);
return node;
}
public parseTypeNode(tokens: BoltTokenStream): BoltTypeNode {
private parsePrimTypeExpression(tokens: BoltTokenStream): BoltTypeExpression {
const t0 = tokens.peek();
if (t0.kind === SyntaxKind.BoltIdentifier) {
return this.parseReferenceTypeNode(tokens);
return this.parseReferenceTypeExpression(tokens);
} else {
throw new ParseError(t0, [SyntaxKind.BoltIdentifier]);
}
}
private parseTypeExpressionOperators(tokens: BoltTokenStream, lhs: BoltTypeExpression, minPrecedence: number): BoltTypeExpression {
while (true) {
const t0 = tokens.peek();
if (t0.kind !== SyntaxKind.BoltOperator) {
break;
}
let desc0 = this.typeOperatorTable.lookup(t0.text);
if (desc0 === null || desc0.arity !== 2 || desc0.precedence < minPrecedence) {
break;
}
console.log(desc0)
tokens.get();
let rhs = this.parsePrimTypeExpression(tokens);
while (true) {
const t1 = tokens.peek()
if (t1.kind !== SyntaxKind.BoltOperator) {
break;
}
const desc1 = this.typeOperatorTable.lookup(t1.text)
if (desc1 === null || desc1.arity !== 2 || desc1.precedence < desc0.precedence || !isRightAssoc(desc1.kind)) {
break;
}
rhs = this.parseTypeExpressionOperators(tokens, rhs, desc1.precedence);
}
const name = createBoltQualName([], t0);
setOrigNodeRange(name, t0, t0);
lhs = createBoltReferenceTypeExpression(name, [lhs, rhs]);
setOrigNodeRange(lhs, t0, rhs);
}
return lhs
}
public parseTypeExpression(tokens: BoltTokenStream) {
const lhs = this.parsePrimTypeExpression(tokens);
return this.parseTypeExpressionOperators(tokens, lhs, 0);
}
public parseConstantExpression(tokens: BoltTokenStream): BoltConstantExpression {
const t0 = tokens.get();
let value: boolean | string | bigint;
@ -396,7 +486,7 @@ export class Parser {
let endNode: BoltSyntax = pattern;
if (t0.kind === SyntaxKind.BoltColon) {
tokens.get();
typeDecl = this.parseTypeNode(tokens);
typeDecl = this.parseTypeExpression(tokens);
endNode = typeDecl;
t0 = tokens.get();
}
@ -434,7 +524,7 @@ export class Parser {
if (t2.kind === SyntaxKind.BoltColon) {
tokens.get();
lastNode = typeDecl = this.parseTypeNode(tokens);
lastNode = typeDecl = this.parseTypeExpression(tokens);
t2 = tokens.peek();
}
@ -456,7 +546,7 @@ export class Parser {
let expr = null;
const t1 = tokens.peek();
if (t1.kind !== SyntaxKind.BoltEOS) {
if (t1.kind !== SyntaxKind.EndOfFile) {
expr = this.parseExpression(tokens)
}
@ -506,9 +596,49 @@ export class Parser {
}
}
public parseGenericTypeParameter(tokens: BoltTokenStream) {
const t0 = tokens.peek();
if (t0.kind === SyntaxKind.BoltIdentifier) {
tokens.get();
const node = createBoltTypeParameter(0, t0, null)
setOrigNodeRange(node, t0, t0);
return node;
} else {
throw new ParseError(t0, [SyntaxKind.BoltIdentifier]);
}
}
private parseGenericTypeParameters(tokens: BoltTokenStream) {
let typeParams: BoltTypeParameter[] = [];
const t0 = tokens.get();
assertToken(t0, SyntaxKind.BoltLtSign);
while (true) {
let t1 = tokens.peek();
if (t1.kind === SyntaxKind.BoltGtSign) {
break;
}
if (t1.kind === SyntaxKind.EndOfFile) {
throw new ParseError(t1, [SyntaxKind.BoltGtSign, SyntaxKind.BoltIdentifier, SyntaxKind.BoltComma]);
}
if (typeParams.length > 0) {
tokens.get();
assertToken(t1, SyntaxKind.BoltComma);
t1 = tokens.peek();
}
if (t1.kind === SyntaxKind.EndOfFile) {
throw new ParseError(t1, [SyntaxKind.BoltGtSign, SyntaxKind.BoltIdentifier]);
}
typeParams.push(this.parseGenericTypeParameter(tokens));
}
const t3 = tokens.get();
assertToken(t3, SyntaxKind.BoltGtSign);
return typeParams;
}
public parseRecordDeclaration(tokens: BoltTokenStream): BoltRecordDeclaration {
let modifiers = 0;
let typeParams = null;
let t0 = tokens.get();
const firstToken = t0;
@ -525,31 +655,49 @@ export class Parser {
assertToken(t1, SyntaxKind.BoltIdentifier);
const name = createBoltQualName([], t1 as BoltIdentifier);
const t2 = tokens.get();
let t2 = tokens.peek();
if (t2.kind === SyntaxKind.EndOfFile) {
const node = createBoltRecordDeclaration(modifiers, name, null, []);
setOrigNodeRange(node, firstToken, t2);
return node;
}
if (t2.kind === SyntaxKind.BoltLtSign) {
typeParams = this.parseGenericTypeParameters(tokens);
t2 = tokens.peek();
}
if (t2.kind !== SyntaxKind.BoltBraced) {
throw new ParseError(t2, [SyntaxKind.BoltBraced])
}
let fields: BoltRecordDeclarationField[] = [];
tokens.get();
const innerTokens = createTokenStream(t2);
while (true) {
const t3 = innerTokens.get();
if (t3.kind === SyntaxKind.BoltEOS) {
const t3 = innerTokens.peek();
if (t3.kind === SyntaxKind.EndOfFile) {
break;
}
const name = innerTokens.get();
assertToken(name, SyntaxKind.BoltIdentifier);
assertToken(t3, SyntaxKind.BoltIdentifier);
innerTokens.get();
const name = t3 as BoltIdentifier;
const t4 = innerTokens.get();
assertToken(t4, SyntaxKind.BoltColon);
const type = this.parseTypeNode(innerTokens);
const type = this.parseTypeExpression(innerTokens);
const field = createBoltRecordDeclarationField(name as BoltIdentifier, type);
const t5 = innerTokens.get();
if (t5.kind === SyntaxKind.EndOfFile) {
break;
}
assertToken(t5, SyntaxKind.BoltComma);
setOrigNodeRange(field, name, type);
fields.push(field);
}
const node = createBoltRecordDeclaration(modifiers, name, fields);
const node = createBoltRecordDeclaration(modifiers, name, typeParams, fields);
setOrigNodeRange(node, firstToken, t2);
return node;
}
@ -558,7 +706,7 @@ export class Parser {
const statements: BoltStatement[] = [];
while (true) {
const t0 = tokens.peek();
if (t0.kind === SyntaxKind.BoltEOS) {
if (t0.kind === SyntaxKind.EndOfFile) {
break;
}
const statement = this.parseStatement(tokens);
@ -579,7 +727,7 @@ export class Parser {
t0 = tokens.peek();
}
if (t0.kind !== SyntaxKind.BoltIdentifier || t0.text !== 'mod') {
if (t0.kind !== SyntaxKind.BoltModKeyword) {
throw new ParseError(t0, [SyntaxKind.BoltModKeyword])
}
@ -589,7 +737,7 @@ export class Parser {
if (t1.kind !== SyntaxKind.BoltBraced) {
throw new ParseError(t1, [SyntaxKind.BoltBraced])
}
const sentences = this.parseSentences(createTokenStream(t1));
const sentences = this.parseSourceElementList(createTokenStream(t1));
const node = createBoltModule(modifiers, name, sentences);
setOrigNodeRange(node, firstToken, t1);
@ -597,33 +745,38 @@ export class Parser {
}
public parseNewTypeDeclaration(tokens: BoltTokenStream): BoltNewTypeDeclaration {
public parseTypeAliasDeclaration(tokens: BoltTokenStream): BoltTypeAliasDeclaration {
let modifiers = 0;
let typeParams = null;
let t0 = tokens.get();
const firstToken = t0;
if (t0.kind === SyntaxKind.BoltPubKeyword) {
tokens.get();
modifiers |= BoltDeclarationModifiers.Public;
t0 = tokens.peek();
if (t0.kind !== SyntaxKind.BoltIdentifier) {
throw new ParseError(t0, [SyntaxKind.BoltNewTypeKeyword])
}
t0 = tokens.get();
}
if (t0.kind !== SyntaxKind.BoltNewTypeKeyword) {
throw new ParseError(t0, [SyntaxKind.BoltNewTypeKeyword])
}
assertToken(t0, SyntaxKind.BoltTypeKeyword);
const name = tokens.get();
if (name.kind !== SyntaxKind.BoltIdentifier) {
throw new ParseError(name, [SyntaxKind.BoltIdentifier])
}
const node = createBoltNewTypeDeclaration(modifiers, name)
setOrigNodeRange(node, firstToken, name);
const t2 = tokens.peek();
if (t2.kind === SyntaxKind.BoltLtSign) {
typeParams = this.parseGenericTypeParameters(tokens);
}
const t3 = tokens.get();
assertToken(t3, SyntaxKind.BoltEqSign);
const typeExpr = this.parseTypeExpression(tokens);
const node = createBoltTypeAliasDeclaration(modifiers, name, typeParams, typeExpr)
setOrigNodeRange(node, firstToken, typeExpr);
return node;
}
@ -725,17 +878,17 @@ export class Parser {
const innerTokens = createTokenStream(t2);
while (true) {
const t3 = innerTokens.peek();
if (t3.kind === SyntaxKind.BoltEOS) {
if (t3.kind === SyntaxKind.EndOfFile) {
break;
}
params.push(this.parseParameter(innerTokens, i++))
const t4 = innerTokens.get();
if (t4.kind === SyntaxKind.BoltComma) {
continue;
} else if (t4.kind === SyntaxKind.BoltEOS) {
} else if (t4.kind === SyntaxKind.EndOfFile) {
break;
} else {
throw new ParseError(t4, [SyntaxKind.BoltComma, SyntaxKind.BoltEOS])
throw new ParseError(t4, [SyntaxKind.BoltComma, SyntaxKind.EndOfFile])
}
}
}
@ -756,7 +909,7 @@ export class Parser {
if (t2.kind === SyntaxKind.BoltRArrow) {
lastToken = t2;
tokens.get();
returnType = this.parseTypeNode(tokens);
returnType = this.parseTypeExpression(tokens);
}
// Parse function body
@ -770,7 +923,8 @@ export class Parser {
body = this.parseStatements(tokens);
break;
case "JS":
body = acorn.parse(t3.text);
const scanner = new Scanner(t3.span!.file, t3.text);
body = this.parseJSSourceElementList(scanner);
break;
default:
throw new Error(`Unrecognised language: ${target}`);
@ -790,6 +944,23 @@ export class Parser {
}
//public parseModuleDeclaration(tokens: BoltTokenStream): BoltModule {
//let modifiers = 0;
//let t0 = tokens.get();
//if (t0.kind === SyntaxKind.BoltPubKeyword) {
//modifiers |= BoltDeclarationModifiers.Public;
//t0 = tokens.get();
//}
//assertToken(t0, SyntaxKind.BoltModKeyword);
//const name = this.parseQualName(tokens);
//const t1 = tokens.get();
//assertToken(t1, SyntaxKind.BoltBraced);
//const elements = this.parseSourceElementList(createTokenStream(t1));
//const node = createBoltModule(modifiers, name, elements);
//setOrigNodeRange(node, t0, t1);
//return node;
//}
public parseDeclaration(tokens: BoltTokenStream): BoltDeclaration {
let t0 = tokens.peek(1);
let i = 1;
@ -810,8 +981,8 @@ export class Parser {
}
}
switch (t0.kind) {
case SyntaxKind.BoltNewTypeKeyword:
return this.parseNewTypeDeclaration(tokens);
case SyntaxKind.BoltTypeKeyword:
return this.parseTypeAliasDeclaration(tokens);
case SyntaxKind.BoltModKeyword:
return this.parseModuleDeclaration(tokens);
case SyntaxKind.BoltFnKeyword:
@ -828,7 +999,6 @@ export class Parser {
}
public parseSourceElement(tokens: BoltTokenStream): BoltSourceElement {
const t0 = tokens.peek();
try {
return this.parseDeclaration(tokens)
} catch (e1) {
@ -846,19 +1016,20 @@ export class Parser {
}
}
protected getOperatorDesc(seekArity: number, seekName: string): OperatorInfo {
for (let i = 0; i < this.operatorTable.length; ++i) {
for (const [kind, arity, name] of this.operatorTable[i]) {
if (arity == seekArity && name === seekName) {
return {
kind,
name,
arity,
precedence: i
}
}
public parseSourceElementList(tokens: BoltTokenStream): BoltSourceElement[] {
const elements: BoltSourceElement[] = []
while (true) {
const t0 = tokens.peek();
if (t0.kind === SyntaxKind.EndOfFile) {
break;
}
if (t0.kind === SyntaxKind.BoltSemi) {
tokens.get();
continue;
}
elements.push(this.parseSourceElement(tokens));
}
return elements
}
//parseBinOp(tokens: TokenStream, lhs: Expr , minPrecedence: number) {
@ -887,12 +1058,12 @@ export class Parser {
// return lhs
//}
public parseCallOrPrimitiveExpression(tokens: BoltTokenStream): BoltExpression {
private parseCallOrPrimitiveExpression(tokens: BoltTokenStream): BoltExpression {
const operator = this.parsePrimitiveExpression(tokens)
const t2 = tokens.get();
if (t2.kind === SyntaxKind.BoltEOS) {
if (t2.kind === SyntaxKind.EndOfFile) {
return operator;
}
assertToken(t2, SyntaxKind.BoltParenthesized);
@ -902,12 +1073,12 @@ export class Parser {
while (true) {
const t3 = innerTokens.peek();
if (t3.kind === SyntaxKind.BoltEOS) {
if (t3.kind === SyntaxKind.EndOfFile) {
break;
}
args.push(this.parseExpression(innerTokens))
const t4 = innerTokens.get();
if (t4.kind === SyntaxKind.BoltEOS) {
if (t4.kind === SyntaxKind.EndOfFile) {
break
} else if (t4.kind !== SyntaxKind.BoltComma){
throw new ParseError(t4, [SyntaxKind.BoltComma])
@ -920,5 +1091,22 @@ export class Parser {
}
public parseJSStatement(tokens: JSTokenStream): JSStatement {
return this.parseJSExpressionStatement(tokens);
}
public parseJSSourceElementList(tokens: JSTokenStream): JSSourceElement[] {
const elements: JSSourceElement[] = [];
while (true) {
const t0 = tokens.peek();
if (t0.kind === SyntaxKind.EndOfFile) {
break;
}
const statement = this.parseJSStatement(tokens)
elements.push(statement);
}
return elements;
}
}

View file

@ -12,6 +12,7 @@ import {
SyntaxKind,
BoltToken,
BoltSentence,
createEndOfFile,
createBoltSentence,
createBoltIdentifier,
createBoltRArrow,
@ -25,7 +26,6 @@ import {
createBoltStringLiteral,
createBoltIntegerLiteral,
createBoltColon,
createBoltEOS,
createBoltDot,
createBoltEqSign,
createBoltPubKeyword,
@ -39,7 +39,12 @@ import {
createBoltFnKeyword,
createBoltLArrow,
createBoltDotDot,
createBoltNewTypeKeyword,
createJSIdentifier,
JSToken,
createBoltLtSign,
createBoltGtSign,
createBoltModKeyword,
createBoltTypeKeyword,
} from "./ast"
export enum PunctType {
@ -136,7 +141,27 @@ function isIdentPart(ch: string) {
}
function isSymbol(ch: string) {
return /[=+\/-*%$!><&^|]/.test(ch)
return /[=+\/\-*%$!><&^|]/.test(ch)
}
function isJSWhiteSpace(ch: string): boolean {
return ch === '\u0009'
|| ch === '\u000B'
|| ch === '\u000C'
|| ch === '\u0020'
|| ch === '\u00A0'
|| ch === '\u000B'
|| ch === '\uFEFF'
|| XRegExp('\\p{Zs}').test(ch)
}
function isJSIdentStart(ch: string): boolean {
return XRegExp('[\\p{ID_Start}$_\\]').test(ch)
}
function isJSIdentPart(ch: string): boolean {
return XRegExp('[\u200C\u200D\\p{ID_Continue}$\\]').test(ch)
}
//function isOperatorPart(ch: string) {
@ -218,7 +243,7 @@ export class Scanner {
const startPos = this.currPos.clone()
if (c0 == EOF) {
return createBoltEOS(new TextSpan(this.file, startPos, startPos));
return createEndOfFile(new TextSpan(this.file, startPos, startPos));
}
switch (c0) {
@ -313,15 +338,16 @@ export class Scanner {
const span = new TextSpan(this.file, startPos, endPos);
switch (name) {
case 'pub': return createBoltPubKeyword(span);
case 'mod': return createBoltModKeyword(span);
case 'fn': return createBoltFnKeyword(span);
case 'return': return createBoltReturnKeyword(span);
case 'yield': return createBoltYieldKeyword(span);
case 'type': return createBoltTypeKeyword(span);
case 'foreign': return createBoltForeignKeyword(span);
case 'let': return createBoltPubKeyword(span);
case 'mut': return createBoltMutKeyword(span);
case 'struct': return createBoltStructKeyword(span);
case 'enum': return createBoltEnumKeyword(span);
case 'newtype': return createBoltNewTypeKeyword(span);
default: return createBoltIdentifier(name, span);
}
@ -331,23 +357,24 @@ export class Scanner {
const endPos = this.currPos.clone()
const span = new TextSpan(this.file, startPos, endPos);
if (text.endsWith('=')) {
const operator = text.substring(0, text.length-1);
if (text === '==') {
return createBoltOperator(text, span);
}
return createBoltAssignment(operator.length === 0 ? null : operator, span);
}
switch (text) {
case '->': return createBoltRArrow(span);
case '<-': return createBoltLArrow(span);
case '<': return createBoltLtSign(span);
case '>': return createBoltGtSign(span);
case '.': return createBoltDot(span);
case '..': return createBoltDotDot(span);
case '=': return createBoltEqSign(span);
default: return createBoltOperator(text, span);
case '==': return createBoltOperator(text, span);
}
if (text.endsWith('=')) {
const operator = text.substring(0, text.length-1);
return createBoltAssignment(operator.length === 0 ? null : operator, span);
}
return createBoltOperator(text, span);
} else {
throw new ScanError(this.file, this.currPos.clone(), c0);
@ -358,14 +385,14 @@ export class Scanner {
}
peek(count = 1): BoltToken {
public peek(count = 1): BoltToken {
while (this.scanned.length < count) {
this.scanned.push(this.scanToken());
}
return this.scanned[count - 1];
}
get(): BoltToken {
public get(): BoltToken {
return this.scanned.length > 0
? this.scanned.shift()!
: this.scanToken();
@ -381,7 +408,7 @@ export class Scanner {
inner: while (true) {
const token = this.scanToken();
if (token.kind === SyntaxKind.BoltEOS) {
if (token.kind === SyntaxKind.EndOfFile) {
if (tokens.length === 0) {
break outer;
} else {
@ -411,7 +438,7 @@ export class Scanner {
return elements
}
scan() {
public scan() {
const startPos = this.currPos.clone();
const elements = this.scanTokens();
const endPos = this.currPos.clone();
@ -421,3 +448,188 @@ export class Scanner {
}
}
export class JSScanner {
private buffer: string[] = [];
private scanned: JSToken[] = [];
private offset = 0;
constructor(
private file: TextFile,
private input: string,
private currPos: TextPos = new TextPos(0,1,1),
) {
}
protected readChar() {
if (this.offset == this.input.length) {
return EOF
}
return this.input[this.offset++]
}
protected peekChar(count = 1) {
while (this.buffer.length < count) {
this.buffer.push(this.readChar());
}
return this.buffer[count - 1];
}
protected getChar() {
const ch = this.buffer.length > 0
? this.buffer.shift()!
: this.readChar()
if (ch == EOF) {
return EOF
}
if (isNewLine(ch)) {
this.currPos.line += 1;
this.currPos.column = 1;
} else {
this.currPos.column += 1;
}
this.currPos.offset += 1;
return ch
}
private assertChar(expected: string) {
const actual = this.getChar();
if (actual !== expected) {
throw new ScanError(this.file, this.currPos.clone(), actual);
}
}
private scanLineComment(): string {
let text = '';
this.assertChar('/');
this.assertChar('/')
while (true) {
const c2 = this.peekChar();
if (c2 === '\n') {
this.getChar();
if (this.peekChar() === '\r') {
this.getChar();
}
break;
}
if (c2 === EOF) {
break;
}
text += this.getChar();
}
return text;
}
private scanMultiLineComment(): string {
let text = '';
while (true) {
const c2 = this.getChar();
if (c2 === '*') {
const c3 = this.getChar();
if (c3 === '/') {
break;
}
text += c2 + c3;
} else if (c2 === EOF) {
throw new ScanError(this.file, this.currPos.clone(), c2);
} else {
text += c2;
}
}
return text;
}
private skipComments() {
while (true) {
const c0 = this.peekChar();
if (c0 === '/') {
const c1 = this.peekChar(2);
if (c1 == '/') {
this.scanLineComment();
} else if (c1 === '*') {
this.scanMultiLineComment();
} else {
break;
}
} else if (isWhiteSpace(c0)) {
this.getChar();
} else {
break;
}
}
}
private scanHexDigit(): number {
const startPos = this.currPos.clone();
const c0 = this.getChar();
switch (c0.toLowerCase()) {
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 0;
case 'a': return 10;
case 'b': return 11;
case 'c': return 12;
case 'd': return 13;
case 'e': return 14;
case 'f': return 15;
default:
throw new ScanError(this.file, startPos, c0);
}
}
private scanUnicodeEscapeSequence() {
throw new Error(`Scanning unicode escape sequences is not yet implemented.`);
}
public scan(): JSToken {
this.skipComments();
const c0 = this.peekChar();
const startPos = this.currPos.clone();
if (isJSIdentStart(c0)) {
let name = '';
while (true) {
const c0 = this.peekChar();
if (!isJSIdentPart(c0)) {
break;
}
if (c0 === '\\') {
name += this.scanUnicodeEscapeSequence();
} else {
name += this.getChar();
}
}
const endPos = this.currPos.clone();
return createJSIdentifier(name, new TextSpan(this.file, startPos, endPos))
} else {
throw new ScanError(this.file, this.currPos.clone(), c0);
}
}
public peek(count = 1): JSToken {
while (this.scanned.length < count) {
this.scanned.push(this.scan());
}
return this.scanned[count - 1];
}
public get(): JSToken {
return this.scanned.length > 0
? this.scanned.shift()!
: this.scan();
}
}

View file

@ -6,7 +6,7 @@ import chalk from "chalk"
import { TextSpan, TextPos } from "./text"
import { Scanner } from "./scanner"
import { kindToString, Syntax, BoltQualName, BoltDeclaration, BoltDeclarationModifiers, createBoltEOS, SyntaxKind, isBoltPunctuated } from "./ast"
import { kindToString, Syntax, BoltQualName, BoltDeclaration, BoltDeclarationModifiers, createEndOfFile, SyntaxKind, isBoltPunctuated } from "./ast"
export function createTokenStream(node: Syntax) {
if (isBoltPunctuated(node)) {
@ -16,7 +16,7 @@ export function createTokenStream(node: Syntax) {
} else if (node.kind === SyntaxKind.BoltSentence) {
return new StreamWrapper(
node.tokens,
() => createBoltEOS(new TextSpan(node.span!.file, node.span!.end.clone(), node.span!.end.clone()))
() => createEndOfFile(new TextSpan(node.span!.file, node.span!.end.clone(), node.span!.end.clone()))
);
} else {
throw new Error(`Could not convert ${kindToString(node.kind)} to a token stream.`);
@ -40,8 +40,36 @@ export function uniq<T>(elements: T[]): T[] {
return out;
}
export interface FastStringMap<T> {
[key: string]: T
export class FastStringMap<K extends PropertyKey, V> {
private mapping = Object.create(null);
public get(key: K): V {
if (!(key in this.mapping)) {
throw new Error(`No value found for key '${key}'.`);
}
return this.mapping[key];
}
public set(key: K, value: V): void {
if (key in this.mapping) {
throw new Error(`A value for key '${key}' already exists.`);
}
this.mapping[key] = value
}
public has(key: K): boolean {
return key in this.mapping;
}
public delete(key: K): void {
if (!(key in this.mapping)) {
throw new Error(`No value found for key '${key}'.`);
}
delete this.mapping[key];
}
}
class DeepMap {

View file

@ -5,7 +5,7 @@
"outDir": "./lib",
"strict": true,
"esModuleInterop": true,
"inlineSourceMap": true,
"sourceMap": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}