PEG.js grammar: Extract the |ActionExpression| rule
Having it separated from the |SequenceExpression| rule is cleaner and more logical.
This commit is contained in:
parent
5c6f4dd38b
commit
8e6f98e45c
128
lib/parser.js
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;
|
||||
}
|
||||
|
|
|
@ -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 ActionExpression is "\"abcd\" { code }". */
|
||||
it("parses ActionExpression", function() {
|
||||
expect('start = "abcd" "efgh" "ijkl" { code }').toParseAs(
|
||||
oneRuleGrammar(actionOnSequence)
|
||||
);
|
||||
expect('start = "abcd" "efgh" "ijkl"\n{ code }').toParseAs(
|
||||
oneRuleGrammar(actionOnSequence)
|
||||
);
|
||||
});
|
||||
|
||||
/* 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 "
|
||||
})
|
||||
);
|
||||
expect('start = a:"abcd"\nb:"efgh"\nc:"ijkl" { code }').toParseAs(
|
||||
oneRuleGrammar({
|
||||
type: "action",
|
||||
expression: sequenceOfLabeleds,
|
||||
code: " code "
|
||||
})
|
||||
);
|
||||
|
||||
expect('start = a:"abcd"').toParseAs(
|
||||
oneRuleGrammar(labeledAbcd)
|
||||
);
|
||||
|
|
|
@ -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…
Reference in a new issue