From 2f2152204a3e3b2fc7f498a816ccd32bd95c3e72 Mon Sep 17 00:00:00 2001 From: David Majda Date: Tue, 3 Dec 2013 20:48:47 +0100 Subject: [PATCH] Refine error handling further Before this commit, the |expected| and |error| functions didn't halt the parsing immediately, but triggered a regular match failure. After they were called, the parser could backtrack, try another branches, and only if no other branch succeeded, it triggered an exception with information possibly based on parameters passed to the |expected| or |error| function (this depended on positions where failures in other branches have occurred). While nice in theory, this solution didn't work well in practice. There were at least two problems: 1. Action expression could have easily triggered a match failure later in the input than the action itself. This resulted in the action-triggered failure to be shadowed by the expression-triggered one. Consider the following example: integer = digits:[0-9]+ { var result = parseInt(digits.join(""), 10); if (result % 2 === 0) { error("The number must be an odd integer."); return; } return result; } Given input "2", the |[0-9]+| expression would record a match failure at position 1 (an unsuccessful attempt to parse yet another digit after "2"). However, a failure triggered by the |error| call would occur at position 0. This problem could have been solved by silencing match failures in action expressions, but that would lead to severe performance problems (yes, I tried and measured). Other possible solutions are hacks which I didn't want to introduce into PEG.js. 2. Triggering a match failure in action code could have lead to unexpected backtracking. Consider the following example: class = "[" (charRange / char)* "]" charRange = begin:char "-" end:char { if (begin.data.charCodeAt(0) > end.data.charCodeAt(0)) { error("Invalid character range: " + begin + "-" + end + "."); } // ... } char = [a-zA-Z0-9_\-] Given input "[b-a]", the |charRange| rule would fail, but the parser would try the |char| rule and succeed repeatedly, resulting in "b-a" being parsed as a sequence of three |char|'s, which it is not. This problem could have been solved by using negative predicates, but that would complicate the grammar and still wouldn't get rid of unintuitive behavior. Given these problems I decided to change the semantics of the |expected| and |error| functions. They don't interact with regular match failure mechanism anymore, but they cause and immediate parse failure by throwing an exception. I think this is more intuitive behavior with less harmful side effects. The disadvantage of the new approach is that one can't backtrack from an action-triggered error. I don't see this as a big deal as I think this will be rarely needed and one can always use a semantic predicate as a workaround. Speed impact ------------ Before: 993.84 kB/s After: 998.05 kB/s Difference: 0.42% Size impact ----------- Before: 1019968 b After: 975434 b Difference: -4.37% (Measured by /tools/impact with Node.js v0.6.18 on x86_64 GNU/Linux.) --- Makefile | 1 - README.md | 16 +- lib/compiler/flags.js | 6 - lib/compiler/passes/generate-bytecode.js | 34 +- lib/compiler/passes/generate-javascript.js | 101 +++--- lib/parser.js | 306 ++++++------------ package.json | 1 - .../compiler/passes/generate-bytecode.spec.js | 72 ++--- spec/generated-parser.spec.js | 130 ++------ src/parser.pegjs | 1 - 10 files changed, 206 insertions(+), 462 deletions(-) delete mode 100644 lib/compiler/flags.js diff --git a/Makefile b/Makefile index 0f7a5bf..2d4e65b 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,6 @@ MODULES = utils \ grammar-error \ parser \ compiler/opcodes \ - compiler/flags \ compiler/passes/generate-bytecode \ compiler/passes/generate-javascript \ compiler/passes/remove-proxy-rules \ diff --git a/README.md b/README.md index 3c86bee..53385fd 100644 --- a/README.md +++ b/README.md @@ -376,14 +376,14 @@ expression as its arguments. The action should return some JavaScript value using the `return` statement. This value is considered match result of the preceding expression. -To indicate a match failure, the code inside the action can invoke the -`expected` function. It takes one parameter — a description of what was expected -at the current position. This description will be used as part of a message of -the exception thrown if the match failure leads to an parse error. - -The code inside an action can also invoke the `error` function. It takes one -parameter — an error message. This message will be used by the exception thrown -if the match failure leads to an parse error. +To indicate an error, the code inside the action can invoke the `expected` +function, which makes the parser throw an exception. The function takes one +parameter — a description of what was expected at the current position. This +description will be used as part of a message of the thrown exception. + +The code inside an action can also invoke the `error` function, which also makes +the parser throw an exception. The function takes one parameter — an error +message. This message will be used by the thrown exception. The code inside the action can access all variables and functions defined in the initializer at the beginning of the grammar. Curly braces in the action code diff --git a/lib/compiler/flags.js b/lib/compiler/flags.js deleted file mode 100644 index 384ca96..0000000 --- a/lib/compiler/flags.js +++ /dev/null @@ -1,6 +0,0 @@ -/* Bytecode instruction flags. */ -module.exports = { - DONT_CHECK_FAILS: 0, - CHECK_FAILS: 1 -}; - diff --git a/lib/compiler/passes/generate-bytecode.js b/lib/compiler/passes/generate-bytecode.js index 772af78..9f13c7b 100644 --- a/lib/compiler/passes/generate-bytecode.js +++ b/lib/compiler/passes/generate-bytecode.js @@ -1,6 +1,5 @@ var utils = require("../../utils"), - op = require("../opcodes"), - flags = require("../flags"); + op = require("../opcodes"); /* Generates bytecode. * @@ -152,9 +151,9 @@ var utils = require("../../utils"), * * reportedPos = currPos; * - * [23] CALL f, c, n, pc, p1, p2, ..., pN + * [23] CALL f, n, pc, p1, p2, ..., pN * - * value = call(consts[f], c, stack[p1], ..., stack[pN]); + * value = consts[f](stack[p1], ..., stack[pN]); * stack.pop(n); * stack.push(value); * @@ -207,16 +206,10 @@ module.exports = function(ast, options) { return condCode.concat([bodyCode.length], bodyCode); } - function buildCall(functionIndex, checkFails, delta, env, sp) { + function buildCall(functionIndex, delta, env, sp) { var params = utils.map( utils.values(env), function(p) { return sp - p; }); - return [ - op.CALL, - functionIndex, - checkFails, - delta, - params.length - ].concat(params); + return [op.CALL, functionIndex, delta, params.length].concat(params); } function buildSimplePredicate(expression, negative, context) { @@ -255,13 +248,7 @@ module.exports = function(ast, options) { return buildSequence( [op.REPORT_CURR_POS], - buildCall( - functionIndex, - flags.DONT_CHECK_FAILS, - 0, - context.env, - context.sp - ), + buildCall(functionIndex, 0, context.env, context.sp), buildCondition( [op.IF], buildSequence( @@ -360,13 +347,7 @@ module.exports = function(ast, options) { [op.IF_NOT_ERROR], buildSequence( [op.REPORT_SAVED_POS, 1], - buildCall( - functionIndex, - flags.CHECK_FAILS, - 1, - env, - context.sp + 2 - ) + buildCall(functionIndex, 1, env, context.sp + 2) ), [] ), @@ -415,7 +396,6 @@ module.exports = function(ast, options) { [op.REPORT_SAVED_POS, node.elements.length], buildCall( functionIndex, - flags.CHECK_FAILS, node.elements.length, context.env, context.sp diff --git a/lib/compiler/passes/generate-javascript.js b/lib/compiler/passes/generate-javascript.js index cfdc383..816957e 100644 --- a/lib/compiler/passes/generate-javascript.js +++ b/lib/compiler/passes/generate-javascript.js @@ -1,6 +1,5 @@ var utils = require("../../utils"), - op = require("../opcodes"), - flags = require("../flags"); + op = require("../opcodes"); /* Generates parser JavaScript code. */ module.exports = function(ast, options) { @@ -103,7 +102,7 @@ module.exports = function(ast, options) { } function generateCall() { - var baseLength = 5, + var baseLength = 4, paramsLengthCode = 'bc[ip + ' + (baseLength - 1) + ']'; return [ @@ -112,15 +111,11 @@ module.exports = function(ast, options) { ' params[i] = stack[stack.length - 1 - params[i]];', '}', '', - 'if (bc[ip + 2] === ' + flags.CHECK_FAILS + ') {', - ' peg$userFail = false;', - '}', - 'result = peg$consts[bc[ip + 1]].apply(null, params);', - 'if (bc[ip + 2] === ' + flags.CHECK_FAILS + ') {', - ' if (peg$userFail) { result = peg$FAILED; }', - '}', - '', - 'stack.splice(stack.length - bc[ip + 3], bc[ip + 3], result);', + 'stack.splice(', + ' stack.length - bc[ip + 2],', + ' bc[ip + 2],', + ' peg$consts[bc[ip + 1]].apply(null, params)', + ');', '', 'ip += ' + baseLength + ' + ' + paramsLengthCode + ';', 'break;' @@ -145,7 +140,7 @@ module.exports = function(ast, options) { ' end = bc.length,', ' ends = [],', ' stack = [],', - ' params, result, i;', + ' params, i;', '' ].join('\n')); @@ -277,7 +272,7 @@ module.exports = function(ast, options) { ' case ' + op.FAIL + ':', // FAIL e ' stack.push(peg$FAILED);', ' if (peg$silentFails === 0) {', - ' peg$expected(peg$consts[bc[ip + 1]], peg$currPos);', + ' peg$fail(peg$consts[bc[ip + 1]]);', ' }', ' ip += 2;', ' break;', @@ -424,7 +419,7 @@ module.exports = function(ast, options) { } function compileCall(cond) { - var baseLength = 5, + var baseLength = 4, paramsLength = bc[ip + baseLength - 1]; var value = c(bc[ip + 1]) + '(' @@ -433,14 +428,8 @@ module.exports = function(ast, options) { stackIndex ).join(', ') + ')'; - stack.pop(bc[ip + 3]); - if (bc[ip + 2] === flags.CHECK_FAILS) { - parts.push('peg$userFail = false;'); - } + stack.pop(bc[ip + 2]); parts.push(stack.push(value)); - if (bc[ip + 2] === flags.CHECK_FAILS) { - parts.push('if (peg$userFail) { ' + stack.top() + ' = peg$FAILED; }'); - } ip += baseLength + paramsLength; } @@ -597,7 +586,7 @@ module.exports = function(ast, options) { case op.FAIL: // FAIL e parts.push(stack.push('peg$FAILED')); - parts.push('if (peg$silentFails === 0) { peg$expected(' + c(bc[ip + 1]) + ', peg$currPos); }'); + parts.push('if (peg$silentFails === 0) { peg$fail(' + c(bc[ip + 1]) + '); }'); ip += 2; break; @@ -745,9 +734,7 @@ module.exports = function(ast, options) { ' peg$cachedPosDetails = { line: 1, column: 1, seenCR: false },', ' peg$maxFailPos = 0,', ' peg$maxFailExpected = [],', - ' peg$maxFailMessage = null,', ' peg$silentFails = 0,', // 0 = report failures, > 0 = silence failures - ' peg$userFail = false,', '' ].join('\n')); @@ -801,20 +788,15 @@ module.exports = function(ast, options) { ' }', '', ' function expected(description) {', - ' if (peg$silentFails === 0) {', - ' peg$expected(', - ' { type: "other", description: description },', - ' peg$reportedPos', - ' );', - ' }', - ' peg$userFail = true;', + ' throw peg$buildException(', + ' null,', + ' [{ type: "other", description: description }],', + ' peg$reportedPos', + ' );', ' }', '', ' function error(message) {', - ' if (peg$silentFails === 0) {', - ' peg$error(message, peg$reportedPos);', - ' }', - ' peg$userFail = true;', + ' throw peg$buildException(message, null, peg$reportedPos);', ' }', '', ' function peg$computePosDetails(pos) {', @@ -850,31 +832,18 @@ module.exports = function(ast, options) { ' return peg$cachedPosDetails;', ' }', '', - ' function peg$expected(expected, pos) {', - ' if (pos < peg$maxFailPos) { return; }', + ' function peg$fail(expected) {', + ' if (peg$currPos < peg$maxFailPos) { return; }', '', - ' if (pos > peg$maxFailPos) {', - ' peg$maxFailPos = pos;', + ' if (peg$currPos > peg$maxFailPos) {', + ' peg$maxFailPos = peg$currPos;', ' peg$maxFailExpected = [];', - ' peg$maxFailMessage = null;', ' }', '', ' peg$maxFailExpected.push(expected);', ' }', '', - ' function peg$error(message, pos) {', - ' if (pos < peg$maxFailPos) { return; }', - '', - ' if (pos > peg$maxFailPos) {', - ' peg$maxFailPos = pos;', - ' peg$maxFailExpected = [];', - ' peg$maxFailMessage = null;', - ' }', - '', - ' peg$maxFailMessage = message;', - ' }', - '', - ' function peg$buildException() {', + ' function peg$buildException(message, expected, pos) {', ' function cleanupExpected(expected) {', ' var i = 1;', '', @@ -888,8 +857,13 @@ module.exports = function(ast, options) { ' }', ' });', '', + /* + * This works because the bytecode generator guarantees that every + * expectation object exists only once, so it's enough to use |===| instead + * of deeper structural comparison. + */ ' while (i < expected.length) {', - ' if (expected[i - 1].description === expected[i].description) {', + ' if (expected[i - 1] === expected[i]) {', ' expected.splice(i, 1);', ' } else {', ' i++;', @@ -953,20 +927,15 @@ module.exports = function(ast, options) { ' return "Expected " + expectedDesc + " but " + foundDesc + " found.";', ' }', '', - ' var pos = Math.max(peg$currPos, peg$maxFailPos),', - ' posDetails = peg$computePosDetails(pos),', - ' expected = peg$maxFailMessage === null ? peg$maxFailExpected : null,', - ' found = pos < input.length ? input.charAt(pos) : null,', - ' message = peg$maxFailMessage !== null', - ' ? peg$maxFailMessage', - ' : buildMessage(expected, found);', + ' var posDetails = peg$computePosDetails(pos),', + ' found = pos < input.length ? input.charAt(pos) : null;', '', ' if (expected !== null) {', ' cleanupExpected(expected);', ' }', '', ' return new SyntaxError(', - ' message,', + ' message !== null ? message : buildMessage(expected, found),', ' expected,', ' found,', ' pos,', @@ -1003,7 +972,11 @@ module.exports = function(ast, options) { ' if (peg$result !== peg$FAILED && peg$currPos === input.length) {', ' return peg$result;', ' } else {', - ' throw peg$buildException();', + ' throw peg$buildException(', + ' null,', + ' peg$maxFailExpected,', + ' Math.max(peg$currPos, peg$maxFailPos)', + ' );', ' }', ' }', '', diff --git a/lib/parser.js b/lib/parser.js index a0b4d2a..cb9d347 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -263,7 +263,6 @@ module.exports = (function() { error( "Invalid character range: " + begin.rawText + "-" + end.rawText + "." ); - return; } return { @@ -341,9 +340,7 @@ module.exports = (function() { peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }, peg$maxFailPos = 0, peg$maxFailExpected = [], - peg$maxFailMessage = null, peg$silentFails = 0, - peg$userFail = false, peg$result; @@ -372,20 +369,15 @@ module.exports = (function() { } function expected(description) { - if (peg$silentFails === 0) { - peg$expected( - { type: "other", description: description }, - peg$reportedPos - ); - } - peg$userFail = true; + throw peg$buildException( + null, + [{ type: "other", description: description }], + peg$reportedPos + ); } function error(message) { - if (peg$silentFails === 0) { - peg$error(message, peg$reportedPos); - } - peg$userFail = true; + throw peg$buildException(message, null, peg$reportedPos); } function peg$computePosDetails(pos) { @@ -421,31 +413,18 @@ module.exports = (function() { return peg$cachedPosDetails; } - function peg$expected(expected, pos) { - if (pos < peg$maxFailPos) { return; } + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { return; } - if (pos > peg$maxFailPos) { - peg$maxFailPos = pos; + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; peg$maxFailExpected = []; - peg$maxFailMessage = null; } peg$maxFailExpected.push(expected); } - function peg$error(message, pos) { - if (pos < peg$maxFailPos) { return; } - - if (pos > peg$maxFailPos) { - peg$maxFailPos = pos; - peg$maxFailExpected = []; - peg$maxFailMessage = null; - } - - peg$maxFailMessage = message; - } - - function peg$buildException() { + function peg$buildException(message, expected, pos) { function cleanupExpected(expected) { var i = 1; @@ -460,7 +439,7 @@ module.exports = (function() { }); while (i < expected.length) { - if (expected[i - 1].description === expected[i].description) { + if (expected[i - 1] === expected[i]) { expected.splice(i, 1); } else { i++; @@ -514,20 +493,15 @@ module.exports = (function() { return "Expected " + expectedDesc + " but " + foundDesc + " found."; } - var pos = Math.max(peg$currPos, peg$maxFailPos), - posDetails = peg$computePosDetails(pos), - expected = peg$maxFailMessage === null ? peg$maxFailExpected : null, - found = pos < input.length ? input.charAt(pos) : null, - message = peg$maxFailMessage !== null - ? peg$maxFailMessage - : buildMessage(expected, found); + var posDetails = peg$computePosDetails(pos), + found = pos < input.length ? input.charAt(pos) : null; if (expected !== null) { cleanupExpected(expected); } return new SyntaxError( - message, + message !== null ? message : buildMessage(expected, found), expected, found, pos, @@ -559,9 +533,7 @@ module.exports = (function() { } if (s3 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c3(s2, s3); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -596,9 +568,7 @@ module.exports = (function() { } if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c4(s1); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -638,9 +608,7 @@ module.exports = (function() { } if (s5 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c5(s1, s2, s4); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -713,9 +681,7 @@ module.exports = (function() { } if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c6(s1, s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -748,9 +714,7 @@ module.exports = (function() { s2 = peg$parseaction(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c7(s1, s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -775,9 +739,7 @@ module.exports = (function() { } if (s1 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c8(s1); - if (peg$userFail) { s1 = peg$FAILED; } } if (s1 === peg$FAILED) { peg$currPos = s0; @@ -801,9 +763,7 @@ module.exports = (function() { s3 = peg$parseprefixed(); if (s3 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c9(s1, s3); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -838,9 +798,7 @@ module.exports = (function() { s2 = peg$parsesuffixed(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c10(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -862,9 +820,7 @@ module.exports = (function() { s2 = peg$parseaction(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c11(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -886,9 +842,7 @@ module.exports = (function() { s2 = peg$parsesuffixed(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c12(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -910,9 +864,7 @@ module.exports = (function() { s2 = peg$parseaction(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c13(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -934,9 +886,7 @@ module.exports = (function() { s2 = peg$parsesuffixed(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c14(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -971,9 +921,7 @@ module.exports = (function() { s2 = peg$parsequestion(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c15(s1); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -995,9 +943,7 @@ module.exports = (function() { s2 = peg$parsestar(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c16(s1); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1019,9 +965,7 @@ module.exports = (function() { s2 = peg$parseplus(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c17(s1); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1080,9 +1024,7 @@ module.exports = (function() { } if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c19(s1); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1106,9 +1048,7 @@ module.exports = (function() { s1 = peg$parsedot(); if (s1 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c20(); - if (peg$userFail) { s1 = peg$FAILED; } } if (s1 === peg$FAILED) { peg$currPos = s0; @@ -1125,9 +1065,7 @@ module.exports = (function() { s3 = peg$parserparen(); if (s3 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c21(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1164,9 +1102,7 @@ module.exports = (function() { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c23(s1); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1184,7 +1120,7 @@ module.exports = (function() { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c22, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c22); } } return s0; @@ -1200,7 +1136,7 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c25, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c25); } } if (s2 !== peg$FAILED) { s3 = []; @@ -1221,7 +1157,7 @@ module.exports = (function() { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c27, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c27); } } if (s4 !== peg$FAILED) { s2 = [s2, s3, s4]; @@ -1271,7 +1207,7 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c29, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c29); } } return s0; @@ -1286,15 +1222,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c31, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c31); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c32(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1322,15 +1256,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c34, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c34); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c35(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1358,15 +1290,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c37, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c37); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c38(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1394,15 +1324,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c40, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c40); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c41(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1430,15 +1358,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c43, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c43); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c44(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1466,15 +1392,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c46, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c46); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c47(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1502,15 +1426,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c49, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c49); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c50(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1538,15 +1460,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c52, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c52); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c53(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1574,15 +1494,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c55, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c55); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c56(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1610,15 +1528,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c58, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c58); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c59(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1646,15 +1562,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c61, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c61); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c62(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1682,15 +1596,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c64, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c64); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c65(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1718,15 +1630,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c67, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c67); } } if (s1 !== peg$FAILED) { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c68(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1759,7 +1669,7 @@ module.exports = (function() { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c71, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c71); } } } if (s3 !== peg$FAILED) { @@ -1773,7 +1683,7 @@ module.exports = (function() { peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c71, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c71); } } } } @@ -1788,7 +1698,7 @@ module.exports = (function() { peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c71, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c71); } } } } @@ -1812,9 +1722,7 @@ module.exports = (function() { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c72(s1); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1832,7 +1740,7 @@ module.exports = (function() { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c69, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c69); } } return s0; @@ -1853,7 +1761,7 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c75, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c75); } } if (s2 === peg$FAILED) { s2 = peg$c1; @@ -1862,9 +1770,7 @@ module.exports = (function() { s3 = peg$parse__(); if (s3 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c76(s1, s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1886,7 +1792,7 @@ module.exports = (function() { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c73, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c73); } } return s0; @@ -1905,9 +1811,7 @@ module.exports = (function() { s2 = peg$parse__(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c78(s1); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -1925,7 +1829,7 @@ module.exports = (function() { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c77, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c77); } } return s0; @@ -1940,7 +1844,7 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c80, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c80); } } if (s1 !== peg$FAILED) { s2 = []; @@ -1955,13 +1859,11 @@ module.exports = (function() { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c80, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c80); } } if (s3 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c81(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2018,7 +1920,7 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c80, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c80); } } if (s2 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 92) { @@ -2026,7 +1928,7 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c83, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c83); } } if (s2 === peg$FAILED) { s2 = peg$parseeolChar(); @@ -2045,13 +1947,11 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c84, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c84); } } if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c85(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2079,7 +1979,7 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c87, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c87); } } if (s1 !== peg$FAILED) { s2 = []; @@ -2094,13 +1994,11 @@ module.exports = (function() { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c87, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c87); } } if (s3 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c81(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2157,7 +2055,7 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c87, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c87); } } if (s2 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 92) { @@ -2165,7 +2063,7 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c83, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c83); } } if (s2 === peg$FAILED) { s2 = peg$parseeolChar(); @@ -2184,13 +2082,11 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c84, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c84); } } if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c85(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2219,7 +2115,7 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c90, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c90); } } if (s1 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 94) { @@ -2227,7 +2123,7 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c92, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c92); } } if (s2 === peg$FAILED) { s2 = peg$c1; @@ -2251,7 +2147,7 @@ module.exports = (function() { peg$currPos++; } else { s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c94, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c94); } } if (s4 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 105) { @@ -2259,7 +2155,7 @@ module.exports = (function() { peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c75, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c75); } } if (s5 === peg$FAILED) { s5 = peg$c1; @@ -2268,9 +2164,7 @@ module.exports = (function() { s6 = peg$parse__(); if (s6 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c95(s2, s3, s5); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2304,7 +2198,7 @@ module.exports = (function() { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c88, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c88); } } return s0; @@ -2321,15 +2215,13 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c97, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c97); } } if (s2 !== peg$FAILED) { s3 = peg$parseclassCharacter(); if (s3 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c98(s1, s3); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2359,9 +2251,7 @@ module.exports = (function() { s1 = peg$parsebracketDelimitedCharacter(); if (s1 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c99(s1); - if (peg$userFail) { s1 = peg$FAILED; } } if (s1 === peg$FAILED) { peg$currPos = s0; @@ -2407,7 +2297,7 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c94, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c94); } } if (s2 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 92) { @@ -2415,7 +2305,7 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c83, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c83); } } if (s2 === peg$FAILED) { s2 = peg$parseeolChar(); @@ -2434,13 +2324,11 @@ module.exports = (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c84, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c84); } } if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c85(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2468,7 +2356,7 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c83, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c83); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2480,7 +2368,7 @@ module.exports = (function() { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c101, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c101); } } if (s3 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 117) { @@ -2488,7 +2376,7 @@ module.exports = (function() { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c103, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c103); } } if (s3 === peg$FAILED) { s3 = peg$parseeolChar(); @@ -2508,13 +2396,11 @@ module.exports = (function() { peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c84, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c84); } } if (s3 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c104(s3); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2546,7 +2432,7 @@ module.exports = (function() { peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c106, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c106); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2561,9 +2447,7 @@ module.exports = (function() { } if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c107(); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2591,7 +2475,7 @@ module.exports = (function() { peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c109, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c109); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2616,9 +2500,7 @@ module.exports = (function() { s2 = s3; if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c110(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2646,7 +2528,7 @@ module.exports = (function() { peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c112, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c112); } } if (s1 !== peg$FAILED) { s2 = peg$currPos; @@ -2683,9 +2565,7 @@ module.exports = (function() { s2 = s3; if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c110(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2713,15 +2593,13 @@ module.exports = (function() { peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c83, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c83); } } if (s1 !== peg$FAILED) { s2 = peg$parseeol(); if (s2 !== peg$FAILED) { peg$reportedPos = s0; - peg$userFail = false; s1 = peg$c113(s2); - if (peg$userFail) { s1 = peg$FAILED; } if (s1 === peg$FAILED) { peg$currPos = s0; s0 = s1; @@ -2748,7 +2626,7 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c115, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c115); } } return s0; @@ -2762,7 +2640,7 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c117, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c117); } } return s0; @@ -2787,7 +2665,7 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c119, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c119); } } return s0; @@ -2801,7 +2679,7 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c121, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c121); } } return s0; @@ -2843,7 +2721,7 @@ module.exports = (function() { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c122, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c122); } } return s0; @@ -2858,7 +2736,7 @@ module.exports = (function() { peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c124, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c124); } } if (s1 !== peg$FAILED) { s2 = []; @@ -2879,7 +2757,7 @@ module.exports = (function() { peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c84, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c84); } } if (s5 !== peg$FAILED) { s4 = [s4, s5]; @@ -2911,7 +2789,7 @@ module.exports = (function() { peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c84, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c84); } } if (s5 !== peg$FAILED) { s4 = [s4, s5]; @@ -2949,7 +2827,7 @@ module.exports = (function() { peg$currPos += 2; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c126, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c126); } } if (s1 !== peg$FAILED) { s2 = []; @@ -2961,7 +2839,7 @@ module.exports = (function() { peg$currPos += 2; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c128, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c128); } } peg$silentFails--; if (s5 === peg$FAILED) { @@ -2976,7 +2854,7 @@ module.exports = (function() { peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c84, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c84); } } if (s5 !== peg$FAILED) { s4 = [s4, s5]; @@ -2999,7 +2877,7 @@ module.exports = (function() { peg$currPos += 2; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c128, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c128); } } peg$silentFails--; if (s5 === peg$FAILED) { @@ -3014,7 +2892,7 @@ module.exports = (function() { peg$currPos++; } else { s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c84, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c84); } } if (s5 !== peg$FAILED) { s4 = [s4, s5]; @@ -3034,7 +2912,7 @@ module.exports = (function() { peg$currPos += 2; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c128, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c128); } } if (s3 !== peg$FAILED) { s1 = [s1, s2, s3]; @@ -3064,7 +2942,7 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c131, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c131); } } if (s0 === peg$FAILED) { if (input.substr(peg$currPos, 2) === peg$c132) { @@ -3072,7 +2950,7 @@ module.exports = (function() { peg$currPos += 2; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c133, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c133); } } if (s0 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 13) { @@ -3080,7 +2958,7 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c135, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c135); } } if (s0 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8232) { @@ -3088,7 +2966,7 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c137, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c137); } } if (s0 === peg$FAILED) { if (input.charCodeAt(peg$currPos) === 8233) { @@ -3096,7 +2974,7 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c139, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c139); } } } } @@ -3105,7 +2983,7 @@ module.exports = (function() { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c129, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c129); } } return s0; @@ -3119,7 +2997,7 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c141, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c141); } } return s0; @@ -3134,12 +3012,12 @@ module.exports = (function() { peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c144, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c144); } } peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$expected(peg$c142, peg$currPos); } + if (peg$silentFails === 0) { peg$fail(peg$c142); } } return s0; @@ -3154,7 +3032,11 @@ module.exports = (function() { if (peg$result !== peg$FAILED && peg$currPos === input.length) { return peg$result; } else { - throw peg$buildException(); + throw peg$buildException( + null, + peg$maxFailExpected, + Math.max(peg$currPos, peg$maxFailPos) + ); } } diff --git a/package.json b/package.json index 645eb3f..fa2fcfb 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "examples/json.pegjs", "lib/compiler.js", "lib/compiler/opcodes.js", - "lib/compiler/flags.js", "lib/compiler/passes/generate-bytecode.js", "lib/compiler/passes/generate-javascript.js", "lib/compiler/passes/remove-proxy-rules.js", diff --git a/spec/compiler/passes/generate-bytecode.spec.js b/spec/compiler/passes/generate-bytecode.spec.js index 1a59668..84ed6b6 100644 --- a/spec/compiler/passes/generate-bytecode.spec.js +++ b/spec/compiler/passes/generate-bytecode.spec.js @@ -89,14 +89,14 @@ describe("compiler pass |generateBytecode|", function() { it("generates correct bytecode", function() { expect(pass).toChangeAST(grammar, bytecodeDetails([ - 1, // PUSH_CURR_POS - 0, 0, // PUSH - 12, 7, 0, // IF_NOT_ERROR - 21, 1, // * REPORT_SAVED_POS - 23, 1, 1, 1, 0, // CALL - 11, 1, 1, // IF_ERROR - 6, // * NIP_CURR_POS - 5 // * NIP + 1, // PUSH_CURR_POS + 0, 0, // PUSH + 12, 6, 0, // IF_NOT_ERROR + 21, 1, // * REPORT_SAVED_POS + 23, 1, 1, 0, // CALL + 11, 1, 1, // IF_ERROR + 6, // * NIP_CURR_POS + 5 // * NIP ])); }); @@ -115,9 +115,9 @@ describe("compiler pass |generateBytecode|", function() { expect(pass).toChangeAST(grammar, bytecodeDetails([ 1, // PUSH_CURR_POS 15, 0, 2, 2, 19, 0, 20, 1, // - 12, 8, 0, // IF_NOT_ERROR + 12, 7, 0, // IF_NOT_ERROR 21, 1, // * REPORT_SAVED_POS - 23, 2, 1, 1, 1, 0, // CALL + 23, 2, 1, 1, 0, // CALL 11, 1, 1, // IF_ERROR 6, // * NIP_CURR_POS 5 // * NIP @@ -139,13 +139,13 @@ describe("compiler pass |generateBytecode|", function() { expect(pass).toChangeAST(grammar, bytecodeDetails([ 1, // PUSH_CURR_POS 15, 1, 2, 2, 19, 1, 20, 2, // - 12, 47, 4, // IF_NOT_ERROR + 12, 46, 4, // IF_NOT_ERROR 15, 3, 2, 2, 19, 3, 20, 4, // * - 12, 31, 5, // IF_NOT_ERROR + 12, 30, 5, // IF_NOT_ERROR 15, 5, 2, 2, 19, 5, 20, 6, // * - 12, 15, 5, // IF_NOT_ERROR + 12, 14, 5, // IF_NOT_ERROR 21, 3, // * REPORT_SAVED_POS - 23, 7, 1, 3, 3, 2, 1, 0, // CALL + 23, 7, 3, 3, 2, 1, 0, // CALL 11, 1, 1, // IF_ERROR 6, // * NIP_CURR_POS 5, // * NIP @@ -315,13 +315,13 @@ describe("compiler pass |generateBytecode|", function() { it("generates correct bytecode", function() { expect(pass).toChangeAST(grammar, bytecodeDetails([ - 22, // REPORT_CURR_POS - 23, 0, 0, 0, 0, // CALL - 10, 3, 3, // IF - 2, // * POP - 0, 1, // PUSH - 2, // * POP - 0, 2 // PUSH + 22, // REPORT_CURR_POS + 23, 0, 0, 0, // CALL + 10, 3, 3, // IF + 2, // * POP + 0, 1, // PUSH + 2, // * POP + 0, 2 // PUSH ])); }); @@ -340,13 +340,13 @@ describe("compiler pass |generateBytecode|", function() { expect(pass).toChangeAST(grammar, bytecodeDetails([ 1, // PUSH_CURR_POS 15, 1, 2, 2, 19, 1, 20, 2, // - 12, 61, 4, // IF_NOT_ERROR + 12, 60, 4, // IF_NOT_ERROR 15, 3, 2, 2, 19, 3, 20, 4, // * - 12, 45, 5, // IF_NOT_ERROR + 12, 44, 5, // IF_NOT_ERROR 15, 5, 2, 2, 19, 5, 20, 6, // * - 12, 29, 5, // IF_NOT_ERROR + 12, 28, 5, // IF_NOT_ERROR 22, // * REPORT_CURR_POS - 23, 7, 0, 0, 3, 2, 1, 0, // CALL + 23, 7, 0, 3, 2, 1, 0, // CALL 10, 3, 3, // IF 2, // * POP 0, 8, // PUSH @@ -392,13 +392,13 @@ describe("compiler pass |generateBytecode|", function() { it("generates correct bytecode", function() { expect(pass).toChangeAST(grammar, bytecodeDetails([ - 22, // REPORT_CURR_POS - 23, 0, 0, 0, 0, // CALL_PREDICATE - 10, 3, 3, // IF - 2, // * POP - 0, 2, // PUSH - 2, // * POP - 0, 1 // PUSH + 22, // REPORT_CURR_POS + 23, 0, 0, 0, // CALL_PREDICATE + 10, 3, 3, // IF + 2, // * POP + 0, 2, // PUSH + 2, // * POP + 0, 1 // PUSH ])); }); @@ -417,13 +417,13 @@ describe("compiler pass |generateBytecode|", function() { expect(pass).toChangeAST(grammar, bytecodeDetails([ 1, // PUSH_CURR_POS 15, 1, 2, 2, 19, 1, 20, 2, // - 12, 61, 4, // IF_NOT_ERROR + 12, 60, 4, // IF_NOT_ERROR 15, 3, 2, 2, 19, 3, 20, 4, // * - 12, 45, 5, // IF_NOT_ERROR + 12, 44, 5, // IF_NOT_ERROR 15, 5, 2, 2, 19, 5, 20, 6, // * - 12, 29, 5, // IF_NOT_ERROR + 12, 28, 5, // IF_NOT_ERROR 22, // * REPORT_CURR_POS - 23, 7, 0, 0, 3, 2, 1, 0, // CALL + 23, 7, 0, 3, 2, 1, 0, // CALL 10, 3, 3, // IF 2, // * POP 0, 0, // PUSH diff --git a/spec/generated-parser.spec.js b/spec/generated-parser.spec.js index a1a5bd4..ec98e28 100644 --- a/spec/generated-parser.spec.js +++ b/spec/generated-parser.spec.js @@ -337,117 +337,35 @@ describe("generated parser", function() { expect(parser).toParse("a", 42); }); - describe("|expected| function", function() { - it("generates a regular match failure", function() { - var parser = PEG.buildParser( - 'start = "a" { expected("a"); }', - options - ); - - expect(parser).toFailToParse("a", { - offset: 0, - line: 1, - column: 1, - expected: [{ type: "other", description: "a" }], - found: "a", - message: 'Expected a but "a" found.' - }); - }); - - it("generated failures combine with failures generated before", function() { - var parser = PEG.buildParser( - 'start = "a" / ("b" { expected("b"); })', - options - ); - - expect(parser).toFailToParse("b", { - expected: [ - { type: "literal", value: "a", description: '"a"' }, - { type: "other", description: "b" } - ] - }); - }); - - it("generated failures combine with failures generated after", function() { - var parser = PEG.buildParser( - 'start = ("a" { expected("a"); }) / "b"', - options - ); - - expect(parser).toFailToParse("a", { - expected: [ - { type: "literal", value: "b", description: '"b"' }, - { type: "other", description: "a" } - ] - }); - }); - - it("multiple invocations generate additional failures", function() { - var parser = PEG.buildParser( - 'start = "a" { expected("a1"); expected("a2"); }', - options - ); + it("can use the |expected| function to trigger an error", function() { + var parser = PEG.buildParser( + 'start = "a" { expected("a"); }', + options + ); - expect(parser).toFailToParse("a", { - expected: [ - { type: "other", description: "a1" }, - { type: "other", description: "a2" } - ] - }); + expect(parser).toFailToParse("a", { + message: 'Expected a but "a" found.', + expected: [{ type: "other", description: "a" }], + found: "a", + offset: 0, + line: 1, + column: 1 }); }); - describe("|error| function", function() { - it("generates a custom match failure", function() { - var parser = PEG.buildParser( - 'start = "a" { error("a"); }', - options - ); - - expect(parser).toFailToParse("a", { - offset: 0, - line: 1, - column: 1, - expected: null, - found: "a", - message: "a" - }); - }); - - it("generated failures overrides failures generated before", function() { - var parser = PEG.buildParser( - 'start = "a" / ("b" { error("b"); })', - options - ); - - expect(parser).toFailToParse("b", { - message: "b", - expected: null - }); - }); - - it("generated failures override failures generated after", function() { - var parser = PEG.buildParser( - 'start = ("a" { error("a"); }) / "b"', - options - ); - - expect(parser).toFailToParse("a", { - message: "a", - expected: null - }); - }); - - it("the last invocation wins", function() { - var parser = PEG.buildParser( - 'start = "a" { error("a1"); error("a2"); }', - options - ); + it("can use the |error| function to trigger an error", function() { + var parser = PEG.buildParser( + 'start = "a" { error("a"); }', + options + ); - expect(parser).toFailToParse("a", { - message: "a2", - expected: null - }); + expect(parser).toFailToParse("a", { + message: "a", + expected: null, + found: "a", + offset: 0, + line: 1, + column: 1 }); }); diff --git a/src/parser.pegjs b/src/parser.pegjs index a864e03..b9efa6c 100644 --- a/src/parser.pegjs +++ b/src/parser.pegjs @@ -270,7 +270,6 @@ classCharacterRange error( "Invalid character range: " + begin.rawText + "-" + end.rawText + "." ); - return; } return {