PEG.js grammar: Extract the |ActionExpression| rule

Having it separated from the |SequenceExpression| rule is cleaner and
more logical.
redux
David Majda 10 years ago
parent 5c6f4dd38b
commit 8e6f98e45c

@ -70,15 +70,10 @@ module.exports = (function() {
? { type: "choice", alternatives: buildList(first, rest, 3) } ? { type: "choice", alternatives: buildList(first, rest, 3) }
: first; : first;
}, },
peg$c11 = function(first, rest, code) { peg$c11 = function(expression, code) {
var expression = rest.length > 0 return code !== null
? { type: "sequence", elements: buildList(first, rest, 1) } ? { type: "action", expression: expression, code: code[1] }
: first; : expression;
return {
type: "action",
expression: expression,
code: code
};
}, },
peg$c12 = function(first, rest) { peg$c12 = function(first, rest) {
return rest.length > 0 return rest.length > 0
@ -748,7 +743,7 @@ module.exports = (function() {
var s0, s1, s2, s3, s4, s5, s6, s7; var s0, s1, s2, s3, s4, s5, s6, s7;
s0 = peg$currPos; s0 = peg$currPos;
s1 = peg$parseSequenceExpression(); s1 = peg$parseActionExpression();
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
s2 = []; s2 = [];
s3 = peg$currPos; s3 = peg$currPos;
@ -764,7 +759,7 @@ module.exports = (function() {
if (s5 !== peg$FAILED) { if (s5 !== peg$FAILED) {
s6 = peg$parse__(); s6 = peg$parse__();
if (s6 !== peg$FAILED) { if (s6 !== peg$FAILED) {
s7 = peg$parseSequenceExpression(); s7 = peg$parseActionExpression();
if (s7 !== peg$FAILED) { if (s7 !== peg$FAILED) {
s4 = [s4, s5, s6, s7]; s4 = [s4, s5, s6, s7];
s3 = s4; s3 = s4;
@ -799,7 +794,7 @@ module.exports = (function() {
if (s5 !== peg$FAILED) { if (s5 !== peg$FAILED) {
s6 = peg$parse__(); s6 = peg$parse__();
if (s6 !== peg$FAILED) { if (s6 !== peg$FAILED) {
s7 = peg$parseSequenceExpression(); s7 = peg$parseActionExpression();
if (s7 !== peg$FAILED) { if (s7 !== peg$FAILED) {
s4 = [s4, s5, s6, s7]; s4 = [s4, s5, s6, s7];
s3 = s4; s3 = s4;
@ -836,6 +831,46 @@ module.exports = (function() {
return s0; return s0;
} }
function peg$parseActionExpression() {
var s0, s1, s2, s3, s4;
s0 = peg$currPos;
s1 = peg$parseSequenceExpression();
if (s1 !== peg$FAILED) {
s2 = peg$currPos;
s3 = peg$parse__();
if (s3 !== peg$FAILED) {
s4 = peg$parseCodeBlock();
if (s4 !== peg$FAILED) {
s3 = [s3, s4];
s2 = s3;
} else {
peg$currPos = s2;
s2 = peg$c0;
}
} else {
peg$currPos = s2;
s2 = peg$c0;
}
if (s2 === peg$FAILED) {
s2 = peg$c1;
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c11(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
return s0;
}
function peg$parseSequenceExpression() { function peg$parseSequenceExpression() {
var s0, s1, s2, s3, s4, s5; var s0, s1, s2, s3, s4, s5;
@ -877,21 +912,9 @@ module.exports = (function() {
} }
} }
if (s2 !== peg$FAILED) { if (s2 !== peg$FAILED) {
s3 = peg$parse__(); peg$reportedPos = s0;
if (s3 !== peg$FAILED) { s1 = peg$c12(s1, s2);
s4 = peg$parseCodeBlock(); s0 = s1;
if (s4 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c11(s1, s2, s4);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$c0; s0 = peg$c0;
@ -900,57 +923,6 @@ module.exports = (function() {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$c0; s0 = peg$c0;
} }
if (s0 === peg$FAILED) {
s0 = peg$currPos;
s1 = peg$parseLabeledExpression();
if (s1 !== peg$FAILED) {
s2 = [];
s3 = peg$currPos;
s4 = peg$parse__();
if (s4 !== peg$FAILED) {
s5 = peg$parseLabeledExpression();
if (s5 !== peg$FAILED) {
s4 = [s4, s5];
s3 = s4;
} else {
peg$currPos = s3;
s3 = peg$c0;
}
} else {
peg$currPos = s3;
s3 = peg$c0;
}
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$currPos;
s4 = peg$parse__();
if (s4 !== peg$FAILED) {
s5 = peg$parseLabeledExpression();
if (s5 !== peg$FAILED) {
s4 = [s4, s5];
s3 = s4;
} else {
peg$currPos = s3;
s3 = peg$c0;
}
} else {
peg$currPos = s3;
s3 = peg$c0;
}
}
if (s2 !== peg$FAILED) {
peg$reportedPos = s0;
s1 = peg$c12(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$c0;
}
} else {
peg$currPos = s0;
s0 = peg$c0;
}
}
return s0; return s0;
} }

@ -24,6 +24,8 @@ describe("PEG.js grammar parser", function() {
type: "sequence", type: "sequence",
elements: [labeledAbcd, labeledEfgh, labeledIjkl] elements: [labeledAbcd, labeledEfgh, labeledIjkl]
}, },
actionOnAbcd = { type: "action", expression: literalAbcd, code: " code " },
actionOnSequence = { type: "action", expression: sequenceOfLiterals, code: " code " },
choiceOfLiterals = { choiceOfLiterals = {
type: "choice", type: "choice",
alternatives: [literalAbcd, literalEfgh, literalIjkl] alternatives: [literalAbcd, literalEfgh, literalIjkl]
@ -234,52 +236,41 @@ describe("PEG.js grammar parser", function() {
/* Canonical ChoiceExpression is "\"abcd\" / \"efgh\" / \"ijkl\"". */ /* Canonical ChoiceExpression is "\"abcd\" / \"efgh\" / \"ijkl\"". */
it("parses ChoiceExpression", function() { it("parses ChoiceExpression", function() {
expect('start = "abcd" "efgh" "ijkl"').toParseAs( expect('start = "abcd" { code }').toParseAs(
oneRuleGrammar(sequenceOfLiterals) oneRuleGrammar(actionOnAbcd)
); );
expect( expect(
'start = "abcd" "efgh" "ijkl" / "abcd" "efgh" "ijkl" / "abcd" "efgh" "ijkl"' 'start = "abcd" { code } / "abcd" { code } / "abcd" { code }'
).toParseAs(oneRuleGrammar({ ).toParseAs(oneRuleGrammar({
type: "choice", type: "choice",
alternatives: [sequenceOfLiterals, sequenceOfLiterals, sequenceOfLiterals] alternatives: [actionOnAbcd, actionOnAbcd, actionOnAbcd]
})); }));
expect( expect(
'start = "abcd" "efgh" "ijkl"\n/ "abcd" "efgh" "ijkl"\n/ "abcd" "efgh" "ijkl"' 'start = "abcd" { code }\n/ "abcd" { code }\n/ "abcd" { code }'
).toParseAs(oneRuleGrammar({ ).toParseAs(oneRuleGrammar({
type: "choice", type: "choice",
alternatives: [sequenceOfLiterals, sequenceOfLiterals, sequenceOfLiterals] alternatives: [actionOnAbcd, actionOnAbcd, actionOnAbcd]
})); }));
expect( expect(
'start = "abcd" "efgh" "ijkl" /\n"abcd" "efgh" "ijkl" /\n"abcd" "efgh" "ijkl"' 'start = "abcd" { code } /\n"abcd" { code } /\n"abcd" { code }'
).toParseAs(oneRuleGrammar({ ).toParseAs(oneRuleGrammar({
type: "choice", type: "choice",
alternatives: [sequenceOfLiterals, sequenceOfLiterals, sequenceOfLiterals] alternatives: [actionOnAbcd, actionOnAbcd, actionOnAbcd]
})); }));
}); });
/* Canonical SequenceExpression is "\"abcd\" \"efgh\" \"ijkl\"". */ /* Canonical ActionExpression is "\"abcd\" { code }". */
it("parses SequenceExpression", function() { it("parses ActionExpression", function() {
expect('start = a:"abcd" { code }').toParseAs( expect('start = "abcd" "efgh" "ijkl" { code }').toParseAs(
oneRuleGrammar({ type: "action", expression: labeledAbcd, code: " code " }) oneRuleGrammar(actionOnSequence)
);
expect('start = a:"abcd"\n{ code }').toParseAs(
oneRuleGrammar({ type: "action", expression: labeledAbcd, code: " code " })
);
expect('start = a:"abcd" b:"efgh" c:"ijkl" { code }').toParseAs(
oneRuleGrammar({
type: "action",
expression: sequenceOfLabeleds,
code: " code "
})
); );
expect('start = a:"abcd"\nb:"efgh"\nc:"ijkl" { code }').toParseAs( expect('start = "abcd" "efgh" "ijkl"\n{ code }').toParseAs(
oneRuleGrammar({ oneRuleGrammar(actionOnSequence)
type: "action",
expression: sequenceOfLabeleds,
code: " code "
})
); );
});
/* Canonical SequenceExpression is "\"abcd\" \"efgh\" \"ijkl\"". */
it("parses SequenceExpression", function() {
expect('start = a:"abcd"').toParseAs( expect('start = a:"abcd"').toParseAs(
oneRuleGrammar(labeledAbcd) oneRuleGrammar(labeledAbcd)
); );

@ -70,24 +70,21 @@ Expression
= ChoiceExpression = ChoiceExpression
ChoiceExpression ChoiceExpression
= first:SequenceExpression rest:(__ "/" __ SequenceExpression)* { = first:ActionExpression rest:(__ "/" __ ActionExpression)* {
return rest.length > 0 return rest.length > 0
? { type: "choice", alternatives: buildList(first, rest, 3) } ? { type: "choice", alternatives: buildList(first, rest, 3) }
: first; : first;
} }
SequenceExpression ActionExpression
= first:LabeledExpression rest:(__ LabeledExpression)* __ code:CodeBlock { = expression:SequenceExpression code:(__ CodeBlock)? {
var expression = rest.length > 0 return code !== null
? { type: "sequence", elements: buildList(first, rest, 1) } ? { type: "action", expression: expression, code: code[1] }
: first; : expression;
return {
type: "action",
expression: expression,
code: code
};
} }
/ first:LabeledExpression rest:(__ LabeledExpression)* {
SequenceExpression
= first:LabeledExpression rest:(__ LabeledExpression)* {
return rest.length > 0 return rest.length > 0
? { type: "sequence", elements: buildList(first, rest, 1) } ? { type: "sequence", elements: buildList(first, rest, 1) }
: first; : first;

Loading…
Cancel
Save