UNPKG

greyscript-core

Version:
212 lines (211 loc) 9.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const miniscript_core_1 = require("miniscript-core"); const greybel_core_1 = require("greybel-core"); const position_1 = require("miniscript-core/dist/types/position"); const range_1 = require("miniscript-core/dist/types/range"); const ast_1 = require("./parser/ast"); const lexer_1 = __importDefault(require("./lexer")); const keywords_1 = require("./types/keywords"); class Parser extends greybel_core_1.Parser { constructor(content, options = {}) { options.lexer = options.lexer || new lexer_1.default(content, { unsafe: options.unsafe, tabWidth: options.tabWidth }); options.astProvider = options.astProvider || new ast_1.ASTProvider(); super(content, options); const me = this; me.nativeImports = []; } parseStatement() { const me = this; if (me.isType(miniscript_core_1.TokenType.Keyword)) { const value = me.token.value; switch (value) { case keywords_1.GreyScriptKeyword.ImportCode: me.next(); const item = me.parseNativeImportCodeStatement(); me.lineRegistry.addItemToLines(item); me.backpatches.peek().body.push(item); return; default: break; } } return super.parseStatement(); } parseFunctionDeclaration(base, asLval = false, statementStart = false) { const me = this; if (!greybel_core_1.Selectors.Function(me.token)) return me.parseOr(asLval, statementStart); me.next(); const functionStartToken = me.previousToken; const functionStatement = me.astProvider.functionStatement({ start: functionStartToken.start, end: null, range: [functionStartToken.range[0], null], scope: me.currentScope, parent: me.outerScopes[me.outerScopes.length - 1], assignment: me.currentAssignment }); const parameters = []; me.pushScope(functionStatement); if (!greybel_core_1.SelectorGroups.BlockEndOfLine(me.token)) { me.requireToken(greybel_core_1.Selectors.LParenthesis, functionStartToken.start); while (!greybel_core_1.SelectorGroups.FunctionDeclarationArgEnd(me.token)) { const parameter = me.parseIdentifier(miniscript_core_1.ASTIdentifierKind.Argument); const parameterStartToken = parameter; if (me.consume(greybel_core_1.Selectors.Assign)) { const defaultValue = me.parseExpr(null); const assign = me.astProvider.assignmentStatement({ variable: parameter, init: defaultValue, start: parameterStartToken.start, end: me.previousToken.end, range: [parameterStartToken.range[0], me.previousToken.range[1]], scope: me.currentScope }); me.currentScope.definitions.push(assign); parameters.push(assign); } else { const assign = me.astProvider.assignmentStatement({ variable: parameter, init: me.astProvider.unknown({ start: parameterStartToken.start, end: me.previousToken.end, range: [parameterStartToken.range[0], me.previousToken.range[1]], scope: me.currentScope }), start: parameterStartToken.start, end: me.previousToken.end, range: [parameterStartToken.range[0], me.previousToken.range[1]], scope: me.currentScope }); me.currentScope.definitions.push(assign); parameters.push(parameter); } if (greybel_core_1.Selectors.RParenthesis(me.token)) break; me.requireToken(greybel_core_1.Selectors.ArgumentSeperator, functionStartToken.start); if (greybel_core_1.Selectors.RParenthesis(me.token)) { me.raise('expected argument instead received right parenthesis', new range_1.Range(me.previousToken.end, me.previousToken.end)); break; } } me.requireToken(greybel_core_1.Selectors.RParenthesis, functionStartToken.start); } functionStatement.parameters = parameters; const pendingBlock = new miniscript_core_1.PendingFunction(functionStatement, base, me.lineRegistry); me.backpatches.push(pendingBlock); return functionStatement; } parseNativeImportCodeStatement() { var _a, _b, _c, _d; const me = this; const startToken = me.previousToken; if (!me.consume(greybel_core_1.Selectors.LParenthesis)) { me.raise(`expected import_code to have opening parenthesis`, new range_1.Range(startToken.start, new position_1.Position((_a = me.token.lastLine) !== null && _a !== void 0 ? _a : me.token.line, me.token.end.character))); return me.parseInvalidCode(); } let directory; if (me.isType(miniscript_core_1.TokenType.StringLiteral)) { directory = me.token.value; me.next(); } else { me.raise(`expected import_code argument to be string literal`, new range_1.Range(startToken.start, new position_1.Position((_b = me.token.lastLine) !== null && _b !== void 0 ? _b : me.token.line, me.token.end.character))); return me.parseInvalidCode(); } if (me.consume(greybel_core_1.Selectors.ImportCodeSeperator)) { if (!me.isType(miniscript_core_1.TokenType.StringLiteral)) { me.raise(`expected import_code argument to be string literal`, new range_1.Range(startToken.start, new position_1.Position((_c = me.token.lastLine) !== null && _c !== void 0 ? _c : me.token.line, me.token.end.character))); return me.parseInvalidCode(); } directory = me.token.value; console.warn(`Warning: Second import_code argument is deprecated. Use the first argument for the file system path instead.`); me.next(); } if (!me.consume(greybel_core_1.Selectors.RParenthesis)) { me.raise(`expected import_code to have closing parenthesis`, new range_1.Range(startToken.start, new position_1.Position((_d = me.token.lastLine) !== null && _d !== void 0 ? _d : me.token.line, me.token.end.character))); return me.parseInvalidCode(); } const endToken = me.previousToken; let currentDirectory = directory; let shouldEmit = true; let shouldEval = true; if (me.isType(miniscript_core_1.TokenType.Comment)) { const options = ast_1.ASTImportCodeExpression.parseMetaOptions(me.token.value); shouldEmit = options.emit; shouldEval = options.eval; if (options.directory) { currentDirectory = options.directory; } } const base = me.astProvider.importCodeExpression({ originalDirectory: directory, directory: currentDirectory, emit: shouldEmit, eval: shouldEval, start: startToken.start, end: endToken.end, range: [startToken.range[0], endToken.range[1]], scope: me.currentScope }); me.nativeImports.push(base); return base; } parseChunk() { const me = this; me.next(); const startToken = me.token; const chunk = me.astProvider.chunk({ start: startToken.start, end: null, range: [startToken.range[0], null] }); const pending = new miniscript_core_1.PendingChunk(chunk, me.lineRegistry); me.backpatches.setDefault(pending); me.pushScope(chunk); while (!greybel_core_1.Selectors.EndOfFile(me.token)) { me.skipNewlines(); if (greybel_core_1.Selectors.EndOfFile(me.token)) break; me.lexer.recordSnapshot(); me.statementErrors = []; me.parseStatement(); if (me.statementErrors.length > 0) { me.tryToRecover(); } } let last = me.backpatches.pop(); while (!(0, miniscript_core_1.isPendingChunk)(last)) { const exception = me.raise(`found open block ${last.block.type}`, new range_1.Range(last.block.start, last.block.start)); last.complete(me.previousToken); me.errors.push(exception); if (!me.unsafe) { throw exception; } last = me.backpatches.pop(); } me.finishRemaingScopes(); me.popScope(); pending.complete(me.token); chunk.literals = me.literals; chunk.comments = me.comments; chunk.scopes = me.scopes; chunk.lines = me.lineRegistry.lines; chunk.nativeImports = me.nativeImports; chunk.imports = me.imports; chunk.includes = me.includes; chunk.injects = me.injects; return chunk; } } exports.default = Parser;