pgn-parser
Version:
1,672 lines (1,465 loc) • 265 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define("pgnParser", [], factory);
else if(typeof exports === 'object')
exports["pgnParser"] = factory();
else
root["pgnParser"] = factory();
})(this, () => {
return /******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/pegjs/lib/compiler/asts.js":
/*!*************************************************!*\
!*** ./node_modules/pegjs/lib/compiler/asts.js ***!
\*************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
var arrays = __webpack_require__(/*! ../utils/arrays */ "./node_modules/pegjs/lib/utils/arrays.js"),
visitor = __webpack_require__(/*! ./visitor */ "./node_modules/pegjs/lib/compiler/visitor.js");
/* AST utilities. */
var asts = {
findRule: function(ast, name) {
return arrays.find(ast.rules, function(r) { return r.name === name; });
},
indexOfRule: function(ast, name) {
return arrays.indexOf(ast.rules, function(r) { return r.name === name; });
},
alwaysConsumesOnSuccess: function(ast, node) {
function consumesTrue() { return true; }
function consumesFalse() { return false; }
function consumesExpression(node) {
return consumes(node.expression);
}
var consumes = visitor.build({
rule: consumesExpression,
named: consumesExpression,
choice: function(node) {
return arrays.every(node.alternatives, consumes);
},
action: consumesExpression,
sequence: function(node) {
return arrays.some(node.elements, consumes);
},
labeled: consumesExpression,
text: consumesExpression,
simple_and: consumesFalse,
simple_not: consumesFalse,
optional: consumesFalse,
zero_or_more: consumesFalse,
one_or_more: consumesExpression,
group: consumesExpression,
semantic_and: consumesFalse,
semantic_not: consumesFalse,
rule_ref: function(node) {
return consumes(asts.findRule(ast, node.name));
},
literal: function(node) {
return node.value !== "";
},
"class": consumesTrue,
any: consumesTrue
});
return consumes(node);
}
};
module.exports = asts;
/***/ }),
/***/ "./node_modules/pegjs/lib/compiler/index.js":
/*!**************************************************!*\
!*** ./node_modules/pegjs/lib/compiler/index.js ***!
\**************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
var arrays = __webpack_require__(/*! ../utils/arrays */ "./node_modules/pegjs/lib/utils/arrays.js"),
objects = __webpack_require__(/*! ../utils/objects */ "./node_modules/pegjs/lib/utils/objects.js");
var compiler = {
/*
* AST node visitor builder. Useful mainly for plugins which manipulate the
* AST.
*/
visitor: __webpack_require__(/*! ./visitor */ "./node_modules/pegjs/lib/compiler/visitor.js"),
/*
* Compiler passes.
*
* Each pass is a function that is passed the AST. It can perform checks on it
* or modify it as needed. If the pass encounters a semantic error, it throws
* |peg.GrammarError|.
*/
passes: {
check: {
reportUndefinedRules: __webpack_require__(/*! ./passes/report-undefined-rules */ "./node_modules/pegjs/lib/compiler/passes/report-undefined-rules.js"),
reportDuplicateRules: __webpack_require__(/*! ./passes/report-duplicate-rules */ "./node_modules/pegjs/lib/compiler/passes/report-duplicate-rules.js"),
reportDuplicateLabels: __webpack_require__(/*! ./passes/report-duplicate-labels */ "./node_modules/pegjs/lib/compiler/passes/report-duplicate-labels.js"),
reportInfiniteRecursion: __webpack_require__(/*! ./passes/report-infinite-recursion */ "./node_modules/pegjs/lib/compiler/passes/report-infinite-recursion.js"),
reportInfiniteRepetition: __webpack_require__(/*! ./passes/report-infinite-repetition */ "./node_modules/pegjs/lib/compiler/passes/report-infinite-repetition.js")
},
transform: {
removeProxyRules: __webpack_require__(/*! ./passes/remove-proxy-rules */ "./node_modules/pegjs/lib/compiler/passes/remove-proxy-rules.js")
},
generate: {
generateBytecode: __webpack_require__(/*! ./passes/generate-bytecode */ "./node_modules/pegjs/lib/compiler/passes/generate-bytecode.js"),
generateJS: __webpack_require__(/*! ./passes/generate-js */ "./node_modules/pegjs/lib/compiler/passes/generate-js.js")
}
},
/*
* Generates a parser from a specified grammar AST. Throws |peg.GrammarError|
* if the AST contains a semantic error. Note that not all errors are detected
* during the generation and some may protrude to the generated parser and
* cause its malfunction.
*/
compile: function(ast, passes, options) {
options = options !== void 0 ? options : {};
var stage;
options = objects.clone(options);
objects.defaults(options, {
allowedStartRules: [ast.rules[0].name],
cache: false,
dependencies: {},
exportVar: null,
format: "bare",
optimize: "speed",
output: "parser",
trace: false
});
for (stage in passes) {
if (passes.hasOwnProperty(stage)) {
arrays.each(passes[stage], function(p) { p(ast, options); });
}
}
switch (options.output) {
case "parser": return eval(ast.code);
case "source": return ast.code;
}
}
};
module.exports = compiler;
/***/ }),
/***/ "./node_modules/pegjs/lib/compiler/js.js":
/*!***********************************************!*\
!*** ./node_modules/pegjs/lib/compiler/js.js ***!
\***********************************************/
/***/ ((module) => {
"use strict";
function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); }
/* JavaScript code generation helpers. */
var js = {
stringEscape: function(s) {
/*
* ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string
* literal except for the closing quote character, backslash, carriage
* return, line separator, paragraph separator, and line feed. Any character
* may appear in the form of an escape sequence.
*
* For portability, we also escape all control and non-ASCII characters.
* Note that the "\v" escape sequence is not used because IE does not like
* it.
*/
return s
.replace(/\\/g, '\\\\') // backslash
.replace(/"/g, '\\"') // closing double quote
.replace(/\0/g, '\\0') // null
.replace(/\x08/g, '\\b') // backspace
.replace(/\t/g, '\\t') // horizontal tab
.replace(/\n/g, '\\n') // line feed
.replace(/\f/g, '\\f') // form feed
.replace(/\r/g, '\\r') // carriage return
.replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x7F-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
.replace(/[\u0100-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
.replace(/[\u1000-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
},
regexpClassEscape: function(s) {
/*
* Based on ECMA-262, 5th ed., 7.8.5 & 15.10.1.
*
* For portability, we also escape all control and non-ASCII characters.
*/
return s
.replace(/\\/g, '\\\\') // backslash
.replace(/\//g, '\\/') // closing slash
.replace(/\]/g, '\\]') // closing bracket
.replace(/\^/g, '\\^') // caret
.replace(/-/g, '\\-') // dash
.replace(/\0/g, '\\0') // null
.replace(/\t/g, '\\t') // horizontal tab
.replace(/\n/g, '\\n') // line feed
.replace(/\v/g, '\\x0B') // vertical tab
.replace(/\f/g, '\\f') // form feed
.replace(/\r/g, '\\r') // carriage return
.replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); })
.replace(/[\x10-\x1F\x7F-\xFF]/g, function(ch) { return '\\x' + hex(ch); })
.replace(/[\u0100-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); })
.replace(/[\u1000-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); });
}
};
module.exports = js;
/***/ }),
/***/ "./node_modules/pegjs/lib/compiler/opcodes.js":
/*!****************************************************!*\
!*** ./node_modules/pegjs/lib/compiler/opcodes.js ***!
\****************************************************/
/***/ ((module) => {
"use strict";
/* Bytecode instruction opcodes. */
var opcodes = {
/* Stack Manipulation */
PUSH: 0, // PUSH c
PUSH_UNDEFINED: 1, // PUSH_UNDEFINED
PUSH_NULL: 2, // PUSH_NULL
PUSH_FAILED: 3, // PUSH_FAILED
PUSH_EMPTY_ARRAY: 4, // PUSH_EMPTY_ARRAY
PUSH_CURR_POS: 5, // PUSH_CURR_POS
POP: 6, // POP
POP_CURR_POS: 7, // POP_CURR_POS
POP_N: 8, // POP_N n
NIP: 9, // NIP
APPEND: 10, // APPEND
WRAP: 11, // WRAP n
TEXT: 12, // TEXT
/* Conditions and Loops */
IF: 13, // IF t, f
IF_ERROR: 14, // IF_ERROR t, f
IF_NOT_ERROR: 15, // IF_NOT_ERROR t, f
WHILE_NOT_ERROR: 16, // WHILE_NOT_ERROR b
/* Matching */
MATCH_ANY: 17, // MATCH_ANY a, f, ...
MATCH_STRING: 18, // MATCH_STRING s, a, f, ...
MATCH_STRING_IC: 19, // MATCH_STRING_IC s, a, f, ...
MATCH_REGEXP: 20, // MATCH_REGEXP r, a, f, ...
ACCEPT_N: 21, // ACCEPT_N n
ACCEPT_STRING: 22, // ACCEPT_STRING s
FAIL: 23, // FAIL e
/* Calls */
LOAD_SAVED_POS: 24, // LOAD_SAVED_POS p
UPDATE_SAVED_POS: 25, // UPDATE_SAVED_POS
CALL: 26, // CALL f, n, pc, p1, p2, ..., pN
/* Rules */
RULE: 27, // RULE r
/* Failure Reporting */
SILENT_FAILS_ON: 28, // SILENT_FAILS_ON
SILENT_FAILS_OFF: 29 // SILENT_FAILS_OFF
};
module.exports = opcodes;
/***/ }),
/***/ "./node_modules/pegjs/lib/compiler/passes/generate-bytecode.js":
/*!*********************************************************************!*\
!*** ./node_modules/pegjs/lib/compiler/passes/generate-bytecode.js ***!
\*********************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
var arrays = __webpack_require__(/*! ../../utils/arrays */ "./node_modules/pegjs/lib/utils/arrays.js"),
objects = __webpack_require__(/*! ../../utils/objects */ "./node_modules/pegjs/lib/utils/objects.js"),
asts = __webpack_require__(/*! ../asts */ "./node_modules/pegjs/lib/compiler/asts.js"),
visitor = __webpack_require__(/*! ../visitor */ "./node_modules/pegjs/lib/compiler/visitor.js"),
op = __webpack_require__(/*! ../opcodes */ "./node_modules/pegjs/lib/compiler/opcodes.js"),
js = __webpack_require__(/*! ../js */ "./node_modules/pegjs/lib/compiler/js.js");
/* Generates bytecode.
*
* Instructions
* ============
*
* Stack Manipulation
* ------------------
*
* [0] PUSH c
*
* stack.push(consts[c]);
*
* [1] PUSH_UNDEFINED
*
* stack.push(undefined);
*
* [2] PUSH_NULL
*
* stack.push(null);
*
* [3] PUSH_FAILED
*
* stack.push(FAILED);
*
* [4] PUSH_EMPTY_ARRAY
*
* stack.push([]);
*
* [5] PUSH_CURR_POS
*
* stack.push(currPos);
*
* [6] POP
*
* stack.pop();
*
* [7] POP_CURR_POS
*
* currPos = stack.pop();
*
* [8] POP_N n
*
* stack.pop(n);
*
* [9] NIP
*
* value = stack.pop();
* stack.pop();
* stack.push(value);
*
* [10] APPEND
*
* value = stack.pop();
* array = stack.pop();
* array.push(value);
* stack.push(array);
*
* [11] WRAP n
*
* stack.push(stack.pop(n));
*
* [12] TEXT
*
* stack.push(input.substring(stack.pop(), currPos));
*
* Conditions and Loops
* --------------------
*
* [13] IF t, f
*
* if (stack.top()) {
* interpret(ip + 3, ip + 3 + t);
* } else {
* interpret(ip + 3 + t, ip + 3 + t + f);
* }
*
* [14] IF_ERROR t, f
*
* if (stack.top() === FAILED) {
* interpret(ip + 3, ip + 3 + t);
* } else {
* interpret(ip + 3 + t, ip + 3 + t + f);
* }
*
* [15] IF_NOT_ERROR t, f
*
* if (stack.top() !== FAILED) {
* interpret(ip + 3, ip + 3 + t);
* } else {
* interpret(ip + 3 + t, ip + 3 + t + f);
* }
*
* [16] WHILE_NOT_ERROR b
*
* while(stack.top() !== FAILED) {
* interpret(ip + 2, ip + 2 + b);
* }
*
* Matching
* --------
*
* [17] MATCH_ANY a, f, ...
*
* if (input.length > currPos) {
* interpret(ip + 3, ip + 3 + a);
* } else {
* interpret(ip + 3 + a, ip + 3 + a + f);
* }
*
* [18] MATCH_STRING s, a, f, ...
*
* if (input.substr(currPos, consts[s].length) === consts[s]) {
* interpret(ip + 4, ip + 4 + a);
* } else {
* interpret(ip + 4 + a, ip + 4 + a + f);
* }
*
* [19] MATCH_STRING_IC s, a, f, ...
*
* if (input.substr(currPos, consts[s].length).toLowerCase() === consts[s]) {
* interpret(ip + 4, ip + 4 + a);
* } else {
* interpret(ip + 4 + a, ip + 4 + a + f);
* }
*
* [20] MATCH_REGEXP r, a, f, ...
*
* if (consts[r].test(input.charAt(currPos))) {
* interpret(ip + 4, ip + 4 + a);
* } else {
* interpret(ip + 4 + a, ip + 4 + a + f);
* }
*
* [21] ACCEPT_N n
*
* stack.push(input.substring(currPos, n));
* currPos += n;
*
* [22] ACCEPT_STRING s
*
* stack.push(consts[s]);
* currPos += consts[s].length;
*
* [23] FAIL e
*
* stack.push(FAILED);
* fail(consts[e]);
*
* Calls
* -----
*
* [24] LOAD_SAVED_POS p
*
* savedPos = stack[p];
*
* [25] UPDATE_SAVED_POS
*
* savedPos = currPos;
*
* [26] CALL f, n, pc, p1, p2, ..., pN
*
* value = consts[f](stack[p1], ..., stack[pN]);
* stack.pop(n);
* stack.push(value);
*
* Rules
* -----
*
* [27] RULE r
*
* stack.push(parseRule(r));
*
* Failure Reporting
* -----------------
*
* [28] SILENT_FAILS_ON
*
* silentFails++;
*
* [29] SILENT_FAILS_OFF
*
* silentFails--;
*/
function generateBytecode(ast) {
var consts = [];
function addConst(value) {
var index = arrays.indexOf(consts, value);
return index === -1 ? consts.push(value) - 1 : index;
}
function addFunctionConst(params, code) {
return addConst(
"function(" + params.join(", ") + ") {" + code + "}"
);
}
function buildSequence() {
return Array.prototype.concat.apply([], arguments);
}
function buildCondition(condCode, thenCode, elseCode) {
return condCode.concat(
[thenCode.length, elseCode.length],
thenCode,
elseCode
);
}
function buildLoop(condCode, bodyCode) {
return condCode.concat([bodyCode.length], bodyCode);
}
function buildCall(functionIndex, delta, env, sp) {
var params = arrays.map(objects.values(env), function(p) { return sp - p; });
return [op.CALL, functionIndex, delta, params.length].concat(params);
}
function buildSimplePredicate(expression, negative, context) {
return buildSequence(
[op.PUSH_CURR_POS],
[op.SILENT_FAILS_ON],
generate(expression, {
sp: context.sp + 1,
env: objects.clone(context.env),
action: null
}),
[op.SILENT_FAILS_OFF],
buildCondition(
[negative ? op.IF_ERROR : op.IF_NOT_ERROR],
buildSequence(
[op.POP],
[negative ? op.POP : op.POP_CURR_POS],
[op.PUSH_UNDEFINED]
),
buildSequence(
[op.POP],
[negative ? op.POP_CURR_POS : op.POP],
[op.PUSH_FAILED]
)
)
);
}
function buildSemanticPredicate(code, negative, context) {
var functionIndex = addFunctionConst(objects.keys(context.env), code);
return buildSequence(
[op.UPDATE_SAVED_POS],
buildCall(functionIndex, 0, context.env, context.sp),
buildCondition(
[op.IF],
buildSequence(
[op.POP],
negative ? [op.PUSH_FAILED] : [op.PUSH_UNDEFINED]
),
buildSequence(
[op.POP],
negative ? [op.PUSH_UNDEFINED] : [op.PUSH_FAILED]
)
)
);
}
function buildAppendLoop(expressionCode) {
return buildLoop(
[op.WHILE_NOT_ERROR],
buildSequence([op.APPEND], expressionCode)
);
}
var generate = visitor.build({
grammar: function(node) {
arrays.each(node.rules, generate);
node.consts = consts;
},
rule: function(node) {
node.bytecode = generate(node.expression, {
sp: -1, // stack pointer
env: { }, // mapping of label names to stack positions
action: null // action nodes pass themselves to children here
});
},
named: function(node, context) {
var nameIndex = addConst(
'peg$otherExpectation("' + js.stringEscape(node.name) + '")'
);
/*
* The code generated below is slightly suboptimal because |FAIL| pushes
* to the stack, so we need to stick a |POP| in front of it. We lack a
* dedicated instruction that would just report the failure and not touch
* the stack.
*/
return buildSequence(
[op.SILENT_FAILS_ON],
generate(node.expression, context),
[op.SILENT_FAILS_OFF],
buildCondition([op.IF_ERROR], [op.FAIL, nameIndex], [])
);
},
choice: function(node, context) {
function buildAlternativesCode(alternatives, context) {
return buildSequence(
generate(alternatives[0], {
sp: context.sp,
env: objects.clone(context.env),
action: null
}),
alternatives.length > 1
? buildCondition(
[op.IF_ERROR],
buildSequence(
[op.POP],
buildAlternativesCode(alternatives.slice(1), context)
),
[]
)
: []
);
}
return buildAlternativesCode(node.alternatives, context);
},
action: function(node, context) {
var env = objects.clone(context.env),
emitCall = node.expression.type !== "sequence"
|| node.expression.elements.length === 0,
expressionCode = generate(node.expression, {
sp: context.sp + (emitCall ? 1 : 0),
env: env,
action: node
}),
functionIndex = addFunctionConst(objects.keys(env), node.code);
return emitCall
? buildSequence(
[op.PUSH_CURR_POS],
expressionCode,
buildCondition(
[op.IF_NOT_ERROR],
buildSequence(
[op.LOAD_SAVED_POS, 1],
buildCall(functionIndex, 1, env, context.sp + 2)
),
[]
),
[op.NIP]
)
: expressionCode;
},
sequence: function(node, context) {
function buildElementsCode(elements, context) {
var processedCount, functionIndex;
if (elements.length > 0) {
processedCount = node.elements.length - elements.slice(1).length;
return buildSequence(
generate(elements[0], {
sp: context.sp,
env: context.env,
action: null
}),
buildCondition(
[op.IF_NOT_ERROR],
buildElementsCode(elements.slice(1), {
sp: context.sp + 1,
env: context.env,
action: context.action
}),
buildSequence(
processedCount > 1 ? [op.POP_N, processedCount] : [op.POP],
[op.POP_CURR_POS],
[op.PUSH_FAILED]
)
)
);
} else {
if (context.action) {
functionIndex = addFunctionConst(
objects.keys(context.env),
context.action.code
);
return buildSequence(
[op.LOAD_SAVED_POS, node.elements.length],
buildCall(
functionIndex,
node.elements.length,
context.env,
context.sp
),
[op.NIP]
);
} else {
return buildSequence([op.WRAP, node.elements.length], [op.NIP]);
}
}
}
return buildSequence(
[op.PUSH_CURR_POS],
buildElementsCode(node.elements, {
sp: context.sp + 1,
env: context.env,
action: context.action
})
);
},
labeled: function(node, context) {
var env = objects.clone(context.env);
context.env[node.label] = context.sp + 1;
return generate(node.expression, {
sp: context.sp,
env: env,
action: null
});
},
text: function(node, context) {
return buildSequence(
[op.PUSH_CURR_POS],
generate(node.expression, {
sp: context.sp + 1,
env: objects.clone(context.env),
action: null
}),
buildCondition(
[op.IF_NOT_ERROR],
buildSequence([op.POP], [op.TEXT]),
[op.NIP]
)
);
},
simple_and: function(node, context) {
return buildSimplePredicate(node.expression, false, context);
},
simple_not: function(node, context) {
return buildSimplePredicate(node.expression, true, context);
},
optional: function(node, context) {
return buildSequence(
generate(node.expression, {
sp: context.sp,
env: objects.clone(context.env),
action: null
}),
buildCondition(
[op.IF_ERROR],
buildSequence([op.POP], [op.PUSH_NULL]),
[]
)
);
},
zero_or_more: function(node, context) {
var expressionCode = generate(node.expression, {
sp: context.sp + 1,
env: objects.clone(context.env),
action: null
});
return buildSequence(
[op.PUSH_EMPTY_ARRAY],
expressionCode,
buildAppendLoop(expressionCode),
[op.POP]
);
},
one_or_more: function(node, context) {
var expressionCode = generate(node.expression, {
sp: context.sp + 1,
env: objects.clone(context.env),
action: null
});
return buildSequence(
[op.PUSH_EMPTY_ARRAY],
expressionCode,
buildCondition(
[op.IF_NOT_ERROR],
buildSequence(buildAppendLoop(expressionCode), [op.POP]),
buildSequence([op.POP], [op.POP], [op.PUSH_FAILED])
)
);
},
group: function(node, context) {
return generate(node.expression, {
sp: context.sp,
env: objects.clone(context.env),
action: null
});
},
semantic_and: function(node, context) {
return buildSemanticPredicate(node.code, false, context);
},
semantic_not: function(node, context) {
return buildSemanticPredicate(node.code, true, context);
},
rule_ref: function(node) {
return [op.RULE, asts.indexOfRule(ast, node.name)];
},
literal: function(node) {
var stringIndex, expectedIndex;
if (node.value.length > 0) {
stringIndex = addConst('"'
+ js.stringEscape(
node.ignoreCase ? node.value.toLowerCase() : node.value
)
+ '"'
);
expectedIndex = addConst(
'peg$literalExpectation('
+ '"' + js.stringEscape(node.value) + '", '
+ node.ignoreCase
+ ')'
);
/*
* For case-sensitive strings the value must match the beginning of the
* remaining input exactly. As a result, we can use |ACCEPT_STRING| and
* save one |substr| call that would be needed if we used |ACCEPT_N|.
*/
return buildCondition(
node.ignoreCase
? [op.MATCH_STRING_IC, stringIndex]
: [op.MATCH_STRING, stringIndex],
node.ignoreCase
? [op.ACCEPT_N, node.value.length]
: [op.ACCEPT_STRING, stringIndex],
[op.FAIL, expectedIndex]
);
} else {
stringIndex = addConst('""');
return [op.PUSH, stringIndex];
}
},
"class": function(node) {
var regexp, parts, regexpIndex, expectedIndex;
if (node.parts.length > 0) {
regexp = '/^['
+ (node.inverted ? '^' : '')
+ arrays.map(node.parts, function(part) {
return part instanceof Array
? js.regexpClassEscape(part[0])
+ '-'
+ js.regexpClassEscape(part[1])
: js.regexpClassEscape(part);
}).join('')
+ ']/' + (node.ignoreCase ? 'i' : '');
} else {
/*
* IE considers regexps /[]/ and /[^]/ as syntactically invalid, so we
* translate them into equivalents it can handle.
*/
regexp = node.inverted ? '/^[\\S\\s]/' : '/^(?!)/';
}
parts = '['
+ arrays.map(node.parts, function(part) {
return part instanceof Array
? '["' + js.stringEscape(part[0]) + '", "' + js.stringEscape(part[1]) + '"]'
: '"' + js.stringEscape(part) + '"';
}).join(', ')
+ ']';
regexpIndex = addConst(regexp);
expectedIndex = addConst(
'peg$classExpectation('
+ parts + ', '
+ node.inverted + ', '
+ node.ignoreCase
+ ')'
);
return buildCondition(
[op.MATCH_REGEXP, regexpIndex],
[op.ACCEPT_N, 1],
[op.FAIL, expectedIndex]
);
},
any: function() {
var expectedIndex = addConst('peg$anyExpectation()');
return buildCondition(
[op.MATCH_ANY],
[op.ACCEPT_N, 1],
[op.FAIL, expectedIndex]
);
}
});
generate(ast);
}
module.exports = generateBytecode;
/***/ }),
/***/ "./node_modules/pegjs/lib/compiler/passes/generate-js.js":
/*!***************************************************************!*\
!*** ./node_modules/pegjs/lib/compiler/passes/generate-js.js ***!
\***************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
var arrays = __webpack_require__(/*! ../../utils/arrays */ "./node_modules/pegjs/lib/utils/arrays.js"),
objects = __webpack_require__(/*! ../../utils/objects */ "./node_modules/pegjs/lib/utils/objects.js"),
asts = __webpack_require__(/*! ../asts */ "./node_modules/pegjs/lib/compiler/asts.js"),
op = __webpack_require__(/*! ../opcodes */ "./node_modules/pegjs/lib/compiler/opcodes.js"),
js = __webpack_require__(/*! ../js */ "./node_modules/pegjs/lib/compiler/js.js");
/* Generates parser JavaScript code. */
function generateJS(ast, options) {
/* These only indent non-empty lines to avoid trailing whitespace. */
function indent2(code) { return code.replace(/^(.+)$/gm, ' $1'); }
function indent6(code) { return code.replace(/^(.+)$/gm, ' $1'); }
function indent10(code) { return code.replace(/^(.+)$/gm, ' $1'); }
function generateTables() {
if (options.optimize === "size") {
return [
'peg$consts = [',
indent2(ast.consts.join(',\n')),
'],',
'',
'peg$bytecode = [',
indent2(arrays.map(ast.rules, function(rule) {
return 'peg$decode("'
+ js.stringEscape(arrays.map(
rule.bytecode,
function(b) { return String.fromCharCode(b + 32); }
).join(''))
+ '")';
}).join(',\n')),
'],'
].join('\n');
} else {
return arrays.map(
ast.consts,
function(c, i) { return 'peg$c' + i + ' = ' + c + ','; }
).join('\n');
}
}
function generateRuleHeader(ruleNameCode, ruleIndexCode) {
var parts = [];
parts.push('');
if (options.trace) {
parts.push([
'peg$tracer.trace({',
' type: "rule.enter",',
' rule: ' + ruleNameCode + ',',
' location: peg$computeLocation(startPos, startPos)',
'});',
''
].join('\n'));
}
if (options.cache) {
parts.push([
'var key = peg$currPos * ' + ast.rules.length + ' + ' + ruleIndexCode + ',',
' cached = peg$resultsCache[key];',
'',
'if (cached) {',
' peg$currPos = cached.nextPos;',
''
].join('\n'));
if (options.trace) {
parts.push([
'if (cached.result !== peg$FAILED) {',
' peg$tracer.trace({',
' type: "rule.match",',
' rule: ' + ruleNameCode + ',',
' result: cached.result,',
' location: peg$computeLocation(startPos, peg$currPos)',
' });',
'} else {',
' peg$tracer.trace({',
' type: "rule.fail",',
' rule: ' + ruleNameCode + ',',
' location: peg$computeLocation(startPos, startPos)',
' });',
'}',
''
].join('\n'));
}
parts.push([
' return cached.result;',
'}',
''
].join('\n'));
}
return parts.join('\n');
}
function generateRuleFooter(ruleNameCode, resultCode) {
var parts = [];
if (options.cache) {
parts.push([
'',
'peg$resultsCache[key] = { nextPos: peg$currPos, result: ' + resultCode + ' };'
].join('\n'));
}
if (options.trace) {
parts.push([
'',
'if (' + resultCode + ' !== peg$FAILED) {',
' peg$tracer.trace({',
' type: "rule.match",',
' rule: ' + ruleNameCode + ',',
' result: ' + resultCode + ',',
' location: peg$computeLocation(startPos, peg$currPos)',
' });',
'} else {',
' peg$tracer.trace({',
' type: "rule.fail",',
' rule: ' + ruleNameCode + ',',
' location: peg$computeLocation(startPos, startPos)',
' });',
'}'
].join('\n'));
}
parts.push([
'',
'return ' + resultCode + ';'
].join('\n'));
return parts.join('\n');
}
function generateInterpreter() {
var parts = [];
function generateCondition(cond, argsLength) {
var baseLength = argsLength + 3,
thenLengthCode = 'bc[ip + ' + (baseLength - 2) + ']',
elseLengthCode = 'bc[ip + ' + (baseLength - 1) + ']';
return [
'ends.push(end);',
'ips.push(ip + ' + baseLength + ' + ' + thenLengthCode + ' + ' + elseLengthCode + ');',
'',
'if (' + cond + ') {',
' end = ip + ' + baseLength + ' + ' + thenLengthCode + ';',
' ip += ' + baseLength + ';',
'} else {',
' end = ip + ' + baseLength + ' + ' + thenLengthCode + ' + ' + elseLengthCode + ';',
' ip += ' + baseLength + ' + ' + thenLengthCode + ';',
'}',
'',
'break;'
].join('\n');
}
function generateLoop(cond) {
var baseLength = 2,
bodyLengthCode = 'bc[ip + ' + (baseLength - 1) + ']';
return [
'if (' + cond + ') {',
' ends.push(end);',
' ips.push(ip);',
'',
' end = ip + ' + baseLength + ' + ' + bodyLengthCode + ';',
' ip += ' + baseLength + ';',
'} else {',
' ip += ' + baseLength + ' + ' + bodyLengthCode + ';',
'}',
'',
'break;'
].join('\n');
}
function generateCall() {
var baseLength = 4,
paramsLengthCode = 'bc[ip + ' + (baseLength - 1) + ']';
return [
'params = bc.slice(ip + ' + baseLength + ', ip + ' + baseLength + ' + ' + paramsLengthCode + ');',
'for (i = 0; i < ' + paramsLengthCode + '; i++) {',
' params[i] = stack[stack.length - 1 - params[i]];',
'}',
'',
'stack.splice(',
' stack.length - bc[ip + 2],',
' bc[ip + 2],',
' peg$consts[bc[ip + 1]].apply(null, params)',
');',
'',
'ip += ' + baseLength + ' + ' + paramsLengthCode + ';',
'break;'
].join('\n');
}
parts.push([
'function peg$decode(s) {',
' var bc = new Array(s.length), i;',
'',
' for (i = 0; i < s.length; i++) {',
' bc[i] = s.charCodeAt(i) - 32;',
' }',
'',
' return bc;',
'}',
'',
'function peg$parseRule(index) {'
].join('\n'));
if (options.trace) {
parts.push([
' var bc = peg$bytecode[index],',
' ip = 0,',
' ips = [],',
' end = bc.length,',
' ends = [],',
' stack = [],',
' startPos = peg$currPos,',
' params, i;'
].join('\n'));
} else {
parts.push([
' var bc = peg$bytecode[index],',
' ip = 0,',
' ips = [],',
' end = bc.length,',
' ends = [],',
' stack = [],',
' params, i;'
].join('\n'));
}
parts.push(indent2(generateRuleHeader('peg$ruleNames[index]', 'index')));
parts.push([
/*
* The point of the outer loop and the |ips| & |ends| stacks is to avoid
* recursive calls for interpreting parts of bytecode. In other words, we
* implement the |interpret| operation of the abstract machine without
* function calls. Such calls would likely slow the parser down and more
* importantly cause stack overflows for complex grammars.
*/
' while (true) {',
' while (ip < end) {',
' switch (bc[ip]) {',
' case ' + op.PUSH + ':', // PUSH c
' stack.push(peg$consts[bc[ip + 1]]);',
' ip += 2;',
' break;',
'',
' case ' + op.PUSH_UNDEFINED + ':', // PUSH_UNDEFINED
' stack.push(void 0);',
' ip++;',
' break;',
'',
' case ' + op.PUSH_NULL + ':', // PUSH_NULL
' stack.push(null);',
' ip++;',
' break;',
'',
' case ' + op.PUSH_FAILED + ':', // PUSH_FAILED
' stack.push(peg$FAILED);',
' ip++;',
' break;',
'',
' case ' + op.PUSH_EMPTY_ARRAY + ':', // PUSH_EMPTY_ARRAY
' stack.push([]);',
' ip++;',
' break;',
'',
' case ' + op.PUSH_CURR_POS + ':', // PUSH_CURR_POS
' stack.push(peg$currPos);',
' ip++;',
' break;',
'',
' case ' + op.POP + ':', // POP
' stack.pop();',
' ip++;',
' break;',
'',
' case ' + op.POP_CURR_POS + ':', // POP_CURR_POS
' peg$currPos = stack.pop();',
' ip++;',
' break;',
'',
' case ' + op.POP_N + ':', // POP_N n
' stack.length -= bc[ip + 1];',
' ip += 2;',
' break;',
'',
' case ' + op.NIP + ':', // NIP
' stack.splice(-2, 1);',
' ip++;',
' break;',
'',
' case ' + op.APPEND + ':', // APPEND
' stack[stack.length - 2].push(stack.pop());',
' ip++;',
' break;',
'',
' case ' + op.WRAP + ':', // WRAP n
' stack.push(stack.splice(stack.length - bc[ip + 1], bc[ip + 1]));',
' ip += 2;',
' break;',
'',
' case ' + op.TEXT + ':', // TEXT
' stack.push(input.substring(stack.pop(), peg$currPos));',
' ip++;',
' break;',
'',
' case ' + op.IF + ':', // IF t, f
indent10(generateCondition('stack[stack.length - 1]', 0)),
'',
' case ' + op.IF_ERROR + ':', // IF_ERROR t, f
indent10(generateCondition(
'stack[stack.length - 1] === peg$FAILED',
0
)),
'',
' case ' + op.IF_NOT_ERROR + ':', // IF_NOT_ERROR t, f
indent10(
generateCondition('stack[stack.length - 1] !== peg$FAILED',
0
)),
'',
' case ' + op.WHILE_NOT_ERROR + ':', // WHILE_NOT_ERROR b
indent10(generateLoop('stack[stack.length - 1] !== peg$FAILED')),
'',
' case ' + op.MATCH_ANY + ':', // MATCH_ANY a, f, ...
indent10(generateCondition('input.length > peg$currPos', 0)),
'',
' case ' + op.MATCH_STRING + ':', // MATCH_STRING s, a, f, ...
indent10(generateCondition(
'input.substr(peg$currPos, peg$consts[bc[ip + 1]].length) === peg$consts[bc[ip + 1]]',
1
)),
'',
' case ' + op.MATCH_STRING_IC + ':', // MATCH_STRING_IC s, a, f, ...
indent10(generateCondition(
'input.substr(peg$currPos, peg$consts[bc[ip + 1]].length).toLowerCase() === peg$consts[bc[ip + 1]]',
1
)),
'',
' case ' + op.MATCH_REGEXP + ':', // MATCH_REGEXP r, a, f, ...
indent10(generateCondition(
'peg$consts[bc[ip + 1]].test(input.charAt(peg$currPos))',
1
)),
'',
' case ' + op.ACCEPT_N + ':', // ACCEPT_N n
' stack.push(input.substr(peg$currPos, bc[ip + 1]));',
' peg$currPos += bc[ip + 1];',
' ip += 2;',
' break;',
'',
' case ' + op.ACCEPT_STRING + ':', // ACCEPT_STRING s
' stack.push(peg$consts[bc[ip + 1]]);',
' peg$currPos += peg$consts[bc[ip + 1]].length;',
' ip += 2;',
' break;',
'',
' case ' + op.FAIL + ':', // FAIL e
' stack.push(peg$FAILED);',
' if (peg$silentFails === 0) {',
' peg$fail(peg$consts[bc[ip + 1]]);',
' }',
' ip += 2;',
' break;',
'',
' case ' + op.LOAD_SAVED_POS + ':', // LOAD_SAVED_POS p
' peg$savedPos = stack[stack.length - 1 - bc[ip + 1]];',
' ip += 2;',
' break;',
'',
' case ' + op.UPDATE_SAVED_POS + ':', // UPDATE_SAVED_POS
' peg$savedPos = peg$currPos;',
' ip++;',
' break;',
'',
' case ' + op.CALL + ':', // CALL f, n, pc, p1, p2, ..., pN
indent10(generateCall()),
'',
' case ' + op.RULE + ':', // RULE r
' stack.push(peg$parseRule(bc[ip + 1]));',
' ip += 2;',
' break;',
'',
' case ' + op.SILENT_FAILS_ON + ':', // SILENT_FAILS_ON
' peg$silentFails++;',
' ip++;',
' break;',
'',
' case ' + op.SILENT_FAILS_OFF + ':', // SILENT_FAILS_OFF
' peg$silentFails--;',
' ip++;',
' break;',
'',
' default:',
' throw new Error("Invalid opcode: " + bc[ip] + ".");',
' }',
' }',
'',
' if (ends.length > 0) {',
' end = ends.pop();',
' ip = ips.pop();',
' } else {',
' break;',
' }',
' }'
].join('\n'));
parts.push(indent2(generateRuleFooter('peg$ruleNames[index]', 'stack[0]')));
parts.push('}');
return parts.join('\n');
}
function generateRuleFunction(rule) {
var parts = [], code;
function c(i) { return "peg$c" + i; } // |consts[i]| of the abstract machine
function s(i) { return "s" + i; } // |stack[i]| of the abstract machine
var stack = {
sp: -1,
maxSp: -1,
push: function(exprCode) {
var code = s(++this.sp) + ' = ' + exprCode + ';';
if (this.sp > this.maxSp) { this.maxSp = this.sp; }
return code;
},
pop: function(n) {
var values;
if (n === void 0) {
return s(this.sp--);
} else {
values = arrays.map(arrays.range(this.sp - n + 1, this.sp + 1), s);
this.sp -= n;
return values;
}
},
top: function() {
return s(this.sp);
},
index: function(i) {
return s(this.sp - i);
}
};
function compile(bc) {
var ip = 0,
end = bc.length,
parts = [],
value;
function compileCondition(cond, argCount) {
var baseLength = argCount + 3,
thenLength = bc[ip + baseLength - 2],
elseLength = bc[ip + baseLength - 1],
baseSp = stack.sp,
thenCode, elseCode, thenSp, elseSp;
ip += baseLength;
thenCode = compile(bc.slice(ip, ip + thenLength));
thenSp = stack.sp;
ip += thenLength;
if (elseLength > 0) {
stack.sp = baseSp;
elseCode = compile(bc.slice(ip, ip + elseLength));
elseSp = stack.sp;
ip += elseLength;
if (thenSp !== elseSp) {
throw new Error(
"Branches of a condition must move the stack pointer in the same way."
);
}
}
parts.push('if (' + cond + ') {');
parts.push(indent2(thenCode));
if (elseLength > 0) {
parts.push('} else {');
parts.push(indent2(elseCode));
}
parts.push('}');
}
function compileLoop(cond) {
var baseLength = 2,
bodyLength = bc[ip + baseLength - 1],
baseSp = stack.sp,
bodyCode, bodySp;
ip += baseLength;
bodyCode = compile(bc.slice(ip, ip + bodyLength));
bodySp = stack.sp;
ip += bodyLength;
if (bodySp !== baseSp) {
throw new Error("Body of a loop can't move the stack pointer.");
}
parts.push('while (' + cond + ') {');
parts.push(indent2(bodyCode));
parts.push('}');
}
function compileCall() {
var baseLength = 4,
paramsLength = bc[ip + baseLength - 1];
var value = c(bc[ip + 1]) + '('
+ arrays.map(
bc.slice(ip + baseLength, ip + baseLength + paramsLength),
function(p) { return stack.index(p); }
).join(', ')
+ ')';
stack.pop(bc[ip + 2]);
parts.push(stack.push(value));
ip += baseLength + paramsLength;
}
while (ip < end) {
switch (bc[ip]) {
case op.PUSH: // PUSH c
parts.push(stack.push(c(bc[ip + 1])));
ip += 2;
break;
case op.PUSH_CURR_POS: // PUSH_CURR_POS
parts.push(stack.push('peg$currPos'));
ip++;
break;
case op.PUSH_UNDEFINED: // PUSH_UNDEFINED
parts.push(stack.push('void 0'));
ip++;
break;
case op.PUSH_NULL: // PUSH_NULL
parts.push(stack.push('null'));
ip++;
break;
case op.PUSH_FAILED: // PUSH_FAILED
parts.push(stack.push('peg$FAILED'));
ip++;
break;
case op.PUSH_EMPTY_ARRAY: // PUSH_EMPTY_ARRAY
parts.push(stack.push('[]'));
ip++;
break;
case op.POP: // POP
stack.pop();
ip++;
break;
case op.POP_CURR_POS: // POP_CURR_POS
parts.push('peg$currPos = ' + stack.pop() + ';');
ip++;
break;
case op.POP_N: // POP_N n
stack.pop(bc[ip + 1]);
ip += 2;
break;
case op.NIP: // NIP
value = stack.pop();
stack.pop();
parts.push(stack.push(value));
ip++;
break;
case op.APPEND: // APPEND
value = stack.pop();
parts.push(stack.top() + '.push(' + value + ');');
ip++;
break;
case op.WRAP: // WRAP n
parts.push(
stack.push('[' + stack.pop(bc[ip + 1]).join(', ') + ']')
);
ip += 2;
break;
case op.TEXT: // TEXT
parts.push(
stack.push('input.substring(' + stack.pop() + ', peg$currPos)')
);
ip++;
break;
case op.IF: // IF t, f
compileCondition(stack.top(), 0);
break;
case op.IF_ERROR: // IF_ERROR t, f
compileCondition(stack.top() + ' === peg$FAILED', 0);
break;
case op.IF_NOT_ERROR: // IF_NOT_ERROR t, f
compileCondition(stack.top() + ' !== peg$FAILED', 0);
break;
case op.WHILE_NOT_ERROR: // WHILE_NOT_ERROR b
compileLoop(stack.top() + ' !== peg$FAILED', 0);
break;
case op.MATCH_ANY: // MATCH_ANY a, f, ...
compileCondition('input.length > peg$currPos', 0);
break;
case op.MATCH_STRING: // MATCH_STRING s, a, f, ...
compileCondition(
eval(ast.consts[bc[ip + 1]]).length > 1
? 'input.substr(peg$currPos, '
+ eval(ast.consts[bc[ip + 1]]).length
+ ') === '
+ c(bc[ip + 1])
: 'input.charCodeAt(peg$currPos) === '
+ eval(ast.consts[bc[ip + 1]]).charCodeAt(0),
1
);
break;
case op.MATCH_STRING_IC: // MATCH_STRING_IC s, a, f, ...
compileCondition(
'input.substr(peg$currPos, '
+ eval(ast.consts[bc[ip + 1]]).length
+ ').toLowerCase() === '
+ c(bc[ip + 1]),
1
);
break;
case op.MATCH_REGEXP: // MATCH_REGEXP r, a, f, ...
compileCondition(
c(bc[ip + 1]) + '.test(input.charAt(peg$currPos))',
1
);
break;
case op.ACCEPT_N: // ACCEPT_N n
parts.push(stack.push(
bc[ip + 1] > 1
? 'input.substr(peg$currPos, ' + bc[ip + 1] + ')'
: 'input.charAt(peg$currPos)'
));
parts.push(
bc[ip + 1] > 1
? 'peg$currPos += ' + bc[ip + 1] + ';'
: 'peg$currPos++;'
);
ip += 2;
break;
case op.ACCEPT_STRING: // ACCEPT_STRING s
parts.push(stack.push(c(bc[ip + 1])));
parts.push(
eval(ast.consts[bc[ip + 1]]).length > 1
? 'peg$currPos += ' + eval(ast.consts[bc[ip + 1]]).length + ';'
: 'peg$currPos++;'
);
ip += 2;
break;
case op.FAIL: // FAIL e
parts.push(stack.push('peg$FAILED'));
parts.push('if (peg$silentFails === 0) { peg$fail(' + c(bc[ip + 1]) + '); }');
ip += 2;
break;
case op.LOAD_SAVED_POS: // LOAD_SAVED_POS p
parts.push('peg$savedPos = ' + stack.index(bc[ip + 1]) + ';');
ip += 2;
break;
case op.UPDATE_SAVED_POS: // UPDATE_SAVED_POS
parts.push('peg$savedPos = peg$currPos;');
ip++;
break;
case op.CALL: // CALL f, n, pc, p1, p2, ..., pN
compileCall();
break;
case op.RULE: // RULE r
parts.push(stack.push("peg$parse" + ast.rules[bc[ip + 1]].name + "()"));
ip += 2;
break;
case op.SILENT_FAILS_ON: // SILENT_FAILS_ON
parts.push('peg$silentFails++;');
ip++;
break;
case op.SILENT_FAILS_OFF: // SILENT_FAILS_OFF