|
|
@ -216,115 +216,4 @@ testWithVaryingTrackLineAndColumn("start rule", function(options) {
|
|
|
|
);
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Following examples are from Wikipedia, see
|
|
|
|
|
|
|
|
* http://en.wikipedia.org/w/index.php?title=Parsing_expression_grammar&oldid=335106938.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
testWithVaryingTrackLineAndColumn("arithmetics", function(options) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Value ← [0-9]+ / '(' Expr ')'
|
|
|
|
|
|
|
|
* Product ← Value (('*' / '/') Value)*
|
|
|
|
|
|
|
|
* Sum ← Product (('+' / '-') Product)*
|
|
|
|
|
|
|
|
* Expr ← Sum
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
var parser = PEG.buildParser([
|
|
|
|
|
|
|
|
'Expr = Sum',
|
|
|
|
|
|
|
|
'Sum = head:Product tail:(("+" / "-") Product)* {',
|
|
|
|
|
|
|
|
' var result = head;',
|
|
|
|
|
|
|
|
' for (var i = 0; i < tail.length; i++) {',
|
|
|
|
|
|
|
|
' if (tail[i][0] == "+") { result += tail[i][1]; }',
|
|
|
|
|
|
|
|
' if (tail[i][0] == "-") { result -= tail[i][1]; }',
|
|
|
|
|
|
|
|
' }',
|
|
|
|
|
|
|
|
' return result;',
|
|
|
|
|
|
|
|
' }',
|
|
|
|
|
|
|
|
'Product = head:Value tail:(("*" / "/") Value)* {',
|
|
|
|
|
|
|
|
' var result = head;',
|
|
|
|
|
|
|
|
' for (var i = 0; i < tail.length; i++) {',
|
|
|
|
|
|
|
|
' if (tail[i][0] == "*") { result *= tail[i][1]; }',
|
|
|
|
|
|
|
|
' if (tail[i][0] == "/") { result /= tail[i][1]; }',
|
|
|
|
|
|
|
|
' }',
|
|
|
|
|
|
|
|
' return result;',
|
|
|
|
|
|
|
|
' }',
|
|
|
|
|
|
|
|
'Value = digits:[0-9]+ { return parseInt(digits.join("")); }',
|
|
|
|
|
|
|
|
' / "(" expr:Expr ")" { return expr; }'
|
|
|
|
|
|
|
|
].join("\n"), options);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Test "value" rule. */
|
|
|
|
|
|
|
|
parses(parser, "0", 0);
|
|
|
|
|
|
|
|
parses(parser, "123", 123);
|
|
|
|
|
|
|
|
parses(parser, "(42+43)", 42+43);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Test "product" rule. */
|
|
|
|
|
|
|
|
parses(parser, "42", 42);
|
|
|
|
|
|
|
|
parses(parser, "42*43", 42*43);
|
|
|
|
|
|
|
|
parses(parser, "42*43*44*45", 42*43*44*45);
|
|
|
|
|
|
|
|
parses(parser, "42/43", 42/43);
|
|
|
|
|
|
|
|
parses(parser, "42/43/44/45", 42/43/44/45);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Test "sum" rule. */
|
|
|
|
|
|
|
|
parses(parser, "42*43", 42*43);
|
|
|
|
|
|
|
|
parses(parser, "42*43+44*45", 42*43+44*45);
|
|
|
|
|
|
|
|
parses(parser, "42*43+44*45+46*47+48*49", 42*43+44*45+46*47+48*49);
|
|
|
|
|
|
|
|
parses(parser, "42*43-44*45", 42*43-44*45);
|
|
|
|
|
|
|
|
parses(parser, "42*43-44*45-46*47-48*49", 42*43-44*45-46*47-48*49);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Test "expr" rule. */
|
|
|
|
|
|
|
|
parses(parser, "42+43", 42+43);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Complex test */
|
|
|
|
|
|
|
|
parses(parser, "(1+2)*(3+4)",(1+2)*(3+4));
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
testWithVaryingTrackLineAndColumn("non-context-free language", function(options) {
|
|
|
|
|
|
|
|
/* The following parsing expression grammar describes the classic
|
|
|
|
|
|
|
|
* non-context-free language { a^n b^n c^n : n >= 1 }:
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* S ← &(A c) a+ B !(a/b/c)
|
|
|
|
|
|
|
|
* A ← a A? b
|
|
|
|
|
|
|
|
* B ← b B? c
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
var parser = PEG.buildParser([
|
|
|
|
|
|
|
|
'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; }',
|
|
|
|
|
|
|
|
'B = b:"b" B:B? c:"c" { return b + B + c; }'
|
|
|
|
|
|
|
|
].join("\n"), options);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parses(parser, "abc", "abc");
|
|
|
|
|
|
|
|
parses(parser, "aaabbbccc", "aaabbbccc");
|
|
|
|
|
|
|
|
doesNotParse(parser, "aabbbccc");
|
|
|
|
|
|
|
|
doesNotParse(parser, "aaaabbbccc");
|
|
|
|
|
|
|
|
doesNotParse(parser, "aaabbccc");
|
|
|
|
|
|
|
|
doesNotParse(parser, "aaabbbbccc");
|
|
|
|
|
|
|
|
doesNotParse(parser, "aaabbbcc");
|
|
|
|
|
|
|
|
doesNotParse(parser, "aaabbbcccc");
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
testWithVaryingTrackLineAndColumn("nested comments", function(options) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
* Begin ← "(*"
|
|
|
|
|
|
|
|
* End ← "*)"
|
|
|
|
|
|
|
|
* C ← Begin N* End
|
|
|
|
|
|
|
|
* N ← C / (!Begin !End Z)
|
|
|
|
|
|
|
|
* Z ← any single character
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
var parser = PEG.buildParser([
|
|
|
|
|
|
|
|
'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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parses(parser, "(**)", "(**)");
|
|
|
|
|
|
|
|
parses(parser, "(*abc*)", "(*abc*)");
|
|
|
|
|
|
|
|
parses(parser, "(*(**)*)", "(*(**)*)");
|
|
|
|
|
|
|
|
parses(
|
|
|
|
|
|
|
|
parser,
|
|
|
|
|
|
|
|
"(*abc(*def*)ghi(*(*(*jkl*)*)*)mno*)",
|
|
|
|
|
|
|
|
"(*abc(*def*)ghi(*(*(*jkl*)*)*)mno*)"
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
})();
|
|
|
|
})();
|
|
|
|