UNPKG

@erml/parser

Version:

Parser implementation of ERML

98 lines (97 loc) 4.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.testables = exports.walkPipeline = exports.processBody = exports.processIdentifier = exports.processStringLiteral = exports.processNumber = exports.assertToken = void 0; var identifiers_1 = require("./identifiers"); var lexer_1 = require("../lexer"); var _1 = require("."); function assertToken(token, expectedValues, callback) { var matchedIndex = expectedValues.indexOf(token.value); if (matchedIndex < 0) { throw new SyntaxError("Expected to find " + expectedValues .map(function (value) { return "'" + value + "'"; }) .join(", ") + " at position " + token.position + ", line " + token.line + ". Instead found '" + token.value + "'"); } if (callback) { callback(matchedIndex); } } exports.assertToken = assertToken; function processNumber(token, range, callback) { var numberValue = Number(token.value); if (isNaN(numberValue)) { throw new TypeError("'" + token.value + "' at position " + token.position + ", line " + token.line + " is not a valid number"); } else if (numberValue < range[0] || numberValue > range[1]) { throw new RangeError("'" + token.value + "' at position " + token.position + ", line " + token.line + " doesn't fall in the range of [" + range[0] + ", " + range[1] + "]"); } callback(numberValue); } exports.processNumber = processNumber; function processStringLiteral(token, callback) { var match = lexer_1.stringLiteralRegexp.exec(token.value); if (match === null) { throw new TypeError("'" + token.value + "' at position " + token.position + ", line " + token.line + " is not a valid string"); } var stringValue = match[1].replace(/\\\\|\\/g, function (match) { return match === "\\\\" ? "\\" : ""; }); callback(stringValue); } exports.processStringLiteral = processStringLiteral; function processIdentifier(token, isReference, callback) { if ((0, identifiers_1.isValidIdentifier)(token.value) === false) { throw new SyntaxError("'" + token.value + "' at position " + token.position + ", line " + token.line + " is not a valid identifier"); } else if (isReference && (0, identifiers_1.isValidReference)(token.value) === false) { throw new ReferenceError("'" + token.value + "' at position " + token.position + ", line " + token.line + " is not defined before"); } else if (isReference === false && (0, identifiers_1.isDuplicateIdentifier)(token.value)) { throw new SyntaxError("'" + token.value + "' at position " + token.position + ", line " + token.line + " is already defined"); } callback(); } exports.processIdentifier = processIdentifier; function processBody(tokens, tokenIndex, callback) { assertToken(tokens[tokenIndex], [_1.Delimiters.OPENING_BRACE]); var closingBracePosition = bracesMatchAt(tokens, tokenIndex); if (closingBracePosition === null) { throw new SyntaxError("Grouping symbols (\"" + _1.Delimiters.OPENING_BRACE + "\" and \"" + _1.Delimiters.CLOSING_BRACE + "\") don't match after \"" + _1.Delimiters.OPENING_BRACE + "\" at position " + tokens[tokenIndex].position + ", line " + tokens[tokenIndex].line); } var bodyStart = tokenIndex + 1; var bodyEnd = closingBracePosition - 1; if (bodyStart > bodyEnd) { throw new SyntaxError("Body can't be empty at position " + tokens[tokenIndex].position + ", line " + tokens[tokenIndex].line); } callback(bodyStart, bodyEnd); return closingBracePosition; } exports.processBody = processBody; function walkPipeline(parsingPipeline, tokens, currentTokenIndex) { for (var _i = 0, parsingPipeline_1 = parsingPipeline; _i < parsingPipeline_1.length; _i++) { var process_1 = parsingPipeline_1[_i]; if (tokens[currentTokenIndex] === undefined) { var previousToken = tokens[currentTokenIndex - 1]; throw new SyntaxError("Didn't expect to reach the end after token '" + previousToken.value + "' at position " + previousToken.position + ", line " + previousToken.line); } var bodyEnd = process_1(tokens[currentTokenIndex], currentTokenIndex); currentTokenIndex = (bodyEnd ? bodyEnd : currentTokenIndex) + 1; } return currentTokenIndex; } exports.walkPipeline = walkPipeline; function bracesMatchAt(tokens, currentPosition) { var scales = 0; do { scales += tokens[currentPosition].value === _1.Delimiters.OPENING_BRACE ? 1 : tokens[currentPosition].value === _1.Delimiters.CLOSING_BRACE ? -1 : 0; if (scales === 0) { return currentPosition; } } while (++currentPosition < tokens.length); return null; } exports.testables = { bracesMatchAt: bracesMatchAt };