|
|
|
@ -449,152 +449,6 @@ testWithVaryingTrackLineAndColumn("one or more expressions", function(options) {
|
|
|
|
|
parses(parser, "aaa", ["a", "a", "a"]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("actions (with trackLineAndColumn: false)", function() {
|
|
|
|
|
var options = { trackLineAndColumn: false };
|
|
|
|
|
|
|
|
|
|
var singleElementUnlabeledParser = PEG.buildParser(
|
|
|
|
|
'start = "a" { return arguments.length; }',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(singleElementUnlabeledParser, "a", 1);
|
|
|
|
|
|
|
|
|
|
var singleElementLabeledParser = PEG.buildParser(
|
|
|
|
|
'start = a:"a" { return [arguments.length, offset, a]; }',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(singleElementLabeledParser, "a", [2, 0, "a"]);
|
|
|
|
|
|
|
|
|
|
var multiElementUnlabeledParser = PEG.buildParser(
|
|
|
|
|
'start = "a" "b" "c" { return arguments.length; }',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(multiElementUnlabeledParser, "abc", 1);
|
|
|
|
|
|
|
|
|
|
var multiElementLabeledParser = PEG.buildParser(
|
|
|
|
|
'start = a:"a" "b" c:"c" { return [arguments.length, offset, a, c]; }',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(multiElementLabeledParser, "abc", [3, 0, "a", "c"]);
|
|
|
|
|
|
|
|
|
|
var innerElementsUnlabeledParser = PEG.buildParser(
|
|
|
|
|
'start = "a" ("b" "c" "d" { return arguments.length; }) "e"',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(innerElementsUnlabeledParser, "abcde", ["a", 1, "e"]);
|
|
|
|
|
|
|
|
|
|
var innerElementsLabeledParser = PEG.buildParser([
|
|
|
|
|
'start = "a"',
|
|
|
|
|
' (b:"b" "c" d:"d" { return [arguments.length, offset, b, d]; })',
|
|
|
|
|
' "e"'
|
|
|
|
|
].join("\n"), options);
|
|
|
|
|
parses(innerElementsLabeledParser, "abcde", ["a", [3, 1, "b", "d"], "e"]);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Test that the parsing position returns after successfull parsing of the
|
|
|
|
|
* action expression and action returning |null|.
|
|
|
|
|
*/
|
|
|
|
|
var posTestParser = PEG.buildParser(
|
|
|
|
|
'start = "a" { return null; } / "a"',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(posTestParser, "a", "a");
|
|
|
|
|
|
|
|
|
|
/* Test that the action is not called when its expression does not match. */
|
|
|
|
|
var notAMatchParser = PEG.buildParser(
|
|
|
|
|
'start = "a" { ok(false, "action got called when it should not be"); }',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
doesNotParse(notAMatchParser, "b");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test("actions (with trackLineAndColumn: true)", function() {
|
|
|
|
|
var options = { trackLineAndColumn: true };
|
|
|
|
|
|
|
|
|
|
var singleElementUnlabeledParser = PEG.buildParser(
|
|
|
|
|
'start = "a" { return arguments.length; }',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(singleElementUnlabeledParser, "a", 3);
|
|
|
|
|
|
|
|
|
|
var singleElementLabeledParser = PEG.buildParser(
|
|
|
|
|
'start = a:"a" { return [arguments.length, offset, line, column, a]; }',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(singleElementLabeledParser, "a", [4, 0, 1, 1, "a"]);
|
|
|
|
|
|
|
|
|
|
var multiElementUnlabeledParser = PEG.buildParser(
|
|
|
|
|
'start = "a" "b" "c" { return arguments.length; }',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(multiElementUnlabeledParser, "abc", 3);
|
|
|
|
|
|
|
|
|
|
var multiElementLabeledParser = PEG.buildParser([
|
|
|
|
|
'start = a:"a" "b" c:"c" {',
|
|
|
|
|
' return [arguments.length, offset, line, column, a, c];',
|
|
|
|
|
'}'
|
|
|
|
|
].join("\n"), options);
|
|
|
|
|
parses(multiElementLabeledParser, "abc", [5, 0, 1, 1, "a", "c"]);
|
|
|
|
|
|
|
|
|
|
var innerElementsUnlabeledParser = PEG.buildParser(
|
|
|
|
|
'start = "a" ("b" "c" "d" { return arguments.length; }) "e"',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(innerElementsUnlabeledParser, "abcde", ["a", 3, "e"]);
|
|
|
|
|
|
|
|
|
|
var innerElementsLabeledParser = PEG.buildParser([
|
|
|
|
|
'start = "a"',
|
|
|
|
|
' (',
|
|
|
|
|
' b:"b" "c" d:"d" {',
|
|
|
|
|
' return [arguments.length, offset, line, column, b, d];',
|
|
|
|
|
' }',
|
|
|
|
|
' )',
|
|
|
|
|
' "e"'
|
|
|
|
|
].join("\n"), options);
|
|
|
|
|
parses(
|
|
|
|
|
innerElementsLabeledParser,
|
|
|
|
|
"abcde",
|
|
|
|
|
["a", [5, 1, 1, 2, "b", "d"], "e"]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Test that the parsing position returns after successfull parsing of the
|
|
|
|
|
* action expression and action returning |null|.
|
|
|
|
|
*/
|
|
|
|
|
var posTestParser = PEG.buildParser(
|
|
|
|
|
'start = "a" { return null; } / "a"',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
parses(posTestParser, "a", "a");
|
|
|
|
|
|
|
|
|
|
/* Test that the action is not called when its expression does not match. */
|
|
|
|
|
var notAMatchParser = PEG.buildParser(
|
|
|
|
|
'start = "a" { ok(false, "action got called when it should not be"); }',
|
|
|
|
|
options
|
|
|
|
|
);
|
|
|
|
|
doesNotParse(notAMatchParser, "b");
|
|
|
|
|
|
|
|
|
|
var numbersParser = PEG.buildParser([
|
|
|
|
|
'{ var result; }',
|
|
|
|
|
'start = line (nl+ line)* { return result; }',
|
|
|
|
|
'line = thing (" "+ thing)*',
|
|
|
|
|
'thing = digit / mark',
|
|
|
|
|
'digit = [0-9]',
|
|
|
|
|
'mark = "x" { result = [line, column]; }',
|
|
|
|
|
'nl = ("\\r" / "\\n" / "\\u2028" / "\\u2029")'
|
|
|
|
|
].join("\n"), options);
|
|
|
|
|
|
|
|
|
|
parses(numbersParser, "1\n2\n\n3\n\n\n4 5 x", [7, 5]);
|
|
|
|
|
|
|
|
|
|
/* Non-Unix newlines */
|
|
|
|
|
parses(numbersParser, "1\rx", [2, 1]); // Old Mac
|
|
|
|
|
parses(numbersParser, "1\r\nx", [2, 1]); // Windows
|
|
|
|
|
parses(numbersParser, "1\n\rx", [3, 1]); // mismatched
|
|
|
|
|
|
|
|
|
|
/* Strange newlines */
|
|
|
|
|
parses(numbersParser, "1\u2028x", [2, 1]); // line separator
|
|
|
|
|
parses(numbersParser, "1\u2029x", [2, 1]); // paragraph separator
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
testWithVaryingTrackLineAndColumn("initializer", function(options) {
|
|
|
|
|
var variableInActionParser = PEG.buildParser(
|
|
|
|
|
'{ a = 42; }; start = "a" { return a; }',
|
|
|
|
|