Browse Source

PEG.js grammar: Extract the |ActionExpression| rule

Having it separated from the |SequenceExpression| rule is cleaner and
more logical.
redux
David Majda 8 years ago
parent
commit
8e6f98e45c
  1. 128
      lib/parser.js
  2. 47
      spec/parser.spec.js
  3. 21
      src/parser.pegjs

128
lib/parser.js

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

47
spec/parser.spec.js

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

21
src/parser.pegjs

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

Loading…
Cancel
Save