Reorder AST stuff more consistently and sensibly

There is no functional change in this commit.
redux
David Majda 14 years ago
parent f28c52fde2
commit 85930cbcfe

@ -200,11 +200,9 @@ PEG.Grammar.Rule.prototype = {
getName: function() { return this._name; } getName: function() { return this._name; }
}; };
PEG.Grammar.Literal = function(value) { this._value = value; }; PEG.Grammar.Choice = function(alternatives) {
this._alternatives = alternatives;
PEG.Grammar.Class = function(characters) { this._characters = characters; }; };
PEG.Grammar.Any = function() {};
PEG.Grammar.Sequence = function(elements) { this._elements = elements; }; PEG.Grammar.Sequence = function(elements) { this._elements = elements; };
@ -212,16 +210,6 @@ PEG.Grammar.Sequence.prototype = {
getElements: function() { return this._elements; } getElements: function() { return this._elements; }
}; };
PEG.Grammar.Choice = function(alternatives) {
this._alternatives = alternatives;
};
PEG.Grammar.Optional = function(expression) { this._expression = expression; };
PEG.Grammar.ZeroOrMore = function(expression) { this._expression = expression; };
PEG.Grammar.OneOrMore = function(expression) { this._expression = expression; };
PEG.Grammar.AndPredicate = function(expression) { PEG.Grammar.AndPredicate = function(expression) {
this._expression = expression; this._expression = expression;
}; };
@ -230,13 +218,25 @@ PEG.Grammar.NotPredicate = function(expression) {
this._expression = expression; this._expression = expression;
}; };
PEG.Grammar.RuleRef = function(name) { this._name = name; }; PEG.Grammar.Optional = function(expression) { this._expression = expression; };
PEG.Grammar.ZeroOrMore = function(expression) { this._expression = expression; };
PEG.Grammar.OneOrMore = function(expression) { this._expression = expression; };
PEG.Grammar.Action = function(expression, action) { PEG.Grammar.Action = function(expression, action) {
this._expression = expression; this._expression = expression;
this._action = action; this._action = action;
}; };
PEG.Grammar.RuleRef = function(name) { this._name = name; };
PEG.Grammar.Literal = function(value) { this._value = value; };
PEG.Grammar.Any = function() {};
PEG.Grammar.Class = function(characters) { this._characters = characters; };
/* ===== Referenced Rule Existence Checks ===== */ /* ===== Referenced Rule Existence Checks ===== */
PEG.Grammar.extendNodes("checkReferencedRulesExist", { PEG.Grammar.extendNodes("checkReferencedRulesExist", {
@ -245,9 +245,12 @@ PEG.Grammar.extendNodes("checkReferencedRulesExist", {
this._expression.checkReferencedRulesExist(grammar); this._expression.checkReferencedRulesExist(grammar);
}, },
Literal: nop, Choice:
Class: nop, function(grammar) {
Any: nop, PEG.ArrayUtils.each(this._alternatives, function(alternative) {
alternative.checkReferencedRulesExist(grammar);
});
},
Sequence: Sequence:
function(grammar) { function(grammar) {
@ -256,12 +259,11 @@ PEG.Grammar.extendNodes("checkReferencedRulesExist", {
}); });
}, },
Choice: AndPredicate:
function(grammar) { function(grammar) { this._expression.checkReferencedRulesExist(grammar); },
PEG.ArrayUtils.each(this._alternatives, function(alternative) {
alternative.checkReferencedRulesExist(grammar); NotPredicate:
}); function(grammar) { this._expression.checkReferencedRulesExist(grammar); },
},
Optional: Optional:
function(grammar) { this._expression.checkReferencedRulesExist(grammar); }, function(grammar) { this._expression.checkReferencedRulesExist(grammar); },
@ -272,10 +274,7 @@ PEG.Grammar.extendNodes("checkReferencedRulesExist", {
OneOrMore: OneOrMore:
function(grammar) { this._expression.checkReferencedRulesExist(grammar); }, function(grammar) { this._expression.checkReferencedRulesExist(grammar); },
AndPredicate: Action:
function(grammar) { this._expression.checkReferencedRulesExist(grammar); },
NotPredicate:
function(grammar) { this._expression.checkReferencedRulesExist(grammar); }, function(grammar) { this._expression.checkReferencedRulesExist(grammar); },
RuleRef: RuleRef:
@ -287,8 +286,9 @@ PEG.Grammar.extendNodes("checkReferencedRulesExist", {
} }
}, },
Action: Literal: nop,
function(grammar) { this._expression.checkReferencedRulesExist(grammar); } Any: nop,
Class: nop
}); });
@ -300,9 +300,12 @@ PEG.Grammar.extendNodes("checkNoLeftRecursion", {
this._expression.checkNoLeftRecursion(grammar, appliedRules.concat(this._name)); this._expression.checkNoLeftRecursion(grammar, appliedRules.concat(this._name));
}, },
Literal: nop, Choice:
Class: nop, function(grammar, appliedRules) {
Any: nop, PEG.ArrayUtils.each(this._alternatives, function(alternative) {
alternative.checkNoLeftRecursion(grammar, appliedRules);
});
},
Sequence: Sequence:
function(grammar, appliedRules) { function(grammar, appliedRules) {
@ -311,34 +314,32 @@ PEG.Grammar.extendNodes("checkNoLeftRecursion", {
} }
}, },
Choice: AndPredicate:
function(grammar, appliedRules) { function(grammar, appliedRules) {
PEG.ArrayUtils.each(this._alternatives, function(alternative) { this._expression.checkNoLeftRecursion(grammar, appliedRules);
alternative.checkNoLeftRecursion(grammar, appliedRules);
});
}, },
Optional: NotPredicate:
function(grammar, appliedRules) { function(grammar, appliedRules) {
this._expression.checkNoLeftRecursion(grammar, appliedRules); this._expression.checkNoLeftRecursion(grammar, appliedRules);
}, },
ZeroOrMore: Optional:
function(grammar, appliedRules) { function(grammar, appliedRules) {
this._expression.checkNoLeftRecursion(grammar, appliedRules); this._expression.checkNoLeftRecursion(grammar, appliedRules);
}, },
OneOrMore: ZeroOrMore:
function(grammar, appliedRules) { function(grammar, appliedRules) {
this._expression.checkNoLeftRecursion(grammar, appliedRules); this._expression.checkNoLeftRecursion(grammar, appliedRules);
}, },
AndPredicate: OneOrMore:
function(grammar, appliedRules) { function(grammar, appliedRules) {
this._expression.checkNoLeftRecursion(grammar, appliedRules); this._expression.checkNoLeftRecursion(grammar, appliedRules);
}, },
NotPredicate: Action:
function(grammar, appliedRules) { function(grammar, appliedRules) {
this._expression.checkNoLeftRecursion(grammar, appliedRules); this._expression.checkNoLeftRecursion(grammar, appliedRules);
}, },
@ -351,10 +352,9 @@ PEG.Grammar.extendNodes("checkNoLeftRecursion", {
grammar[this._name].checkNoLeftRecursion(grammar, appliedRules); grammar[this._name].checkNoLeftRecursion(grammar, appliedRules);
}, },
Action: Literal: nop,
function(grammar, appliedRules) { Any: nop,
this._expression.checkNoLeftRecursion(grammar, appliedRules); Class: nop
}
}); });
/* ===== PEG.Compiler ===== */ /* ===== PEG.Compiler ===== */
@ -754,69 +754,31 @@ PEG.Grammar.Rule.prototype.compile = function() {
* |null|. * |null|.
*/ */
PEG.Grammar.Literal.prototype.compile = function(resultVar) { PEG.Grammar.Choice.prototype.compile = function(resultVar) {
return PEG.Compiler.formatCode( var code = PEG.Compiler.formatCode(
"if (this._input.substr(this._pos, ${length}) === ${value|string}) {", "var ${resultVar} = null;",
" var ${resultVar} = ${value|string};", { resultVar: resultVar }
" this._pos += ${length};",
"} else {",
" var ${resultVar} = null;",
" if (context.reportMatchFailures) {",
" this._matchFailed(this._quoteString(${value|string}));",
" }",
"}",
{
value: this._value,
length: this._value.length,
resultVar: resultVar
}
); );
};
PEG.Grammar.Class.prototype.compile = function(resultVar) { for (var i = this._alternatives.length - 1; i >= 0; i--) {
/* var alternativeResultVar = PEG.Compiler.generateUniqueIdentifier("result");
* Stupid IE considers regexps /[]/ and /[^]/ syntactically invalid, so we code = PEG.Compiler.formatCode(
* translate them into euqivalents it can handle. "${alternativeCode}",
*/ "if (${alternativeResultVar} !== null) {",
if (this._characters === "") { " var ${resultVar} = ${alternativeResultVar};",
var regexp = "/^(?!)/"; "} else {",
} else if (this._characters === "^") { " ${code};",
var regexp = "/^[\\S\\s]/"; "}",
} else { {
var regexp = "/^[" + this._characters + "]/"; alternativeCode: this._alternatives[i].compile(alternativeResultVar),
alternativeResultVar: alternativeResultVar,
code: code,
resultVar: resultVar
}
);
} }
return PEG.Compiler.formatCode( return code;
"if (this._input.substr(this._pos).match(${regexp}) !== null) {",
" var ${resultVar} = this._input.charAt(this._pos);",
" this._pos++;",
"} else {",
" var ${resultVar} = null;",
" if (context.reportMatchFailures) {",
" this._matchFailed('[' + ${characters|string} + ']');",
" }",
"}",
{
characters: this._characters,
regexp: regexp,
resultVar: resultVar
}
);
};
PEG.Grammar.Any.prototype.compile = function(resultVar) {
return PEG.Compiler.formatCode(
"if (this._input.length > this._pos) {",
" var ${resultVar} = this._input.charAt(this._pos);",
" this._pos++;",
"} else {",
" var ${resultVar} = null;",
" if (context.reportMatchFailures) {",
" this._matchFailed('any character');",
" }",
"}",
{ resultVar: resultVar }
);
}; };
PEG.Grammar.Sequence.prototype.compile = function(resultVar) { PEG.Grammar.Sequence.prototype.compile = function(resultVar) {
@ -863,31 +825,58 @@ PEG.Grammar.Sequence.prototype.compile = function(resultVar) {
); );
}; };
PEG.Grammar.Choice.prototype.compile = function(resultVar) { PEG.Grammar.AndPredicate.prototype.compile = function(resultVar) {
var code = PEG.Compiler.formatCode( var savedPosVar = PEG.Compiler.generateUniqueIdentifier("savedPos");
"var ${resultVar} = null;", var savedReportMatchFailuresVar = PEG.Compiler.generateUniqueIdentifier("savedReportMatchFailuresVar");
{ resultVar: resultVar } var expressionResultVar = PEG.Compiler.generateUniqueIdentifier("result");
return PEG.Compiler.formatCode(
"var ${savedPosVar} = this._pos;",
"var ${savedReportMatchFailuresVar} = context.reportMatchFailures;",
"context.reportMatchFailures = false;",
"${expressionCode}",
"context.reportMatchFailures = ${savedReportMatchFailuresVar};",
"if (${expressionResultVar} !== null) {",
" var ${resultVar} = '';",
" this._pos = ${savedPosVar};",
"} else {",
" var ${resultVar} = null;",
"}",
{
expressionCode: this._expression.compile(expressionResultVar),
expressionResultVar: expressionResultVar,
savedPosVar: savedPosVar,
savedReportMatchFailuresVar: savedReportMatchFailuresVar,
resultVar: resultVar
}
); );
};
for (var i = this._alternatives.length - 1; i >= 0; i--) { PEG.Grammar.NotPredicate.prototype.compile = function(resultVar) {
var alternativeResultVar = PEG.Compiler.generateUniqueIdentifier("result"); var savedPosVar = PEG.Compiler.generateUniqueIdentifier("savedPos");
code = PEG.Compiler.formatCode( var savedReportMatchFailuresVar = PEG.Compiler.generateUniqueIdentifier("savedReportMatchFailuresVar");
"${alternativeCode}", var expressionResultVar = PEG.Compiler.generateUniqueIdentifier("result");
"if (${alternativeResultVar} !== null) {",
" var ${resultVar} = ${alternativeResultVar};",
"} else {",
" ${code};",
"}",
{
alternativeCode: this._alternatives[i].compile(alternativeResultVar),
alternativeResultVar: alternativeResultVar,
code: code,
resultVar: resultVar
}
);
}
return code; return PEG.Compiler.formatCode(
"var ${savedPosVar} = this._pos;",
"var ${savedReportMatchFailuresVar} = context.reportMatchFailures;",
"context.reportMatchFailures = false;",
"${expressionCode}",
"context.reportMatchFailures = ${savedReportMatchFailuresVar};",
"if (${expressionResultVar} === null) {",
" var ${resultVar} = '';",
"} else {",
" var ${resultVar} = null;",
" this._pos = ${savedPosVar};",
"}",
{
expressionCode: this._expression.compile(expressionResultVar),
expressionResultVar: expressionResultVar,
savedPosVar: savedPosVar,
savedReportMatchFailuresVar: savedReportMatchFailuresVar,
resultVar: resultVar
}
);
}; };
PEG.Grammar.Optional.prototype.compile = function(resultVar) { PEG.Grammar.Optional.prototype.compile = function(resultVar) {
@ -944,70 +933,6 @@ PEG.Grammar.OneOrMore.prototype.compile = function(resultVar) {
); );
}; };
PEG.Grammar.NotPredicate.prototype.compile = function(resultVar) {
var savedPosVar = PEG.Compiler.generateUniqueIdentifier("savedPos");
var savedReportMatchFailuresVar = PEG.Compiler.generateUniqueIdentifier("savedReportMatchFailuresVar");
var expressionResultVar = PEG.Compiler.generateUniqueIdentifier("result");
return PEG.Compiler.formatCode(
"var ${savedPosVar} = this._pos;",
"var ${savedReportMatchFailuresVar} = context.reportMatchFailures;",
"context.reportMatchFailures = false;",
"${expressionCode}",
"context.reportMatchFailures = ${savedReportMatchFailuresVar};",
"if (${expressionResultVar} === null) {",
" var ${resultVar} = '';",
"} else {",
" var ${resultVar} = null;",
" this._pos = ${savedPosVar};",
"}",
{
expressionCode: this._expression.compile(expressionResultVar),
expressionResultVar: expressionResultVar,
savedPosVar: savedPosVar,
savedReportMatchFailuresVar: savedReportMatchFailuresVar,
resultVar: resultVar
}
);
};
PEG.Grammar.AndPredicate.prototype.compile = function(resultVar) {
var savedPosVar = PEG.Compiler.generateUniqueIdentifier("savedPos");
var savedReportMatchFailuresVar = PEG.Compiler.generateUniqueIdentifier("savedReportMatchFailuresVar");
var expressionResultVar = PEG.Compiler.generateUniqueIdentifier("result");
return PEG.Compiler.formatCode(
"var ${savedPosVar} = this._pos;",
"var ${savedReportMatchFailuresVar} = context.reportMatchFailures;",
"context.reportMatchFailures = false;",
"${expressionCode}",
"context.reportMatchFailures = ${savedReportMatchFailuresVar};",
"if (${expressionResultVar} !== null) {",
" var ${resultVar} = '';",
" this._pos = ${savedPosVar};",
"} else {",
" var ${resultVar} = null;",
"}",
{
expressionCode: this._expression.compile(expressionResultVar),
expressionResultVar: expressionResultVar,
savedPosVar: savedPosVar,
savedReportMatchFailuresVar: savedReportMatchFailuresVar,
resultVar: resultVar
}
);
};
PEG.Grammar.RuleRef.prototype.compile = function(resultVar) {
return PEG.Compiler.formatCode(
"var ${resultVar} = this.${ruleMethod}(context);",
{
ruleMethod: "_parse_" + this._name,
resultVar: resultVar
}
);
};
PEG.Grammar.Action.prototype.compile = function(resultVar) { PEG.Grammar.Action.prototype.compile = function(resultVar) {
/* /*
* In case of sequences, we splat their elements into function arguments one * In case of sequences, we splat their elements into function arguments one
@ -1058,4 +983,80 @@ PEG.Grammar.Action.prototype.compile = function(resultVar) {
); );
}; };
PEG.Grammar.RuleRef.prototype.compile = function(resultVar) {
return PEG.Compiler.formatCode(
"var ${resultVar} = this.${ruleMethod}(context);",
{
ruleMethod: "_parse_" + this._name,
resultVar: resultVar
}
);
};
PEG.Grammar.Literal.prototype.compile = function(resultVar) {
return PEG.Compiler.formatCode(
"if (this._input.substr(this._pos, ${length}) === ${value|string}) {",
" var ${resultVar} = ${value|string};",
" this._pos += ${length};",
"} else {",
" var ${resultVar} = null;",
" if (context.reportMatchFailures) {",
" this._matchFailed(this._quoteString(${value|string}));",
" }",
"}",
{
value: this._value,
length: this._value.length,
resultVar: resultVar
}
);
};
PEG.Grammar.Any.prototype.compile = function(resultVar) {
return PEG.Compiler.formatCode(
"if (this._input.length > this._pos) {",
" var ${resultVar} = this._input.charAt(this._pos);",
" this._pos++;",
"} else {",
" var ${resultVar} = null;",
" if (context.reportMatchFailures) {",
" this._matchFailed('any character');",
" }",
"}",
{ resultVar: resultVar }
);
};
PEG.Grammar.Class.prototype.compile = function(resultVar) {
/*
* Stupid IE considers regexps /[]/ and /[^]/ syntactically invalid, so we
* translate them into euqivalents it can handle.
*/
if (this._characters === "") {
var regexp = "/^(?!)/";
} else if (this._characters === "^") {
var regexp = "/^[\\S\\s]/";
} else {
var regexp = "/^[" + this._characters + "]/";
}
return PEG.Compiler.formatCode(
"if (this._input.substr(this._pos).match(${regexp}) !== null) {",
" var ${resultVar} = this._input.charAt(this._pos);",
" this._pos++;",
"} else {",
" var ${resultVar} = null;",
" if (context.reportMatchFailures) {",
" this._matchFailed('[' + ${characters|string} + ']');",
" }",
"}",
{
characters: this._characters,
regexp: regexp,
resultVar: resultVar
}
);
};
})(); })();

@ -202,15 +202,15 @@ test("buildParser reports missing start rule", function() {
test("buildParser reports missing referenced rules", function() { test("buildParser reports missing referenced rules", function() {
var grammars = [ var grammars = [
'start: missing', 'start: missing',
'start: missing "a" "b"',
'start: "a" "b" missing',
'start: missing / "a" / "b"', 'start: missing / "a" / "b"',
'start: "a" / "b" / missing', 'start: "a" / "b" / missing',
'start: missing "a" "b"',
'start: "a" "b" missing',
'start: &missing',
'start: !missing',
'start: missing?', 'start: missing?',
'start: missing*', 'start: missing*',
'start: missing+', 'start: missing+',
'start: &missing',
'start: !missing',
'start: missing { }' 'start: missing { }'
]; ];
@ -227,14 +227,14 @@ test("buildParser reports left recursion", function() {
var grammars = [ var grammars = [
/* Direct */ /* Direct */
'start: start', 'start: start',
'start: start "a" "b"',
'start: start / "a" / "b"', 'start: start / "a" / "b"',
'start: "a" / "b" / start', 'start: "a" / "b" / start',
'start: start "a" "b"',
'start: &start',
'start: !start',
'start: start?', 'start: start?',
'start: start*', 'start: start*',
'start: start+', 'start: start+',
'start: &start',
'start: !start',
'start: start { }', 'start: start { }',
/* Indirect */ /* Indirect */
@ -259,69 +259,14 @@ test("buildParser allows custom start rule", function() {
module("Generated Parser"); module("Generated Parser");
test("literals", function() { test("choices", function() {
var parser = PEG.buildParser('start: "abcd"'); var parser = PEG.buildParser('start: "a" / "b" / "c"');
parses(parser, "abcd", "abcd");
doesNotParse(parser, "");
doesNotParse(parser, "abc");
doesNotParse(parser, "abcde");
doesNotParse(parser, "efgh");
/*
* Test that the parsing position moves forward after successful parsing of
* a literal.
*/
var posTestParser = PEG.buildParser('start: "a" "b"');
parses(posTestParser, "ab", ["a", "b"]);
});
test("anys", function() {
var parser = PEG.buildParser('start: .');
parses(parser, "a", "a"); parses(parser, "a", "a");
parses(parser, "b", "b");
parses(parser, "c", "c");
doesNotParse(parser, ""); doesNotParse(parser, "");
doesNotParse(parser, "ab"); doesNotParse(parser, "ab");
doesNotParse(parser, "d");
/*
* Test that the parsing position moves forward after successful parsing of
* an any.
*/
var posTestParser = PEG.buildParser('start: . .');
parses(posTestParser, "ab", ["a", "b"]);
});
test("classes", function() {
var emptyClassParser = PEG.buildParser('start: []');
doesNotParse(emptyClassParser, "");
doesNotParse(emptyClassParser, "a");
doesNotParse(emptyClassParser, "ab");
var nonEmptyClassParser = PEG.buildParser('start: [ab-d]');
parses(nonEmptyClassParser, "a", "a");
parses(nonEmptyClassParser, "b", "b");
parses(nonEmptyClassParser, "c", "c");
parses(nonEmptyClassParser, "d", "d");
doesNotParse(nonEmptyClassParser, "");
doesNotParse(nonEmptyClassParser, "ab");
var invertedEmptyClassParser = PEG.buildParser('start: [^]');
doesNotParse(invertedEmptyClassParser, "");
parses(invertedEmptyClassParser, "a", "a");
doesNotParse(invertedEmptyClassParser, "ab");
var invertedNonEmptyClassParser = PEG.buildParser('start: [^ab-d]');
doesNotParse(invertedNonEmptyClassParser, "a", "a");
doesNotParse(invertedNonEmptyClassParser, "b", "b");
doesNotParse(invertedNonEmptyClassParser, "c", "c");
doesNotParse(invertedNonEmptyClassParser, "d", "d");
doesNotParse(invertedNonEmptyClassParser, "");
doesNotParse(invertedNonEmptyClassParser, "ab");
/*
* Test that the parsing position moves forward after successful parsing of
* a class.
*/
var posTestParser = PEG.buildParser('start: [ab-d] [ab-d]');
parses(posTestParser, "ab", ["a", "b"]);
}); });
test("sequences", function() { test("sequences", function() {
@ -344,36 +289,6 @@ test("sequences", function() {
parses(posTestParser, "a", "a"); parses(posTestParser, "a", "a");
}); });
test("choices", function() {
var parser = PEG.buildParser('start: "a" / "b" / "c"');
parses(parser, "a", "a");
parses(parser, "b", "b");
parses(parser, "c", "c");
doesNotParse(parser, "");
doesNotParse(parser, "ab");
doesNotParse(parser, "d");
});
test("optional expressions", function() {
var parser = PEG.buildParser('start: "a"?');
parses(parser, "", "");
parses(parser, "a", "a");
});
test("zero or more expressions", function() {
var parser = PEG.buildParser('start: "a"*');
parses(parser, "", []);
parses(parser, "a", ["a"]);
parses(parser, "aaa", ["a", "a", "a"]);
});
test("one or more expressions", function() {
var parser = PEG.buildParser('start: "a"+');
doesNotParse(parser, "");
parses(parser, "a", ["a"]);
parses(parser, "aaa", ["a", "a", "a"]);
});
test("and predicate", function() { test("and predicate", function() {
var parser = PEG.buildParser('start: "a" &"b" "b"'); var parser = PEG.buildParser('start: "a" &"b" "b"');
parses(parser, "ab", ["a", "", "b"]); parses(parser, "ab", ["a", "", "b"]);
@ -398,14 +313,24 @@ test("not predicate", function() {
parses(posTestParser, "ac", ["a", "", "c"]); parses(posTestParser, "ac", ["a", "", "c"]);
}); });
test("rule references", function() { test("optional expressions", function() {
var parser = PEG.buildParser([ var parser = PEG.buildParser('start: "a"?');
'start: static / dynamic', parses(parser, "", "");
'static: "C" / "C++" / "Java" / "C#"', parses(parser, "a", "a");
'dynamic: "Ruby" / "Python" / "JavaScript"' });
].join("\n"));
parses(parser, "Java", "Java"); test("zero or more expressions", function() {
parses(parser, "Python", "Python"); var parser = PEG.buildParser('start: "a"*');
parses(parser, "", []);
parses(parser, "a", ["a"]);
parses(parser, "aaa", ["a", "a", "a"]);
});
test("one or more expressions", function() {
var parser = PEG.buildParser('start: "a"+');
doesNotParse(parser, "");
parses(parser, "a", ["a"]);
parses(parser, "aaa", ["a", "a", "a"]);
}); });
test("actions", function() { test("actions", function() {
@ -438,6 +363,81 @@ test("actions", function() {
parses(variablesParser, "abcdefghij", "ABCDEFGHIJ"); parses(variablesParser, "abcdefghij", "ABCDEFGHIJ");
}); });
test("rule references", function() {
var parser = PEG.buildParser([
'start: static / dynamic',
'static: "C" / "C++" / "Java" / "C#"',
'dynamic: "Ruby" / "Python" / "JavaScript"'
].join("\n"));
parses(parser, "Java", "Java");
parses(parser, "Python", "Python");
});
test("literals", function() {
var parser = PEG.buildParser('start: "abcd"');
parses(parser, "abcd", "abcd");
doesNotParse(parser, "");
doesNotParse(parser, "abc");
doesNotParse(parser, "abcde");
doesNotParse(parser, "efgh");
/*
* Test that the parsing position moves forward after successful parsing of
* a literal.
*/
var posTestParser = PEG.buildParser('start: "a" "b"');
parses(posTestParser, "ab", ["a", "b"]);
});
test("anys", function() {
var parser = PEG.buildParser('start: .');
parses(parser, "a", "a");
doesNotParse(parser, "");
doesNotParse(parser, "ab");
/*
* Test that the parsing position moves forward after successful parsing of
* an any.
*/
var posTestParser = PEG.buildParser('start: . .');
parses(posTestParser, "ab", ["a", "b"]);
});
test("classes", function() {
var emptyClassParser = PEG.buildParser('start: []');
doesNotParse(emptyClassParser, "");
doesNotParse(emptyClassParser, "a");
doesNotParse(emptyClassParser, "ab");
var nonEmptyClassParser = PEG.buildParser('start: [ab-d]');
parses(nonEmptyClassParser, "a", "a");
parses(nonEmptyClassParser, "b", "b");
parses(nonEmptyClassParser, "c", "c");
parses(nonEmptyClassParser, "d", "d");
doesNotParse(nonEmptyClassParser, "");
doesNotParse(nonEmptyClassParser, "ab");
var invertedEmptyClassParser = PEG.buildParser('start: [^]');
doesNotParse(invertedEmptyClassParser, "");
parses(invertedEmptyClassParser, "a", "a");
doesNotParse(invertedEmptyClassParser, "ab");
var invertedNonEmptyClassParser = PEG.buildParser('start: [^ab-d]');
doesNotParse(invertedNonEmptyClassParser, "a", "a");
doesNotParse(invertedNonEmptyClassParser, "b", "b");
doesNotParse(invertedNonEmptyClassParser, "c", "c");
doesNotParse(invertedNonEmptyClassParser, "d", "d");
doesNotParse(invertedNonEmptyClassParser, "");
doesNotParse(invertedNonEmptyClassParser, "ab");
/*
* Test that the parsing position moves forward after successful parsing of
* a class.
*/
var posTestParser = PEG.buildParser('start: [ab-d] [ab-d]');
parses(posTestParser, "ab", ["a", "b"]);
});
test("cache", function() { test("cache", function() {
/* /*
* Should trigger a codepath where the cache is used (for the "a" rule). * Should trigger a codepath where the cache is used (for the "a" rule).

Loading…
Cancel
Save