|
|
|
@ -288,13 +288,13 @@ function generateBytecode(ast) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let generate = visitor.build({
|
|
|
|
|
grammar: function(node) {
|
|
|
|
|
grammar(node) {
|
|
|
|
|
node.rules.forEach(generate);
|
|
|
|
|
|
|
|
|
|
node.consts = consts;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
rule: function(node) {
|
|
|
|
|
rule(node) {
|
|
|
|
|
node.bytecode = generate(node.expression, {
|
|
|
|
|
sp: -1, // stack pointer
|
|
|
|
|
env: { }, // mapping of label names to stack positions
|
|
|
|
@ -302,7 +302,7 @@ function generateBytecode(ast) {
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
named: function(node, context) {
|
|
|
|
|
named(node, context) {
|
|
|
|
|
let nameIndex = addConst(
|
|
|
|
|
"peg$otherExpectation(\"" + js.stringEscape(node.name) + "\")"
|
|
|
|
|
);
|
|
|
|
@ -319,7 +319,7 @@ function generateBytecode(ast) {
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
choice: function(node, context) {
|
|
|
|
|
choice(node, context) {
|
|
|
|
|
function buildAlternativesCode(alternatives, context) {
|
|
|
|
|
return buildSequence(
|
|
|
|
|
generate(alternatives[0], {
|
|
|
|
@ -343,7 +343,7 @@ function generateBytecode(ast) {
|
|
|
|
|
return buildAlternativesCode(node.alternatives, context);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
action: function(node, context) {
|
|
|
|
|
action(node, context) {
|
|
|
|
|
let env = cloneEnv(context.env);
|
|
|
|
|
let emitCall = node.expression.type !== "sequence"
|
|
|
|
|
|| node.expression.elements.length === 0;
|
|
|
|
@ -371,7 +371,7 @@ function generateBytecode(ast) {
|
|
|
|
|
: expressionCode;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
sequence: function(node, context) {
|
|
|
|
|
sequence(node, context) {
|
|
|
|
|
function buildElementsCode(elements, context) {
|
|
|
|
|
if (elements.length > 0) {
|
|
|
|
|
let processedCount = node.elements.length - elements.slice(1).length;
|
|
|
|
@ -429,7 +429,7 @@ function generateBytecode(ast) {
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
labeled: function(node, context) {
|
|
|
|
|
labeled(node, context) {
|
|
|
|
|
let env = cloneEnv(context.env);
|
|
|
|
|
|
|
|
|
|
context.env[node.label] = context.sp + 1;
|
|
|
|
@ -441,7 +441,7 @@ function generateBytecode(ast) {
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
text: function(node, context) {
|
|
|
|
|
text(node, context) {
|
|
|
|
|
return buildSequence(
|
|
|
|
|
[op.PUSH_CURR_POS],
|
|
|
|
|
generate(node.expression, {
|
|
|
|
@ -457,15 +457,15 @@ function generateBytecode(ast) {
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
simple_and: function(node, context) {
|
|
|
|
|
simple_and(node, context) {
|
|
|
|
|
return buildSimplePredicate(node.expression, false, context);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
simple_not: function(node, context) {
|
|
|
|
|
simple_not(node, context) {
|
|
|
|
|
return buildSimplePredicate(node.expression, true, context);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
optional: function(node, context) {
|
|
|
|
|
optional(node, context) {
|
|
|
|
|
return buildSequence(
|
|
|
|
|
generate(node.expression, {
|
|
|
|
|
sp: context.sp,
|
|
|
|
@ -480,7 +480,7 @@ function generateBytecode(ast) {
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
zero_or_more: function(node, context) {
|
|
|
|
|
zero_or_more(node, context) {
|
|
|
|
|
let expressionCode = generate(node.expression, {
|
|
|
|
|
sp: context.sp + 1,
|
|
|
|
|
env: cloneEnv(context.env),
|
|
|
|
@ -495,7 +495,7 @@ function generateBytecode(ast) {
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
one_or_more: function(node, context) {
|
|
|
|
|
one_or_more(node, context) {
|
|
|
|
|
let expressionCode = generate(node.expression, {
|
|
|
|
|
sp: context.sp + 1,
|
|
|
|
|
env: cloneEnv(context.env),
|
|
|
|
@ -513,7 +513,7 @@ function generateBytecode(ast) {
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
group: function(node, context) {
|
|
|
|
|
group(node, context) {
|
|
|
|
|
return generate(node.expression, {
|
|
|
|
|
sp: context.sp,
|
|
|
|
|
env: cloneEnv(context.env),
|
|
|
|
@ -521,19 +521,19 @@ function generateBytecode(ast) {
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
semantic_and: function(node, context) {
|
|
|
|
|
semantic_and(node, context) {
|
|
|
|
|
return buildSemanticPredicate(node.code, false, context);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
semantic_not: function(node, context) {
|
|
|
|
|
semantic_not(node, context) {
|
|
|
|
|
return buildSemanticPredicate(node.code, true, context);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
rule_ref: function(node) {
|
|
|
|
|
rule_ref(node) {
|
|
|
|
|
return [op.RULE, asts.indexOfRule(ast, node.name)];
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
literal: function(node) {
|
|
|
|
|
literal(node) {
|
|
|
|
|
if (node.value.length > 0) {
|
|
|
|
|
let stringIndex = addConst("\""
|
|
|
|
|
+ js.stringEscape(
|
|
|
|
@ -567,7 +567,7 @@ function generateBytecode(ast) {
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
class: function(node) {
|
|
|
|
|
class(node) {
|
|
|
|
|
let regexp = "/^["
|
|
|
|
|
+ (node.inverted ? "^" : "")
|
|
|
|
|
+ node.parts.map(part =>
|
|
|
|
@ -601,7 +601,7 @@ function generateBytecode(ast) {
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
any: function() {
|
|
|
|
|
any() {
|
|
|
|
|
let expectedIndex = addConst("peg$anyExpectation()");
|
|
|
|
|
|
|
|
|
|
return buildCondition(
|
|
|
|
|