From 824cf57c133b8423ce79281faf02433b59c58e3d Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Sun, 10 May 2020 18:21:44 +0200 Subject: [PATCH] Fix most error in src/parser.ts --- spec/ast.txt | 17 +- src/ast.d.ts | 359 +++++++++++++--------- src/compiler.ts | 11 +- src/emitter.ts | 5 + src/parser.ts | 576 ++++++++++++++++++++++-------------- src/treegen/ast-template.js | 4 - src/treegen/index.ts | 3 +- 7 files changed, 590 insertions(+), 385 deletions(-) diff --git a/spec/ast.txt b/spec/ast.txt index 5c87cceac..8799a2d23 100644 --- a/spec/ast.txt +++ b/spec/ast.txt @@ -40,15 +40,21 @@ node BoltDotDot > BoltToken; node BoltRArrow > BoltToken; node BoltLArrow > BoltToken; node BoltEqSign > BoltToken; +node BoltGtSign > BoltToken; +node BoltLtSign > BoltToken; node BoltKeyword; node BoltFnKeyword > BoltToken, BoltKeyword; node BoltForeignKeyword > BoltToken, BoltKeyword; node BoltLetKeyword > BoltToken, BoltKeyword; +node BoltReturnKeyword > BoltToken, BoltKeyword; +node BoltLoopKeyword > BoltToken, BoltKeyword; +node BoltYieldKeyword > BoltToken, BoltKeyword; node BoltImportKeyword > BoltToken, BoltKeyword; node BoltPubKeyword > BoltToken, BoltKeyword; node BoltModKeyword > BoltToken, BoltKeyword; +node BoltMutKeyword > BoltToken, BoltKeyword; node BoltEnumKeyword > BoltToken, BoltKeyword; node BoltStructKeyword > BoltToken, BoltKeyword; node BoltNewTypeKeyword > BoltToken, BoltKeyword; @@ -84,7 +90,7 @@ node BoltReferenceTypeNode > BoltTypeNode { node BoltPattern; node BoltBindPattern > BoltPattern { - name: String, + name: BoltIdentifier, } node BoltTypePattern > BoltPattern { @@ -181,9 +187,10 @@ node BoltParameter { node BoltDeclaration > BoltSourceElement; enum BoltDeclarationModifiers { - Mutable = 0x1, - Public = 0x2, - IsType = 0x4, + Mutable = 0x1, + Public = 0x2, + IsType = 0x4, + IsForeign = 0x8, } node BoltNewTypeDeclaration > BoltDeclaration { @@ -261,7 +268,7 @@ node JSIdentifier > JSToken { node JSPattern; node JSBindPattern > JSPattern { - name: String, + name: JSIdentifier, } node JSExpression; diff --git a/src/ast.d.ts b/src/ast.d.ts index 331a59075..ebba7b430 100644 --- a/src/ast.d.ts +++ b/src/ast.d.ts @@ -14,71 +14,77 @@ export const enum SyntaxKind { BoltRArrow = 16, BoltLArrow = 17, BoltEqSign = 18, - BoltFnKeyword = 20, - BoltForeignKeyword = 21, - BoltLetKeyword = 22, - BoltImportKeyword = 23, - BoltPubKeyword = 24, - BoltModKeyword = 25, - BoltEnumKeyword = 26, - BoltStructKeyword = 27, - BoltNewTypeKeyword = 28, - BoltParenthesized = 30, - BoltBraced = 31, - BoltBracketed = 32, - BoltSourceFile = 33, - BoltQualName = 34, - BoltSentence = 35, - BoltReferenceTypeNode = 37, - BoltBindPattern = 39, - BoltTypePattern = 40, - BoltExpressionPattern = 41, - BoltTuplePatternElement = 42, - BoltTuplePattern = 43, - BoltRecordPatternField = 44, - BoltRecordPattern = 45, - BoltReferenceExpression = 47, - BoltCallExpression = 48, - BoltYieldExpression = 49, - BoltMatchArm = 50, - BoltMatchExpression = 51, - BoltCase = 52, - BoltCaseExpression = 53, - BoltBlockExpression = 54, - BoltConstantExpression = 55, - BoltReturnStatement = 57, - BoltResumeStatement = 58, - BoltExpressionStatement = 59, - BoltParameter = 60, - BoltNewTypeDeclaration = 63, - BoltModule = 64, - BoltFunctionDeclaration = 65, - BoltForeignFunctionDeclaration = 66, - BoltVariableDeclaration = 67, - BoltPlainImportSymbol = 69, - BoltImportDeclaration = 70, - BoltRecordDeclarationField = 71, - BoltRecordDeclaration = 73, - JSOperator = 76, - JSIdentifier = 77, - JSBindPattern = 79, - JSConstantExpression = 81, - JSMemberExpression = 83, - JSCallExpression = 84, - JSBinaryExpression = 85, - JSUnaryExpression = 86, - JSNewExpression = 87, - JSSequenceExpression = 88, - JSConditionalExpression = 89, - JSReferenceExpression = 90, - JSExpressionStatement = 92, - JSConditionalStatement = 93, - JSParameter = 94, - JSFunctionDeclaration = 97, - JSArrowFunctionDeclaration = 98, - JSLetDeclaration = 99, - JSSourceFile = 100, - JSSourceElement = 101, + BoltGtSign = 19, + BoltLtSign = 20, + BoltFnKeyword = 22, + BoltForeignKeyword = 23, + BoltLetKeyword = 24, + BoltReturnKeyword = 25, + BoltLoopKeyword = 26, + BoltYieldKeyword = 27, + BoltImportKeyword = 28, + BoltPubKeyword = 29, + BoltModKeyword = 30, + BoltMutKeyword = 31, + BoltEnumKeyword = 32, + BoltStructKeyword = 33, + BoltNewTypeKeyword = 34, + BoltParenthesized = 36, + BoltBraced = 37, + BoltBracketed = 38, + BoltSourceFile = 39, + BoltQualName = 40, + BoltSentence = 41, + BoltReferenceTypeNode = 43, + BoltBindPattern = 45, + BoltTypePattern = 46, + BoltExpressionPattern = 47, + BoltTuplePatternElement = 48, + BoltTuplePattern = 49, + BoltRecordPatternField = 50, + BoltRecordPattern = 51, + BoltReferenceExpression = 53, + BoltCallExpression = 54, + BoltYieldExpression = 55, + BoltMatchArm = 56, + BoltMatchExpression = 57, + BoltCase = 58, + BoltCaseExpression = 59, + BoltBlockExpression = 60, + BoltConstantExpression = 61, + BoltReturnStatement = 63, + BoltResumeStatement = 64, + BoltExpressionStatement = 65, + BoltParameter = 66, + BoltNewTypeDeclaration = 69, + BoltModule = 70, + BoltFunctionDeclaration = 71, + BoltForeignFunctionDeclaration = 72, + BoltVariableDeclaration = 73, + BoltPlainImportSymbol = 75, + BoltImportDeclaration = 76, + BoltRecordDeclarationField = 77, + BoltRecordDeclaration = 79, + JSOperator = 82, + JSIdentifier = 83, + JSBindPattern = 85, + JSConstantExpression = 87, + JSMemberExpression = 89, + JSCallExpression = 90, + JSBinaryExpression = 91, + JSUnaryExpression = 92, + JSNewExpression = 93, + JSSequenceExpression = 94, + JSConditionalExpression = 95, + JSReferenceExpression = 96, + JSExpressionStatement = 98, + JSConditionalStatement = 99, + JSParameter = 100, + JSFunctionDeclaration = 103, + JSArrowFunctionDeclaration = 104, + JSLetDeclaration = 105, + JSSourceFile = 106, + JSSourceElement = 107, } @@ -91,7 +97,6 @@ interface SyntaxBase { kind: SyntaxKind; parentNode: Syntax | null; span: TextSpan | null; - origNodes: SyntaxRange | null; } export interface FunctionBody extends SyntaxBase { kind: SyntaxKind.FunctionBody; @@ -111,12 +116,18 @@ export type BoltToken | BoltRArrow | BoltLArrow | BoltEqSign + | BoltGtSign + | BoltLtSign | BoltFnKeyword | BoltForeignKeyword | BoltLetKeyword + | BoltReturnKeyword + | BoltLoopKeyword + | BoltYieldKeyword | BoltImportKeyword | BoltPubKeyword | BoltModKeyword + | BoltMutKeyword | BoltEnumKeyword | BoltStructKeyword | BoltNewTypeKeyword @@ -186,13 +197,25 @@ export interface BoltEqSign extends SyntaxBase { kind: SyntaxKind.BoltEqSign; } +export interface BoltGtSign extends SyntaxBase { + kind: SyntaxKind.BoltGtSign; +} + +export interface BoltLtSign extends SyntaxBase { + kind: SyntaxKind.BoltLtSign; +} + export type BoltKeyword = BoltFnKeyword | BoltForeignKeyword | BoltLetKeyword + | BoltReturnKeyword + | BoltLoopKeyword + | BoltYieldKeyword | BoltImportKeyword | BoltPubKeyword | BoltModKeyword + | BoltMutKeyword | BoltEnumKeyword | BoltStructKeyword | BoltNewTypeKeyword @@ -210,6 +233,18 @@ export interface BoltLetKeyword extends SyntaxBase { kind: SyntaxKind.BoltLetKeyword; } +export interface BoltReturnKeyword extends SyntaxBase { + kind: SyntaxKind.BoltReturnKeyword; +} + +export interface BoltLoopKeyword extends SyntaxBase { + kind: SyntaxKind.BoltLoopKeyword; +} + +export interface BoltYieldKeyword extends SyntaxBase { + kind: SyntaxKind.BoltYieldKeyword; +} + export interface BoltImportKeyword extends SyntaxBase { kind: SyntaxKind.BoltImportKeyword; } @@ -222,6 +257,10 @@ export interface BoltModKeyword extends SyntaxBase { kind: SyntaxKind.BoltModKeyword; } +export interface BoltMutKeyword extends SyntaxBase { + kind: SyntaxKind.BoltMutKeyword; +} + export interface BoltEnumKeyword extends SyntaxBase { kind: SyntaxKind.BoltEnumKeyword; } @@ -291,7 +330,7 @@ export type BoltPattern export interface BoltBindPattern extends SyntaxBase { kind: SyntaxKind.BoltBindPattern; - name: string; + name: BoltIdentifier; } export interface BoltTypePattern extends SyntaxBase { @@ -427,7 +466,7 @@ export type BoltDeclaration export const enum BoltDeclarationModifiers { - Mutable = 1,Public = 2,IsType = 4,} + Mutable = 1,Public = 2,IsType = 4,IsForeign = 8,} export interface BoltNewTypeDeclaration extends SyntaxBase { kind: SyntaxKind.BoltNewTypeDeclaration; @@ -531,7 +570,7 @@ export type JSPattern export interface JSBindPattern extends SyntaxBase { kind: SyntaxKind.JSBindPattern; - name: string; + name: JSIdentifier; } export type JSExpression @@ -682,12 +721,18 @@ export type BoltSyntax | BoltRArrow | BoltLArrow | BoltEqSign + | BoltGtSign + | BoltLtSign | BoltFnKeyword | BoltForeignKeyword | BoltLetKeyword + | BoltReturnKeyword + | BoltLoopKeyword + | BoltYieldKeyword | BoltImportKeyword | BoltPubKeyword | BoltModKeyword + | BoltMutKeyword | BoltEnumKeyword | BoltStructKeyword | BoltNewTypeKeyword @@ -767,12 +812,18 @@ export type Syntax | BoltRArrow | BoltLArrow | BoltEqSign + | BoltGtSign + | BoltLtSign | BoltFnKeyword | BoltForeignKeyword | BoltLetKeyword + | BoltReturnKeyword + | BoltLoopKeyword + | BoltYieldKeyword | BoltImportKeyword | BoltPubKeyword | BoltModKeyword + | BoltMutKeyword | BoltEnumKeyword | BoltStructKeyword | BoltNewTypeKeyword @@ -836,85 +887,91 @@ export type Syntax export function kindToString(kind: SyntaxKind): string; -export function createFunctionBody(span?: TextSpan | null, origNodes?: SyntaxRange | null): FunctionBody; -export function createBoltStringLiteral(value: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltStringLiteral; -export function createBoltIntegerLiteral(value: bigint, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltIntegerLiteral; -export function createBoltIdentifier(text: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltIdentifier; -export function createBoltOperator(text: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltOperator; -export function createBoltEOS(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltEOS; -export function createBoltComma(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltComma; -export function createBoltSemi(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltSemi; -export function createBoltColon(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltColon; -export function createBoltDot(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltDot; -export function createBoltDotDot(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltDotDot; -export function createBoltRArrow(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltRArrow; -export function createBoltLArrow(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltLArrow; -export function createBoltEqSign(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltEqSign; -export function createBoltFnKeyword(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltFnKeyword; -export function createBoltForeignKeyword(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltForeignKeyword; -export function createBoltLetKeyword(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltLetKeyword; -export function createBoltImportKeyword(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltImportKeyword; -export function createBoltPubKeyword(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltPubKeyword; -export function createBoltModKeyword(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltModKeyword; -export function createBoltEnumKeyword(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltEnumKeyword; -export function createBoltStructKeyword(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltStructKeyword; -export function createBoltNewTypeKeyword(span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltNewTypeKeyword; -export function createBoltParenthesized(text: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltParenthesized; -export function createBoltBraced(text: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltBraced; -export function createBoltBracketed(text: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltBracketed; -export function createBoltSourceFile(elements: BoltSourceElement[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltSourceFile; -export function createBoltQualName(modulePath: BoltIdentifier[], name: BoltSymbol, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltQualName; -export function createBoltSentence(tokens: BoltToken[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltSentence; -export function createBoltReferenceTypeNode(name: BoltQualName, arguments: BoltTypeNode[] | null, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltReferenceTypeNode; -export function createBoltBindPattern(name: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltBindPattern; -export function createBoltTypePattern(type: BoltTypeNode, nestedPattern: BoltPattern, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltTypePattern; -export function createBoltExpressionPattern(expression: BoltExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltExpressionPattern; -export function createBoltTuplePatternElement(index: number, pattern: BoltPattern, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltTuplePatternElement; -export function createBoltTuplePattern(elements: BoltTuplePatternElement[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltTuplePattern; -export function createBoltRecordPatternField(name: BoltIdentifier, pattern: BoltPattern, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltRecordPatternField; -export function createBoltRecordPattern(name: BoltTypeNode, fields: BoltRecordPatternField[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltRecordPattern; -export function createBoltReferenceExpression(name: BoltQualName, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltReferenceExpression; -export function createBoltCallExpression(operator: BoltExpression, operands: BoltExpression[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltCallExpression; -export function createBoltYieldExpression(value: BoltExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltYieldExpression; -export function createBoltMatchArm(pattern: BoltPattern, body: BoltExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltMatchArm; -export function createBoltMatchExpression(value: BoltExpression, arms: BoltMatchArm[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltMatchExpression; -export function createBoltCase(test: BoltExpression, result: BoltExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltCase; -export function createBoltCaseExpression(cases: BoltCase[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltCaseExpression; -export function createBoltBlockExpression(statements: BoltStatement[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltBlockExpression; -export function createBoltConstantExpression(value: BoltValue, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltConstantExpression; -export function createBoltReturnStatement(value: BoltExpression | null, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltReturnStatement; -export function createBoltResumeStatement(value: BoltExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltResumeStatement; -export function createBoltExpressionStatement(expression: BoltExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltExpressionStatement; -export function createBoltParameter(index: number, bindings: BoltPattern, type: BoltTypeNode | null, defaultValue: BoltExpression | null, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltParameter; -export function createBoltNewTypeDeclaration(modifiers: BoltDeclarationModifiers, name: BoltIdentifier, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltNewTypeDeclaration; -export function createBoltModule(modifiers: BoltDeclarationModifiers, name: BoltQualName, elements: BoltSourceElement[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltModule; -export function createBoltFunctionDeclaration(modifiers: BoltDeclarationModifiers, name: BoltSymbol, params: BoltParameter[], returnType: BoltTypeNode | null, body: BoltExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltFunctionDeclaration; -export function createBoltForeignFunctionDeclaration(modifiers: BoltDeclarationModifiers, target: string, name: BoltSymbol, params: BoltParameter[], returnType: BoltTypeNode | null, body: FunctionBody, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltForeignFunctionDeclaration; -export function createBoltVariableDeclaration(modifiers: BoltDeclarationModifiers, bindings: BoltPattern, type: BoltTypeNode | null, value: BoltExpression | null, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltVariableDeclaration; -export function createBoltPlainImportSymbol(name: BoltQualName, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltPlainImportSymbol; -export function createBoltImportDeclaration(file: string, symbols: BoltImportSymbol[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltImportDeclaration; -export function createBoltRecordDeclarationField(name: BoltIdentifier, type: BoltTypeNode, span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltRecordDeclarationField; -export function createBoltRecordDeclaration(name: BoltQualName, fields: BoltRecordDeclarationField[], span?: TextSpan | null, origNodes?: SyntaxRange | null): BoltRecordDeclaration; -export function createJSOperator(text: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSOperator; -export function createJSIdentifier(text: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSIdentifier; -export function createJSBindPattern(name: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSBindPattern; -export function createJSConstantExpression(value: BoltValue, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSConstantExpression; -export function createJSMemberExpression(value: JSExpression, property: JSExpression, modifiers: JSMemberExpressionModifiers, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSMemberExpression; -export function createJSCallExpression(operator: JSExpression, operands: JSExpression[], span?: TextSpan | null, origNodes?: SyntaxRange | null): JSCallExpression; -export function createJSBinaryExpression(left: JSExpression, operator: JSOperator, right: JSExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSBinaryExpression; -export function createJSUnaryExpression(operator: JSOperator, operand: JSExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSUnaryExpression; -export function createJSNewExpression(target: JSExpression, arguments: JSExpression[], span?: TextSpan | null, origNodes?: SyntaxRange | null): JSNewExpression; -export function createJSSequenceExpression(expressions: JSExpression[], span?: TextSpan | null, origNodes?: SyntaxRange | null): JSSequenceExpression; -export function createJSConditionalExpression(test: JSExpression, consequent: JSExpression, alternate: JSExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSConditionalExpression; -export function createJSReferenceExpression(name: string, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSReferenceExpression; -export function createJSExpressionStatement(expression: JSExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSExpressionStatement; -export function createJSConditionalStatement(test: JSExpression, consequent: JSStatement[], alternate: JSStatement[], span?: TextSpan | null, origNodes?: SyntaxRange | null): JSConditionalStatement; -export function createJSParameter(index: number, bindings: JSPattern, defaultValue: JSExpression | null, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSParameter; -export function createJSFunctionDeclaration(modifiers: JSDeclarationModifiers, name: JSIdentifier, params: JSParameter[], body: JSStatement[], span?: TextSpan | null, origNodes?: SyntaxRange | null): JSFunctionDeclaration; -export function createJSArrowFunctionDeclaration(name: JSIdentifier, params: JSParameter[], body: JSExpression, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSArrowFunctionDeclaration; -export function createJSLetDeclaration(bindings: JSPattern, value: JSExpression | null, span?: TextSpan | null, origNodes?: SyntaxRange | null): JSLetDeclaration; -export function createJSSourceFile(elements: JSSourceElement[], span?: TextSpan | null, origNodes?: SyntaxRange | null): JSSourceFile; -export function createJSSourceElement(span?: TextSpan | null, origNodes?: SyntaxRange | null): JSSourceElement; +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 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; +export function createBoltDot(span?: TextSpan | null): BoltDot; +export function createBoltDotDot(span?: TextSpan | null): BoltDotDot; +export function createBoltRArrow(span?: TextSpan | null): BoltRArrow; +export function createBoltLArrow(span?: TextSpan | null): BoltLArrow; +export function createBoltEqSign(span?: TextSpan | null): BoltEqSign; +export function createBoltGtSign(span?: TextSpan | null): BoltGtSign; +export function createBoltLtSign(span?: TextSpan | null): BoltLtSign; +export function createBoltFnKeyword(span?: TextSpan | null): BoltFnKeyword; +export function createBoltForeignKeyword(span?: TextSpan | null): BoltForeignKeyword; +export function createBoltLetKeyword(span?: TextSpan | null): BoltLetKeyword; +export function createBoltReturnKeyword(span?: TextSpan | null): BoltReturnKeyword; +export function createBoltLoopKeyword(span?: TextSpan | null): BoltLoopKeyword; +export function createBoltYieldKeyword(span?: TextSpan | null): BoltYieldKeyword; +export function createBoltImportKeyword(span?: TextSpan | null): BoltImportKeyword; +export function createBoltPubKeyword(span?: TextSpan | null): BoltPubKeyword; +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 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 createBoltBindPattern(name: BoltIdentifier, span?: TextSpan | null): BoltBindPattern; +export function createBoltTypePattern(type: BoltTypeNode, 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 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; +export function createBoltMatchArm(pattern: BoltPattern, body: BoltExpression, span?: TextSpan | null): BoltMatchArm; +export function createBoltMatchExpression(value: BoltExpression, arms: BoltMatchArm[], span?: TextSpan | null): BoltMatchExpression; +export function createBoltCase(test: BoltExpression, result: BoltExpression, span?: TextSpan | null): BoltCase; +export function createBoltCaseExpression(cases: BoltCase[], span?: TextSpan | null): BoltCaseExpression; +export function createBoltBlockExpression(statements: BoltStatement[], span?: TextSpan | null): BoltBlockExpression; +export function createBoltConstantExpression(value: BoltValue, span?: TextSpan | null): BoltConstantExpression; +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 createBoltModule(modifiers: BoltDeclarationModifiers, name: BoltQualName, elements: BoltSourceElement[], span?: TextSpan | null): BoltModule; +export function createBoltFunctionDeclaration(modifiers: BoltDeclarationModifiers, name: BoltSymbol, params: BoltParameter[], returnType: BoltTypeNode | null, body: BoltExpression, span?: TextSpan | null): BoltFunctionDeclaration; +export function createBoltForeignFunctionDeclaration(modifiers: BoltDeclarationModifiers, target: string, name: BoltSymbol, params: BoltParameter[], returnType: BoltTypeNode | null, body: FunctionBody, span?: TextSpan | null): BoltForeignFunctionDeclaration; +export function createBoltVariableDeclaration(modifiers: BoltDeclarationModifiers, bindings: BoltPattern, type: BoltTypeNode | 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(name: BoltQualName, 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 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; +export function createJSCallExpression(operator: JSExpression, operands: JSExpression[], span?: TextSpan | null): JSCallExpression; +export function createJSBinaryExpression(left: JSExpression, operator: JSOperator, right: JSExpression, span?: TextSpan | null): JSBinaryExpression; +export function createJSUnaryExpression(operator: JSOperator, operand: JSExpression, span?: TextSpan | null): JSUnaryExpression; +export function createJSNewExpression(target: JSExpression, arguments: JSExpression[], span?: TextSpan | null): JSNewExpression; +export function createJSSequenceExpression(expressions: JSExpression[], span?: TextSpan | null): JSSequenceExpression; +export function createJSConditionalExpression(test: JSExpression, consequent: JSExpression, alternate: JSExpression, span?: TextSpan | null): JSConditionalExpression; +export function createJSReferenceExpression(name: string, span?: TextSpan | null): JSReferenceExpression; +export function createJSExpressionStatement(expression: JSExpression, span?: TextSpan | null): JSExpressionStatement; +export function createJSConditionalStatement(test: JSExpression, consequent: JSStatement[], alternate: JSStatement[], span?: TextSpan | null): JSConditionalStatement; +export function createJSParameter(index: number, bindings: JSPattern, defaultValue: JSExpression | null, span?: TextSpan | null): JSParameter; +export function createJSFunctionDeclaration(modifiers: JSDeclarationModifiers, name: JSIdentifier, params: JSParameter[], body: JSStatement[], span?: TextSpan | null): JSFunctionDeclaration; +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 isFunctionBody(value: any): value is FunctionBody; export function isBoltToken(value: any): value is BoltToken; @@ -932,13 +989,19 @@ export function isBoltDotDot(value: any): value is BoltDotDot; export function isBoltRArrow(value: any): value is BoltRArrow; export function isBoltLArrow(value: any): value is BoltLArrow; export function isBoltEqSign(value: any): value is BoltEqSign; +export function isBoltGtSign(value: any): value is BoltGtSign; +export function isBoltLtSign(value: any): value is BoltLtSign; export function isBoltKeyword(value: any): value is BoltKeyword; export function isBoltFnKeyword(value: any): value is BoltFnKeyword; export function isBoltForeignKeyword(value: any): value is BoltForeignKeyword; export function isBoltLetKeyword(value: any): value is BoltLetKeyword; +export function isBoltReturnKeyword(value: any): value is BoltReturnKeyword; +export function isBoltLoopKeyword(value: any): value is BoltLoopKeyword; +export function isBoltYieldKeyword(value: any): value is BoltYieldKeyword; export function isBoltImportKeyword(value: any): value is BoltImportKeyword; export function isBoltPubKeyword(value: any): value is BoltPubKeyword; 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; diff --git a/src/compiler.ts b/src/compiler.ts index 8c7120183..64468b403 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -60,7 +60,7 @@ export class Compiler { for (const element of s.elements) { this.compileDecl(element, body); } - return createJSSourceFile(body, s.span, [s, s]); + return createJSSourceFile(body, s.span); }); } @@ -75,21 +75,18 @@ export class Compiler { compiledOperator, compiledArgs, node.span, - [node, node], ); case SyntaxKind.BoltReferenceExpression: return createJSReferenceExpression( getFullTextOfQualName(node.name), node.span, - [node, node], ); case SyntaxKind.BoltConstantExpression: return createJSConstantExpression( node.value, node.span, - [node, node] ); default: @@ -128,10 +125,9 @@ export class Compiler { const compiledValue = node.value !== null ? this.compileExpr(node.value, preamble) : null; preamble.push( createJSLetDeclaration( - createJSBindPattern((node.bindings as BoltBindPattern).name, node.bindings.span, [node.bindings, node.bindings]), + createJSBindPattern((node.bindings as BoltBindPattern).name, node.bindings.span), compiledValue, node.span, - [node, node], ), ); break; @@ -145,11 +141,10 @@ export class Compiler { } let result = createJSFunctionDeclaration( 0, - createJSIdentifier(node.name.text, node.name.span, [node.name, node.name]), + createJSIdentifier(node.name.text, node.name.span), params, body, node.span, - [node, node], ); if (hasPublicModifier(node)) { result.modifiers |= JSDeclarationModifiers.IsExported;; diff --git a/src/emitter.ts b/src/emitter.ts index 4e8a028b6..77abbbed2 100644 --- a/src/emitter.ts +++ b/src/emitter.ts @@ -5,8 +5,13 @@ export class Emitter { emit(node: Syntax) { + debug(node); + switch (node.kind) { + case SyntaxKind.JSReferenceExpression: + return node.name; + case SyntaxKind.JSSourceFile: let out = '' for (const element of node.elements) { diff --git a/src/parser.ts b/src/parser.ts index 715cbd0ac..a28cdaac2 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1,46 +1,34 @@ -import * as acorn from "acorn" - import { SyntaxKind, - BoltToken, + kindToString, + BoltToken, BoltIdentifier, - createBoltFuncDecl, - createBoltIdentifier, - createBoltSyntaxKind, - createBoltTokenStream, - createBoltRetStmt, - createBoltVarDecl, - createBoltStmt, - createBoltPatt, - createBoltExpr, - createBoltBindPatt, - createBoltParam, - createBoltRefExpr, - createBoltTypeRef, - createBoltTypeDecl, - createBoltConstExpr, + BoltConstantExpression, + BoltReferenceExpression, + BoltExpression, + BoltRecordDeclaration, + BoltStatement, createBoltQualName, - createBoltCallExpr, - createBoltImportDecl, - createBoltSourceElement, - createBoltModule, - createBoltRecordDecl, - createBoltNewTypeDecl, BoltQualName, BoltPattern, createBoltBindPattern, BoltImportDeclaration, BoltTypeNode, createBoltReferenceTypeNode, - createJSReferenceExpression, + createBoltConstantExpression, createBoltReferenceExpression, + createBoltParameter, + BoltBindPattern, + createBoltRecordDeclaration, + createBoltRecordDeclarationField, + createBoltImportDeclaration, + BoltDeclarationModifiers, + BoltStringLiteral, + BoltImportSymbol, } from "./ast" -import { stringType, intType } from "./checker" - -import { PrimValue } from "./evaluator" -import {BoltTokenStream} from "./util" +import { BoltTokenStream, setOrigNodeRange } from "./util" function describeKind(kind: SyntaxKind): string { switch (kind) { @@ -99,8 +87,8 @@ function enumerate(elements: string[]) { export class ParseError extends Error { - constructor(public actual: Token, public expected: SyntaxKind[]) { - super(`${actual.span.file.path}:${actual.span.start.line}:${actual.span.start.column}: expected ${enumerate(expected.map(e => describeKind(e)))} but got ${describeKind(actual.kind)}`) + 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)}`) } } @@ -118,6 +106,24 @@ interface OperatorInfo { precedence: number; } +function assertToken(node: BoltToken, kind: SyntaxKind) { + if (node.kind !== kind) { + throw new ParseError(node, [kind]); + } +} + +const KIND_EXPRESSION_T0 = [ + SyntaxKind.BoltStringLiteral, + SyntaxKind.BoltIntegerLiteral, + SyntaxKind.BoltIdentifier, + SyntaxKind.BoltOperator, + ] + +const KIND_STATEMENT_T0 = [ + SyntaxKind.BoltReturnKeyword, + ...KIND_EXPRESSION_T0, +] + export class Parser { operatorTable = [ @@ -149,8 +155,14 @@ export class Parser { ], ]; + protected assertEmpty(tokens: BoltTokenStream) { + const t0 = tokens.peek(1); + if (t0.kind !== SyntaxKind.BoltEOS) { + throw new ParseError(t0, [SyntaxKind.BoltEOS]); + } + } - parseQualName(tokens: BoltTokenStream): BoltQualName { + public parseQualName(tokens: BoltTokenStream): BoltQualName { const path: BoltIdentifier[] = []; @@ -167,221 +179,335 @@ export class Parser { if (name.kind !== SyntaxKind.BoltIdentifier) { throw new ParseError(name, [SyntaxKind.BoltIdentifier]); } - const startNode = path.length > 0 ? path[0] : name; const endNode = name; - return createBoltQualName(path, name, null, [startNode, endNode]); + const node = createBoltQualName(path, name, null); + setOrigNodeRange(node, startNode, endNode); + return node; } - parsePattern(tokens: BoltTokenStream): BoltPattern { + public parseBindPattern(tokens: BoltTokenStream): BoltBindPattern { + const t0 = tokens.get(); + assertToken(t0, SyntaxKind.BoltIdentifier); + const node = createBoltBindPattern((t0 as BoltIdentifier).text); + setOrigNodeRange(node, t0, t0); + return node; + } + + public parsePattern(tokens: BoltTokenStream): BoltPattern { const t0 = tokens.peek(1); if (t0.kind === SyntaxKind.BoltIdentifier) { - tokens.get(); - return createBoltBindPattern(t0.text, null, [t0, t0]) + return this.parseBindPattern(tokens); } else { throw new ParseError(t0, [SyntaxKind.BoltIdentifier]) } } - parseImportDecl(tokens: BoltTokenStream): BoltImportDeclaration { - - // Assuming first keyword is 'import' - tokens.get(); + public parseImportDeclaration(tokens: BoltTokenStream): BoltImportDeclaration { const t0 = tokens.get(); - if (t0.kind !== SyntaxKind.BoltStringLiteral) { - throw new ParseError(t0, [SyntaxKind.BoltStringLiteral]) - } + assertToken(t0, SyntaxKind.BoltImportKeyword); - return createBoltImportDecl(t0.value, null, t0); + const t1 = tokens.get(); + assertToken(t1, SyntaxKind.BoltStringLiteral); + const filename = (t1 as BoltStringLiteral).value; + const symbols: BoltImportSymbol[] = []; + // TODO implement grammar and parsing logic for symbols + + const node = createBoltImportDeclaration(filename, symbols); + setOrigNodeRange(node, t0, t1); + return node; } - parseTypeDecl(tokens: BoltTokenStream): BoltTypeNode { + public parseReferenceTypeNode(tokens: BoltTokenStream) { + + const name = this.parseQualName(tokens) + + const t1 = tokens.peek(); + + let typeArgs: BoltTypeNode[] | null = null; + + if (t1.kind === SyntaxKind.BoltLtSign) { + tokens.get(); + let first = true; + while (true) { + const t2 = tokens.peek(); + if (t2.kind === SyntaxKind.BoltGtSign) { + break; + } + if (first) { + first = false; + } else { + assertToken(t2, SyntaxKind.BoltComma); + tokens.get(); + } + typeArgs!.push(this.parseTypeNode(tokens)); + } + const t4 = tokens.get(); + assertToken(t4, SyntaxKind.BoltGtSign); + } + + const node = createBoltReferenceTypeNode(name, typeArgs); + setOrigNodeRange(node, name, name); + return node; + } + + public parseTypeNode(tokens: BoltTokenStream): BoltTypeNode { const t0 = tokens.peek(); if (t0.kind === SyntaxKind.BoltIdentifier) { - const name = this.parseQualName(tokens) - return createBoltReferenceTypeNode(name, [], null, name.origNodes) + return this.parseReferenceTypeNode(tokens); } else { throw new ParseError(t0, [SyntaxKind.BoltIdentifier]); } } - parsePrimExpr(tokens: TokenStream): Expr { - const t0 = tokens.peek(); + public parseConstantExpression(tokens: BoltTokenStream): BoltConstantExpression { + const t0 = tokens.get(); + let value: boolean | string | bigint; if (t0.kind === SyntaxKind.BoltStringLiteral) { - tokens.get(); - return new ConstExpr(new PrimValue(stringType, t0.value), null, t0); + value = t0.value; } else if (t0.kind === SyntaxKind.BoltIntegerLiteral) { - tokens.get(); - return new ConstExpr(new PrimValue(intType, t0.value), null, t0); + value = t0.value; + } else { + throw new ParseError(t0, [SyntaxKind.BoltStringLiteral, SyntaxKind.BoltIntegerLiteral]); + } + const node = createBoltConstantExpression(value); + setOrigNodeRange(node, t0, t0); + return node; + } + + public parseReferenceExpression(tokens: BoltTokenStream): BoltReferenceExpression { + const name = this.parseQualName(tokens); + const node = createBoltReferenceExpression(name); + setOrigNodeRange(node, name, name); + return node; + } + + protected parsePrimitiveExpression(tokens: BoltTokenStream): BoltExpression { + const t0 = tokens.peek(); + if (t0.kind === SyntaxKind.BoltIntegerLiteral || t0.kind === SyntaxKind.BoltStringLiteral) { + return this.parseConstantExpression(tokens); } else if (t0.kind === SyntaxKind.BoltIdentifier) { - const name = this.parseQualName(tokens); - return createBoltReferenceExpression(name, null, name.origNode); + return this.parseReferenceExpression(tokens); } else { throw new ParseError(t0, [SyntaxKind.BoltStringLiteral, SyntaxKind.BoltIdentifier]); } } - parseSyntax(tokens: TokenStream): Syntax { + //parseSyntax(tokens: TokenStream): Syntax { - // Assuming first token is 'syntax' - tokens.get(); + // // Assuming first token is 'syntax' + // const t0 = tokens.get(); + // assertToken(t0, SyntaxKind.Bolt - const t1 = tokens.get(); - if (t1.kind !== SyntaxKind.BoltBraced) { - throw new ParseError(t1, [SyntaxKind.BoltBraced]) - } + // const t1 = tokens.get(); + // if (t1.kind !== SyntaxKind.BoltBraced) { + // throw new ParseError(t1, [SyntaxKind.BoltBraced]) + // } - const innerTokens = t1.toTokenStream(); + // const innerTokens = t1.toTokenStream(); - const pattern = this.parsePattern(innerTokens) + // const pattern = this.parsePattern(innerTokens) - const t2 = innerTokens.get(); - if (t2.kind !== SyntaxKind.BoltRArrow) { - throw new ParseError(t2, [SyntaxKind.BoltRArrow]); - } + // const t2 = innerTokens.get(); + // if (t2.kind !== SyntaxKind.BoltRArrow) { + // throw new ParseError(t2, [SyntaxKind.BoltRArrow]); + // } - const body = this.parseBody(innerTokens); + // const body = this.parseBody(innerTokens); - return new Macro(pattern, body) + // return new Macro(pattern, body) + //} + + public parseExpression(tokens: BoltTokenStream): BoltExpression { + return this.parsePrimitiveExpression(tokens) } - parseExpr(tokens: TokenStream): Expr { - return this.parsePrimExpr(tokens) - } - - parseParam(tokens: TokenStream): Param { + public parseParameter(tokens: BoltTokenStream): BoltParameter { let defaultValue = null; let typeDecl = null; const pattern = this.parsePattern(tokens) - const t0 = tokens.peek(1); + let t0 = tokens.peek(1); + let endNode: BoltSyntax = pattern; if (t0.kind === SyntaxKind.BoltColon) { tokens.get(); - typeDecl = this.parseTypeDecl(tokens); - const t1 = tokens.peek(1); - if (t1.kind === SyntaxKind.BoltEqSign) { - tokens.get(); - defaultValue = this.parseExpr(tokens); - } + typeDecl = this.parseTypeNode(tokens); + endNode = typeDecl; + t0 = tokens.get(); } - if (t0.kind === SyntaxKind.BoltEqSign) { tokens.get(); - defaultValue = this.parseExpr(tokens); + defaultValue = this.parseExpression(tokens); + endNode = defaultValue; } - return new Param(pattern, typeDecl, defaultValue) + const node = createBoltParameter(0, pattern, typeDecl, defaultValue) + setOrigNodeRange(node, pattern, endNode); + return node; } - parseVarDecl(tokens: TokenStream): VarDecl { + public parseVariableDeclaration(tokens: BoltTokenStream): BoltVariableDeclaration { - let isMutable = false; + let modifiers = 0; let typeDecl = null; let value = null; - // Assuming first token is 'let' - tokens.get(); + const t0 = tokens.get(); + assertToken(t0, SyntaxKind.BoltLetKeyword); - const t0 = tokens.peek(); - if (t0.kind === SyntaxKind.BoltIdentifier && t0.text === 'mut') { + const t1 = tokens.peek(); + if (t1.kind === SyntaxKind.BoltMutKeyword) { tokens.get(); - isMutable = true; + modifiers |= BoltDeclarationModifiers.Mutable; } const bindings = this.parsePattern(tokens) - const t1 = tokens.peek(); - if (t1.kind === SyntaxKind.BoltColon) { + let t2 = tokens.peek(); + let lastNode: BoltSyntax = bindings; + + if (t2.kind === SyntaxKind.BoltColon) { tokens.get(); - typeDecl = this.parseTypeDecl(tokens); + lastNode = typeDecl = this.parseTypeNode(tokens); + t2 = tokens.peek(); } - const t2 = tokens.peek(); if (t2.kind === SyntaxKind.BoltEqSign) { tokens.get(); - value = this.parseExpr(tokens); + lastNode = value = this.parseExpression(tokens); } - return new VarDecl(isMutable, bindings, typeDecl, value, null) - + const node = createBoltVariableDeclaration(modifiers, bindings, typeDecl, value) + setOrigNodeRange(node, t0, lastNode); + return node; } - parseRetStmt(tokens: TokenStream): RetStmt { + public parseReturnStatement(tokens: BoltTokenStream): BoltReturnStatement { - // Assuming first token is 'return' const t0 = tokens.get(); + assertToken(t0, SyntaxKind.BoltReturnKeyword); let expr = null; const t1 = tokens.peek(); if (t1.kind !== SyntaxKind.BoltEOS) { - expr = this.parseExpr(tokens) + expr = this.parseExpression(tokens) } - return new RetStmt(expr, null, [t0, expr.getEndNode()]); + const node = createBoltReturnStatement(expr); + setOrigNodeRange(node, t0, expr !== null ? expr : t0); + return node; } - parseStmt(tokens: TokenStream): Stmt { - this.parseCallExpr(tokens) + protected lookaheadHasExpression(tokens: BoltTokenStream, i = 1): boolean { + const t0 = tokens.peek(i); + if (t0.kind === SyntaxKind.BoltParenthesized) { + return this.lookaheadHasExpression(tokens, i+1); + } + return t0.kind === SyntaxKind.BoltIdentifier + || t0.kind === SyntaxKind.BoltStringLiteral + || t0.kind === SyntaxKind.BoltIntegerLiteral + || (t0.kind === SyntaxKind.BoltOperator && this.isUnaryOperator(t0.text)); } - parseRecordDecl(tokens: TokenStream): RecordDecl { - - let isPublic = false; - - let kw = tokens.get(); - if (kw.kind !== SyntaxKind.BoltIdentifier) { - throw new ParseError(kw, [SyntaxKind.BoltPubKeyword, SyntaxKind.BoltStructKeyword]); + public parseStatement(tokens: BoltTokenStream): BoltStatement { + const t0 = tokens.peek(); + if (t0.kind === SyntaxKind.BoltReturnKeyword) { + return this.parseReturnStatement(tokens); + } else if (t0.kind === SyntaxKind.BoltLoopKeyword) { + return this.parseLoopStatement(tokens); + } else { + try { + return this.parseExpressionStatement(tokens); + } catch (e) { + if (!(e instanceof ParseError)) { + throw e; + } + throw new ParseError(t0, KIND_STATEMENT_T0); + } } - if (kw.text === 'pub') { - isPublic = true; - kw = tokens.get(); + } + + public parseRecordDeclaration(tokens: BoltTokenStream): BoltRecordDeclaration { + + let modifiers = 0; + + let t0 = tokens.get(); + const firstToken = t0; + if (t0.kind === SyntaxKind.BoltPubKeyword) { + modifiers |= BoltDeclarationModifiers.Public; + t0 = tokens.get(); } - if (kw.kind !== SyntaxKind.BoltIdentifier || kw.text !== 'struct') { - throw new ParseError(kw, [SyntaxKind.BoltStructKeyword]) + if (t0.kind !== SyntaxKind.BoltStructKeyword) { + throw new ParseError(t0, [SyntaxKind.BoltStructKeyword]) } - const name = this.parseQualName(tokens); + const name = tokens.get(); + assertToken(name, SyntaxKind.BoltIdentifier); const t2 = tokens.get(); if (t2.kind !== SyntaxKind.BoltBraced) { - throw new ParseError(kw, [SyntaxKind.BoltBraced]) + throw new ParseError(t2, [SyntaxKind.BoltBraced]) } - let fields = []; - - return new RecordDecl(isPublic, name, fields); + let fields: BoltRecordDeclarationField[] = []; + const innerTokens = createTokenStream(t2); + while (true) { + const t3 = innerTokens.get(); + if (t3.kind === SyntaxKind.EOS) { + break; + } + const name = innerTokens.get(); + assertToken(name, SyntaxKind.BoltIdentifier); + const t4 = innerTokens.get(); + assertToken(t4, SyntaxKind.BoltColon); + const type = this.parseTypeNode(innerTokens); + const field = createBoltRecordDeclarationField(name as BoltIdentifier, type); + setOrigNodeRange(field, name, type); + fields.push(field); + } + + const node = new RecordDecl(modifiers, name, fields); + setOrigNodeRange(node, firstToken, t2); + return node; } - parseStmts(tokens: TokenStream, origNode: Syntax | null): Stmt[] { - // TODO - return [] + public parseStatements(tokens: BoltTokenStream): BoltStatement[] { + const statements: BoltStatement[] = []; + while (true) { + const t0 = tokens.peek(); + if (t0.kind === SyntaxKind.BoltEOS) { + break; + } + const statement = this.parseStatement(tokens); + statements.push(statement); + } + return statements; } - parseModDecl(tokens: TokenStream): Module { + public parseModuleDeclaration(tokens: BoltTokenStream): BoltModule { - let isPublic = false; + let modifiers = 0; - let kw = tokens.get(); - if (kw.kind !== SyntaxKind.BoltIdentifier) { - throw new ParseError(kw, [SyntaxKind.BoltPubKeyword, SyntaxKind.BoltModKeyword]); - } - if (kw.text === 'pub') { - isPublic = true; - kw = tokens.get(); + let t0 = tokens.get(); + const firstToken = t0; + if (t0.kind === SyntaxKind.BoltPubKeyword) { + tokens.get(); + modifiers |= BoltDeclarationModifiers.Public; + t0 = tokens.peek(); } - if (kw.kind !== SyntaxKind.BoltIdentifier || kw.text !== 'mod') { - throw new ParseError(kw, [SyntaxKind.BoltModKeyword]) + if (t0.kind !== SyntaxKind.BoltIdentifier || t0.text !== 'mod') { + throw new ParseError(t0, [SyntaxKind.BoltModKeyword]) } const name = this.parseQualName(tokens); @@ -390,34 +516,30 @@ export class Parser { if (t1.kind !== SyntaxKind.BoltBraced) { throw new ParseError(t1, [SyntaxKind.BoltBraced]) } + const sentences = this.parseSentences(createTokenStream(t1)); - return new Module(isPublic, name, t1.toSentences()); - + const node = createBoltModule(modifiers, name, sentences); + setOrigNodeRange(node, firstToken, t1); + return node; } - protected assertEmpty(tokens: TokenStream) { - const t0 = tokens.peek(1); - if (t0.kind !== SyntaxKind.BoltEOS) { - throw new ParseError(t0, [SyntaxKind.BoltEOS]); - } - } - parseNewType(tokens: TokenSteam): NewTypeDecl { + public parseNewTypeDeclaration(tokens: BoltTokenSteam): BoltNewTypeDeclaration { + + let modifiers = 0; - let isPublic = false; let t0 = tokens.get(); - if (t0.kind !== SyntaxKind.BoltIdentifier) { - throw new ParseError(t0, [SyntaxKind.BoltPubKeyword, SyntaxKind.BoltNewTypeKeyword]) - } - if (t0.text === 'pub') { - isPublic = true; - t0 = tokens.get(); + + if (t0.kind === SyntaxKind.BoltPubKeyword) { + tokens.get(); + modifiers |= BoltDeclarationModifiers.Public; + t0 = tokens.peek(); if (t0.kind !== SyntaxKind.BoltIdentifier) { throw new ParseError(t0, [SyntaxKind.BoltNewTypeKeyword]) } } - if (t0.text !== 'newtype') { + if (t0.kind !== SyntaxKind.BoltNewTypeKeyword) { throw new ParseError(t0, [SyntaxKind.BoltNewTypeKeyword]) } @@ -426,63 +548,71 @@ export class Parser { throw new ParseError(name, [SyntaxKind.BoltIdentifier]) } - return new NewTypeDecl(isPublic, name) - + const node = createBoltNewTypeDeclaration(modifiers, name) + setOrigNodeRange(node, firstToken, name); + return node; } - parseFuncDecl(tokens: TokenStream, origNode: Syntax | null): FuncDecl { + private parseFunctionDeclarationMaybeForeign(tokens: BoltTokenStream): BoltFunctionDeclaration | BoltForeignFunctionDeclaration { let target = "Bolt"; - let isPublic = false; + let modifiers = 0; - const k0 = tokens.peek(); - if (k0.kind !== SyntaxKind.BoltIdentifier) { - throw new ParseError(k0, [SyntaxKind.BoltPubKeyword, SyntaxKind.BoltForeignKeyword, SyntaxKind.BoltFnKeyword]) - } - if (k0.text === 'pub') { + let k0 = tokens.peek(); + let lastNode: BoltSyntax; + const firstToken = k0; + + if (k0.kind !== SyntaxKind.BoltPubKeyword) { tokens.get(); - isPublic = true; + modifiers |= BoltDeclarationModifiers.Public; + k0 = tokens.peek(); } - const k1 = tokens.peek(); - if (k1.kind !== SyntaxKind.BoltIdentifier) { - throw new ParseError(k1, [SyntaxKind.BoltForeignKeyword, SyntaxKind.BoltFnKeyword]) - } - if (k1.text === 'foreign') { + if (k0.kind === SyntaxKind.BoltForeignKeyword) { tokens.get(); + modifiers |= BoltDeclarationModifiers.IsForeign; const l1 = tokens.get(); if (l1.kind !== SyntaxKind.BoltStringLiteral) { throw new ParseError(l1, [SyntaxKind.BoltStringLiteral]) } target = l1.value; - } - const k2 = tokens.get(); - if (k2.kind !== SyntaxKind.BoltIdentifier || k2.text !== 'fn') { - throw new ParseError(k2, [SyntaxKind.BoltFnKeyword]) + k0 = tokens.peek(); } - let name: QualName; + if (k0.kind !== SyntaxKind.BoltFnKeyword) { + throw new ParseError(k0, [SyntaxKind.BoltFnKeyword]) + } + + tokens.get(); + + let name: BoltQualName; let returnType = null; let body = null; - let params: Param[] = []; + let params: BoltParameter[] = []; // Parse parameters + let i = 0; + const t0 = tokens.peek(1); const t1 = tokens.peek(2); - const isParamLike = (token: Token) => + const isParamLike = (token: BoltToken) => token.kind === SyntaxKind.BoltIdentifier || token.kind === SyntaxKind.BoltParenthesized; - const parseParamLike = (tokens: TokenStream) => { + const parseParamLike = (tokens: BoltTokenStream) => { const t0 = tokens.peek(1); if (t0.kind === SyntaxKind.BoltIdentifier) { tokens.get(); - return new Param(new BindPatt(t0, null, t0), null, null, null, t0) + const bindings = createBoltBindPattern(t0 as BoltIdentifier); + setOrigNodeRange(bindings, t0, t0); + const param = createBoltParameter(i++, bindings, null, null); + setOrigNodeRange(param, t0, t0); + return param; } else if (t0.kind === SyntaxKind.BoltParenthesized) { tokens.get(); - const innerTokens = t0.toTokenStream(); - const param = this.parseParam(innerTokens) + const innerTokens = createTokenStream(t0); + const param = this.parseParameter(innerTokens, i++) this.assertEmpty(innerTokens); return param } else { @@ -492,14 +622,16 @@ export class Parser { if (t0.kind === SyntaxKind.BoltOperator) { - name = new QualName(t0, [], null, t0); + name = createBoltQualName([], t0); + setOrigNodeRange(name, t0, t0); tokens.get(); params.push(parseParamLike(tokens)) } else if (isParamLike(t0) && t1.kind == SyntaxKind.BoltOperator) { params.push(parseParamLike(tokens)); - name = new QualName(t1, [], null, t1); + name = createBoltQualName([], t1); + setOrigNodeRange(name, t1, t1); while (true) { const t2 = tokens.peek(); if (t2.kind !== SyntaxKind.BoltOperator) { @@ -517,13 +649,13 @@ export class Parser { name = this.parseQualName(tokens) const t2 = tokens.get(); if (t2.kind === SyntaxKind.BoltParenthesized) { - const innerTokens = t2.toTokenStream(); + const innerTokens = createTokenStream(t2); while (true) { const t3 = innerTokens.peek(); if (t3.kind === SyntaxKind.BoltEOS) { break; } - params.push(this.parseParam(innerTokens)) + params.push(this.parseParameter(innerTokens, i++)) const t4 = innerTokens.get(); if (t4.kind === SyntaxKind.BoltComma) { continue; @@ -546,7 +678,7 @@ export class Parser { const t2 = tokens.peek(); if (t2.kind === SyntaxKind.BoltRArrow) { tokens.get(); - returnType = this.parseTypeDecl(tokens); + returnType = this.parseTypeNode(tokens); } // Parse function body @@ -556,21 +688,29 @@ export class Parser { tokens.get(); switch (target) { case "Bolt": - body = this.parseStmts(tokens, t3); + body = this.parseStatements(tokens); break; case "JS": - body = acorn.parse(t3.text).body; + // TODO + //body = acorn.parse(t3.text).body; break; default: throw new Error(`Unrecognised language: ${target}`); } } - return new FuncDecl(isPublic, target, name, params, returnType, body, null, origNode) + const node = createBoltFunctionDeclaration( + modifiers, + name, + params, + returnType, + body + ); + setOrigNodeRange(node, firstToken, lastNode); } - parseSourceElement(tokens: TokenStream): SourceElement { + parseSourceElement(tokens: BoltTokenStream): SourceElement { const t0 = tokens.peek(1); if (t0.kind === SyntaxKind.BoltIdentifier) { let i = 1; @@ -608,7 +748,7 @@ export class Parser { return this.parseVariantDecl(tokens); default: try { - return this.parseExpr(tokens) + return this.parseExpression(tokens) } catch (e) { if (e instanceof ParseError) { throw new ParseError(kw, [...e.expected, SyntaxKind.BoltModKeyword, SyntaxKind.BoltLetKeyword, @@ -619,7 +759,7 @@ export class Parser { } } } else { - return this.parseStmt(tokens) + return this.parseStatement(tokens) } } @@ -638,35 +778,35 @@ export class Parser { } } - parseBinOp(tokens: TokenStream, lhs: Expr , minPrecedence: number) { - let lookahead = tokens.peek(1); - while (true) { - if (lookahead.kind !== SyntaxKind.BoltOperator) { - break; - } - const lookaheadDesc = this.getOperatorDesc(2, lookahead.text); - if (lookaheadDesc === null || lookaheadDesc.precedence < minPrecedence) { - break; - } - const op = lookahead; - const opDesc = this.getOperatorDesc(2, op.text); - tokens.get(); - let rhs = this.parsePrimExpr(tokens) - lookahead = tokens.peek() - while (lookaheadDesc.arity === 2 - && ((lookaheadDesc.precedence > opDesc.precedence) - || lookaheadDesc.kind === OperatorKind.InfixR && lookaheadDesc.precedence === opDesc.precedence)) { - rhs = this.parseBinOp(tokens, rhs, lookaheadDesc.precedence) - } - lookahead = tokens.peek(); - lhs = new CallExpr(new RefExpr(new QualName(op, [])), [lhs, rhs]); - } - return lhs - } + //parseBinOp(tokens: TokenStream, lhs: Expr , minPrecedence: number) { + // let lookahead = tokens.peek(1); + // while (true) { + // if (lookahead.kind !== SyntaxKind.BoltOperator) { + // break; + // } + // const lookaheadDesc = this.getOperatorDesc(2, lookahead.text); + // if (lookaheadDesc === null || lookaheadDesc.precedence < minPrecedence) { + // break; + // } + // const op = lookahead; + // const opDesc = this.getOperatorDesc(2, op.text); + // tokens.get(); + // let rhs = this.parsePrimExpr(tokens) + // lookahead = tokens.peek() + // while (lookaheadDesc.arity === 2 + // && ((lookaheadDesc.precedence > opDesc.precedence) + // || lookaheadDesc.kind === OperatorKind.InfixR && lookaheadDesc.precedence === opDesc.precedence)) { + // rhs = this.parseBinOp(tokens, rhs, lookaheadDesc.precedence) + // } + // lookahead = tokens.peek(); + // lhs = new CallExpr(new RefExpr(new QualName(op, [])), [lhs, rhs]); + // } + // return lhs + //} parseCallExpr(tokens: TokenStream): CallExpr { - const operator = this.parsePrimExpr(tokens) + const operator = this.parsePrimitiveExpression(tokens) const args: Expr[] = [] const t2 = tokens.get(); @@ -681,7 +821,7 @@ export class Parser { if (t3.kind === SyntaxKind.BoltEOS) { break; } - args.push(this.parseExpr(innerTokens)) + args.push(this.parseExpression(innerTokens)) const t4 = innerTokens.get(); if (t4.kind === SyntaxKind.BoltEOS) { break diff --git a/src/treegen/ast-template.js b/src/treegen/ast-template.js index 9210549c6..3c4bfaedf 100644 --- a/src/treegen/ast-template.js +++ b/src/treegen/ast-template.js @@ -29,7 +29,6 @@ function createNode(nodeType) { } }); obj.span = null; - obj.origNodes = null; return obj; } @@ -59,9 +58,6 @@ for (const nodeName of Object.keys(NODE_TYPES)) { if (i < args.length) { node.span = args[i++]; } - if (i < args.length) { - node.origNodes = i < args.length ? args[i++] : null; - } if (i < args.length) { throw new Error(`Too many arguments provided to function create${nodeName}`); } diff --git a/src/treegen/index.ts b/src/treegen/index.ts index 2d36447d9..f30f8ae60 100644 --- a/src/treegen/index.ts +++ b/src/treegen/index.ts @@ -112,7 +112,6 @@ interface SyntaxBase { kind: SyntaxKind; parentNode: Syntax | null; span: TextSpan | null; - origNodes: SyntaxRange | null; } `); @@ -180,7 +179,7 @@ interface SyntaxBase { for (const field of getAllFields(decl)) { dtsFile.write(`${field.name}: ${emitTypeScriptType(field.typeNode)}, `); } - dtsFile.write(`span?: TextSpan | null, origNodes?: SyntaxRange | null): ${decl.name};\n`); + dtsFile.write(`span?: TextSpan | null): ${decl.name};\n`); } dtsFile.write('\n');