diff --git a/spec/generated-parser.spec.js b/spec/generated-parser.spec.js index aac6e8b..c8a7158 100644 --- a/spec/generated-parser.spec.js +++ b/spec/generated-parser.spec.js @@ -91,6 +91,65 @@ describe("generated parser", function() { }); }); + describe("semantic and code", function() { + varyAll(function(options) { + it("causes successful match by returning |true|", function() { + var parser = PEG.buildParser('start = &{ return true; }', options); + + expect(parser).toParse("", ""); + }); + + it("causes match failure by returning |false|", function() { + var parser = PEG.buildParser('start = &{ return false; }', options); + + expect(parser).toFailToParse(""); + }); + + it("can use label variables", function() { + var parser = PEG.buildParser( + 'start = a:"a" &{ return a === "a"; }', + options + ); + + expect(parser).toParse("a", ["a", ""]); + }); + + it("can use the |offset| variable to get the current parse position", function() { + var parser = PEG.buildParser( + 'start = "a" &{ return offset === 1; }', + options + ); + + expect(parser).toParse("a", ["a", ""]); + }); + + if (options.trackLineAndColumn) { + it("can use the |line| and |column| variables to get the current line and column", function() { + var parser = PEG.buildParser([ + '{ var result; }', + 'start = line (nl+ line)* { return result; }', + 'line = thing (" "+ thing)*', + 'thing = digit / mark', + 'digit = [0-9]', + 'mark = &{ result = [line, column]; return true; } "x"', + 'nl = ("\\r" / "\\n" / "\\u2028" / "\\u2029")' + ].join("\n"), options); + + expect(parser).toParse("1\n2\n\n3\n\n\n4 5 x", [7, 5]); + + /* Non-Unix newlines */ + expect(parser).toParse("1\rx", [2, 1]); // Old Mac + expect(parser).toParse("1\r\nx", [2, 1]); // Windows + expect(parser).toParse("1\n\rx", [3, 1]); // mismatched + + /* Strange newlines */ + expect(parser).toParse("1\u2028x", [2, 1]); // line separator + expect(parser).toParse("1\u2029x", [2, 1]); // paragraph separator + }); + } + }); + }); + describe("semantic not code", function() { varyAll(function(options) { it("causes successful match by returning |false|", function() { diff --git a/test/compiler-test.js b/test/compiler-test.js index f6cec8d..48f2df9 100644 --- a/test/compiler-test.js +++ b/test/compiler-test.js @@ -73,184 +73,6 @@ testWithVaryingTrackLineAndColumn("simple not", function(options) { parses(posTestParser, "ac", ["a", "", "c"]); }); -test("semantic and (with trackLineAndColumn: false)", function() { - var options = { trackLineAndColumn: false }; - - var acceptingParser = PEG.buildParser( - 'start = "a" &{ return true; } "b"', - options - ); - parses(acceptingParser, "ab", ["a", "", "b"]); - - var rejectingParser = PEG.buildParser( - 'start = "a" &{ return false; } "b"', - options - ); - doesNotParse(rejectingParser, "ab"); - - var singleElementUnlabeledParser = PEG.buildParser( - 'start = "a" &{ return arguments.length === 1 && offset === 1; }', - options - ); - parses(singleElementUnlabeledParser, "a", ["a", ""]); - - var singleElementLabeledParser = PEG.buildParser([ - 'start = a:"a" &{', - ' return arguments.length === 2', - ' && offset === 1', - ' && a === "a";', - ' }' - ].join("\n"), options); - parses(singleElementLabeledParser, "a", ["a", ""]); - - var multiElementUnlabeledParser = PEG.buildParser( - 'start = "a" "b" "c" &{ return arguments.length === 1 && offset === 3; }', - options - ); - parses(multiElementUnlabeledParser, "abc", ["a", "b", "c", ""]); - - var multiElementLabeledParser = PEG.buildParser([ - 'start = a:"a" "b" c:"c" &{', - ' return arguments.length === 3', - ' && offset === 3', - ' && a === "a"', - ' && c === "c";', - ' }' - ].join("\n"), options); - parses(multiElementLabeledParser, "abc", ["a", "b", "c", ""]); - - var innerElementsUnlabeledParser = PEG.buildParser([ - 'start = "a"', - ' ("b" "c" "d" &{ return arguments.length === 1 && offset === 4; })', - ' "e"' - ].join("\n"), options); - parses(innerElementsUnlabeledParser, "abcde", ["a", ["b", "c", "d", ""], "e"]); - - var innerElementsLabeledParser = PEG.buildParser([ - 'start = "a"', - ' (', - ' b:"b" "c" d:"d" &{', - ' return arguments.length === 3', - ' && offset === 4', - ' && b === "b"', - ' && d === "d";', - ' }', - ' )', - ' "e"' - ].join("\n"), options); - parses(innerElementsLabeledParser, "abcde", ["a", ["b", "c", "d", ""], "e"]); -}); - -test("semantic and (with trackLineAndColumn: true)", function() { - var options = { trackLineAndColumn: true }; - - var acceptingParser = PEG.buildParser( - 'start = "a" &{ return true; } "b"', - options - ); - parses(acceptingParser, "ab", ["a", "", "b"]); - - var rejectingParser = PEG.buildParser( - 'start = "a" &{ return false; } "b"', - options - ); - doesNotParse(rejectingParser, "ab"); - - var singleElementUnlabeledParser = PEG.buildParser([ - 'start = "a" &{', - ' return arguments.length === 3', - ' && offset === 1', - ' && line === 1', - ' && column === 2;', - ' }' - ].join("\n"), options); - parses(singleElementUnlabeledParser, "a", ["a", ""]); - - var singleElementLabeledParser = PEG.buildParser([ - 'start = a:"a" &{', - ' return arguments.length === 4', - ' && offset === 1', - ' && line === 1', - ' && column === 2', - ' && a === "a";', - ' }' - ].join("\n"), options); - parses(singleElementLabeledParser, "a", ["a", ""]); - - var multiElementUnlabeledParser = PEG.buildParser([ - 'start = "a" "b" "c" &{', - ' return arguments.length === 3', - ' && offset === 3', - ' && line === 1', - ' && column === 4;', - ' }' - ].join("\n"), options); - parses(multiElementUnlabeledParser, "abc", ["a", "b", "c", ""]); - - var multiElementLabeledParser = PEG.buildParser([ - 'start = a:"a" "b" c:"c" &{', - ' return arguments.length === 5', - ' && offset === 3', - ' && line === 1', - ' && column === 4', - ' && a === "a"', - ' && c === "c";', - ' }' - ].join("\n"), options); - parses(multiElementLabeledParser, "abc", ["a", "b", "c", ""]); - - var innerElementsUnlabeledParser = PEG.buildParser([ - 'start = "a"', - ' (', - ' "b" "c" "d" &{', - ' return arguments.length === 3', - ' && offset === 4', - ' && line === 1', - ' && column === 5;', - ' }', - ' )', - ' "e"' - ].join("\n"), options); - parses(innerElementsUnlabeledParser, "abcde", ["a", ["b", "c", "d", ""], "e"]); - - var innerElementsLabeledParser = PEG.buildParser([ - 'start = "a"', - ' (', - ' b:"b" "c" d:"d" &{', - ' return arguments.length === 5', - ' && offset === 4', - ' && line === 1', - ' && column === 5', - ' && b === "b"', - ' && d === "d";', - ' }', - ' )', - ' "e"' - ].join("\n"), options); - parses(innerElementsLabeledParser, "abcde", ["a", ["b", "c", "d", ""], "e"]); - - var digitsParser = PEG.buildParser([ - '{ var result; }', - 'start = line (nl+ line)* { return result; }', - 'line = thing (" "+ thing)*', - 'thing = digit / mark', - 'digit = [0-9]', - 'mark = &{ result = [line, column]; return true; } "x"', - 'nl = ("\\r" / "\\n" / "\\u2028" / "\\u2029")' - ].join("\n"), options); - - parses(digitsParser, "1\n2\n\n3\n\n\n4 5 x", [7, 5]); - - /* Non-Unix newlines */ - parses(digitsParser, "1\rx", [2, 1]); // Old Mac - parses(digitsParser, "1\r\nx", [2, 1]); // Windows - parses(digitsParser, "1\n\rx", [3, 1]); // mismatched - - /* Strange newlines */ - parses(digitsParser, "1\u2028x", [2, 1]); // line separator - parses(digitsParser, "1\u2029x", [2, 1]); // paragraph separator -}); - testWithVaryingTrackLineAndColumn("initializer", function(options) { var variableInActionParser = PEG.buildParser( '{ a = 42; }; start = "a" { return a; }',