From 7ca229a43247636de73e35248ca8597a1e70b04f Mon Sep 17 00:00:00 2001 From: David Majda Date: Tue, 4 Oct 2016 11:00:25 +0200 Subject: [PATCH] Improve indentation of variable declarations Before this commit, continuation lines of multi-line values in variable declaration initializers were aligned with the variable name: let foo = { a: 5, b: 6 }; This was highly irregular, maintenance intensive, and made declarations look different from assignments. This commit changes the indentation to be more regular and similar to assignments: let foo = { a: 5, b: 6 }; --- benchmark/index.js | 6 +- benchmark/runner.js | 32 +- lib/compiler/passes/generate-bytecode.js | 66 +- lib/compiler/passes/generate-js.js | 156 ++--- lib/compiler/visitor.js | 60 +- lib/parser.js | 52 +- lib/peg.js | 6 +- spec/api/generated-parser-api.spec.js | 16 +- spec/api/pegjs-api.spec.js | 16 +- spec/api/plugin-api.spec.js | 128 ++-- .../generated-parser-behavior.spec.js | 642 +++++++++--------- spec/unit/parser.spec.js | 44 +- 12 files changed, 612 insertions(+), 612 deletions(-) diff --git a/benchmark/index.js b/benchmark/index.js index c84f449..8bf2919 100644 --- a/benchmark/index.js +++ b/benchmark/index.js @@ -62,9 +62,9 @@ $("#run").click(() => { let runCount = parseInt($("#run-count").val(), 10); let options = { - cache: $("#cache").is(":checked"), - optimize: $("#optimize").val() - }; + cache: $("#cache").is(":checked"), + optimize: $("#optimize").val() + }; if (isNaN(runCount) || runCount <= 0) { alert("Number of runs must be a positive integer."); diff --git a/benchmark/runner.js b/benchmark/runner.js index af4a8de..3e01abe 100644 --- a/benchmark/runner.js +++ b/benchmark/runner.js @@ -10,22 +10,22 @@ let Runner = { // Queue let Q = { - functions: [], - - add: function(f) { - this.functions.push(f); - }, - - run: function() { - if (this.functions.length > 0) { - this.functions.shift()(); - - // We can't use |arguments.callee| here because |this| would get - // messed-up in that case. - setTimeout(() => { Q.run(); }, 0); - } - } - }; + functions: [], + + add: function(f) { + this.functions.push(f); + }, + + run: function() { + if (this.functions.length > 0) { + this.functions.shift()(); + + // We can't use |arguments.callee| here because |this| would get + // messed-up in that case. + setTimeout(() => { Q.run(); }, 0); + } + } + }; // The benchmark itself is factored out into several functions (some of them // generated), which are enqueued and run one by one using |setTimeout|. We diff --git a/lib/compiler/passes/generate-bytecode.js b/lib/compiler/passes/generate-bytecode.js index 7bde9de..63d0b44 100644 --- a/lib/compiler/passes/generate-bytecode.js +++ b/lib/compiler/passes/generate-bytecode.js @@ -348,10 +348,10 @@ function generateBytecode(ast) { let emitCall = node.expression.type !== "sequence" || node.expression.elements.length === 0; let expressionCode = generate(node.expression, { - sp: context.sp + (emitCall ? 1 : 0), - env: env, - action: node - }); + sp: context.sp + (emitCall ? 1 : 0), + env: env, + action: node + }); let functionIndex = addFunctionConst(Object.keys(env), node.code); return emitCall @@ -482,10 +482,10 @@ function generateBytecode(ast) { zero_or_more: function(node, context) { let expressionCode = generate(node.expression, { - sp: context.sp + 1, - env: cloneEnv(context.env), - action: null - }); + sp: context.sp + 1, + env: cloneEnv(context.env), + action: null + }); return buildSequence( [op.PUSH_EMPTY_ARRAY], @@ -497,10 +497,10 @@ function generateBytecode(ast) { one_or_more: function(node, context) { let expressionCode = generate(node.expression, { - sp: context.sp + 1, - env: cloneEnv(context.env), - action: null - }); + sp: context.sp + 1, + env: cloneEnv(context.env), + action: null + }); return buildSequence( [op.PUSH_EMPTY_ARRAY], @@ -569,30 +569,30 @@ function generateBytecode(ast) { "class": function(node) { let regexp = "/^[" - + (node.inverted ? "^" : "") - + node.parts.map(part => - Array.isArray(part) - ? js.regexpClassEscape(part[0]) - + "-" - + js.regexpClassEscape(part[1]) - : js.regexpClassEscape(part) - ).join("") - + "]/" + (node.ignoreCase ? "i" : ""); + + (node.inverted ? "^" : "") + + node.parts.map(part => + Array.isArray(part) + ? js.regexpClassEscape(part[0]) + + "-" + + js.regexpClassEscape(part[1]) + : js.regexpClassEscape(part) + ).join("") + + "]/" + (node.ignoreCase ? "i" : ""); let parts = "[" - + node.parts.map(part => - Array.isArray(part) - ? "[\"" + js.stringEscape(part[0]) + "\", \"" + js.stringEscape(part[1]) + "\"]" - : "\"" + js.stringEscape(part) + "\"" - ).join(", ") - + "]"; + + node.parts.map(part => + Array.isArray(part) + ? "[\"" + js.stringEscape(part[0]) + "\", \"" + js.stringEscape(part[1]) + "\"]" + : "\"" + js.stringEscape(part) + "\"" + ).join(", ") + + "]"; let regexpIndex = addConst(regexp); let expectedIndex = addConst( - "peg$classExpectation(" - + parts + ", " - + node.inverted + ", " - + node.ignoreCase - + ")" - ); + "peg$classExpectation(" + + parts + ", " + + node.inverted + ", " + + node.ignoreCase + + ")" + ); return buildCondition( [op.MATCH_REGEXP, regexpIndex], diff --git a/lib/compiler/passes/generate-js.js b/lib/compiler/passes/generate-js.js index 3bd3ebc..fe50287 100644 --- a/lib/compiler/passes/generate-js.js +++ b/lib/compiler/passes/generate-js.js @@ -411,41 +411,41 @@ function generateJS(ast, options) { function s(i) { return "s" + i; } // |stack[i]| of the abstract machine let stack = { - sp: -1, - maxSp: -1, + sp: -1, + maxSp: -1, - push: function(exprCode) { - let code = s(++this.sp) + " = " + exprCode + ";"; + push: function(exprCode) { + let code = s(++this.sp) + " = " + exprCode + ";"; - if (this.sp > this.maxSp) { this.maxSp = this.sp; } + if (this.sp > this.maxSp) { this.maxSp = this.sp; } - return code; - }, + return code; + }, - pop: function(n) { - if (n === undefined) { - return s(this.sp--); - } else { - let values = Array(n); + pop: function(n) { + if (n === undefined) { + return s(this.sp--); + } else { + let values = Array(n); - for (var i = 0; i < n; i++) { - values[i] = s(this.sp - n + 1 + i); - } + for (var i = 0; i < n; i++) { + values[i] = s(this.sp - n + 1 + i); + } - this.sp -= n; + this.sp -= n; - return values; - } - }, + return values; + } + }, - top: function() { - return s(this.sp); - }, + top: function() { + return s(this.sp); + }, - index: function(i) { - return s(this.sp - i); - } - }; + index: function(i) { + return s(this.sp - i); + } + }; function compile(bc) { let ip = 0; @@ -512,10 +512,10 @@ function generateJS(ast, options) { let paramsLength = bc[ip + baseLength - 1]; let value = c(bc[ip + 1]) + "(" - + bc.slice(ip + baseLength, ip + baseLength + paramsLength).map( - p => stack.index(p) - ).join(", ") - + ")"; + + bc.slice(ip + baseLength, ip + baseLength + paramsLength).map( + p => stack.index(p) + ).join(", ") + + ")"; stack.pop(bc[ip + 2]); parts.push(stack.push(value)); ip += baseLength + paramsLength; @@ -767,32 +767,32 @@ function generateJS(ast, options) { "", "peg$SyntaxError.buildMessage = function(expected, found) {", " var DESCRIBE_EXPECTATION_FNS = {", - " literal: function(expectation) {", - " return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";", - " },", - "", - " \"class\": function(expectation) {", - " var escapedParts = expectation.parts.map(function(part) {", - " return Array.isArray(part)", - " ? classEscape(part[0]) + \"-\" + classEscape(part[1])", - " : classEscape(part);", - " });", - "", - " return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";", - " },", - "", - " any: function(expectation) {", - " return \"any character\";", - " },", - "", - " end: function(expectation) {", - " return \"end of input\";", - " },", - "", - " other: function(expectation) {", - " return expectation.description;", - " }", - " };", + " literal: function(expectation) {", + " return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";", + " },", + "", + " \"class\": function(expectation) {", + " var escapedParts = expectation.parts.map(function(part) {", + " return Array.isArray(part)", + " ? classEscape(part[0]) + \"-\" + classEscape(part[1])", + " : classEscape(part);", + " });", + "", + " 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();", @@ -935,10 +935,10 @@ function generateJS(ast, options) { if (options.optimize === "size") { let startRuleIndices = "{ " - + options.allowedStartRules.map( - r => r + ": " + asts.indexOfRule(ast, r) - ).join(", ") - + " }"; + + options.allowedStartRules.map( + r => r + ": " + asts.indexOfRule(ast, r) + ).join(", ") + + " }"; let startRuleIndex = asts.indexOfRule(ast, options.allowedStartRules[0]); parts.push([ @@ -947,10 +947,10 @@ function generateJS(ast, options) { ].join("\n")); } else { let startRuleFunctions = "{ " - + options.allowedStartRules.map( - r => r + ": peg$parse" + r - ).join(", ") - + " }"; + + options.allowedStartRules.map( + r => r + ": peg$parse" + r + ).join(", ") + + " }"; let startRuleFunction = "peg$parse" + options.allowedStartRules[0]; parts.push([ @@ -984,10 +984,10 @@ function generateJS(ast, options) { if (options.trace) { if (options.optimize === "size") { let ruleNames = "[" - + ast.rules.map( - r => "\"" + js.stringEscape(r.name) + "\"" - ).join(", ") - + "]"; + + ast.rules.map( + r => "\"" + js.stringEscape(r.name) + "\"" + ).join(", ") + + "]"; parts.push([ " var peg$ruleNames = " + ruleNames + ";", @@ -1272,10 +1272,10 @@ function generateJS(ast, options) { let dependencyVars = Object.keys(options.dependencies); let dependencyIds = dependencyIds.map(v => options.dependencies[v]); let dependencies = "[" - + dependencyIds.map( - id => "\"" + js.stringEscape(id) + "\"" - ).join(", ") - + "]"; + + dependencyIds.map( + id => "\"" + js.stringEscape(id) + "\"" + ).join(", ") + + "]"; let params = dependencyVars.join(", "); return [ @@ -1310,13 +1310,13 @@ function generateJS(ast, options) { let dependencyVars = Object.keys(options.dependencies); let dependencyIds = dependencyIds.map(v => options.dependencies[v]); let dependencies = "[" - + dependencyIds.map( - id => "\"" + js.stringEscape(id) + "\"" - ).join(", ") - + "]"; + + dependencyIds.map( + id => "\"" + js.stringEscape(id) + "\"" + ).join(", ") + + "]"; let requires = dependencyIds.map( - id => "require(\"" + js.stringEscape(id) + "\")" - ).join(", "); + id => "require(\"" + js.stringEscape(id) + "\")" + ).join(", "); let params = dependencyVars.join(", "); parts.push([ diff --git a/lib/compiler/visitor.js b/lib/compiler/visitor.js index 74143ec..b51084d 100644 --- a/lib/compiler/visitor.js +++ b/lib/compiler/visitor.js @@ -26,39 +26,39 @@ let visitor = { } const DEFAULT_FUNCTIONS = { - grammar: function(node) { - let extraArgs = Array.prototype.slice.call(arguments, 1); + grammar: function(node) { + let extraArgs = Array.prototype.slice.call(arguments, 1); - if (node.initializer) { - visit.apply(null, [node.initializer].concat(extraArgs)); - } + if (node.initializer) { + visit.apply(null, [node.initializer].concat(extraArgs)); + } - node.rules.forEach(rule => { - visit.apply(null, [rule].concat(extraArgs)); - }); - }, + node.rules.forEach(rule => { + visit.apply(null, [rule].concat(extraArgs)); + }); + }, - initializer: visitNop, - rule: visitExpression, - named: visitExpression, - choice: visitChildren("alternatives"), - action: visitExpression, - sequence: visitChildren("elements"), - labeled: visitExpression, - text: visitExpression, - simple_and: visitExpression, - simple_not: visitExpression, - optional: visitExpression, - zero_or_more: visitExpression, - one_or_more: visitExpression, - group: visitExpression, - semantic_and: visitNop, - semantic_not: visitNop, - rule_ref: visitNop, - literal: visitNop, - "class": visitNop, - any: visitNop - }; + initializer: visitNop, + rule: visitExpression, + named: visitExpression, + choice: visitChildren("alternatives"), + action: visitExpression, + sequence: visitChildren("elements"), + labeled: visitExpression, + text: visitExpression, + simple_and: visitExpression, + simple_not: visitExpression, + optional: visitExpression, + zero_or_more: visitExpression, + one_or_more: visitExpression, + group: visitExpression, + semantic_and: visitNop, + semantic_not: visitNop, + rule_ref: visitNop, + literal: visitNop, + "class": visitNop, + any: visitNop + }; Object.keys(DEFAULT_FUNCTIONS).forEach(type => { if (!functions.hasOwnProperty(type)) { diff --git a/lib/parser.js b/lib/parser.js index 506d40b..61c51cb 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -28,32 +28,32 @@ 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 = expectation.parts.map(function(part) { - return Array.isArray(part) - ? classEscape(part[0]) + "-" + classEscape(part[1]) - : classEscape(part); - }); - - return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; - }, - - any: function(expectation) { - return "any character"; - }, - - end: function(expectation) { - return "end of input"; - }, - - other: function(expectation) { - return expectation.description; - } - }; + literal: function(expectation) { + return "\"" + literalEscape(expectation.text) + "\""; + }, + + "class": function(expectation) { + var escapedParts = expectation.parts.map(function(part) { + return Array.isArray(part) + ? classEscape(part[0]) + "-" + classEscape(part[1]) + : classEscape(part); + }); + + 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(); diff --git a/lib/peg.js b/lib/peg.js index 1557ba2..39ac51a 100644 --- a/lib/peg.js +++ b/lib/peg.js @@ -33,9 +33,9 @@ let peg = { let plugins = "plugins" in options ? options.plugins : []; let config = { - parser: peg.parser, - passes: convertPasses(peg.compiler.passes) - }; + parser: peg.parser, + passes: convertPasses(peg.compiler.passes) + }; plugins.forEach(p => { p.use(config, options); }); diff --git a/spec/api/generated-parser-api.spec.js b/spec/api/generated-parser-api.spec.js index f25de0a..a52cfaa 100644 --- a/spec/api/generated-parser-api.spec.js +++ b/spec/api/generated-parser-api.spec.js @@ -21,10 +21,10 @@ describe("generated parser API", function() { describe("start rule", function() { let parser = peg.generate([ - "a = 'x' { return 'a'; }", - "b = 'x' { return 'b'; }", - "c = 'x' { return 'c'; }" - ].join("\n"), { allowedStartRules: ["b", "c"] }); + "a = 'x' { return 'a'; }", + "b = 'x' { return 'b'; }", + "c = 'x' { return 'c'; }" + ].join("\n"), { allowedStartRules: ["b", "c"] }); describe("when |startRule| is not set", function() { it("starts parsing from the first allowed rule", function() { @@ -48,10 +48,10 @@ describe("generated parser API", function() { describe("tracing", function() { let parser = peg.generate([ - "start = a / b", - "a = 'a'", - "b = 'b'" - ].join("\n"), { trace: true }); + "start = a / b", + "a = 'a'", + "b = 'b'" + ].join("\n"), { trace: true }); describe("default tracer", function() { it("traces using console.log (if console is defined)", function() { diff --git a/spec/api/pegjs-api.spec.js b/spec/api/pegjs-api.spec.js index 047ff91..956e0b0 100644 --- a/spec/api/pegjs-api.spec.js +++ b/spec/api/pegjs-api.spec.js @@ -21,10 +21,10 @@ describe("PEG.js API", function() { describe("allowed start rules", function() { let grammar = [ - "a = 'x'", - "b = 'x'", - "c = 'x'" - ].join("\n"); + "a = 'x'", + "b = 'x'", + "c = 'x'" + ].join("\n"); // The |allowedStartRules| option is implemented separately for each // optimization mode, so we need to test it in both. @@ -82,10 +82,10 @@ describe("PEG.js API", function() { describe("intermediate results caching", function() { let grammar = [ - "{ var n = 0; }", - "start = (a 'b') / (a 'c') { return n; }", - "a = 'a' { n++; }" - ].join("\n"); + "{ var n = 0; }", + "start = (a 'b') / (a 'c') { return n; }", + "a = 'a' { n++; }" + ].join("\n"); describe("when |cache| is not set", function() { it("generated parser doesn't cache intermediate parse results", function() { diff --git a/spec/api/plugin-api.spec.js b/spec/api/plugin-api.spec.js index 4c0b1ee..56db185 100644 --- a/spec/api/plugin-api.spec.js +++ b/spec/api/plugin-api.spec.js @@ -40,10 +40,10 @@ describe("plugin API", function() { it("is called for each plugin", function() { let pluginsUsed = [false, false, false]; let plugins = [ - { use: function() { pluginsUsed[0] = true; } }, - { use: function() { pluginsUsed[1] = true; } }, - { use: function() { pluginsUsed[2] = true; } } - ]; + { use: function() { pluginsUsed[0] = true; } }, + { use: function() { pluginsUsed[1] = true; } }, + { use: function() { pluginsUsed[2] = true; } } + ]; peg.generate(grammar, { plugins: plugins }); @@ -52,40 +52,40 @@ describe("plugin API", function() { it("receives configuration", function() { let plugin = { - use: function(config) { - expect(config).toBeObject(); + use: function(config) { + expect(config).toBeObject(); - expect(config.parser).toBeObject(); - expect(config.parser.parse("start = 'a'")).toBeObject(); + expect(config.parser).toBeObject(); + expect(config.parser.parse("start = 'a'")).toBeObject(); - expect(config.passes).toBeObject(); + expect(config.passes).toBeObject(); - expect(config.passes.check).toBeArray(); - config.passes.check.forEach(pass => { - expect(pass).toBeFunction(); - }); + expect(config.passes.check).toBeArray(); + config.passes.check.forEach(pass => { + expect(pass).toBeFunction(); + }); - expect(config.passes.transform).toBeArray(); - config.passes.transform.forEach(pass => { - expect(pass).toBeFunction(); - }); + expect(config.passes.transform).toBeArray(); + config.passes.transform.forEach(pass => { + expect(pass).toBeFunction(); + }); - expect(config.passes.generate).toBeArray(); - config.passes.generate.forEach(pass => { - expect(pass).toBeFunction(); - }); - } - }; + expect(config.passes.generate).toBeArray(); + config.passes.generate.forEach(pass => { + expect(pass).toBeFunction(); + }); + } + }; peg.generate(grammar, { plugins: [plugin] }); }); it("receives options", function() { let plugin = { - use: function(config, options) { - expect(options).toEqual(generateOptions); - } - }; + use: function(config, options) { + expect(options).toEqual(generateOptions); + } + }; let generateOptions = { plugins: [plugin], foo: 42 }; peg.generate(grammar, generateOptions); @@ -93,25 +93,25 @@ describe("plugin API", function() { it("can replace parser", function() { let plugin = { - use: function(config) { - let parser = peg.generate([ - "start = .* {", - " return {", - " type: 'grammar',", - " rules: [", - " {", - " type: 'rule',", - " name: 'start',", - " expression: { type: 'literal', value: text(), ignoreCase: false }", - " }", - " ]", - " };", - "}" - ].join("\n")); - - config.parser = parser; - } - }; + use: function(config) { + let parser = peg.generate([ + "start = .* {", + " return {", + " type: 'grammar',", + " rules: [", + " {", + " type: 'rule',", + " name: 'start',", + " expression: { type: 'literal', value: text(), ignoreCase: false }", + " }", + " ]", + " };", + "}" + ].join("\n")); + + config.parser = parser; + } + }; let parser = peg.generate("a", { plugins: [plugin] }); expect(parser.parse("a")).toBe("a"); @@ -119,14 +119,14 @@ describe("plugin API", function() { it("can change compiler passes", function() { let plugin = { - use: function(config) { - let pass = ast => { - ast.code = "({ parse: function() { return 42; } })"; - }; - - config.passes.generate = [pass]; - } + use: function(config) { + let pass = ast => { + ast.code = "({ parse: function() { return 42; } })"; }; + + config.passes.generate = [pass]; + } + }; let parser = peg.generate(grammar, { plugins: [plugin] }); expect(parser.parse("a")).toBe(42); @@ -134,19 +134,19 @@ describe("plugin API", function() { it("can change options", function() { let grammar = [ - "a = 'x'", - "b = 'x'", - "c = 'x'" - ].join("\n"); + "a = 'x'", + "b = 'x'", + "c = 'x'" + ].join("\n"); let plugin = { - use: function(config, options) { - options.allowedStartRules = ["b", "c"]; - } - }; + use: function(config, options) { + options.allowedStartRules = ["b", "c"]; + } + }; let parser = peg.generate(grammar, { - allowedStartRules: ["a"], - plugins: [plugin] - }); + allowedStartRules: ["a"], + plugins: [plugin] + }); expect(() => { parser.parse("x", { startRule: "a" }); }).toThrow(); expect(parser.parse("x", { startRule: "b" })).toBe("x"); diff --git a/spec/behavior/generated-parser-behavior.spec.js b/spec/behavior/generated-parser-behavior.spec.js index a28da22..607d21e 100644 --- a/spec/behavior/generated-parser-behavior.spec.js +++ b/spec/behavior/generated-parser-behavior.spec.js @@ -18,15 +18,15 @@ describe("generated parser behavior", function() { } let optionsVariants = [ - { cache: false, optimize: "speed", trace: false }, - { cache: false, optimize: "speed", trace: true }, - { cache: false, optimize: "size", trace: false }, - { cache: false, optimize: "size", trace: true }, - { cache: true, optimize: "speed", trace: false }, - { cache: true, optimize: "speed", trace: true }, - { cache: true, optimize: "size", trace: false }, - { cache: true, optimize: "size", trace: true } - ]; + { cache: false, optimize: "speed", trace: false }, + { cache: false, optimize: "speed", trace: true }, + { cache: false, optimize: "size", trace: false }, + { cache: false, optimize: "size", trace: true }, + { cache: true, optimize: "speed", trace: false }, + { cache: true, optimize: "speed", trace: true }, + { cache: true, optimize: "size", trace: false }, + { cache: true, optimize: "size", trace: true } + ]; optionsVariants.forEach(variant => { describe( @@ -131,9 +131,9 @@ describe("generated parser behavior", function() { describe("initializer", function() { it("executes the code before parsing starts", function() { let parser = peg.generate([ - "{ var result = 42; }", - "start = 'a' { return result; }" - ].join("\n"), options); + "{ var result = 42; }", + "start = 'a' { return result; }" + ].join("\n"), options); expect(parser).toParse("a", 42); }); @@ -141,9 +141,9 @@ describe("generated parser behavior", function() { describe("available variables and functions", function() { it("|options| contains options", function() { let parser = peg.generate([ - "{ var result = options; }", - "start = 'a' { return result; }" - ].join("\n"), options); + "{ var result = options; }", + "start = 'a' { return result; }" + ].join("\n"), options); expect(parser).toParse("a", { a: 42 }, { a: 42 }); }); @@ -154,20 +154,20 @@ describe("generated parser behavior", function() { if (options.cache) { it("caches rule match results", function() { let parser = peg.generate([ - "{ var n = 0; }", - "start = (a 'b') / (a 'c') { return n; }", - "a = 'a' { n++; }" - ].join("\n"), options); + "{ var n = 0; }", + "start = (a 'b') / (a 'c') { return n; }", + "a = 'a' { n++; }" + ].join("\n"), options); expect(parser).toParse("ac", 1); }); } else { it("doesn't cache rule match results", function() { let parser = peg.generate([ - "{ var n = 0; }", - "start = (a 'b') / (a 'c') { return n; }", - "a = 'a' { n++; }" - ].join("\n"), options); + "{ var n = 0; }", + "start = (a 'b') / (a 'c') { return n; }", + "a = 'a' { n++; }" + ].join("\n"), options); expect(parser).toParse("ac", 2); }); @@ -387,9 +387,9 @@ describe("generated parser behavior", function() { describe("when referenced rule's expression matches", function() { it("returns its result", function() { let parser = peg.generate([ - "start = a", - "a = 'a'" - ].join("\n"), options); + "start = a", + "a = 'a'" + ].join("\n"), options); expect(parser).toParse("a", "a"); }); @@ -398,9 +398,9 @@ describe("generated parser behavior", function() { describe("when referenced rule's expression doesn't match", function() { it("reports match failure", function() { let parser = peg.generate([ - "start = a", - "a = 'a'" - ].join("\n"), options); + "start = a", + "a = 'a'" + ].join("\n"), options); expect(parser).toFailToParse("b"); }); @@ -431,78 +431,78 @@ describe("generated parser behavior", function() { describe("in containing sequence", function() { it("can access variables defined by preceding labeled elements", function() { let parser = peg.generate( - "start = a:'a' &{ return a === 'a'; }", - options - ); + "start = a:'a' &{ return a === 'a'; }", + options + ); expect(parser).toParse("a"); }); it("cannot access variable defined by labeled predicate element", function() { let parser = peg.generate( - "start = 'a' b:&{ return b === undefined; } 'c'", - options - ); + "start = 'a' b:&{ return b === undefined; } 'c'", + options + ); expect(parser).toFailToParse("ac"); }); it("cannot access variables defined by following labeled elements", function() { let parser = peg.generate( - "start = &{ return a === 'a'; } a:'a'", - options - ); + "start = &{ return a === 'a'; } a:'a'", + options + ); expect(parser).toFailToParse("a"); }); it("cannot access variables defined by subexpressions", function() { let testcases = [ - { - grammar: "start = (a:'a') &{ return a === 'a'; }", - input: "a" - }, - { - grammar: "start = (a:'a')? &{ return a === 'a'; }", - input: "a" - }, - { - grammar: "start = (a:'a')* &{ return a === 'a'; }", - input: "a" - }, - { - grammar: "start = (a:'a')+ &{ return a === 'a'; }", - input: "a" - }, - { - grammar: "start = $(a:'a') &{ return a === 'a'; }", - input: "a" - }, - { - grammar: "start = &(a:'a') 'a' &{ return a === 'a'; }", - input: "a" - }, - { - grammar: "start = !(a:'a') 'b' &{ return a === 'a'; }", - input: "b" - }, - { - grammar: "start = b:(a:'a') &{ return a === 'a'; }", - input: "a" - }, - { - grammar: "start = ('a' b:'b' 'c') &{ return b === 'b'; }", - input: "abc" - }, - { - grammar: "start = (a:'a' { return a; }) &{ return a === 'a'; }", - input: "a" - }, - { - grammar: "start = ('a' / b:'b' / 'c') &{ return b === 'b'; }", - input: "b" - } - ]; + { + grammar: "start = (a:'a') &{ return a === 'a'; }", + input: "a" + }, + { + grammar: "start = (a:'a')? &{ return a === 'a'; }", + input: "a" + }, + { + grammar: "start = (a:'a')* &{ return a === 'a'; }", + input: "a" + }, + { + grammar: "start = (a:'a')+ &{ return a === 'a'; }", + input: "a" + }, + { + grammar: "start = $(a:'a') &{ return a === 'a'; }", + input: "a" + }, + { + grammar: "start = &(a:'a') 'a' &{ return a === 'a'; }", + input: "a" + }, + { + grammar: "start = !(a:'a') 'b' &{ return a === 'a'; }", + input: "b" + }, + { + grammar: "start = b:(a:'a') &{ return a === 'a'; }", + input: "a" + }, + { + grammar: "start = ('a' b:'b' 'c') &{ return b === 'b'; }", + input: "abc" + }, + { + grammar: "start = (a:'a' { return a; }) &{ return a === 'a'; }", + input: "a" + }, + { + grammar: "start = ('a' / b:'b' / 'c') &{ return b === 'b'; }", + input: "b" + } + ]; testcases.forEach(testcase => { let parser = peg.generate(testcase.grammar, options); @@ -514,27 +514,27 @@ describe("generated parser behavior", function() { describe("in outer sequence", function() { it("can access variables defined by preceding labeled elements", function() { let parser = peg.generate( - "start = a:'a' ('b' &{ return a === 'a'; })", - options - ); + "start = a:'a' ('b' &{ return a === 'a'; })", + options + ); expect(parser).toParse("ab"); }); it("cannot access variable defined by labeled predicate element", function() { let parser = peg.generate( - "start = 'a' b:('b' &{ return b === undefined; }) 'c'", - options - ); + "start = 'a' b:('b' &{ return b === undefined; }) 'c'", + options + ); expect(parser).toFailToParse("abc"); }); it("cannot access variables defined by following labeled elements", function() { let parser = peg.generate( - "start = ('a' &{ return b === 'b'; }) b:'b'", - options - ); + "start = ('a' &{ return b === 'b'; }) b:'b'", + options + ); expect(parser).toFailToParse("ab"); }); @@ -544,18 +544,18 @@ describe("generated parser behavior", function() { describe("initializer variables & functions", function() { it("can access variables defined in the initializer", function() { let parser = peg.generate([ - "{ var v = 42 }", - "start = &{ return v === 42; }" - ].join("\n"), options); + "{ var v = 42 }", + "start = &{ return v === 42; }" + ].join("\n"), options); expect(parser).toParse(""); }); it("can access functions defined in the initializer", function() { let parser = peg.generate([ - "{ function f() { return 42; } }", - "start = &{ return f() === 42; }" - ].join("\n"), options); + "{ function f() { return 42; } }", + "start = &{ return f() === 42; }" + ].join("\n"), options); expect(parser).toParse(""); }); @@ -564,23 +564,23 @@ describe("generated parser behavior", function() { describe("available variables & functions", function() { it("|options| contains options", function() { let parser = peg.generate([ - "{ var result; }", - "start = &{ result = options; return true; } { return result; }" - ].join("\n"), options); + "{ var result; }", + "start = &{ result = options; return true; } { return result; }" + ].join("\n"), options); expect(parser).toParse("", { a: 42 }, { a: 42 }); }); it("|location| returns current location info", function() { let parser = peg.generate([ - "{ var result; }", - "start = line (nl+ line)* { return result; }", - "line = thing (' '+ thing)*", - "thing = digit / mark", - "digit = [0-9]", - "mark = &{ result = location(); return true; } 'x'", - "nl = '\\r'? '\\n'" - ].join("\n"), options); + "{ var result; }", + "start = line (nl+ line)* { return result; }", + "line = thing (' '+ thing)*", + "thing = digit / mark", + "digit = [0-9]", + "mark = &{ result = location(); return true; } 'x'", + "nl = '\\r'? '\\n'" + ].join("\n"), options); expect(parser).toParse("1\n2\n\n3\n\n\n4 5 x", { start: { offset: 13, line: 7, column: 5 }, @@ -624,78 +624,78 @@ describe("generated parser behavior", function() { describe("in containing sequence", function() { it("can access variables defined by preceding labeled elements", function() { let parser = peg.generate( - "start = a:'a' !{ return a !== 'a'; }", - options - ); + "start = a:'a' !{ return a !== 'a'; }", + options + ); expect(parser).toParse("a"); }); it("cannot access variable defined by labeled predicate element", function() { let parser = peg.generate( - "start = 'a' b:!{ return b !== undefined; } 'c'", - options - ); + "start = 'a' b:!{ return b !== undefined; } 'c'", + options + ); expect(parser).toFailToParse("ac"); }); it("cannot access variables defined by following labeled elements", function() { let parser = peg.generate( - "start = !{ return a !== 'a'; } a:'a'", - options - ); + "start = !{ return a !== 'a'; } a:'a'", + options + ); expect(parser).toFailToParse("a"); }); it("cannot access variables defined by subexpressions", function() { let testcases = [ - { - grammar: "start = (a:'a') !{ return a !== 'a'; }", - input: "a" - }, - { - grammar: "start = (a:'a')? !{ return a !== 'a'; }", - input: "a" - }, - { - grammar: "start = (a:'a')* !{ return a !== 'a'; }", - input: "a" - }, - { - grammar: "start = (a:'a')+ !{ return a !== 'a'; }", - input: "a" - }, - { - grammar: "start = $(a:'a') !{ return a !== 'a'; }", - input: "a" - }, - { - grammar: "start = &(a:'a') 'a' !{ return a !== 'a'; }", - input: "a" - }, - { - grammar: "start = !(a:'a') 'b' !{ return a !== 'a'; }", - input: "b" - }, - { - grammar: "start = b:(a:'a') !{ return a !== 'a'; }", - input: "a" - }, - { - grammar: "start = ('a' b:'b' 'c') !{ return b !== 'b'; }", - input: "abc" - }, - { - grammar: "start = (a:'a' { return a; }) !{ return a !== 'a'; }", - input: "a" - }, - { - grammar: "start = ('a' / b:'b' / 'c') !{ return b !== 'b'; }", - input: "b" - } - ]; + { + grammar: "start = (a:'a') !{ return a !== 'a'; }", + input: "a" + }, + { + grammar: "start = (a:'a')? !{ return a !== 'a'; }", + input: "a" + }, + { + grammar: "start = (a:'a')* !{ return a !== 'a'; }", + input: "a" + }, + { + grammar: "start = (a:'a')+ !{ return a !== 'a'; }", + input: "a" + }, + { + grammar: "start = $(a:'a') !{ return a !== 'a'; }", + input: "a" + }, + { + grammar: "start = &(a:'a') 'a' !{ return a !== 'a'; }", + input: "a" + }, + { + grammar: "start = !(a:'a') 'b' !{ return a !== 'a'; }", + input: "b" + }, + { + grammar: "start = b:(a:'a') !{ return a !== 'a'; }", + input: "a" + }, + { + grammar: "start = ('a' b:'b' 'c') !{ return b !== 'b'; }", + input: "abc" + }, + { + grammar: "start = (a:'a' { return a; }) !{ return a !== 'a'; }", + input: "a" + }, + { + grammar: "start = ('a' / b:'b' / 'c') !{ return b !== 'b'; }", + input: "b" + } + ]; testcases.forEach(testcase => { let parser = peg.generate(testcase.grammar, options); @@ -707,27 +707,27 @@ describe("generated parser behavior", function() { describe("in outer sequence", function() { it("can access variables defined by preceding labeled elements", function() { let parser = peg.generate( - "start = a:'a' ('b' !{ return a !== 'a'; })", - options - ); + "start = a:'a' ('b' !{ return a !== 'a'; })", + options + ); expect(parser).toParse("ab"); }); it("cannot access variable defined by labeled predicate element", function() { let parser = peg.generate( - "start = 'a' b:('b' !{ return b !== undefined; }) 'c'", - options - ); + "start = 'a' b:('b' !{ return b !== undefined; }) 'c'", + options + ); expect(parser).toFailToParse("abc"); }); it("cannot access variables defined by following labeled elements", function() { let parser = peg.generate( - "start = ('a' !{ return b !== 'b'; }) b:'b'", - options - ); + "start = ('a' !{ return b !== 'b'; }) b:'b'", + options + ); expect(parser).toFailToParse("ab"); }); @@ -737,18 +737,18 @@ describe("generated parser behavior", function() { describe("initializer variables & functions", function() { it("can access variables defined in the initializer", function() { let parser = peg.generate([ - "{ var v = 42 }", - "start = !{ return v !== 42; }" - ].join("\n"), options); + "{ var v = 42 }", + "start = !{ return v !== 42; }" + ].join("\n"), options); expect(parser).toParse(""); }); it("can access functions defined in the initializer", function() { let parser = peg.generate([ - "{ function f() { return 42; } }", - "start = !{ return f() !== 42; }" - ].join("\n"), options); + "{ function f() { return 42; } }", + "start = !{ return f() !== 42; }" + ].join("\n"), options); expect(parser).toParse(""); }); @@ -757,23 +757,23 @@ describe("generated parser behavior", function() { describe("available variables & functions", function() { it("|options| contains options", function() { let parser = peg.generate([ - "{ var result; }", - "start = !{ result = options; return false; } { return result; }" - ].join("\n"), options); + "{ var result; }", + "start = !{ result = options; return false; } { return result; }" + ].join("\n"), options); expect(parser).toParse("", { a: 42 }, { a: 42 }); }); it("|location| returns current location info", function() { let parser = peg.generate([ - "{ var result; }", - "start = line (nl+ line)* { return result; }", - "line = thing (' '+ thing)*", - "thing = digit / mark", - "digit = [0-9]", - "mark = !{ result = location(); return false; } 'x'", - "nl = '\\r'? '\\n'" - ].join("\n"), options); + "{ var result; }", + "start = line (nl+ line)* { return result; }", + "line = thing (' '+ thing)*", + "thing = digit / mark", + "digit = [0-9]", + "mark = !{ result = location(); return false; } 'x'", + "nl = '\\r'? '\\n'" + ].join("\n"), options); expect(parser).toParse("1\n2\n\n3\n\n\n4 5 x", { start: { offset: 13, line: 7, column: 5 }, @@ -1010,60 +1010,60 @@ describe("generated parser behavior", function() { it("can access variables defined by labeled sequence elements", function() { let parser = peg.generate( - "start = a:'a' b:'b' c:'c' { return [a, b, c]; }", - options - ); + "start = a:'a' b:'b' c:'c' { return [a, b, c]; }", + options + ); expect(parser).toParse("abc", ["a", "b", "c"]); }); it("cannot access variables defined by subexpressions", function() { let testcases = [ - { - grammar: "start = (a:'a') { return a; }", - input: "a" - }, - { - grammar: "start = (a:'a')? { return a; }", - input: "a" - }, - { - grammar: "start = (a:'a')* { return a; }", - input: "a" - }, - { - grammar: "start = (a:'a')+ { return a; }", - input: "a" - }, - { - grammar: "start = $(a:'a') { return a; }", - input: "a" - }, - { - grammar: "start = &(a:'a') 'a' { return a; }", - input: "a" - }, - { - grammar: "start = !(a:'a') 'b' { return a; }", - input: "b" - }, - { - grammar: "start = b:(a:'a') { return a; }", - input: "a" - }, - { - grammar: "start = ('a' b:'b' 'c') { return b; }", - input: "abc" - }, - { - grammar: "start = (a:'a' { return a; }) { return a; }", - input: "a" - }, - { - grammar: "start = ('a' / b:'b' / 'c') { return b; }", - input: "b" - } - ]; + { + grammar: "start = (a:'a') { return a; }", + input: "a" + }, + { + grammar: "start = (a:'a')? { return a; }", + input: "a" + }, + { + grammar: "start = (a:'a')* { return a; }", + input: "a" + }, + { + grammar: "start = (a:'a')+ { return a; }", + input: "a" + }, + { + grammar: "start = $(a:'a') { return a; }", + input: "a" + }, + { + grammar: "start = &(a:'a') 'a' { return a; }", + input: "a" + }, + { + grammar: "start = !(a:'a') 'b' { return a; }", + input: "b" + }, + { + grammar: "start = b:(a:'a') { return a; }", + input: "a" + }, + { + grammar: "start = ('a' b:'b' 'c') { return b; }", + input: "abc" + }, + { + grammar: "start = (a:'a' { return a; }) { return a; }", + input: "a" + }, + { + grammar: "start = ('a' / b:'b' / 'c') { return b; }", + input: "b" + } + ]; testcases.forEach(testcase => { let parser = peg.generate(testcase.grammar, options); @@ -1075,27 +1075,27 @@ describe("generated parser behavior", function() { describe("in outer sequence", function() { it("can access variables defined by preceding labeled elements", function() { let parser = peg.generate( - "start = a:'a' ('b' { return a; })", - options - ); + "start = a:'a' ('b' { return a; })", + options + ); expect(parser).toParse("ab", ["a", "a"]); }); it("cannot access variable defined by labeled action element", function() { let parser = peg.generate( - "start = 'a' b:('b' { return b; }) c:'c'", - options - ); + "start = 'a' b:('b' { return b; }) c:'c'", + options + ); expect(parser).toFailToParse("abc"); }); it("cannot access variables defined by following labeled elements", function() { let parser = peg.generate( - "start = ('a' { return b; }) b:'b'", - options - ); + "start = ('a' { return b; }) b:'b'", + options + ); expect(parser).toFailToParse("ab"); }); @@ -1105,18 +1105,18 @@ describe("generated parser behavior", function() { describe("initializer variables & functions", function() { it("can access variables defined in the initializer", function() { let parser = peg.generate([ - "{ var v = 42 }", - "start = 'a' { return v; }" - ].join("\n"), options); + "{ var v = 42 }", + "start = 'a' { return v; }" + ].join("\n"), options); expect(parser).toParse("a", 42); }); it("can access functions defined in the initializer", function() { let parser = peg.generate([ - "{ function f() { return 42; } }", - "start = 'a' { return f(); }" - ].join("\n"), options); + "{ function f() { return 42; } }", + "start = 'a' { return f(); }" + ].join("\n"), options); expect(parser).toParse("a", 42); }); @@ -1125,32 +1125,32 @@ describe("generated parser behavior", function() { describe("available variables & functions", function() { it("|options| contains options", function() { let parser = peg.generate( - "start = 'a' { return options; }", - options - ); + "start = 'a' { return options; }", + options + ); expect(parser).toParse("a", { a: 42 }, { a: 42 }); }); it("|text| returns text matched by the expression", function() { let parser = peg.generate( - "start = 'a' { return text(); }", - options - ); + "start = 'a' { return text(); }", + options + ); expect(parser).toParse("a", "a"); }); it("|location| returns location info of the expression", function() { let parser = peg.generate([ - "{ var result; }", - "start = line (nl+ line)* { return result; }", - "line = thing (' '+ thing)*", - "thing = digit / mark", - "digit = [0-9]", - "mark = 'x' { result = location(); }", - "nl = '\\r'? '\\n'" - ].join("\n"), options); + "{ var result; }", + "start = line (nl+ line)* { return result; }", + "line = thing (' '+ thing)*", + "thing = digit / mark", + "digit = [0-9]", + "mark = 'x' { result = location(); }", + "nl = '\\r'? '\\n'" + ].join("\n"), options); expect(parser).toParse("1\n2\n\n3\n\n\n4 5 x", { start: { offset: 13, line: 7, column: 5 }, @@ -1171,9 +1171,9 @@ describe("generated parser behavior", function() { describe("|expected|", function() { it("terminates parsing and throws an exception", function() { let parser = peg.generate( - "start = 'a' { expected('a'); }", - options - ); + "start = 'a' { expected('a'); }", + options + ); expect(parser).toFailToParse("a", { message: "Expected a but \"a\" found.", @@ -1188,13 +1188,13 @@ describe("generated parser behavior", function() { it("allows to set custom location info", function() { let parser = peg.generate([ - "start = 'a' {", - " expected('a', {", - " start: { offset: 1, line: 1, column: 2 },", - " end: { offset: 2, line: 1, column: 3 }", - " });", - "}" - ].join("\n"), options); + "start = 'a' {", + " expected('a', {", + " start: { offset: 1, line: 1, column: 2 },", + " end: { offset: 2, line: 1, column: 3 }", + " });", + "}" + ].join("\n"), options); expect(parser).toFailToParse("a", { message: "Expected a but \"a\" found.", @@ -1211,9 +1211,9 @@ describe("generated parser behavior", function() { describe("|error|", function() { it("terminates parsing and throws an exception", function() { let parser = peg.generate( - "start = 'a' { error('a'); }", - options - ); + "start = 'a' { error('a'); }", + options + ); expect(parser).toFailToParse("a", { message: "a", @@ -1228,13 +1228,13 @@ describe("generated parser behavior", function() { it("allows to set custom location info", function() { let parser = peg.generate([ - "start = 'a' {", - " error('a', {", - " start: { offset: 1, line: 1, column: 2 },", - " end: { offset: 2, line: 1, column: 3 }", - " });", - "}" - ].join("\n"), options); + "start = 'a' {", + " error('a', {", + " start: { offset: 1, line: 1, column: 2 },", + " end: { offset: 2, line: 1, column: 3 }", + " });", + "}" + ].join("\n"), options); expect(parser).toFailToParse("a", { message: "a", @@ -1259,9 +1259,9 @@ describe("generated parser behavior", function() { it("doesn't execute the code", function() { let parser = peg.generate( - "start = 'a' { throw 'Boom!'; } / 'b'", - options - ); + "start = 'a' { throw 'Boom!'; } / 'b'", + options + ); expect(parser).toParse("b"); }); @@ -1438,11 +1438,11 @@ describe("generated parser behavior", function() { it("reports position correctly in complex cases", function() { let parser = peg.generate([ - "start = line (nl+ line)*", - "line = digit (' '+ digit)*", - "digit = [0-9]", - "nl = '\\r'? '\\n'" - ].join("\n"), options); + "start = line (nl+ line)*", + "line = digit (' '+ digit)*", + "digit = [0-9]", + "nl = '\\r'? '\\n'" + ].join("\n"), options); expect(parser).toFailToParse("1\n2\n\n3\n\n\n4 5 x", { location: { @@ -1477,22 +1477,22 @@ describe("generated parser behavior", function() { // Sum ← Product (('+' / '-') Product)* // Expr ← Sum let parser = peg.generate([ - "Expr = Sum", - "Sum = head:Product tail:(('+' / '-') Product)* {", - " return tail.reduce(function(result, element) {", - " if (element[0] === '+') { return result + element[1]; }", - " if (element[0] === '-') { return result - element[1]; }", - " }, head);", - " }", - "Product = head:Value tail:(('*' / '/') Value)* {", - " return tail.reduce(function(result, element) {", - " if (element[0] === '*') { return result * element[1]; }", - " if (element[0] === '/') { return result / element[1]; }", - " }, head);", - " }", - "Value = digits:[0-9]+ { return parseInt(digits.join(''), 10); }", - " / '(' expr:Expr ')' { return expr; }" - ].join("\n"), options); + "Expr = Sum", + "Sum = head:Product tail:(('+' / '-') Product)* {", + " return tail.reduce(function(result, element) {", + " if (element[0] === '+') { return result + element[1]; }", + " if (element[0] === '-') { return result - element[1]; }", + " }, head);", + " }", + "Product = head:Value tail:(('*' / '/') Value)* {", + " return tail.reduce(function(result, element) {", + " if (element[0] === '*') { return result * element[1]; }", + " if (element[0] === '/') { return result / element[1]; }", + " }, head);", + " }", + "Value = digits:[0-9]+ { return parseInt(digits.join(''), 10); }", + " / '(' expr:Expr ')' { return expr; }" + ].join("\n"), options); // The "value" rule expect(parser).toParse("0", 0); @@ -1528,10 +1528,10 @@ describe("generated parser behavior", function() { // A ← a A? b // B ← b B? c let parser = peg.generate([ - "S = &(A 'c') a:'a'+ B:B !('a' / 'b' / 'c') { return a.join('') + B; }", - "A = a:'a' A:A? b:'b' { return [a, A, b].join(''); }", - "B = b:'b' B:B? c:'c' { return [b, B, c].join(''); }" - ].join("\n"), options); + "S = &(A 'c') a:'a'+ B:B !('a' / 'b' / 'c') { return a.join('') + B; }", + "A = a:'a' A:A? b:'b' { return [a, A, b].join(''); }", + "B = b:'b' B:B? c:'c' { return [b, B, c].join(''); }" + ].join("\n"), options); expect(parser).toParse("abc", "abc"); expect(parser).toParse("aaabbbccc", "aaabbbccc"); @@ -1550,13 +1550,13 @@ describe("generated parser behavior", function() { // N ← C / (!Begin !End Z) // Z ← any single character let parser = peg.generate([ - "C = begin:Begin ns:N* end:End { return begin + ns.join('') + end; }", - "N = C", - " / !Begin !End z:Z { return z; }", - "Z = .", - "Begin = '(*'", - "End = '*)'" - ].join("\n"), options); + "C = begin:Begin ns:N* end:End { return begin + ns.join('') + end; }", + "N = C", + " / !Begin !End z:Z { return z; }", + "Z = .", + "Begin = '(*'", + "End = '*)'" + ].join("\n"), options); expect(parser).toParse("(**)", "(**)"); expect(parser).toParse("(*abc*)", "(*abc*)"); diff --git a/spec/unit/parser.spec.js b/spec/unit/parser.spec.js index 9aac7e1..2a06125 100644 --- a/spec/unit/parser.spec.js +++ b/spec/unit/parser.spec.js @@ -22,17 +22,17 @@ describe("PEG.js grammar parser", function() { let labeledMnop = { type: "labeled", label: "d", expression: literalMnop }; let labeledSimpleNot = { type: "labeled", label: "a", expression: simpleNotAbcd }; let sequence = { - type: "sequence", - elements: [literalAbcd, literalEfgh, literalIjkl] - }; + type: "sequence", + elements: [literalAbcd, literalEfgh, literalIjkl] + }; let sequence2 = { - type: "sequence", - elements: [labeledAbcd, labeledEfgh] - }; + type: "sequence", + elements: [labeledAbcd, labeledEfgh] + }; let sequence4 = { - type: "sequence", - elements: [labeledAbcd, labeledEfgh, labeledIjkl, labeledMnop] - }; + type: "sequence", + elements: [labeledAbcd, labeledEfgh, labeledIjkl, labeledMnop] + }; let groupLabeled = { type: "group", expression: labeledAbcd }; let groupSequence = { type: "group", expression: sequence }; let actionAbcd = { type: "action", expression: literalAbcd, code: " code " }; @@ -41,17 +41,17 @@ describe("PEG.js grammar parser", function() { let actionMnop = { type: "action", expression: literalMnop, code: " code " }; let actionSequence = { type: "action", expression: sequence, code: " code " }; let choice = { - type: "choice", - alternatives: [literalAbcd, literalEfgh, literalIjkl] - }; + type: "choice", + alternatives: [literalAbcd, literalEfgh, literalIjkl] + }; let choice2 = { - type: "choice", - alternatives: [actionAbcd, actionEfgh] - }; + type: "choice", + alternatives: [actionAbcd, actionEfgh] + }; let choice4 = { - type: "choice", - alternatives: [actionAbcd, actionEfgh, actionIjkl, actionMnop] - }; + type: "choice", + alternatives: [actionAbcd, actionEfgh, actionIjkl, actionMnop] + }; let named = { type: "named", name: "start rule", expression: literalAbcd }; let ruleA = { type: "rule", name: "a", expression: literalAbcd }; let ruleB = { type: "rule", name: "b", expression: literalEfgh }; @@ -98,10 +98,10 @@ describe("PEG.js grammar parser", function() { let trivialGrammar = literalGrammar("abcd", false); let twoRuleGrammar = { - type: "grammar", - initializer: null, - rules: [ruleA, ruleB] - }; + type: "grammar", + initializer: null, + rules: [ruleA, ruleB] + }; let stripLocation = (function() { function buildVisitor(functions) {