Change ordering of "literal", "class" and "any" code

Changes all code that does something with "literal", "class" or "any"
AST nodes so that the code deals with these in the follwing order:

  1. literal
  2. class
  3. any

Previously the code used this ordering:

  1. literal
  2. any
  3. class

The new ordering is more logical because the nodes are handled from the
most specific to the most generic.
redux
David Majda 13 years ago
parent eb4badab24
commit cdf23e0a49

@ -211,16 +211,16 @@ describe("compiler pass |computeVarNames|", function() {
}));
});
it("computes variable names for an any", function() {
expect(pass).toChangeAST('start = .', ruleDetails({
it("computes variable names for a class", function() {
expect(pass).toChangeAST('start = [a-z]', ruleDetails({
resultVars: ["result0"],
posVars: [],
expression: leafDetails
}));
});
it("computes variable names for a class", function() {
expect(pass).toChangeAST('start = [a-z]', ruleDetails({
it("computes variable names for an any", function() {
expect(pass).toChangeAST('start = .', ruleDetails({
resultVars: ["result0"],
posVars: [],
expression: leafDetails

@ -601,26 +601,6 @@ describe("generated parser", function() {
});
});
describe("any matching", function() {
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"]);
});
it("sets expected string correctly on failure", function() {
var parser = PEG.buildParser('start = .', options);
expect(parser).toFailToParse("", { expected: ['any character'] });
});
});
describe("class matching", function() {
it("matches empty class correctly", function() {
var parser = PEG.buildParser('start = []', options);
@ -680,6 +660,26 @@ describe("generated parser", function() {
});
});
describe("any matching", function() {
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"]);
});
it("sets expected string correctly on failure", function() {
var parser = PEG.buildParser('start = .', options);
expect(parser).toFailToParse("", { expected: ['any character'] });
});
});
describe("error reporting", function() {
describe("behavior", function() {
it("reports only the rightmost error", function() {

@ -309,8 +309,8 @@ describe("PEG.js grammar parser", function() {
it("parses primary", function() {
expect('start = a' ).toParseAs(ruleRefGrammar("a"));
expect('start = "abcd"' ).toParseAs(literalGrammar("abcd"));
expect('start = .' ).toParseAs(oneRuleGrammar({ type: "any" }));
expect('start = [a-d]' ).toParseAs(classGrammar([["a", "d"]], "[a-d]"));
expect('start = .' ).toParseAs(oneRuleGrammar({ type: "any" }));
expect('start = ("abcd")').toParseAs(literalGrammar("abcd"));
});

@ -97,8 +97,8 @@ PEG.compiler.passes.computeParams = function(ast) {
rule_ref: nop,
literal: nop,
any: nop,
"class": nop
"class": nop,
any: nop
});
compute(ast);

@ -119,8 +119,8 @@ PEG.compiler.passes.computeVarNames = function(ast) {
action: computeFromExpression({ result: 0, pos: 1 }),
rule_ref: computeLeaf,
literal: computeLeaf,
any: computeLeaf,
"class": computeLeaf
"class": computeLeaf,
any: computeLeaf
});
compute(ast, { result: 0, pos: 0 });

@ -711,25 +711,25 @@ PEG.compiler.passes.generateCode = function(ast, options) {
' }',
'#end'
],
any: [
'if (input.length > #{posOffset("pos")}) {',
"class": [
'if (#{regexp}.test(input.charAt(#{posOffset("pos")}))) {',
' #{node.resultVar} = input.charAt(#{posOffset("pos")});',
' #{posAdvance(1)};',
'} else {',
' #{node.resultVar} = null;',
' if (reportFailures === 0) {',
' matchFailed("any character");',
' matchFailed(#{string(node.rawText)});',
' }',
'}'
],
"class": [
'if (#{regexp}.test(input.charAt(#{posOffset("pos")}))) {',
any: [
'if (input.length > #{posOffset("pos")}) {',
' #{node.resultVar} = input.charAt(#{posOffset("pos")});',
' #{posAdvance(1)};',
'} else {',
' #{node.resultVar} = null;',
' if (reportFailures === 0) {',
' matchFailed(#{string(node.rawText)});',
' matchFailed("any character");',
' }',
'}'
]
@ -858,7 +858,6 @@ PEG.compiler.passes.generateCode = function(ast, options) {
action: emitSimple("action"),
rule_ref: emitSimple("rule_ref"),
literal: emitSimple("literal"),
any: emitSimple("any"),
"class": function(node) {
var regexp;
@ -883,7 +882,9 @@ PEG.compiler.passes.generateCode = function(ast, options) {
}
return fill("class", { node: node, regexp: regexp });
}
},
any: emitSimple("any")
});
ast.code = emit(ast);

@ -45,8 +45,8 @@ PEG.compiler.passes.removeProxyRules = function(ast) {
},
literal: nop,
any: nop,
"class": nop
"class": nop,
any: nop
});
replace(ast, from, to);

@ -53,8 +53,8 @@ PEG.compiler.passes.reportLeftRecursion = function(ast) {
},
literal: nop,
any: nop,
"class": nop
"class": nop,
any: nop
});
check(ast, []);

@ -34,8 +34,8 @@ PEG.compiler.passes.reportMissingRules = function(ast) {
},
literal: nop,
any: nop,
"class": nop
"class": nop,
any: nop
});
check(ast);

@ -743,16 +743,16 @@ PEG.parser = (function(){
if (result0 === null) {
result0 = parse_literal();
if (result0 === null) {
pos0 = pos;
result0 = parse_dot();
if (result0 !== null) {
result0 = (function(offset) { return { type: "any" }; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
result0 = parse_class();
if (result0 === null) {
result0 = parse_class();
pos0 = pos;
result0 = parse_dot();
if (result0 !== null) {
result0 = (function(offset) { return { type: "any" }; })(pos0);
}
if (result0 === null) {
pos = pos0;
}
if (result0 === null) {
pos0 = pos;
pos1 = pos;

@ -139,8 +139,8 @@ primary
};
}
/ literal
/ dot { return { type: "any" }; }
/ class
/ dot { return { type: "any" }; }
/ lparen expression:expression rparen { return expression; }
/* "Lexical" elements */

Loading…
Cancel
Save