diff --git a/lib/compiler/passes/generate-bytecode.js b/lib/compiler/passes/generate-bytecode.js index 960811a..2fba3d6 100644 --- a/lib/compiler/passes/generate-bytecode.js +++ b/lib/compiler/passes/generate-bytecode.js @@ -458,14 +458,6 @@ function generateBytecode(ast) { return buildSimplePredicate(node.expression, true, context); }, - semantic_and: function(node, context) { - return buildSemanticPredicate(node.code, false, context); - }, - - semantic_not: function(node, context) { - return buildSemanticPredicate(node.code, true, context); - }, - optional: function(node, context) { return buildSequence( generate(node.expression, { @@ -514,6 +506,14 @@ function generateBytecode(ast) { ); }, + semantic_and: function(node, context) { + return buildSemanticPredicate(node.code, false, context); + }, + + semantic_not: function(node, context) { + return buildSemanticPredicate(node.code, true, context); + }, + rule_ref: function(node) { return [op.RULE, asts.indexOfRule(ast, node.name)]; }, diff --git a/lib/compiler/visitor.js b/lib/compiler/visitor.js index 607788a..3dcbad1 100644 --- a/lib/compiler/visitor.js +++ b/lib/compiler/visitor.js @@ -49,11 +49,11 @@ var visitor = { text: visitExpression, simple_and: visitExpression, simple_not: visitExpression, - semantic_and: visitNop, - semantic_not: visitNop, optional: visitExpression, zero_or_more: visitExpression, one_or_more: visitExpression, + semantic_and: visitNop, + semantic_not: visitNop, rule_ref: visitNop, literal: visitNop, "class": visitNop, diff --git a/spec/unit/compiler/passes/generate-bytecode.spec.js b/spec/unit/compiler/passes/generate-bytecode.spec.js index 4f51585..ebf3398 100644 --- a/spec/unit/compiler/passes/generate-bytecode.spec.js +++ b/spec/unit/compiler/passes/generate-bytecode.spec.js @@ -283,6 +283,74 @@ describe("compiler pass |generateBytecode|", function() { }); }); + describe("for optional", function() { + var grammar = 'start = "a"?'; + + it("generates correct bytecode", function() { + expect(pass).toChangeAST(grammar, bytecodeDetails([ + 14, 0, 2, 2, 18, 0, 19, 1, // + 10, 2, 0, // IF_ERROR + 2, // * POP + 27 // PUSH_NULL + ])); + }); + + it("defines correct constants", function() { + expect(pass).toChangeAST(grammar, constsDetails([ + '"a"', + '{ type: "literal", value: "a", description: "\\"a\\"" }' + ])); + }); + }); + + describe("for zero or more", function() { + var grammar = 'start = "a"*'; + + it("generates correct bytecode", function() { + expect(pass).toChangeAST(grammar, bytecodeDetails([ + 29, // PUSH_EMPTY_ARRAY + 14, 0, 2, 2, 18, 0, 19, 1, // + 12, 9, // WHILE_NOT_ERROR + 6, // * APPEND + 14, 0, 2, 2, 18, 0, 19, 1, // + 2 // POP + ])); + }); + + it("defines correct constants", function() { + expect(pass).toChangeAST(grammar, constsDetails([ + '"a"', + '{ type: "literal", value: "a", description: "\\"a\\"" }' + ])); + }); + }); + + describe("for one or more", function() { + var grammar = 'start = "a"+'; + + it("generates correct bytecode", function() { + expect(pass).toChangeAST(grammar, bytecodeDetails([ + 29, // PUSH_EMPTY_ARRAY + 14, 0, 2, 2, 18, 0, 19, 1, // + 11, 12, 3, // IF_NOT_ERROR + 12, 9, // * WHILE_NOT_ERROR + 6, // * APPEND + 14, 0, 2, 2, 18, 0, 19, 1, // + 2, // POP + 2, // * POP + 2, // POP + 28 // PUSH_FAILED + ])); + }); + + it("defines correct constants", function() { + expect(pass).toChangeAST(grammar, constsDetails([ + '"a"', + '{ type: "literal", value: "a", description: "\\"a\\"" }' + ])); + }); + }); + describe("for semantic and", function() { describe("without labels", function() { var grammar = 'start = &{ code }'; @@ -433,74 +501,6 @@ describe("compiler pass |generateBytecode|", function() { }); }); - describe("for optional", function() { - var grammar = 'start = "a"?'; - - it("generates correct bytecode", function() { - expect(pass).toChangeAST(grammar, bytecodeDetails([ - 14, 0, 2, 2, 18, 0, 19, 1, // - 10, 2, 0, // IF_ERROR - 2, // * POP - 27 // PUSH_NULL - ])); - }); - - it("defines correct constants", function() { - expect(pass).toChangeAST(grammar, constsDetails([ - '"a"', - '{ type: "literal", value: "a", description: "\\"a\\"" }' - ])); - }); - }); - - describe("for zero or more", function() { - var grammar = 'start = "a"*'; - - it("generates correct bytecode", function() { - expect(pass).toChangeAST(grammar, bytecodeDetails([ - 29, // PUSH_EMPTY_ARRAY - 14, 0, 2, 2, 18, 0, 19, 1, // - 12, 9, // WHILE_NOT_ERROR - 6, // * APPEND - 14, 0, 2, 2, 18, 0, 19, 1, // - 2 // POP - ])); - }); - - it("defines correct constants", function() { - expect(pass).toChangeAST(grammar, constsDetails([ - '"a"', - '{ type: "literal", value: "a", description: "\\"a\\"" }' - ])); - }); - }); - - describe("for one or more", function() { - var grammar = 'start = "a"+'; - - it("generates correct bytecode", function() { - expect(pass).toChangeAST(grammar, bytecodeDetails([ - 29, // PUSH_EMPTY_ARRAY - 14, 0, 2, 2, 18, 0, 19, 1, // - 11, 12, 3, // IF_NOT_ERROR - 12, 9, // * WHILE_NOT_ERROR - 6, // * APPEND - 14, 0, 2, 2, 18, 0, 19, 1, // - 2, // POP - 2, // * POP - 2, // POP - 28 // PUSH_FAILED - ])); - }); - - it("defines correct constants", function() { - expect(pass).toChangeAST(grammar, constsDetails([ - '"a"', - '{ type: "literal", value: "a", description: "\\"a\\"" }' - ])); - }); - }); - describe("for rule reference", function() { it("generates correct bytecode", function() { expect(pass).toChangeAST([