describe("generated parser", function() { function vary(names, block) { var values = { trackLineAndColumn: [false, true], cache: [false, true] }; function varyStep(names, options) { var clonedOptions = {}, key, name, i; if (names.length === 0) { /* * We have to clone the options so that the block can save them safely * (e.g. by capturing in a closure) without the risk that they will be * changed later. */ for (key in options) { clonedOptions[key] = options[key]; } describe( "with options " + jasmine.pp(clonedOptions), function() { block(clonedOptions); } ); } else { name = names[0]; for (i = 0; i < values[name].length; i++) { options[name] = values[name][i]; varyStep(names.slice(1), options); } } } varyStep(names, {}); } function varyAll(block) { vary(["cache", "trackLineAndColumn"], block); } beforeEach(function() { this.addMatchers({ toParse: function(input, expected) { var result; try { result = this.actual.parse(input); this.message = function() { return "Expected " + jasmine.pp(input) + " " + (this.isNot ? "not " : "") + "to parse as " + jasmine.pp(expected) + ", " + "but it parsed as " + jasmine.pp(result) + "."; }; return this.env.equals_(result, expected); } catch (e) { this.message = function() { return "Expected " + jasmine.pp(input) + " " + "to parse as " + jasmine.pp(expected) + ", " + "but it failed to parse with message " + jasmine.pp(e.message) + "."; }; return false; } }, toFailToParse: function(input) { var result; try { result = this.actual.parse(input); this.message = function() { return "Expected " + jasmine.pp(input) + " to fail to parse, " + "but it parsed as " + jasmine.pp(result) + "."; }; return false; } catch (e) { this.message = function() { return "Expected " + jasmine.pp(input) + " to parse, " + "but it failed with message " + jasmine.pp(e.message) + "."; }; return true; } } }); }); describe("literal matching", function() { varyAll(function(options) { it("matches empty literal correctly", function() { var parser = PEG.buildParser('start = ""', options); expect(parser).toParse("", ""); }); it("matches one-character literal correctly", function() { var parser = PEG.buildParser('start = "a"', options); expect(parser).toParse("a", "a"); expect(parser).toFailToParse("b"); }); it("matches multiple-character literal correctly", function() { var parser = PEG.buildParser('start = "abcd"', options); expect(parser).toParse("abcd", "abcd"); expect(parser).toFailToParse("ebcd"); expect(parser).toFailToParse("afcd"); expect(parser).toFailToParse("abgd"); expect(parser).toFailToParse("abch"); }); it("is case sensitive without the \"i\" flag", function() { var parser = PEG.buildParser('start = "a"', options); expect(parser).toParse("a", "a"); expect(parser).toFailToParse("A"); }); it("is case insensitive with the \"i\" flag", function() { var parser = PEG.buildParser('start = "a"i', options); expect(parser).toParse("a", "a"); expect(parser).toParse("A", "A"); }); it("advances position on success", function() { var parser = PEG.buildParser('start = "a" .', options); expect(parser).toParse("ab", ["a", "b"]); }); }); }); describe("any matching", function() { varyAll(function(options) { it("matches correctly", function() { var parser = PEG.buildParser('start = .', options); expect(parser).toParse("a", "a"); }); it("advances position on success", function() { var parser = PEG.buildParser('start = . .', options); expect(parser).toParse("ab", ["a", "b"]); }); }); }); });