diff --git a/spec/ast.txt b/spec/ast.txt index ac606b300..1e5b66fd7 100644 --- a/spec/ast.txt +++ b/spec/ast.txt @@ -3,6 +3,8 @@ @language JS; node EndOfFile > BoltToken, JSToken; +node Token; +node SourceFile; // Bolt language AST definitions @@ -10,7 +12,7 @@ type BoltValue = Integer | bool | String; node FunctionBody; -node BoltToken; +node BoltToken > Token; node BoltStringLiteral > BoltToken { value: String, @@ -50,6 +52,7 @@ node BoltLtSign > BoltToken; node BoltKeyword; +node BoltQuoteKeyword > BoltToken, BoltKeyword; node BoltFnKeyword > BoltToken, BoltKeyword; node BoltForeignKeyword > BoltToken, BoltKeyword; node BoltForKeyword > BoltToken, BoltKeyword; @@ -76,7 +79,7 @@ node BoltParenthesized > BoltPunctuated; node BoltBraced > BoltPunctuated; node BoltBracketed > BoltPunctuated; -node BoltSourceFile { +node BoltSourceFile > SourceFile { elements: Vec, } @@ -92,6 +95,11 @@ node BoltReferenceTypeExpression > BoltTypeExpression { arguments: Option>, } +node BoltFunctionTypeExpression > BoltTypeExpression { + params: Vec, + returnType: Option, +} + node BoltTypeParameter { index: usize, name: BoltIdentifier, @@ -122,18 +130,23 @@ node BoltTuplePattern > BoltPattern { elements: Vec, } -node BoltRecordPatternField { - name: BoltIdentifier, - pattern: BoltPattern, +node BoltRecordFieldPattern { + isRest: bool, + name: Option, + pattern: Option, } node BoltRecordPattern > BoltPattern { - name: BoltTypeExpression, - fields: Vec, + name: BoltQualName, + fields: Vec, } node BoltExpression; +node BoltQuoteExpression > BoltExpression { + tokens: Vec, +} + node BoltReferenceExpression > BoltExpression { name: BoltQualName, } @@ -297,7 +310,7 @@ node BoltMacroCall > BoltRecordMember, BoltStatement, BoltDeclaration, BoltExpre type JSValue = Int | String | Bool | Void; -node JSToken; +node JSToken > Token; node JSOperator > JSToken { text: String, @@ -489,7 +502,7 @@ node JSLetDeclaration > JSDeclaration, JSFunctionBodyElement { value: Option, } -node JSSourceFile { +node JSSourceFile > SourceFile { elements: Vec, } diff --git a/src/ast.d.ts b/src/ast.d.ts index 1bf9224b3..46b100bb1 100644 --- a/src/ast.d.ts +++ b/src/ast.d.ts @@ -1,143 +1,146 @@ export const enum SyntaxKind { EndOfFile = 2, - FunctionBody = 4, - BoltStringLiteral = 6, - BoltIntegerLiteral = 7, - BoltIdentifier = 9, - BoltOperator = 10, - BoltAssignment = 11, - BoltComma = 12, - BoltSemi = 13, - BoltColon = 14, - BoltDot = 15, - BoltDotDot = 16, - BoltRArrow = 17, - BoltRArrowAlt = 18, - BoltLArrow = 19, - BoltEqSign = 20, - BoltGtSign = 21, - BoltLtSign = 22, - BoltFnKeyword = 24, - BoltForeignKeyword = 25, - BoltForKeyword = 26, - BoltLetKeyword = 27, - BoltReturnKeyword = 28, - BoltLoopKeyword = 29, - BoltYieldKeyword = 30, - BoltMatchKeyword = 31, - BoltImportKeyword = 32, - BoltPubKeyword = 33, - BoltModKeyword = 34, - BoltMutKeyword = 35, - BoltEnumKeyword = 36, - BoltStructKeyword = 37, - BoltTypeKeyword = 38, - BoltTraitKeyword = 39, - BoltImplKeyword = 40, - BoltParenthesized = 42, - BoltBraced = 43, - BoltBracketed = 44, - BoltSourceFile = 45, - BoltQualName = 46, - BoltReferenceTypeExpression = 48, - BoltTypeParameter = 49, - BoltBindPattern = 51, - BoltTypePattern = 52, - BoltExpressionPattern = 53, - BoltTuplePatternElement = 54, - BoltTuplePattern = 55, - BoltRecordPatternField = 56, - BoltRecordPattern = 57, - BoltReferenceExpression = 59, - BoltCallExpression = 60, - BoltYieldExpression = 61, - BoltMatchArm = 62, - BoltMatchExpression = 63, - BoltCase = 64, - BoltCaseExpression = 65, - BoltBlockExpression = 66, - BoltConstantExpression = 67, - BoltReturnStatement = 69, - BoltConditionalCase = 70, - BoltConditionalStatement = 71, - BoltResumeStatement = 72, - BoltExpressionStatement = 73, - BoltParameter = 74, - BoltModule = 78, - BoltFunctionDeclaration = 80, - BoltVariableDeclaration = 81, - BoltPlainImportSymbol = 83, - BoltImportDeclaration = 84, - BoltTraitDeclaration = 85, - BoltImplDeclaration = 86, - BoltTypeAliasDeclaration = 87, - BoltRecordField = 89, - BoltRecordDeclaration = 90, - BoltMacroCall = 92, - JSOperator = 95, - JSIdentifier = 96, - JSString = 97, - JSInteger = 98, - JSFromKeyword = 99, - JSReturnKeyword = 100, - JSTryKeyword = 101, - JSFinallyKeyword = 102, - JSCatchKeyword = 103, - JSImportKeyword = 104, - JSAsKeyword = 105, - JSConstKeyword = 106, - JSLetKeyword = 107, - JSExportKeyword = 108, - JSFunctionKeyword = 109, - JSWhileKeyword = 110, - JSForKeyword = 111, - JSCloseBrace = 112, - JSCloseBracket = 113, - JSCloseParen = 114, - JSOpenBrace = 115, - JSOpenBracket = 116, - JSOpenParen = 117, - JSSemi = 118, - JSComma = 119, - JSDot = 120, - JSDotDotDot = 121, - JSMulOp = 122, - JSAddOp = 123, - JSDivOp = 124, - JSSubOp = 125, - JSLtOp = 126, - JSGtOp = 127, - JSBOrOp = 128, - JSBXorOp = 129, - JSBAndOp = 130, - JSBNotOp = 131, - JSNotOp = 132, - JSBindPattern = 134, - JSConstantExpression = 136, - JSMemberExpression = 137, - JSCallExpression = 138, - JSBinaryExpression = 139, - JSUnaryExpression = 140, - JSNewExpression = 141, - JSSequenceExpression = 142, - JSConditionalExpression = 143, - JSLiteralExpression = 145, - JSReferenceExpression = 146, - JSCatchBlock = 150, - JSTryCatchStatement = 151, - JSExpressionStatement = 152, - JSConditionalCase = 153, - JSConditionalStatement = 154, - JSReturnStatement = 155, - JSParameter = 156, - JSImportStarBinding = 160, - JSImportAsBinding = 161, - JSImportDeclaration = 162, - JSFunctionDeclaration = 163, - JSArrowFunctionDeclaration = 164, - JSLetDeclaration = 165, - JSSourceFile = 166, + FunctionBody = 6, + BoltStringLiteral = 8, + BoltIntegerLiteral = 9, + BoltIdentifier = 11, + BoltOperator = 12, + BoltAssignment = 13, + BoltComma = 14, + BoltSemi = 15, + BoltColon = 16, + BoltDot = 17, + BoltDotDot = 18, + BoltRArrow = 19, + BoltRArrowAlt = 20, + BoltLArrow = 21, + BoltEqSign = 22, + BoltGtSign = 23, + BoltLtSign = 24, + BoltQuoteKeyword = 26, + BoltFnKeyword = 27, + BoltForeignKeyword = 28, + BoltForKeyword = 29, + BoltLetKeyword = 30, + BoltReturnKeyword = 31, + BoltLoopKeyword = 32, + BoltYieldKeyword = 33, + BoltMatchKeyword = 34, + BoltImportKeyword = 35, + BoltPubKeyword = 36, + BoltModKeyword = 37, + BoltMutKeyword = 38, + BoltEnumKeyword = 39, + BoltStructKeyword = 40, + BoltTypeKeyword = 41, + BoltTraitKeyword = 42, + BoltImplKeyword = 43, + BoltParenthesized = 45, + BoltBraced = 46, + BoltBracketed = 47, + BoltSourceFile = 48, + BoltQualName = 49, + BoltReferenceTypeExpression = 51, + BoltFunctionTypeExpression = 52, + BoltTypeParameter = 53, + BoltBindPattern = 55, + BoltTypePattern = 56, + BoltExpressionPattern = 57, + BoltTuplePatternElement = 58, + BoltTuplePattern = 59, + BoltRecordFieldPattern = 60, + BoltRecordPattern = 61, + BoltQuoteExpression = 63, + BoltReferenceExpression = 64, + BoltCallExpression = 65, + BoltYieldExpression = 66, + BoltMatchArm = 67, + BoltMatchExpression = 68, + BoltCase = 69, + BoltCaseExpression = 70, + BoltBlockExpression = 71, + BoltConstantExpression = 72, + BoltReturnStatement = 74, + BoltConditionalCase = 75, + BoltConditionalStatement = 76, + BoltResumeStatement = 77, + BoltExpressionStatement = 78, + BoltParameter = 79, + BoltModule = 83, + BoltFunctionDeclaration = 85, + BoltVariableDeclaration = 86, + BoltPlainImportSymbol = 88, + BoltImportDeclaration = 89, + BoltTraitDeclaration = 90, + BoltImplDeclaration = 91, + BoltTypeAliasDeclaration = 92, + BoltRecordField = 94, + BoltRecordDeclaration = 95, + BoltMacroCall = 97, + JSOperator = 100, + JSIdentifier = 101, + JSString = 102, + JSInteger = 103, + JSFromKeyword = 104, + JSReturnKeyword = 105, + JSTryKeyword = 106, + JSFinallyKeyword = 107, + JSCatchKeyword = 108, + JSImportKeyword = 109, + JSAsKeyword = 110, + JSConstKeyword = 111, + JSLetKeyword = 112, + JSExportKeyword = 113, + JSFunctionKeyword = 114, + JSWhileKeyword = 115, + JSForKeyword = 116, + JSCloseBrace = 117, + JSCloseBracket = 118, + JSCloseParen = 119, + JSOpenBrace = 120, + JSOpenBracket = 121, + JSOpenParen = 122, + JSSemi = 123, + JSComma = 124, + JSDot = 125, + JSDotDotDot = 126, + JSMulOp = 127, + JSAddOp = 128, + JSDivOp = 129, + JSSubOp = 130, + JSLtOp = 131, + JSGtOp = 132, + JSBOrOp = 133, + JSBXorOp = 134, + JSBAndOp = 135, + JSBNotOp = 136, + JSNotOp = 137, + JSBindPattern = 139, + JSConstantExpression = 141, + JSMemberExpression = 142, + JSCallExpression = 143, + JSBinaryExpression = 144, + JSUnaryExpression = 145, + JSNewExpression = 146, + JSSequenceExpression = 147, + JSConditionalExpression = 148, + JSLiteralExpression = 150, + JSReferenceExpression = 151, + JSCatchBlock = 155, + JSTryCatchStatement = 156, + JSExpressionStatement = 157, + JSConditionalCase = 158, + JSConditionalStatement = 159, + JSReturnStatement = 160, + JSParameter = 161, + JSImportStarBinding = 165, + JSImportAsBinding = 166, + JSImportDeclaration = 167, + JSFunctionDeclaration = 168, + JSArrowFunctionDeclaration = 169, + JSLetDeclaration = 170, + JSSourceFile = 171, } @@ -162,6 +165,91 @@ export interface EndOfFile extends SyntaxBase { kind: SyntaxKind.EndOfFile; } +export type Token + = EndOfFile + | BoltStringLiteral + | BoltIntegerLiteral + | BoltIdentifier + | BoltOperator + | BoltAssignment + | BoltComma + | BoltSemi + | BoltColon + | BoltDot + | BoltDotDot + | BoltRArrow + | BoltRArrowAlt + | BoltLArrow + | BoltEqSign + | BoltGtSign + | BoltLtSign + | BoltQuoteKeyword + | BoltFnKeyword + | BoltForeignKeyword + | BoltForKeyword + | BoltLetKeyword + | BoltReturnKeyword + | BoltLoopKeyword + | BoltYieldKeyword + | BoltMatchKeyword + | BoltImportKeyword + | BoltPubKeyword + | BoltModKeyword + | BoltMutKeyword + | BoltEnumKeyword + | BoltStructKeyword + | BoltTypeKeyword + | BoltTraitKeyword + | BoltImplKeyword + | BoltParenthesized + | BoltBraced + | BoltBracketed + | EndOfFile + | JSOperator + | JSIdentifier + | JSString + | JSInteger + | JSFromKeyword + | JSReturnKeyword + | JSTryKeyword + | JSFinallyKeyword + | JSCatchKeyword + | JSImportKeyword + | JSAsKeyword + | JSConstKeyword + | JSLetKeyword + | JSExportKeyword + | JSFunctionKeyword + | JSWhileKeyword + | JSForKeyword + | JSCloseBrace + | JSCloseBracket + | JSCloseParen + | JSOpenBrace + | JSOpenBracket + | JSOpenParen + | JSSemi + | JSComma + | JSDot + | JSDotDotDot + | JSMulOp + | JSAddOp + | JSDivOp + | JSSubOp + | JSLtOp + | JSGtOp + | JSBOrOp + | JSBXorOp + | JSBAndOp + | JSBNotOp + | JSNotOp + + +export type SourceFile + = BoltSourceFile + | JSSourceFile + + export interface FunctionBody extends SyntaxBase { kind: SyntaxKind.FunctionBody; } @@ -184,6 +272,7 @@ export type BoltToken | BoltEqSign | BoltGtSign | BoltLtSign + | BoltQuoteKeyword | BoltFnKeyword | BoltForeignKeyword | BoltForKeyword @@ -281,7 +370,8 @@ export interface BoltLtSign extends SyntaxBase { } export type BoltKeyword - = BoltFnKeyword + = BoltQuoteKeyword + | BoltFnKeyword | BoltForeignKeyword | BoltForKeyword | BoltLetKeyword @@ -300,6 +390,10 @@ export type BoltKeyword | BoltImplKeyword +export interface BoltQuoteKeyword extends SyntaxBase { + kind: SyntaxKind.BoltQuoteKeyword; +} + export interface BoltFnKeyword extends SyntaxBase { kind: SyntaxKind.BoltFnKeyword; } @@ -402,6 +496,7 @@ export interface BoltQualName extends SyntaxBase { export type BoltTypeExpression = BoltReferenceTypeExpression + | BoltFunctionTypeExpression export interface BoltReferenceTypeExpression extends SyntaxBase { @@ -410,6 +505,12 @@ export interface BoltReferenceTypeExpression extends SyntaxBase { + kind: SyntaxKind.BoltFunctionTypeExpression; + params: BoltParameter[]; + returnType: BoltTypeExpression | null; +} + export interface BoltTypeParameter extends SyntaxBase { kind: SyntaxKind.BoltTypeParameter; index: number; @@ -452,20 +553,22 @@ export interface BoltTuplePattern extends SyntaxBase { - kind: SyntaxKind.BoltRecordPatternField; - name: BoltIdentifier; - pattern: BoltPattern; +export interface BoltRecordFieldPattern extends SyntaxBase { + kind: SyntaxKind.BoltRecordFieldPattern; + isRest: boolean; + name: BoltIdentifier | null; + pattern: BoltPattern | null; } export interface BoltRecordPattern extends SyntaxBase { kind: SyntaxKind.BoltRecordPattern; - name: BoltTypeExpression; - fields: BoltRecordPatternField[]; + name: BoltQualName; + fields: BoltRecordFieldPattern[]; } export type BoltExpression - = BoltReferenceExpression + = BoltQuoteExpression + | BoltReferenceExpression | BoltCallExpression | BoltYieldExpression | BoltMatchExpression @@ -475,6 +578,11 @@ export type BoltExpression | BoltMacroCall +export interface BoltQuoteExpression extends SyntaxBase { + kind: SyntaxKind.BoltQuoteExpression; + tokens: Token[]; +} + export interface BoltReferenceExpression extends SyntaxBase { kind: SyntaxKind.BoltReferenceExpression; name: BoltQualName; @@ -1126,6 +1234,7 @@ export type BoltSyntax | BoltEqSign | BoltGtSign | BoltLtSign + | BoltQuoteKeyword | BoltFnKeyword | BoltForeignKeyword | BoltForKeyword @@ -1149,14 +1258,16 @@ export type BoltSyntax | BoltSourceFile | BoltQualName | BoltReferenceTypeExpression + | BoltFunctionTypeExpression | BoltTypeParameter | BoltBindPattern | BoltTypePattern | BoltExpressionPattern | BoltTuplePatternElement | BoltTuplePattern - | BoltRecordPatternField + | BoltRecordFieldPattern | BoltRecordPattern + | BoltQuoteExpression | BoltReferenceExpression | BoltCallExpression | BoltYieldExpression @@ -1270,6 +1381,7 @@ export type Syntax | BoltEqSign | BoltGtSign | BoltLtSign + | BoltQuoteKeyword | BoltFnKeyword | BoltForeignKeyword | BoltForKeyword @@ -1293,14 +1405,16 @@ export type Syntax | BoltSourceFile | BoltQualName | BoltReferenceTypeExpression + | BoltFunctionTypeExpression | BoltTypeParameter | BoltBindPattern | BoltTypePattern | BoltExpressionPattern | BoltTuplePatternElement | BoltTuplePattern - | BoltRecordPatternField + | BoltRecordFieldPattern | BoltRecordPattern + | BoltQuoteExpression | BoltReferenceExpression | BoltCallExpression | BoltYieldExpression @@ -1412,6 +1526,7 @@ 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 createBoltQuoteKeyword(span?: TextSpan | null): BoltQuoteKeyword; export function createBoltFnKeyword(span?: TextSpan | null): BoltFnKeyword; export function createBoltForeignKeyword(span?: TextSpan | null): BoltForeignKeyword; export function createBoltForKeyword(span?: TextSpan | null): BoltForKeyword; @@ -1435,14 +1550,16 @@ export function createBoltBracketed(text: string, span?: TextSpan | null): BoltB export function createBoltSourceFile(elements: BoltSourceElement[], span?: TextSpan | null): BoltSourceFile; export function createBoltQualName(modulePath: BoltIdentifier[] | null, name: BoltSymbol, span?: TextSpan | null): BoltQualName; export function createBoltReferenceTypeExpression(name: BoltQualName, arguments: BoltTypeExpression[] | null, span?: TextSpan | null): BoltReferenceTypeExpression; +export function createBoltFunctionTypeExpression(params: BoltParameter[], returnType: BoltTypeExpression | null, span?: TextSpan | null): BoltFunctionTypeExpression; 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: 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: BoltTypeExpression, fields: BoltRecordPatternField[], span?: TextSpan | null): BoltRecordPattern; +export function createBoltRecordFieldPattern(isRest: boolean, name: BoltIdentifier | null, pattern: BoltPattern | null, span?: TextSpan | null): BoltRecordFieldPattern; +export function createBoltRecordPattern(name: BoltQualName, fields: BoltRecordFieldPattern[], span?: TextSpan | null): BoltRecordPattern; +export function createBoltQuoteExpression(tokens: Token[], span?: TextSpan | null): BoltQuoteExpression; 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; @@ -1534,6 +1651,8 @@ export function createJSLetDeclaration(bindings: JSPattern, value: JSExpression export function createJSSourceFile(elements: JSSourceElement[], span?: TextSpan | null): JSSourceFile; export function isEndOfFile(value: any): value is EndOfFile; +export function isToken(value: any): value is Token; +export function isSourceFile(value: any): value is SourceFile; export function isFunctionBody(value: any): value is FunctionBody; export function isBoltToken(value: any): value is BoltToken; export function isBoltStringLiteral(value: any): value is BoltStringLiteral; @@ -1554,6 +1673,7 @@ 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 isBoltQuoteKeyword(value: any): value is BoltQuoteKeyword; export function isBoltFnKeyword(value: any): value is BoltFnKeyword; export function isBoltForeignKeyword(value: any): value is BoltForeignKeyword; export function isBoltForKeyword(value: any): value is BoltForKeyword; @@ -1579,6 +1699,7 @@ export function isBoltSourceFile(value: any): value is BoltSourceFile; export function isBoltQualName(value: any): value is BoltQualName; export function isBoltTypeExpression(value: any): value is BoltTypeExpression; export function isBoltReferenceTypeExpression(value: any): value is BoltReferenceTypeExpression; +export function isBoltFunctionTypeExpression(value: any): value is BoltFunctionTypeExpression; export function isBoltTypeParameter(value: any): value is BoltTypeParameter; export function isBoltPattern(value: any): value is BoltPattern; export function isBoltBindPattern(value: any): value is BoltBindPattern; @@ -1586,9 +1707,10 @@ export function isBoltTypePattern(value: any): value is BoltTypePattern; export function isBoltExpressionPattern(value: any): value is BoltExpressionPattern; export function isBoltTuplePatternElement(value: any): value is BoltTuplePatternElement; export function isBoltTuplePattern(value: any): value is BoltTuplePattern; -export function isBoltRecordPatternField(value: any): value is BoltRecordPatternField; +export function isBoltRecordFieldPattern(value: any): value is BoltRecordFieldPattern; export function isBoltRecordPattern(value: any): value is BoltRecordPattern; export function isBoltExpression(value: any): value is BoltExpression; +export function isBoltQuoteExpression(value: any): value is BoltQuoteExpression; export function isBoltReferenceExpression(value: any): value is BoltReferenceExpression; export function isBoltCallExpression(value: any): value is BoltCallExpression; export function isBoltYieldExpression(value: any): value is BoltYieldExpression; diff --git a/src/parser.ts b/src/parser.ts index 198dbf44c..b47a37433 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -64,6 +64,19 @@ import { BoltMatchArm, createBoltMatchExpression, createBoltExpressionPattern, + BoltFunctionTypeExpression, + BoltReferenceTypeExpression, + createBoltFunctionTypeExpression, + BoltRecordPattern, + createBoltRecordPattern, + createBoltRecordFieldPattern, + BoltQuoteKeyword, + isBoltPunctuated, + Token, + createBoltQuoteExpression, + BoltQuoteExpression, + BoltBlockExpression, + createBoltBlockExpression, } from "./ast" import { parseForeignLanguage } from "./foreign" @@ -77,6 +90,7 @@ import { setOrigNodeRange, createTokenStream, uniq, + assert, } from "./util" export type BoltTokenStream = Stream; @@ -99,6 +113,7 @@ const KIND_EXPRESSION_T0 = [ SyntaxKind.BoltIdentifier, SyntaxKind.BoltOperator, SyntaxKind.BoltMatchKeyword, + SyntaxKind.BoltQuoteKeyword, SyntaxKind.BoltYieldKeyword, ] @@ -205,9 +220,62 @@ export class Parser { return node; } + public parseRecordPattern(tokens: BoltTokenStream): BoltRecordPattern { + + const name = this.parseQualName(tokens); + const t1 = tokens.get(); + assertToken(t1, SyntaxKind.BoltBraced); + + const innerTokens = createTokenStream(t1); + const members = []; + + while (true) { + + let t0 = innerTokens.get(); + const firstToken = t0; + + if (t0.kind === SyntaxKind.EndOfFile) { + break; + } + + let isRest = false; + let name = null; + let pattern = null; + if (t0.kind === SyntaxKind.BoltDotDot) { + isRest = true; + t0 = innerTokens.peek(); + } + if (t0.kind === SyntaxKind.BoltIdentifier) { + name = t0; + t0 = innerTokens.peek(); + } else if (!isRest) { + throw new ParseError(t0, [SyntaxKind.BoltIdentifier]); + } + if (t0.kind === SyntaxKind.BoltEqSign) { + pattern = this.parsePattern(innerTokens); + } + let member = createBoltRecordFieldPattern(isRest, name, pattern); + setOrigNodeRange(member, firstToken, t0); + members.push(member); + + if (t0.kind === SyntaxKind.EndOfFile) { + break; + } + assertToken(t0, SyntaxKind.BoltComma); + + } + + const result = createBoltRecordPattern(name, members); + setOrigNodeRange(result, name, t1); + return result; + } + public parsePattern(tokens: BoltTokenStream): BoltPattern { const t0 = tokens.peek(1); - if (t0.kind === SyntaxKind.BoltIdentifier) { + const t1 = tokens.peek(2); + if (t0.kind === SyntaxKind.BoltIdentifier && t1.kind === SyntaxKind.BoltBraced) { + return this.parseRecordPattern(tokens); + } else if (t0.kind === SyntaxKind.BoltIdentifier) { return this.parseBindPattern(tokens); } else if (t0.kind === SyntaxKind.BoltOperator && t0.text === '^') { tokens.get(); @@ -242,7 +310,40 @@ export class Parser { return node; } - public parseReferenceTypeExpression(tokens: BoltTokenStream) { + public parseFunctionTypeExpression(tokens: BoltTokenStream): BoltFunctionTypeExpression { + const t0 = tokens.get(); + assertToken(t0, SyntaxKind.BoltFnKeyword); + const t1 = tokens.get(); + assertToken(t1, SyntaxKind.BoltParenthesized); + const innerTokens = createTokenStream(t1); + let i = 0; + const params: BoltParameter[] = []; + while (true) { + const t2 = innerTokens.peek(); + if (t2.kind === SyntaxKind.EndOfFile) { + break; + } + const param = this.parseParameter(innerTokens, i++) + params.push(param); + const t3 = innerTokens.peek() + if (t3.kind === SyntaxKind.EndOfFile) { + break; + } + const t4 = innerTokens.get(); + assertToken(t4, SyntaxKind.BoltComma); + } + const t3 = tokens.peek(); + let returnType = null; + if (t3.kind === SyntaxKind.BoltRArrow) { + tokens.get(); + returnType = this.parseTypeExpression(tokens); + } + const result = createBoltFunctionTypeExpression(params, returnType) + setOrigNodeRange(result, t0, returnType !== null ? returnType : t1); + return result; + } + + public parseReferenceTypeExpression(tokens: BoltTokenStream): BoltReferenceTypeExpression { const name = this.parseQualName(tokens) @@ -278,7 +379,9 @@ export class Parser { private parsePrimTypeExpression(tokens: BoltTokenStream): BoltTypeExpression { const t0 = tokens.peek(); - if (t0.kind === SyntaxKind.BoltIdentifier) { + if (t0.kind === SyntaxKind.BoltFnKeyword) { + return this.parseFunctionTypeExpression(tokens); + } else if (t0.kind === SyntaxKind.BoltIdentifier) { return this.parseReferenceTypeExpression(tokens); } else { throw new ParseError(t0, [SyntaxKind.BoltIdentifier]); @@ -376,9 +479,58 @@ export class Parser { return result; } - protected parsePrimitiveExpression(tokens: BoltTokenStream): BoltExpression { + public parseQuoteExpression(tokens: BoltTokenStream): BoltQuoteExpression { + const t0 = tokens.get(); + assertToken(t0, SyntaxKind.BoltQuoteKeyword); + let t1 = tokens.get(); + let target = "Bolt"; + if (t1.kind === SyntaxKind.BoltStringLiteral) { + target = t1.value; + t1 = tokens.get(); + } + if (!isBoltPunctuated(t1)) { + throw new ParseError(t1, [SyntaxKind.BoltBraced, SyntaxKind.BoltParenthesized, SyntaxKind.BoltBracketed]); + } + let scanner; + switch (target) { + case "Bolt": + scanner = new Scanner(t1.span!.file, t1.text, t1.span!.start.clone()); + break; + case "JS": + scanner = new JSScanner(t1.span!.file, t1.text, t1.span!.start.clone()); + break; + default: + throw new Error(`Unrecognised language.`); + } + const scanned: Token[] = []; + while (true) { + const t2 = scanner.scan(); + if (t2.kind === SyntaxKind.EndOfFile) { + break; + } + scanned.push(t2); + } + const result = createBoltQuoteExpression(scanned); + setOrigNodeRange(result, t0, t1); + return result; + } + + public parseBlockExpression(tokens: BoltTokenStream): BoltBlockExpression { + const t0 = tokens.get(); + const innerTokens = createTokenStream(t0); + const elements = this.parseFunctionBodyElements(innerTokens) + const result = createBoltBlockExpression(elements); + setOrigNodeRange(result, t0, t0); + return result; + } + + private parsePrimitiveExpression(tokens: BoltTokenStream): BoltExpression { const t0 = tokens.peek(); - if (t0.kind === SyntaxKind.BoltMatchKeyword) { + if (t0.kind === SyntaxKind.BoltBraced) { + return this.parseBlockExpression(tokens); + } else if (t0.kind === SyntaxKind.BoltQuoteKeyword) { + return this.parseQuoteExpression(tokens); + } else if (t0.kind === SyntaxKind.BoltMatchKeyword) { return this.parseMatchExpression(tokens); } else if (t0.kind === SyntaxKind.BoltIntegerLiteral || t0.kind === SyntaxKind.BoltStringLiteral) { return this.parseConstantExpression(tokens); @@ -393,7 +545,7 @@ export class Parser { return this.parseCallOrPrimitiveExpression(tokens) } - public parseParameter(tokens: BoltTokenStream): BoltParameter { + public parseParameter(tokens: BoltTokenStream, index: number): BoltParameter { let defaultValue = null; let typeDecl = null; @@ -414,7 +566,7 @@ export class Parser { endNode = defaultValue; } - const node = createBoltParameter(0, pattern, typeDecl, defaultValue) + const node = createBoltParameter(index, pattern, typeDecl, defaultValue) setOrigNodeRange(node, pattern, endNode); return node; @@ -970,7 +1122,7 @@ export class Parser { i += 2; t0 = tokens.peek(i); } - if (mustBeFunctionOrVariable + if (mustBeFunctionOrVariable && t0.kind !== SyntaxKind.BoltStructKeyword && t0.kind !== SyntaxKind.BoltFnKeyword) { throw new ParseError(t0, [SyntaxKind.BoltStructKeyword, SyntaxKind.BoltFnKeyword]); @@ -1236,6 +1388,7 @@ export class Parser { import { Scanner } from "./scanner" import { TextFile, TextSpan, TextPos } from "./text" import * as fs from "fs" +import {JSScanner} from "./foreign/js/scanner"; export function parseSourceFile(filepath: string): BoltSourceFile { const file = new TextFile(filepath); @@ -1246,4 +1399,4 @@ export function parseSourceFile(filepath: string): BoltSourceFile { setParents(sourceFile); return sourceFile; } -; + diff --git a/src/scanner.ts b/src/scanner.ts index 42047f604..4ee7de37f 100644 --- a/src/scanner.ts +++ b/src/scanner.ts @@ -46,6 +46,8 @@ import { createBoltTraitKeyword, createBoltImplKeyword, createBoltMatchKeyword, + createBoltQuoteKeyword, + createBoltLetKeyword, } from "./ast" export enum PunctType { @@ -114,7 +116,7 @@ function isIdentPart(ch: string) { } function isSymbol(ch: string) { - return /[=+\/\-*%$!><&^|]/.test(ch) + return /[=+\/\-*%$!><&^|\.]/.test(ch) } export class Scanner { @@ -176,7 +178,7 @@ export class Scanner { return text; } - scanToken(): BoltToken { + public scan(): BoltToken { while (true) { @@ -301,9 +303,10 @@ export class Scanner { case 'impl': return createBoltImplKeyword(span); case 'type': return createBoltTypeKeyword(span); case 'foreign': return createBoltForeignKeyword(span); - case 'let': return createBoltPubKeyword(span); + case 'let': return createBoltLetKeyword(span); case 'mut': return createBoltMutKeyword(span); case 'struct': return createBoltStructKeyword(span); + case 'quote': return createBoltQuoteKeyword(span); case 'enum': return createBoltEnumKeyword(span); default: return createBoltIdentifier(name, span); } @@ -376,7 +379,7 @@ export class Scanner { public peek(count = 1): BoltToken { while (this.scanned.length < count) { - this.scanned.push(this.scanToken()); + this.scanned.push(this.scan()); } return this.scanned[count - 1]; } @@ -384,56 +387,7 @@ export class Scanner { public get(): BoltToken { return this.scanned.length > 0 ? this.scanned.shift()! - : this.scanToken(); - } - - scanTokens() { - - const elements: BoltSentence[] = [] - - outer: while (true) { - - const tokens: BoltToken[] = []; - - inner: while (true) { - const token = this.scanToken(); - if (token.kind === SyntaxKind.EndOfFile) { - if (tokens.length === 0) { - break outer; - } else { - break inner; - } - } - if (token.kind === SyntaxKind.BoltSemi) { - break; - } - tokens.push(token) - if (token.kind === SyntaxKind.BoltBraced) { - break; - } - } - - if (tokens.length > 0) { - elements.push( - createBoltSentence( - tokens, - new TextSpan(this.file, tokens[0].span!.start.clone(), tokens[tokens.length-1].span!.end.clone()) - ) - ) - } - - } - - return elements - } - - public scan() { - const startPos = this.currPos.clone(); - const elements = this.scanTokens(); - const endPos = this.currPos.clone(); - const sourceFile = createBoltSourceFile(elements, new TextSpan(this.file, startPos, endPos)); - setParents(sourceFile); - return sourceFile; + : this.scan(); } } diff --git a/src/util.ts b/src/util.ts index 6c77a71f0..0697f501d 100644 --- a/src/util.ts +++ b/src/util.ts @@ -249,6 +249,10 @@ export function describeKind(kind: SyntaxKind): string { return "an integer" case SyntaxKind.BoltFnKeyword: return "'fn'" + case SyntaxKind.BoltQuoteKeyword: + return "'quote'"; + case SyntaxKind.BoltModKeyword: + return "'mod'"; case SyntaxKind.BoltForeignKeyword: return "'foreign'" case SyntaxKind.BoltMatchKeyword: