Skip to content

Commit

Permalink
Issue pegjs#194: Process expectations from predicates
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingun committed Dec 20, 2017
1 parent 6e7566f commit 4912536
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 17 deletions.
2 changes: 1 addition & 1 deletion lib/compiler/opcodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const opcodes = {
SILENT_FAILS_OFF: 29, // SILENT_FAILS_OFF

EXPECT_NS_BEGIN: 38, // EXPECT_NS_BEGIN
EXPECT_NS_END: 39 // EXPECT_NS_END
EXPECT_NS_END: 39 // EXPECT_NS_END invert

};

Expand Down
14 changes: 10 additions & 4 deletions lib/compiler/passes/generate-bytecode.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,15 @@ const visitor = require( "../visitor" );
//
// expected.push({ pos: curPos, variants: [] });
//
// [39] EXPECT_NS_END
//
// expected.pop();
// [39] EXPECT_NS_END invert
//
// value = expected.pop();
// if (value.pos === expected.top().pos) {
// if (invert) {
// value.variants.forEach(e => { e.not = !e.not; });
// }
// expected.top().variants.pushAll(value.variants);
// }
function generateBytecode( ast ) {

const consts = [];
Expand Down Expand Up @@ -265,7 +271,7 @@ function generateBytecode( ast ) {
env: cloneEnv( context.env ),
action: null
} ),
[ op.EXPECT_NS_END ],
[ op.EXPECT_NS_END, negative ? 1 : 0 ],
buildCondition(
[ negative ? op.IF_ERROR : op.IF_NOT_ERROR ],
buildSequence(
Expand Down
32 changes: 24 additions & 8 deletions lib/compiler/passes/generate-js.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,9 @@ function generateJS( ast, options ) {
" ip++;",
" break;",
"",
" case " + op.EXPECT_NS_END + ":", // EXPECT_NS_END
" peg$end();",
" ip++;",
" case " + op.EXPECT_NS_END + ":", // EXPECT_NS_END invert
" peg$end(bc[ip + 1]);",
" ip += 2;",
" break;",
"",
" // istanbul ignore next",
Expand Down Expand Up @@ -796,9 +796,9 @@ function generateJS( ast, options ) {
ip++;
break;

case op.EXPECT_NS_END: // EXPECT_NS_END
parts.push( "peg$end();" );
ip++;
case op.EXPECT_NS_END: // EXPECT_NS_END invert
parts.push( "peg$end(" + ( bc[ ip + 1 ] !== 0 ) + ");" );
ip += 2;
break;

// istanbul ignore next
Expand Down Expand Up @@ -899,6 +899,10 @@ function generateJS( ast, options ) {
"",
" other: function(expectation) {",
" return expectation.description;",
" },",
"",
" not: function(expectation) {",
" return \"not \" + describeExpectation(expectation.expected);",
" }",
" };",
"",
Expand Down Expand Up @@ -1280,8 +1284,20 @@ function generateJS( ast, options ) {
" top.variants.push(expected);",
" }",
"",
" function peg$end() {",
" peg$expected.pop();",
" function peg$end(invert) {",
" var expected = peg$expected.pop();",
" var top = peg$expected[peg$expected.length - 1];",
" var variants = expected.variants;",
"",
" if (top.pos !== expected.pos) { return; }",
"",
" if (invert) {",
" variants = variants.map(function(e) {",
" return e.type === \"not\" ? e.expected : { type: \"not\", expected: e };",
" });",
" }",
"",
" Array.prototype.push.apply(top.variants, variants);",
" }",
"",
" function peg$buildSimpleError(message, location) {",
Expand Down
44 changes: 42 additions & 2 deletions test/spec/behavior/generated-parser-behavior.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1194,19 +1194,33 @@ describe( "generated parser behavior", function () {

} );

it( "discards any expectations recorded when matching the expression", function () {
it( "not discards any expectations recorded when matching the expression", function () {

const parser = peg.generate( "start = 'a' / &'b' / 'c'", options );

expect( parser ).to.failToParse( "d", {
expected: [
{ type: "literal", text: "a", ignoreCase: false },
{ type: "literal", text: "b", ignoreCase: false },
{ type: "literal", text: "c", ignoreCase: false }
]
} );

} );

it( "records expectations from right place", function () {

const parser = peg.generate( "start = 'a' / &'b' .", options );

expect( parser ).to.failToParse( "d", {
expected: [
{ type: "literal", text: "a", ignoreCase: false },
{ type: "literal", text: "b", ignoreCase: false }
]
} );

} );

} );

} );
Expand Down Expand Up @@ -1243,19 +1257,45 @@ describe( "generated parser behavior", function () {

} );

it( "discards any expectations recorded when matching the expression", function () {
it( "inverts any expectations recorded when matching the expression", function () {

const parser = peg.generate( "start = 'a' / !'b' / 'c'", options );

expect( parser ).to.failToParse( "b", {
expected: [
{ type: "literal", text: "a", ignoreCase: false },
{ type: "not", expected: { type: "literal", text: "b", ignoreCase: false } },
{ type: "literal", text: "c", ignoreCase: false }
]
} );

} );

it( "records expectations from right place", function () {

const parser = peg.generate( "start = 'a' / !'b' .", options );

expect( parser ).to.failToParse( "b", {
expected: [
{ type: "literal", text: "a", ignoreCase: false },
{ type: "not", expected: { type: "literal", text: "b", ignoreCase: false } }
]
} );

} );

it( "reports not inverted expectations when the expression inverted twice", function () {

const parser = peg.generate( "start = !(!'a')", options );

expect( parser ).to.failToParse( "b", {
expected: [
{ type: "literal", text: "a", ignoreCase: false }
]
} );

} );

} );

} );
Expand Down
4 changes: 2 additions & 2 deletions test/spec/unit/compiler/passes/generate-bytecode.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ describe( "compiler pass |generateBytecode|", function () {
5, // PUSH_CURR_POS
38, // EXPECT_NS_BEGIN
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
39, // EXPECT_NS_END
39, 0, // EXPECT_NS_END <false>
15, 3, 3, // IF_NOT_ERROR
6, // * POP
7, // POP_CURR_POS
Expand Down Expand Up @@ -341,7 +341,7 @@ describe( "compiler pass |generateBytecode|", function () {
5, // PUSH_CURR_POS
38, // EXPECT_NS_BEGIN
23, 1, 18, 0, 2, 1, 22, 0, 3, // <expression>
39, // EXPECT_NS_END
39, 1, // EXPECT_NS_END <true>
14, 3, 3, // IF_ERROR
6, // * POP
6, // POP
Expand Down

0 comments on commit 4912536

Please sign in to comment.