From aad00c5024f0b040169d4c9f5fd939418e17f8da Mon Sep 17 00:00:00 2001 From: Sam Vervaeck Date: Sun, 24 May 2020 21:03:15 +0200 Subject: [PATCH] Add support in parser for even more nodes --- spec/ast.txt | 38 ++++-- src/ast.d.ts | 338 +++++++++++++++++++++++++++++-------------------- src/emitter.ts | 28 +++- src/parser.ts | 121 ++++++++++++++++-- src/scanner.ts | 9 ++ src/util.ts | 6 + 6 files changed, 379 insertions(+), 161 deletions(-) diff --git a/spec/ast.txt b/spec/ast.txt index 1e5b66fd7..17e0636ff 100644 --- a/spec/ast.txt +++ b/spec/ast.txt @@ -22,14 +22,14 @@ node BoltIntegerLiteral > BoltToken { value: Int, } -node BoltSymbol > BoltToken { - -} +node BoltSymbol > BoltToken; node BoltIdentifier > BoltSymbol { text: String, } +node BoltOperatorLike > BoltSymbol; + node BoltOperator > BoltSymbol { text: String, } @@ -38,17 +38,21 @@ node BoltAssignment > BoltToken { operator: Option, } -node BoltComma > BoltToken; -node BoltSemi > BoltToken; -node BoltColon > BoltToken; -node BoltDot > BoltToken; -node BoltDotDot > BoltToken; -node BoltRArrow > BoltToken; -node BoltRArrowAlt > BoltToken; -node BoltLArrow > BoltToken; -node BoltEqSign > BoltToken; -node BoltGtSign > BoltToken; -node BoltLtSign > BoltToken; +node BoltComma > BoltToken; +node BoltSemi > BoltToken; +node BoltColon > BoltToken; +node BoltColonColon > BoltToken; +node BoltDot > BoltToken; +node BoltDotDot > BoltToken; +node BoltRArrow > BoltToken; +node BoltRArrowAlt > BoltToken; +node BoltLArrow > BoltToken; +node BoltEqSign > BoltToken; + +node BoltGtSign > BoltToken, BoltOperatorLike; +node BoltExMark > BoltToken, BoltOperatorLike; +node BoltLtSign > BoltToken, BoltOperatorLike; +node BoltVBar > BoltToken, BoltOperatorLike; node BoltKeyword; @@ -151,6 +155,12 @@ node BoltReferenceExpression > BoltExpression { name: BoltQualName, } +node BoltFunctionExpression > BoltExpression { + params: Vec, + returnType: Option, + body: Vec, +} + node BoltCallExpression > BoltExpression { operator: BoltExpression, operands: Vec, diff --git a/src/ast.d.ts b/src/ast.d.ts index 46b100bb1..92fb7d2a6 100644 --- a/src/ast.d.ts +++ b/src/ast.d.ts @@ -5,142 +5,146 @@ export const enum SyntaxKind { 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, + BoltOperator = 13, + BoltAssignment = 14, + BoltComma = 15, + BoltSemi = 16, + BoltColon = 17, + BoltColonColon = 18, + BoltDot = 19, + BoltDotDot = 20, + BoltRArrow = 21, + BoltRArrowAlt = 22, + BoltLArrow = 23, + BoltEqSign = 24, + BoltGtSign = 25, + BoltExMark = 26, + BoltLtSign = 27, + BoltVBar = 28, + BoltQuoteKeyword = 30, + BoltFnKeyword = 31, + BoltForeignKeyword = 32, + BoltForKeyword = 33, + BoltLetKeyword = 34, + BoltReturnKeyword = 35, + BoltLoopKeyword = 36, + BoltYieldKeyword = 37, + BoltMatchKeyword = 38, + BoltImportKeyword = 39, + BoltPubKeyword = 40, + BoltModKeyword = 41, + BoltMutKeyword = 42, + BoltEnumKeyword = 43, + BoltStructKeyword = 44, + BoltTypeKeyword = 45, + BoltTraitKeyword = 46, + BoltImplKeyword = 47, + BoltParenthesized = 49, + BoltBraced = 50, + BoltBracketed = 51, + BoltSourceFile = 52, + BoltQualName = 53, + BoltReferenceTypeExpression = 55, + BoltFunctionTypeExpression = 56, + BoltTypeParameter = 57, + BoltBindPattern = 59, + BoltTypePattern = 60, + BoltExpressionPattern = 61, + BoltTuplePatternElement = 62, + BoltTuplePattern = 63, + BoltRecordFieldPattern = 64, + BoltRecordPattern = 65, + BoltQuoteExpression = 67, + BoltReferenceExpression = 68, + BoltFunctionExpression = 69, + BoltCallExpression = 70, + BoltYieldExpression = 71, + BoltMatchArm = 72, + BoltMatchExpression = 73, + BoltCase = 74, + BoltCaseExpression = 75, + BoltBlockExpression = 76, + BoltConstantExpression = 77, + BoltReturnStatement = 79, + BoltConditionalCase = 80, + BoltConditionalStatement = 81, + BoltResumeStatement = 82, + BoltExpressionStatement = 83, + BoltParameter = 84, + BoltModule = 88, + BoltFunctionDeclaration = 90, + BoltVariableDeclaration = 91, + BoltPlainImportSymbol = 93, + BoltImportDeclaration = 94, + BoltTraitDeclaration = 95, + BoltImplDeclaration = 96, + BoltTypeAliasDeclaration = 97, + BoltRecordField = 99, + BoltRecordDeclaration = 100, + BoltMacroCall = 102, + JSOperator = 105, + JSIdentifier = 106, + JSString = 107, + JSInteger = 108, + JSFromKeyword = 109, + JSReturnKeyword = 110, + JSTryKeyword = 111, + JSFinallyKeyword = 112, + JSCatchKeyword = 113, + JSImportKeyword = 114, + JSAsKeyword = 115, + JSConstKeyword = 116, + JSLetKeyword = 117, + JSExportKeyword = 118, + JSFunctionKeyword = 119, + JSWhileKeyword = 120, + JSForKeyword = 121, + JSCloseBrace = 122, + JSCloseBracket = 123, + JSCloseParen = 124, + JSOpenBrace = 125, + JSOpenBracket = 126, + JSOpenParen = 127, + JSSemi = 128, + JSComma = 129, + JSDot = 130, + JSDotDotDot = 131, + JSMulOp = 132, + JSAddOp = 133, + JSDivOp = 134, + JSSubOp = 135, + JSLtOp = 136, + JSGtOp = 137, + JSBOrOp = 138, + JSBXorOp = 139, + JSBAndOp = 140, + JSBNotOp = 141, + JSNotOp = 142, + JSBindPattern = 144, + JSConstantExpression = 146, + JSMemberExpression = 147, + JSCallExpression = 148, + JSBinaryExpression = 149, + JSUnaryExpression = 150, + JSNewExpression = 151, + JSSequenceExpression = 152, + JSConditionalExpression = 153, + JSLiteralExpression = 155, + JSReferenceExpression = 156, + JSCatchBlock = 160, + JSTryCatchStatement = 161, + JSExpressionStatement = 162, + JSConditionalCase = 163, + JSConditionalStatement = 164, + JSReturnStatement = 165, + JSParameter = 166, + JSImportStarBinding = 170, + JSImportAsBinding = 171, + JSImportDeclaration = 172, + JSFunctionDeclaration = 173, + JSArrowFunctionDeclaration = 174, + JSLetDeclaration = 175, + JSSourceFile = 176, } @@ -170,11 +174,16 @@ export type Token | BoltStringLiteral | BoltIntegerLiteral | BoltIdentifier + | BoltGtSign + | BoltExMark + | BoltLtSign + | BoltVBar | BoltOperator | BoltAssignment | BoltComma | BoltSemi | BoltColon + | BoltColonColon | BoltDot | BoltDotDot | BoltRArrow @@ -182,7 +191,9 @@ export type Token | BoltLArrow | BoltEqSign | BoltGtSign + | BoltExMark | BoltLtSign + | BoltVBar | BoltQuoteKeyword | BoltFnKeyword | BoltForeignKeyword @@ -259,11 +270,16 @@ export type BoltToken | BoltStringLiteral | BoltIntegerLiteral | BoltIdentifier + | BoltGtSign + | BoltExMark + | BoltLtSign + | BoltVBar | BoltOperator | BoltAssignment | BoltComma | BoltSemi | BoltColon + | BoltColonColon | BoltDot | BoltDotDot | BoltRArrow @@ -271,7 +287,9 @@ export type BoltToken | BoltLArrow | BoltEqSign | BoltGtSign + | BoltExMark | BoltLtSign + | BoltVBar | BoltQuoteKeyword | BoltFnKeyword | BoltForeignKeyword @@ -307,6 +325,10 @@ export interface BoltIntegerLiteral extends SyntaxBase { text: string; } +export type BoltOperatorLike + = BoltGtSign + | BoltExMark + | BoltLtSign + | BoltVBar + + export interface BoltOperator extends SyntaxBase { kind: SyntaxKind.BoltOperator; text: string; @@ -337,6 +366,10 @@ export interface BoltColon extends SyntaxBase { kind: SyntaxKind.BoltColon; } +export interface BoltColonColon extends SyntaxBase { + kind: SyntaxKind.BoltColonColon; +} + export interface BoltDot extends SyntaxBase { kind: SyntaxKind.BoltDot; } @@ -365,10 +398,18 @@ export interface BoltGtSign extends SyntaxBase { kind: SyntaxKind.BoltGtSign; } +export interface BoltExMark extends SyntaxBase { + kind: SyntaxKind.BoltExMark; +} + export interface BoltLtSign extends SyntaxBase { kind: SyntaxKind.BoltLtSign; } +export interface BoltVBar extends SyntaxBase { + kind: SyntaxKind.BoltVBar; +} + export type BoltKeyword = BoltQuoteKeyword | BoltFnKeyword @@ -569,6 +610,7 @@ export interface BoltRecordPattern extends SyntaxBase { + kind: SyntaxKind.BoltFunctionExpression; + params: BoltParameter[]; + returnType: BoltTypeExpression | null; + body: BoltFunctionBodyElement[]; +} + export interface BoltCallExpression extends SyntaxBase { kind: SyntaxKind.BoltCallExpression; operator: BoltExpression; @@ -1226,6 +1275,7 @@ export type BoltSyntax | BoltComma | BoltSemi | BoltColon + | BoltColonColon | BoltDot | BoltDotDot | BoltRArrow @@ -1233,7 +1283,9 @@ export type BoltSyntax | BoltLArrow | BoltEqSign | BoltGtSign + | BoltExMark | BoltLtSign + | BoltVBar | BoltQuoteKeyword | BoltFnKeyword | BoltForeignKeyword @@ -1269,6 +1321,7 @@ export type BoltSyntax | BoltRecordPattern | BoltQuoteExpression | BoltReferenceExpression + | BoltFunctionExpression | BoltCallExpression | BoltYieldExpression | BoltMatchArm @@ -1373,6 +1426,7 @@ export type Syntax | BoltComma | BoltSemi | BoltColon + | BoltColonColon | BoltDot | BoltDotDot | BoltRArrow @@ -1380,7 +1434,9 @@ export type Syntax | BoltLArrow | BoltEqSign | BoltGtSign + | BoltExMark | BoltLtSign + | BoltVBar | BoltQuoteKeyword | BoltFnKeyword | BoltForeignKeyword @@ -1416,6 +1472,7 @@ export type Syntax | BoltRecordPattern | BoltQuoteExpression | BoltReferenceExpression + | BoltFunctionExpression | BoltCallExpression | BoltYieldExpression | BoltMatchArm @@ -1518,6 +1575,7 @@ export function createBoltAssignment(operator: string | null, span?: TextSpan | export function createBoltComma(span?: TextSpan | null): BoltComma; export function createBoltSemi(span?: TextSpan | null): BoltSemi; export function createBoltColon(span?: TextSpan | null): BoltColon; +export function createBoltColonColon(span?: TextSpan | null): BoltColonColon; export function createBoltDot(span?: TextSpan | null): BoltDot; export function createBoltDotDot(span?: TextSpan | null): BoltDotDot; export function createBoltRArrow(span?: TextSpan | null): BoltRArrow; @@ -1525,7 +1583,9 @@ export function createBoltRArrowAlt(span?: TextSpan | null): BoltRArrowAlt; export function createBoltLArrow(span?: TextSpan | null): BoltLArrow; export function createBoltEqSign(span?: TextSpan | null): BoltEqSign; export function createBoltGtSign(span?: TextSpan | null): BoltGtSign; +export function createBoltExMark(span?: TextSpan | null): BoltExMark; export function createBoltLtSign(span?: TextSpan | null): BoltLtSign; +export function createBoltVBar(span?: TextSpan | null): BoltVBar; export function createBoltQuoteKeyword(span?: TextSpan | null): BoltQuoteKeyword; export function createBoltFnKeyword(span?: TextSpan | null): BoltFnKeyword; export function createBoltForeignKeyword(span?: TextSpan | null): BoltForeignKeyword; @@ -1561,6 +1621,7 @@ export function createBoltRecordFieldPattern(isRest: boolean, name: BoltIdentifi 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 createBoltFunctionExpression(params: BoltParameter[], returnType: BoltTypeExpression | null, body: BoltFunctionBodyElement[], span?: TextSpan | null): BoltFunctionExpression; 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; @@ -1659,11 +1720,13 @@ export function isBoltStringLiteral(value: any): value is BoltStringLiteral; export function isBoltIntegerLiteral(value: any): value is BoltIntegerLiteral; export function isBoltSymbol(value: any): value is BoltSymbol; export function isBoltIdentifier(value: any): value is BoltIdentifier; +export function isBoltOperatorLike(value: any): value is BoltOperatorLike; export function isBoltOperator(value: any): value is BoltOperator; export function isBoltAssignment(value: any): value is BoltAssignment; export function isBoltComma(value: any): value is BoltComma; export function isBoltSemi(value: any): value is BoltSemi; export function isBoltColon(value: any): value is BoltColon; +export function isBoltColonColon(value: any): value is BoltColonColon; export function isBoltDot(value: any): value is BoltDot; export function isBoltDotDot(value: any): value is BoltDotDot; export function isBoltRArrow(value: any): value is BoltRArrow; @@ -1671,7 +1734,9 @@ export function isBoltRArrowAlt(value: any): value is BoltRArrowAlt; 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 isBoltExMark(value: any): value is BoltExMark; export function isBoltLtSign(value: any): value is BoltLtSign; +export function isBoltVBar(value: any): value is BoltVBar; export function isBoltKeyword(value: any): value is BoltKeyword; export function isBoltQuoteKeyword(value: any): value is BoltQuoteKeyword; export function isBoltFnKeyword(value: any): value is BoltFnKeyword; @@ -1712,6 +1777,7 @@ 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 isBoltFunctionExpression(value: any): value is BoltFunctionExpression; export function isBoltCallExpression(value: any): value is BoltCallExpression; export function isBoltYieldExpression(value: any): value is BoltYieldExpression; export function isBoltMatchArm(value: any): value is BoltMatchArm; diff --git a/src/emitter.ts b/src/emitter.ts index 404ce562f..b48e5b5e1 100644 --- a/src/emitter.ts +++ b/src/emitter.ts @@ -3,12 +3,37 @@ import { Syntax, SyntaxKind, kindToString } from "./ast" export class Emitter { - emit(node: Syntax) { + public emit(node: Syntax) { let out = ''; switch (node.kind) { + case SyntaxKind.BoltIdentifier: + case SyntaxKind.BoltOperator: + out += node.text; + break; + + case SyntaxKind.BoltGtSign: + out += '>'; + break; + + case SyntaxKind.BoltLtSign: + out += '<'; + break; + + case SyntaxKind.BoltEqSign: + out += '='; + break; + + case SyntaxKind.BoltVBar: + out += '|'; + break; + + case SyntaxKind.BoltExMark: + out += '!'; + break; + case SyntaxKind.JSExpressionStatement: out += this.emit(node.expression) + ';\n'; break; @@ -54,6 +79,7 @@ export class Emitter { return out; } + } /** diff --git a/src/parser.ts b/src/parser.ts index b47a37433..659ec679f 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -77,6 +77,11 @@ import { BoltQuoteExpression, BoltBlockExpression, createBoltBlockExpression, + isBoltOperatorLike, + BoltFunctionExpression, + createBoltFunctionExpression, + BoltMacroCall, + createBoltMacroCall, } from "./ast" import { parseForeignLanguage } from "./foreign" @@ -112,6 +117,7 @@ const KIND_EXPRESSION_T0 = [ SyntaxKind.BoltIntegerLiteral, SyntaxKind.BoltIdentifier, SyntaxKind.BoltOperator, + SyntaxKind.BoltVBar, SyntaxKind.BoltMatchKeyword, SyntaxKind.BoltQuoteKeyword, SyntaxKind.BoltYieldKeyword, @@ -146,6 +152,10 @@ const KIND_SOURCEELEMENT_T0 = uniq([ ...KIND_DECLARATION_T0, ]) +function isRightAssoc(kind: OperatorKind): boolean { + return kind === OperatorKind.InfixR; +} + export class Parser { exprOperatorTable = new OperatorTable([ @@ -187,6 +197,31 @@ export class Parser { return (this as any)['parse' + kindToString(kind).substring('Bolt'.length)](tokens); } + public parseNamespacePath(tokens: BoltTokenStream): BoltQualName { + + let modulePath = null; + + if (tokens.peek(2).kind === SyntaxKind.BoltColonColon) { + modulePath = []; + while (true) { + modulePath.push(tokens.get() as BoltIdentifier) + tokens.get(); + const t0 = tokens.peek(2); + if (t0.kind !== SyntaxKind.BoltColonColon) { + break; + } + } + } + + const name = tokens.get(); + assertToken(name, SyntaxKind.BoltIdentifier); + const startNode = modulePath !== null ? modulePath[0] : name; + const endNode = name; + const node = createBoltQualName(modulePath, name as BoltIdentifier, null); + setOrigNodeRange(node, startNode, endNode); + return node; + } + public parseQualName(tokens: BoltTokenStream): BoltQualName { let modulePath = null; @@ -222,7 +257,7 @@ export class Parser { public parseRecordPattern(tokens: BoltTokenStream): BoltRecordPattern { - const name = this.parseQualName(tokens); + const name = this.parseNamespacePath(tokens); const t1 = tokens.get(); assertToken(t1, SyntaxKind.BoltBraced); @@ -345,7 +380,7 @@ export class Parser { public parseReferenceTypeExpression(tokens: BoltTokenStream): BoltReferenceTypeExpression { - const name = this.parseQualName(tokens) + const name = this.parseNamespacePath(tokens) const t1 = tokens.peek(); @@ -391,10 +426,10 @@ export class Parser { private parseTypeExpressionOperators(tokens: BoltTokenStream, lhs: BoltTypeExpression, minPrecedence: number): BoltTypeExpression { while (true) { const t0 = tokens.peek(); - if (t0.kind !== SyntaxKind.BoltOperator) { + if (!isBoltOperatorLike(t0)) { break; } - let desc0 = this.typeOperatorTable.lookup(t0.text); + let desc0 = this.typeOperatorTable.lookup(emit(t0)); if (desc0 === null || desc0.arity !== 2 || desc0.precedence < minPrecedence) { break; } @@ -403,10 +438,10 @@ export class Parser { let rhs = this.parsePrimTypeExpression(tokens); while (true) { const t1 = tokens.peek() - if (t1.kind !== SyntaxKind.BoltOperator) { + if (!isBoltOperatorLike(t1.kind)) { break; } - const desc1 = this.typeOperatorTable.lookup(t1.text) + const desc1 = this.typeOperatorTable.lookup(emit(t1)) if (desc1 === null || desc1.arity !== 2 || desc1.precedence < desc0.precedence || !isRightAssoc(desc1.kind)) { break; } @@ -440,8 +475,43 @@ export class Parser { return node; } + public parseFunctionExpression(tokens: BoltTokenStream): BoltFunctionExpression { + const t0 = tokens.get(); + assertToken(t0, SyntaxKind.BoltVBar); + let i = 0; + const params: BoltParameter[] = []; + while (true) { + const t1 = tokens.peek(); + if (t1.kind === SyntaxKind.BoltVBar) { + tokens.get(); + break; + } + const param = this.parseParameter(tokens, i++); + params.push(param); + const t2 = tokens.peek(); + if (t2.kind === SyntaxKind.BoltVBar) { + tokens.get(); + break; + } + const t3 = tokens.get(); + assertToken(t3, SyntaxKind.BoltComma); + } + let returnType = null; + let t4 = tokens.get(); + if (t4.kind === SyntaxKind.BoltRArrow) { + returnType = this.parseTypeExpression(tokens); + t4 = tokens.get(); + } + assertToken(t4, SyntaxKind.BoltBraced); + const innerTokens = createTokenStream(t4); + const body = this.parseFunctionBodyElements(innerTokens); + const result = createBoltFunctionExpression(params, returnType, body); + setOrigNodeRange(result, t0, t4); + return result; + } + public parseReferenceExpression(tokens: BoltTokenStream): BoltReferenceExpression { - const name = this.parseQualName(tokens); + const name = this.parseNamespacePath(tokens); const node = createBoltReferenceExpression(name); setOrigNodeRange(node, name, name); return node; @@ -526,7 +596,9 @@ export class Parser { private parsePrimitiveExpression(tokens: BoltTokenStream): BoltExpression { const t0 = tokens.peek(); - if (t0.kind === SyntaxKind.BoltBraced) { + if (t0.kind === SyntaxKind.BoltVBar) { + return this.parseFunctionExpression(tokens); + } else if (t0.kind === SyntaxKind.BoltBraced) { return this.parseBlockExpression(tokens); } else if (t0.kind === SyntaxKind.BoltQuoteKeyword) { return this.parseQuoteExpression(tokens); @@ -649,6 +721,9 @@ export class Parser { } public parseStatement(tokens: BoltTokenStream): BoltStatement { + if (this.lookaheadIsMacroCall(tokens)) { + return this.parseMacroCall(tokens); + } const t0 = tokens.peek(); if (KIND_EXPRESSION_T0.indexOf(t0.kind) !== -1) { return this.parseExpressionStatement(tokens); @@ -807,7 +882,7 @@ export class Parser { throw new ParseError(t0, [SyntaxKind.BoltModKeyword]) } - const name = this.parseQualName(tokens); + const name = this.parseNamespacePath(tokens); const t1 = tokens.get(); if (t1.kind !== SyntaxKind.BoltBraced) { @@ -1133,15 +1208,26 @@ export class Parser { return t0; } + private lookaheadIsMacroCall(tokens: BoltTokenStream): boolean { + return tokens.peek(1).kind === SyntaxKind.BoltIdentifier + && tokens.peek(2).kind === SyntaxKind.BoltExMark; + } + public parseSourceElement(tokens: BoltTokenStream): BoltSourceElement { + if (this.lookaheadIsMacroCall(tokens)) { + return this.parseMacroCall(tokens); + } const t0 = this.getFirstTokenAfterModifiers(tokens); if (KIND_STATEMENT_T0.indexOf(t0.kind) !== -1) { return this.parseStatement(tokens); } - return this.parseDeclaration(tokens) + return this.parseDeclaration(tokens); } public parseFunctionBodyElement(tokens: BoltTokenStream): BoltFunctionBodyElement { + if (this.lookaheadIsMacroCall(tokens)) { + return this.parseMacroCall(tokens); + } const t0 = this.getFirstTokenAfterModifiers(tokens); if (KIND_STATEMENT_T0.indexOf(t0.kind) !== -1) { return this.parseStatement(tokens); @@ -1154,6 +1240,20 @@ export class Parser { } } + public parseMacroCall(tokens: BoltTokenStream): BoltMacroCall { + const t0 = tokens.get(); + assertToken(t0, SyntaxKind.BoltIdentifier); + const t1 = tokens.get(); + assertToken(t1, SyntaxKind.BoltExMark); + const t2 = tokens.get(); + if (!isBoltPunctuated(t2)) { + throw new ParseError(t2, [SyntaxKind.BoltBraced, SyntaxKind.BoltParenthesized, SyntaxKind.BoltBracketed]); + } + const result = createBoltMacroCall(t0 as BoltIdentifier, t2.text); + setOrigNodeRange(result, t0, t2); + return result; + } + public parseFunctionBodyElements(tokens: BoltTokenStream): BoltFunctionBodyElement[] { const elements: BoltFunctionBodyElement[] = [] while (true) { @@ -1389,6 +1489,7 @@ import { Scanner } from "./scanner" import { TextFile, TextSpan, TextPos } from "./text" import * as fs from "fs" import {JSScanner} from "./foreign/js/scanner"; +import {emit} from "./emitter"; export function parseSourceFile(filepath: string): BoltSourceFile { const file = new TextFile(filepath); diff --git a/src/scanner.ts b/src/scanner.ts index 4ee7de37f..c5d9b5f3a 100644 --- a/src/scanner.ts +++ b/src/scanner.ts @@ -48,6 +48,9 @@ import { createBoltMatchKeyword, createBoltQuoteKeyword, createBoltLetKeyword, + createBoltVBar, + createBoltColonColon, + createBoltExMark, } from "./ast" export enum PunctType { @@ -210,6 +213,10 @@ export class Scanner { return createBoltComma(new TextSpan(this.file, startPos, this.currPos.clone())); case ':': this.getChar(); + if (this.peekChar() === ':') { + this.getChar(); + return createBoltColonColon(new TextSpan(this.file, startPos, this.currPos.clone())); + } return createBoltColon(new TextSpan(this.file, startPos, this.currPos.clone())); } @@ -318,6 +325,8 @@ export class Scanner { const span = new TextSpan(this.file, startPos, endPos); switch (text) { + case '!': return createBoltExMark(span); + case '|': return createBoltVBar(span); case '->': return createBoltRArrow(span); case '=>': return createBoltRArrowAlt(span); case '<-': return createBoltLArrow(span); diff --git a/src/util.ts b/src/util.ts index 0697f501d..13fc27e6e 100644 --- a/src/util.ts +++ b/src/util.ts @@ -237,6 +237,8 @@ export function getFileStem(filepath: string): string { export function describeKind(kind: SyntaxKind): string { switch (kind) { + case SyntaxKind.BoltExMark: + return "'!'"; case SyntaxKind.JSIdentifier: return "a JavaScript identifier" case SyntaxKind.BoltIdentifier: @@ -269,6 +271,8 @@ export function describeKind(kind: SyntaxKind): string { return "';'" case SyntaxKind.BoltColon: return "':'" + case SyntaxKind.BoltColonColon: + return "'::'"; case SyntaxKind.BoltDot: return "'.'" case SyntaxKind.JSDot: @@ -277,6 +281,8 @@ export function describeKind(kind: SyntaxKind): string { return "'...'" case SyntaxKind.BoltRArrow: return "'->'" + case SyntaxKind.BoltVBar: + return "'|'"; case SyntaxKind.BoltComma: return "','" case SyntaxKind.BoltModKeyword: