'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); /** * Returns a new set representing the union of a and b. */ function union(a, b) { var s = new Set(a); addAll(s, b); return s; } /** * Adds all items from the set b to a. */ function addAll(a, b) { for (var x of b) { a.add(x); } } /** * Returns whether two sets are equal */ function equal(a, b) { if (a === b) return true; if (a.size !== b.size) return false; for (var x of a) { if (!b.has(x)) { return false; } } return true; } /** * Base AST node */ class Node { constructor() { Object.defineProperty(this, 'followpos', { value: new Set() }); } calcFollowpos() { for (var key in this) { if (this[key] instanceof Node) { this[key].calcFollowpos(); } } } } /** * Represents a variable reference */ class Variable extends Node { constructor(name) { super(); this.name = name; } copy() { return new Variable(this.name); } } /** * Represents a comment */ class Comment extends Node { constructor(value) { super(); this.value = value; } } /** * Represents an assignment statement. * e.g. `variable = expression;` */ class Assignment extends Node { constructor(variable, expression) { super(); this.variable = variable; this.expression = expression; } } /** * Represents an alternation. * e.g. `a | b` */ class Alternation extends Node { constructor(a, b) { super(); this.a = a; this.b = b; } get nullable() { return this.a.nullable || this.b.nullable; } get firstpos() { return union(this.a.firstpos, this.b.firstpos); } get lastpos() { return union(this.a.lastpos, this.b.lastpos); } copy() { return new Alternation(this.a.copy(), this.b.copy()); } } /** * Represents a concatenation, or chain. * e.g. `a b c` */ class Concatenation extends Node { constructor(a, b) { super(); this.a = a; this.b = b; } get nullable() { return this.a.nullable && this.b.nullable; } get firstpos() { var s = this.a.firstpos; if (this.a.nullable) { s = union(s, this.b.firstpos); } return s; } get lastpos() { var s = this.b.lastpos; if (this.b.nullable) { s = union(s, this.a.lastpos); } return s; } calcFollowpos() { super.calcFollowpos(); for (var n of this.a.lastpos) { addAll(n.followpos, this.b.firstpos); } } copy() { return new Concatenation(this.a.copy(), this.b.copy()); } } /** * Represents a repetition. * e.g. `a+`, `b*`, or `c?` */ class Repeat extends Node { constructor(expression, op) { super(); this.expression = expression; this.op = op; } get nullable() { return this.op === '*' || this.op === '?'; } get firstpos() { return this.expression.firstpos; } get lastpos() { return this.expression.lastpos; } calcFollowpos() { super.calcFollowpos(); if (this.op === '*' || this.op === '+') { for (var n of this.lastpos) { addAll(n.followpos, this.firstpos); } } } copy() { return new Repeat(this.expression.copy(), this.op); } } function buildRepetition(expression, min = 0, max = Infinity) { if (min < 0 || min > max) { throw new Error("Invalid repetition range: ".concat(min, " ").concat(max)); } var res = null; for (var i = 0; i < min; i++) { res = concat(res, expression.copy()); } if (max === Infinity) { res = concat(res, new Repeat(expression.copy(), '*')); } else { for (var _i = min; _i < max; _i++) { res = concat(res, new Repeat(expression.copy(), '?')); } } return res; } function concat(a, b) { if (!a) { return b; } return new Concatenation(a, b); } /** * Base class for leaf nodes */ class Leaf extends Node { get nullable() { return false; } get firstpos() { return new Set([this]); } get lastpos() { return new Set([this]); } } /** * Represents a literal value, e.g. a number */ class Literal extends Leaf { constructor(value) { super(); this.value = value; } copy() { return new Literal(this.value); } } /** * Marks the end of an expression */ class EndMarker extends Leaf {} /** * Represents a tag * e.g. `a:(a b)` */ class Tag extends Leaf { constructor(name) { super(); this.name = name; } get nullable() { return true; } copy() { return new Tag(this.name); } } var nodes = /*#__PURE__*/Object.freeze({ Node: Node, Variable: Variable, Comment: Comment, Assignment: Assignment, Alternation: Alternation, Concatenation: Concatenation, Repeat: Repeat, buildRepetition: buildRepetition, Literal: Literal, EndMarker: EndMarker, Tag: Tag }); function peg$subclass(child, parent) { function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); } function peg$SyntaxError(message, expected, found, location) { this.message = message; this.expected = expected; this.found = found; this.location = location; this.name = "SyntaxError"; if (typeof Error.captureStackTrace === "function") { Error.captureStackTrace(this, peg$SyntaxError); } } peg$subclass(peg$SyntaxError, Error); peg$SyntaxError.buildMessage = function (expected, found) { var DESCRIBE_EXPECTATION_FNS = { literal: function (expectation) { return "\"" + literalEscape(expectation.text) + "\""; }, "class": function (expectation) { var escapedParts = "", i; for (i = 0; i < expectation.parts.length; i++) { escapedParts += expectation.parts[i] instanceof Array ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1]) : classEscape(expectation.parts[i]); } return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; }, any: function (expectation) { return "any character"; }, end: function (expectation) { return "end of input"; }, other: function (expectation) { return expectation.description; } }; function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } function literalEscape(s) { return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\0/g, '\\0').replace(/\t/g, '\\t').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/[\x00-\x0F]/g, function (ch) { return '\\x0' + hex(ch); }).replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) { return '\\x' + hex(ch); }); } function classEscape(s) { return s.replace(/\\/g, '\\\\').replace(/\]/g, '\\]').replace(/\^/g, '\\^').replace(/-/g, '\\-').replace(/\0/g, '\\0').replace(/\t/g, '\\t').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/[\x00-\x0F]/g, function (ch) { return '\\x0' + hex(ch); }).replace(/[\x10-\x1F\x7F-\x9F]/g, function (ch) { return '\\x' + hex(ch); }); } function describeExpectation(expectation) { return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); } function describeExpected(expected) { var descriptions = new Array(expected.length), i, j; for (i = 0; i < expected.length; i++) { descriptions[i] = describeExpectation(expected[i]); } descriptions.sort(); if (descriptions.length > 0) { for (i = 1, j = 1; i < descriptions.length; i++) { if (descriptions[i - 1] !== descriptions[i]) { descriptions[j] = descriptions[i]; j++; } } descriptions.length = j; } switch (descriptions.length) { case 1: return descriptions[0]; case 2: return descriptions[0] + " or " + descriptions[1]; default: return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1]; } } function describeFound(found) { return found ? "\"" + literalEscape(found) + "\"" : "end of input"; } return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; }; function peg$parse(input, options) { options = options !== void 0 ? options : {}; var peg$FAILED = {}, peg$startRuleFunctions = { rules: peg$parserules }, peg$startRuleFunction = peg$parserules, peg$c0 = function (s) { return s; }, peg$c1 = "#", peg$c2 = peg$literalExpectation("#", false), peg$c3 = /^[^\r\n]/, peg$c4 = peg$classExpectation(["\r", "\n"], true, false), peg$c5 = /^[\r\n]/, peg$c6 = peg$classExpectation(["\r", "\n"], false, false), peg$c7 = function (v) { return new n.Comment(v.join('')); }, peg$c8 = "=", peg$c9 = peg$literalExpectation("=", false), peg$c10 = ";", peg$c11 = peg$literalExpectation(";", false), peg$c12 = function (v, e) { return new n.Assignment(v, e); }, peg$c13 = function (v) { return new n.Variable(v); }, peg$c14 = "|", peg$c15 = peg$literalExpectation("|", false), peg$c16 = function (a, b) { return new n.Alternation(a, b); }, peg$c17 = function (a, b) { return new n.Concatenation(a, b); }, peg$c18 = ":", peg$c19 = peg$literalExpectation(":", false), peg$c20 = function (t, e) { return new n.Concatenation(e, new n.Tag(t)); }, peg$c21 = "*", peg$c22 = peg$literalExpectation("*", false), peg$c23 = function (t) { return new n.Repeat(t, '*'); }, peg$c24 = "?", peg$c25 = peg$literalExpectation("?", false), peg$c26 = function (t) { return new n.Repeat(t, '?'); }, peg$c27 = "+", peg$c28 = peg$literalExpectation("+", false), peg$c29 = function (t) { return new n.Repeat(t, '+'); }, peg$c30 = "{", peg$c31 = peg$literalExpectation("{", false), peg$c32 = "}", peg$c33 = peg$literalExpectation("}", false), peg$c34 = function (t, m) { return n.buildRepetition(t, m, m); }, peg$c35 = ",", peg$c36 = peg$literalExpectation(",", false), peg$c37 = function (t, min) { return n.buildRepetition(t, min, Infinity); }, peg$c38 = function (t, max) { return n.buildRepetition(t, 0, max); }, peg$c39 = function (t, min, max) { return n.buildRepetition(t, min, max); }, peg$c40 = function (x) { return new n.Literal(x); }, peg$c41 = "(", peg$c42 = peg$literalExpectation("(", false), peg$c43 = ")", peg$c44 = peg$literalExpectation(")", false), peg$c45 = function (e) { return e; }, peg$c47 = function (a, b) { return a + b.join(''); }, peg$c48 = "_", peg$c49 = peg$literalExpectation("_", false), peg$c50 = /^[a-zA-Z]/, peg$c51 = peg$classExpectation([["a", "z"], ["A", "Z"]], false, false), peg$c52 = /^[0-9]/, peg$c53 = peg$classExpectation([["0", "9"]], false, false), peg$c54 = function (num) { return parseInt(num.join('')); }, peg$c55 = /^[ \t\r\n]/, peg$c56 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false), peg$currPos = 0, peg$posDetailsCache = [{ line: 1, column: 1 }], peg$maxFailPos = 0, peg$maxFailExpected = [], peg$result; if ("startRule" in options) { if (!(options.startRule in peg$startRuleFunctions)) { throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); } peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; } function peg$literalExpectation(text, ignoreCase) { return { type: "literal", text: text, ignoreCase: ignoreCase }; } function peg$classExpectation(parts, inverted, ignoreCase) { return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase }; } function peg$endExpectation() { return { type: "end" }; } function peg$computePosDetails(pos) { var details = peg$posDetailsCache[pos], p; if (details) { return details; } else { p = pos - 1; while (!peg$posDetailsCache[p]) { p--; } details = peg$posDetailsCache[p]; details = { line: details.line, column: details.column }; while (p < pos) { if (input.charCodeAt(p) === 10) { details.line++; details.column = 1; } else { details.column++; } p++; } peg$posDetailsCache[pos] = details; return details; } } function peg$computeLocation(startPos, endPos) { var startPosDetails = peg$computePosDetails(startPos), endPosDetails = peg$computePosDetails(endPos); return { start: { offset: startPos, line: startPosDetails.line, column: startPosDetails.column }, end: { offset: endPos, line: endPosDetails.line, column: endPosDetails.column } }; } function peg$fail(expected) { if (peg$currPos < peg$maxFailPos) { return; } if (peg$currPos > peg$maxFailPos) { peg$maxFailPos = peg$currPos; peg$maxFailExpected = []; } peg$maxFailExpected.push(expected); } function peg$buildStructuredError(expected, found, location) { return new peg$SyntaxError(peg$SyntaxError.buildMessage(expected, found), expected, found, location); } function peg$parserules() { var s0, s1; s0 = []; s1 = peg$parsestatement(); if (s1 !== peg$FAILED) { while (s1 !== peg$FAILED) { s0.push(s1); s1 = peg$parsestatement(); } } else { s0 = peg$FAILED; } return s0; } function peg$parsestatement() { var s0, s1, s2; s0 = peg$currPos; s1 = peg$parsestatement_type(); if (s1 !== peg$FAILED) { s2 = peg$parse_(); if (s2 !== peg$FAILED) { s1 = peg$c0(s1); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } return s0; } function peg$parsestatement_type() { var s0; s0 = peg$parseassignment(); if (s0 === peg$FAILED) { s0 = peg$parsecomment(); } return s0; } function peg$parsecomment() { var s0, s1, s2, s3; s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 35) { s1 = peg$c1; peg$currPos++; } else { s1 = peg$FAILED; { peg$fail(peg$c2); } } if (s1 !== peg$FAILED) { s2 = []; if (peg$c3.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { peg$fail(peg$c4); } } while (s3 !== peg$FAILED) { s2.push(s3); if (peg$c3.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { peg$fail(peg$c4); } } } if (s2 !== peg$FAILED) { if (peg$c5.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; { peg$fail(peg$c6); } } if (s3 !== peg$FAILED) { s1 = peg$c7(s2); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } return s0; } function peg$parseassignment() { var s0, s1, s2, s3, s4, s5, s6, s7; s0 = peg$currPos; s1 = peg$parsevariable(); if (s1 !== peg$FAILED) { s2 = peg$parse_(); if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 61) { s3 = peg$c8; peg$currPos++; } else { s3 = peg$FAILED; { peg$fail(peg$c9); } } if (s3 !== peg$FAILED) { s4 = peg$parse_(); if (s4 !== peg$FAILED) { s5 = peg$parsealternation(); if (s5 !== peg$FAILED) { s6 = peg$parse_(); if (s6 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 59) { s7 = peg$c10; peg$currPos++; } else { s7 = peg$FAILED; { peg$fail(peg$c11); } } if (s7 !== peg$FAILED) { s1 = peg$c12(s1, s5); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } return s0; } function peg$parsevariable() { var s0, s1; s0 = peg$currPos; s1 = peg$parsename(); if (s1 !== peg$FAILED) { s1 = peg$c13(s1); } s0 = s1; return s0; } function peg$parsealternation() { var s0, s1, s2, s3, s4, s5; s0 = peg$currPos; s1 = peg$parseconcatenation(); if (s1 !== peg$FAILED) { s2 = peg$parse_(); if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 124) { s3 = peg$c14; peg$currPos++; } else { s3 = peg$FAILED; { peg$fail(peg$c15); } } if (s3 !== peg$FAILED) { s4 = peg$parse_(); if (s4 !== peg$FAILED) { s5 = peg$parsealternation(); if (s5 !== peg$FAILED) { s1 = peg$c16(s1, s5); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } if (s0 === peg$FAILED) { s0 = peg$parseconcatenation(); } return s0; } function peg$parseconcatenation() { var s0, s1, s2, s3; s0 = peg$currPos; s1 = peg$parserepeat(); if (s1 !== peg$FAILED) { s2 = peg$parse_(); if (s2 !== peg$FAILED) { s3 = peg$parseconcatenation(); if (s3 !== peg$FAILED) { s1 = peg$c17(s1, s3); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } if (s0 === peg$FAILED) { s0 = peg$parserepeat(); } return s0; } function peg$parserepeat() { var s0, s1, s2, s3, s4, s5, s6; s0 = peg$currPos; s1 = peg$parsename(); if (s1 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 58) { s2 = peg$c18; peg$currPos++; } else { s2 = peg$FAILED; { peg$fail(peg$c19); } } if (s2 !== peg$FAILED) { s3 = peg$parserepeat(); if (s3 !== peg$FAILED) { s1 = peg$c20(s1, s3); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = peg$parseterm(); if (s1 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 42) { s2 = peg$c21; peg$currPos++; } else { s2 = peg$FAILED; { peg$fail(peg$c22); } } if (s2 !== peg$FAILED) { s1 = peg$c23(s1); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = peg$parseterm(); if (s1 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 63) { s2 = peg$c24; peg$currPos++; } else { s2 = peg$FAILED; { peg$fail(peg$c25); } } if (s2 !== peg$FAILED) { s1 = peg$c26(s1); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = peg$parseterm(); if (s1 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 43) { s2 = peg$c27; peg$currPos++; } else { s2 = peg$FAILED; { peg$fail(peg$c28); } } if (s2 !== peg$FAILED) { s1 = peg$c29(s1); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = peg$parseterm(); if (s1 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 123) { s2 = peg$c30; peg$currPos++; } else { s2 = peg$FAILED; { peg$fail(peg$c31); } } if (s2 !== peg$FAILED) { s3 = peg$parsenumber(); if (s3 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 125) { s4 = peg$c32; peg$currPos++; } else { s4 = peg$FAILED; { peg$fail(peg$c33); } } if (s4 !== peg$FAILED) { s1 = peg$c34(s1, s3); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = peg$parseterm(); if (s1 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 123) { s2 = peg$c30; peg$currPos++; } else { s2 = peg$FAILED; { peg$fail(peg$c31); } } if (s2 !== peg$FAILED) { s3 = peg$parsenumber(); if (s3 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 44) { s4 = peg$c35; peg$currPos++; } else { s4 = peg$FAILED; { peg$fail(peg$c36); } } if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 125) { s5 = peg$c32; peg$currPos++; } else { s5 = peg$FAILED; { peg$fail(peg$c33); } } if (s5 !== peg$FAILED) { s1 = peg$c37(s1, s3); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = peg$parseterm(); if (s1 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 123) { s2 = peg$c30; peg$currPos++; } else { s2 = peg$FAILED; { peg$fail(peg$c31); } } if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 44) { s3 = peg$c35; peg$currPos++; } else { s3 = peg$FAILED; { peg$fail(peg$c36); } } if (s3 !== peg$FAILED) { s4 = peg$parsenumber(); if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 125) { s5 = peg$c32; peg$currPos++; } else { s5 = peg$FAILED; { peg$fail(peg$c33); } } if (s5 !== peg$FAILED) { s1 = peg$c38(s1, s4); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = peg$parseterm(); if (s1 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 123) { s2 = peg$c30; peg$currPos++; } else { s2 = peg$FAILED; { peg$fail(peg$c31); } } if (s2 !== peg$FAILED) { s3 = peg$parsenumber(); if (s3 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 44) { s4 = peg$c35; peg$currPos++; } else { s4 = peg$FAILED; { peg$fail(peg$c36); } } if (s4 !== peg$FAILED) { s5 = peg$parsenumber(); if (s5 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 125) { s6 = peg$c32; peg$currPos++; } else { s6 = peg$FAILED; { peg$fail(peg$c33); } } if (s6 !== peg$FAILED) { s1 = peg$c39(s1, s3, s5); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } if (s0 === peg$FAILED) { s0 = peg$parseterm(); } } } } } } } } return s0; } function peg$parseterm() { var s0, s1, s2, s3; s0 = peg$parsevariable(); if (s0 === peg$FAILED) { s0 = peg$currPos; s1 = peg$parsenumber(); if (s1 !== peg$FAILED) { s1 = peg$c40(s1); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 40) { s1 = peg$c41; peg$currPos++; } else { s1 = peg$FAILED; { peg$fail(peg$c42); } } if (s1 !== peg$FAILED) { s2 = peg$parsealternation(); if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 41) { s3 = peg$c43; peg$currPos++; } else { s3 = peg$FAILED; { peg$fail(peg$c44); } } if (s3 !== peg$FAILED) { s1 = peg$c45(s2); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } } } return s0; } function peg$parsename() { var s0, s1, s2, s3; s0 = peg$currPos; s1 = peg$parsename_start_char(); if (s1 !== peg$FAILED) { s2 = []; s3 = peg$parsename_char(); while (s3 !== peg$FAILED) { s2.push(s3); s3 = peg$parsename_char(); } if (s2 !== peg$FAILED) { s1 = peg$c47(s1, s2); s0 = s1; } else { peg$currPos = s0; s0 = peg$FAILED; } } else { peg$currPos = s0; s0 = peg$FAILED; } return s0; } function peg$parsename_start_char() { var s0; if (input.charCodeAt(peg$currPos) === 95) { s0 = peg$c48; peg$currPos++; } else { s0 = peg$FAILED; { peg$fail(peg$c49); } } if (s0 === peg$FAILED) { if (peg$c50.test(input.charAt(peg$currPos))) { s0 = input.charAt(peg$currPos); peg$currPos++; } else { s0 = peg$FAILED; { peg$fail(peg$c51); } } } return s0; } function peg$parsename_char() { var s0; s0 = peg$parsename_start_char(); if (s0 === peg$FAILED) { if (peg$c52.test(input.charAt(peg$currPos))) { s0 = input.charAt(peg$currPos); peg$currPos++; } else { s0 = peg$FAILED; { peg$fail(peg$c53); } } } return s0; } function peg$parsenumber() { var s0, s1, s2; s0 = peg$currPos; s1 = []; if (peg$c52.test(input.charAt(peg$currPos))) { s2 = input.charAt(peg$currPos); peg$currPos++; } else { s2 = peg$FAILED; { peg$fail(peg$c53); } } if (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) { s1.push(s2); if (peg$c52.test(input.charAt(peg$currPos))) { s2 = input.charAt(peg$currPos); peg$currPos++; } else { s2 = peg$FAILED; { peg$fail(peg$c53); } } } } else { s1 = peg$FAILED; } if (s1 !== peg$FAILED) { s1 = peg$c54(s1); } s0 = s1; return s0; } function peg$parse_() { var s0, s1; s0 = []; if (peg$c55.test(input.charAt(peg$currPos))) { s1 = input.charAt(peg$currPos); peg$currPos++; } else { s1 = peg$FAILED; { peg$fail(peg$c56); } } while (s1 !== peg$FAILED) { s0.push(s1); if (peg$c55.test(input.charAt(peg$currPos))) { s1 = input.charAt(peg$currPos); peg$currPos++; } else { s1 = peg$FAILED; { peg$fail(peg$c56); } } } return s0; } var n = nodes; peg$result = peg$startRuleFunction(); if (peg$result !== peg$FAILED && peg$currPos === input.length) { return peg$result; } else { if (peg$result !== peg$FAILED && peg$currPos < input.length) { peg$fail(peg$endExpectation()); } throw peg$buildStructuredError(peg$maxFailExpected, peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, peg$maxFailPos < input.length ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) : peg$computeLocation(peg$maxFailPos, peg$maxFailPos)); } } var grammar = { SyntaxError: peg$SyntaxError, parse: peg$parse }; /** * Processes a list of statements into a symbol table */ class SymbolTable { constructor(statements, externalSymbols = {}) { this.variables = {}; this.symbols = {}; this.main = null; this.size = 0; this.addExternalSymbols(externalSymbols); this.process(statements); } addExternalSymbols(externalSymbols) { for (var key in externalSymbols) { this.variables[key] = new Literal(externalSymbols[key]); this.symbols[key] = externalSymbols[key]; this.size++; } } process(statements) { for (var statement of statements) { if (statement instanceof Assignment) { this.variables[statement.variable.name] = this.processExpression(statement.expression); if (statement.expression instanceof Literal) { this.symbols[statement.variable.name] = statement.expression.value; this.size++; } } } this.main = this.variables.main; if (!this.main) { throw new Error('No main variable declaration found'); } } processExpression(expr) { // Process children for (var key in expr) { if (expr[key] instanceof Node) { expr[key] = this.processExpression(expr[key]); } } // Replace variable references with their values if (expr instanceof Variable) { var value = this.variables[expr.name]; if (value == null) throw new Error("Undeclared indentifier ".concat(expr.name)); expr = this.processExpression(value.copy()); } return expr; } } var END_MARKER = new EndMarker(); /** * This is an implementation of the direct regular expression to DFA algorithm described * in section 3.9.5 of "Compilers: Principles, Techniques, and Tools" by Aho, * Lam, Sethi, and Ullman. http://dragonbook.stanford.edu * There is a PDF of the book here: * http://www.informatik.uni-bremen.de/agbkb/lehre/ccfl/Material/ALSUdragonbook.pdf */ function buildDFA(root, numSymbols) { root = new Concatenation(root, END_MARKER); root.calcFollowpos(); var failState = new State(new Set(), numSymbols); var initialState = new State(root.firstpos, numSymbols); var dstates = [failState, initialState]; // while there is an unmarked state S in dstates while (1) { var s = null; for (var j = 1; j < dstates.length; j++) { if (!dstates[j].marked) { s = dstates[j]; break; } } if (s == null) { break; } // mark S s.marked = true; // for each input symbol a for (var a = 0; a < numSymbols; a++) { // let U be the union of followpos(p) for all // p in S that correspond to a var u = new Set(); for (var p of s.positions) { if (p instanceof Literal && p.value === a) { addAll(u, p.followpos); } } if (u.size === 0) { continue; } // if U is not in dstates var ux = -1; for (var i = 0; i < dstates.length; i++) { if (equal(u, dstates[i].positions)) { ux = i; break; } } if (ux === -1) { // Add U as an unmarked state to dstates dstates.push(new State(u, numSymbols)); ux = dstates.length - 1; } s.transitions[a] = ux; } } return dstates; } class State { constructor(positions, len) { this.positions = positions; this.transitions = new Uint16Array(len); this.accepting = positions.has(END_MARKER); this.marked = false; this.tags = new Set(); for (var pos of positions) { if (pos instanceof Tag) { this.tags.add(pos.name); } } } } var INITIAL_STATE = 1; var FAIL_STATE = 0; /** * A StateMachine represents a deterministic finite automaton. * It can perform matches over a sequence of values, similar to a regular expression. */ class StateMachine { constructor(dfa) { this.stateTable = dfa.stateTable; this.accepting = dfa.accepting; this.tags = dfa.tags; } /** * Returns an iterable object that yields pattern matches over the input sequence. * Matches are of the form [startIndex, endIndex, tags]. */ match(str) { var self = this; return { *[Symbol.iterator]() { var state = INITIAL_STATE; var startRun = null; var lastAccepting = null; var lastState = null; for (var p = 0; p < str.length; p++) { var c = str[p]; lastState = state; state = self.stateTable[state][c]; if (state === FAIL_STATE) { // yield the last match if any if (startRun != null && lastAccepting != null && lastAccepting >= startRun) { yield [startRun, lastAccepting, self.tags[lastState]]; } // reset the state as if we started over from the initial state state = self.stateTable[INITIAL_STATE][c]; startRun = null; } // start a run if not in the failure state if (state !== FAIL_STATE && startRun == null) { startRun = p; } // if accepting, mark the potential match end if (self.accepting[state]) { lastAccepting = p; } // reset the state to the initial state if we get into the failure state if (state === FAIL_STATE) { state = INITIAL_STATE; } } // yield the last match if any if (startRun != null && lastAccepting != null && lastAccepting >= startRun) { yield [startRun, lastAccepting, self.tags[state]]; } } }; } /** * For each match over the input sequence, action functions matching * the tag definitions in the input pattern are called with the startIndex, * endIndex, and sub-match sequence. */ apply(str, actions) { for (var [start, end, tags] of this.match(str)) { for (var tag of tags) { if (typeof actions[tag] === 'function') { actions[tag](start, end, str.slice(start, end + 1)); } } } } } function parse(string, externalSymbols) { var ast = grammar.parse(string); return new SymbolTable(ast, externalSymbols); } function build(symbolTable) { var states = buildDFA(symbolTable.main, symbolTable.size); return new StateMachine({ stateTable: states.map(s => Array.from(s.transitions)), accepting: states.map(s => s.accepting), tags: states.map(s => Array.from(s.tags)) }); } function compile(string, externalSymbols) { return build(parse(string, externalSymbols)); } exports.build = build; exports.default = compile; exports.parse = parse; //# sourceMappingURL=compile.js.map