|
|
|
@ -226,37 +226,11 @@ PEG.compiler.emitter = function(ast) {
|
|
|
|
|
return Codie;
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
function formatCode() {
|
|
|
|
|
var args = Array.prototype.slice.call(arguments);
|
|
|
|
|
var vars = args[args.length - 1] instanceof Object ? args.pop() : {};
|
|
|
|
|
|
|
|
|
|
vars.string = quote;
|
|
|
|
|
|
|
|
|
|
return Codie.template(args.join('\n'))(vars);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function resultVar(index) { return "result" + index; }
|
|
|
|
|
function posVar(index) { return "pos" + index; }
|
|
|
|
|
|
|
|
|
|
var emit = buildNodeVisitor({
|
|
|
|
|
grammar: function(node) {
|
|
|
|
|
var initializerCode = node.initializer !== null
|
|
|
|
|
? emit(node.initializer)
|
|
|
|
|
: "";
|
|
|
|
|
var name;
|
|
|
|
|
|
|
|
|
|
var parseFunctionTableItems = [];
|
|
|
|
|
for (name in node.rules) {
|
|
|
|
|
parseFunctionTableItems.push(quote(name) + ": parse_" + name);
|
|
|
|
|
}
|
|
|
|
|
parseFunctionTableItems.sort();
|
|
|
|
|
|
|
|
|
|
var parseFunctionDefinitions = [];
|
|
|
|
|
for (name in node.rules) {
|
|
|
|
|
parseFunctionDefinitions.push(emit(node.rules[name]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return formatCode(
|
|
|
|
|
var templates = (function() {
|
|
|
|
|
var name,
|
|
|
|
|
templates = {},
|
|
|
|
|
sources = {
|
|
|
|
|
grammar: [
|
|
|
|
|
'(function(){',
|
|
|
|
|
' /* Generated by PEG.js @VERSION (http://pegjs.majda.cz/). */',
|
|
|
|
|
' ',
|
|
|
|
@ -479,34 +453,9 @@ PEG.compiler.emitter = function(ast) {
|
|
|
|
|
' result.SyntaxError.prototype = Error.prototype;',
|
|
|
|
|
' ',
|
|
|
|
|
' return result;',
|
|
|
|
|
'})()',
|
|
|
|
|
{
|
|
|
|
|
initializerCode: initializerCode,
|
|
|
|
|
parseFunctionTableItems: parseFunctionTableItems,
|
|
|
|
|
parseFunctionDefinitions: parseFunctionDefinitions,
|
|
|
|
|
startRule: node.startRule
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
initializer: function(node) {
|
|
|
|
|
return node.code;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
rule: function(node) {
|
|
|
|
|
var context = {
|
|
|
|
|
resultIndex: 0,
|
|
|
|
|
posIndex: 0,
|
|
|
|
|
delta: function(resultIndexDelta, posIndexDelta) {
|
|
|
|
|
return {
|
|
|
|
|
resultIndex: this.resultIndex + resultIndexDelta,
|
|
|
|
|
posIndex: this.posIndex + posIndexDelta,
|
|
|
|
|
delta: this.delta
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return formatCode(
|
|
|
|
|
'})()'
|
|
|
|
|
],
|
|
|
|
|
rule: [
|
|
|
|
|
'function parse_#{node.name}() {',
|
|
|
|
|
' var cacheKey = "#{node.name}@" + pos;',
|
|
|
|
|
' var cachedResult = cache[cacheKey];',
|
|
|
|
@ -538,15 +487,209 @@ PEG.compiler.emitter = function(ast) {
|
|
|
|
|
' result: #{resultVar}',
|
|
|
|
|
' };',
|
|
|
|
|
' return #{resultVar};',
|
|
|
|
|
'}'
|
|
|
|
|
],
|
|
|
|
|
choice: [
|
|
|
|
|
'#block currentAlternativeCode',
|
|
|
|
|
'#block nextAlternativesCode'
|
|
|
|
|
],
|
|
|
|
|
"choice.next": [
|
|
|
|
|
'if (#{resultVar} === null) {',
|
|
|
|
|
' #block code',
|
|
|
|
|
'}'
|
|
|
|
|
],
|
|
|
|
|
sequence: [
|
|
|
|
|
'#{posVar} = pos;',
|
|
|
|
|
'#block code'
|
|
|
|
|
],
|
|
|
|
|
"sequence.iteration": [
|
|
|
|
|
'#block elementCode',
|
|
|
|
|
'if (#{elementResultVar} !== null) {',
|
|
|
|
|
' #block code',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
' pos = #{posVar};',
|
|
|
|
|
'}'
|
|
|
|
|
],
|
|
|
|
|
"sequence.inner": [
|
|
|
|
|
'#{resultVar} = [#{elementResultVars.join(", ")}];'
|
|
|
|
|
],
|
|
|
|
|
simple_and: [
|
|
|
|
|
'#{posVar} = pos;',
|
|
|
|
|
'reportFailures++;',
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'reportFailures--;',
|
|
|
|
|
'if (#{resultVar} !== null) {',
|
|
|
|
|
' #{resultVar} = "";',
|
|
|
|
|
' pos = #{posVar};',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
'}'
|
|
|
|
|
],
|
|
|
|
|
simple_not: [
|
|
|
|
|
'#{posVar} = pos;',
|
|
|
|
|
'reportFailures++;',
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'reportFailures--;',
|
|
|
|
|
'if (#{resultVar} === null) {',
|
|
|
|
|
' #{resultVar} = "";',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
' pos = #{posVar};',
|
|
|
|
|
'}'
|
|
|
|
|
],
|
|
|
|
|
semantic_and: [
|
|
|
|
|
'#{resultVar} = (function() {#{node.code}})() ? "" : null;'
|
|
|
|
|
],
|
|
|
|
|
semantic_not: [
|
|
|
|
|
'#{resultVar} = (function() {#{node.code}})() ? null : "";'
|
|
|
|
|
],
|
|
|
|
|
optional: [
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'#{resultVar} = #{resultVar} !== null ? #{resultVar} : "";'
|
|
|
|
|
],
|
|
|
|
|
zero_or_more: [
|
|
|
|
|
'#{resultVar} = [];',
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'while (#{expressionResultVar} !== null) {',
|
|
|
|
|
' #{resultVar}.push(#{expressionResultVar});',
|
|
|
|
|
' #block expressionCode',
|
|
|
|
|
'}'
|
|
|
|
|
],
|
|
|
|
|
one_or_more: [
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'if (#{expressionResultVar} !== null) {',
|
|
|
|
|
' #{resultVar} = [];',
|
|
|
|
|
' while (#{expressionResultVar} !== null) {',
|
|
|
|
|
' #{resultVar}.push(#{expressionResultVar});',
|
|
|
|
|
' #block expressionCode',
|
|
|
|
|
' }',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
'}'
|
|
|
|
|
],
|
|
|
|
|
action: [
|
|
|
|
|
'#{posVar} = pos;',
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'if (#{resultVar} !== null) {',
|
|
|
|
|
' #{resultVar} = (function(#{formalParams.join(", ")}) {#{node.code}})(#{actualParams.join(", ")});',
|
|
|
|
|
'}',
|
|
|
|
|
'if (#{resultVar} === null) {',
|
|
|
|
|
' pos = #{posVar};',
|
|
|
|
|
'}'
|
|
|
|
|
],
|
|
|
|
|
rule_ref: [
|
|
|
|
|
'#{resultVar} = parse_#{node.name}();'
|
|
|
|
|
],
|
|
|
|
|
literal: [
|
|
|
|
|
'#if node.value.length === 0',
|
|
|
|
|
' #{resultVar} = "";',
|
|
|
|
|
'#else',
|
|
|
|
|
' #if node.value.length === 1',
|
|
|
|
|
' if (input.charCodeAt(pos) === #{node.value.charCodeAt(0)}) {',
|
|
|
|
|
' #else',
|
|
|
|
|
' if (input.substr(pos, #{node.value.length}) === #{string(node.value)}) {',
|
|
|
|
|
' #end',
|
|
|
|
|
' #{resultVar} = #{string(node.value)};',
|
|
|
|
|
' pos += #{node.value.length};',
|
|
|
|
|
' } else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
' if (reportFailures === 0) {',
|
|
|
|
|
' matchFailed(#{string(string(node.value))});',
|
|
|
|
|
' }',
|
|
|
|
|
' }',
|
|
|
|
|
'#end'
|
|
|
|
|
],
|
|
|
|
|
any: [
|
|
|
|
|
'if (input.length > pos) {',
|
|
|
|
|
' #{resultVar} = input.charAt(pos);',
|
|
|
|
|
' pos++;',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
' if (reportFailures === 0) {',
|
|
|
|
|
' matchFailed("any character");',
|
|
|
|
|
' }',
|
|
|
|
|
{
|
|
|
|
|
'}'
|
|
|
|
|
],
|
|
|
|
|
"class": [
|
|
|
|
|
'if (#{regexp}.test(input.charAt(pos))) {',
|
|
|
|
|
' #{resultVar} = input.charAt(pos);',
|
|
|
|
|
' pos++;',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
' if (reportFailures === 0) {',
|
|
|
|
|
' matchFailed(#{string(node.rawText)});',
|
|
|
|
|
' }',
|
|
|
|
|
'}'
|
|
|
|
|
]
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (name in sources) {
|
|
|
|
|
templates[name] = Codie.template(sources[name].join('\n'));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return templates;
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
function fill(name, vars) {
|
|
|
|
|
vars.string = quote;
|
|
|
|
|
|
|
|
|
|
return templates[name](vars);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function resultVar(index) { return "result" + index; }
|
|
|
|
|
function posVar(index) { return "pos" + index; }
|
|
|
|
|
|
|
|
|
|
var emit = buildNodeVisitor({
|
|
|
|
|
grammar: function(node) {
|
|
|
|
|
var initializerCode = node.initializer !== null
|
|
|
|
|
? emit(node.initializer)
|
|
|
|
|
: "";
|
|
|
|
|
var name;
|
|
|
|
|
|
|
|
|
|
var parseFunctionTableItems = [];
|
|
|
|
|
for (name in node.rules) {
|
|
|
|
|
parseFunctionTableItems.push(quote(name) + ": parse_" + name);
|
|
|
|
|
}
|
|
|
|
|
parseFunctionTableItems.sort();
|
|
|
|
|
|
|
|
|
|
var parseFunctionDefinitions = [];
|
|
|
|
|
for (name in node.rules) {
|
|
|
|
|
parseFunctionDefinitions.push(emit(node.rules[name]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return fill("grammar", {
|
|
|
|
|
initializerCode: initializerCode,
|
|
|
|
|
parseFunctionTableItems: parseFunctionTableItems,
|
|
|
|
|
parseFunctionDefinitions: parseFunctionDefinitions,
|
|
|
|
|
startRule: node.startRule
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
initializer: function(node) {
|
|
|
|
|
return node.code;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
rule: function(node) {
|
|
|
|
|
var context = {
|
|
|
|
|
resultIndex: 0,
|
|
|
|
|
posIndex: 0,
|
|
|
|
|
delta: function(resultIndexDelta, posIndexDelta) {
|
|
|
|
|
return {
|
|
|
|
|
resultIndex: this.resultIndex + resultIndexDelta,
|
|
|
|
|
posIndex: this.posIndex + posIndexDelta,
|
|
|
|
|
delta: this.delta
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return fill("rule", {
|
|
|
|
|
node: node,
|
|
|
|
|
resultVars: map(range(node.resultStackDepth), resultVar),
|
|
|
|
|
posVars: map(range(node.posStackDepth), posVar),
|
|
|
|
|
code: emit(node.expression, context),
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -584,24 +727,15 @@ PEG.compiler.emitter = function(ast) {
|
|
|
|
|
|
|
|
|
|
for (var i = node.alternatives.length - 1; i >= 0; i--) {
|
|
|
|
|
nextAlternativesCode = i !== node.alternatives.length - 1
|
|
|
|
|
? formatCode(
|
|
|
|
|
'if (#{resultVar} === null) {',
|
|
|
|
|
' #block code',
|
|
|
|
|
'}',
|
|
|
|
|
{
|
|
|
|
|
? fill("choice.next", {
|
|
|
|
|
code: code,
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
: '';
|
|
|
|
|
code = formatCode(
|
|
|
|
|
'#block currentAlternativeCode',
|
|
|
|
|
'#block nextAlternativesCode',
|
|
|
|
|
{
|
|
|
|
|
code = fill("choice", {
|
|
|
|
|
currentAlternativeCode: emit(node.alternatives[i], context),
|
|
|
|
|
nextAlternativesCode: nextAlternativesCode
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return code;
|
|
|
|
@ -612,41 +746,22 @@ PEG.compiler.emitter = function(ast) {
|
|
|
|
|
return resultVar(context.resultIndex + i);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var code = formatCode(
|
|
|
|
|
'#{resultVar} = [#{elementResultVars.join(", ")}];',
|
|
|
|
|
{
|
|
|
|
|
var code = fill("sequence.inner", {
|
|
|
|
|
resultVar: resultVar(context.resultIndex),
|
|
|
|
|
elementResultVars: elementResultVars
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (var i = node.elements.length - 1; i >= 0; i--) {
|
|
|
|
|
code = formatCode(
|
|
|
|
|
'#block elementCode',
|
|
|
|
|
'if (#{elementResultVar} !== null) {',
|
|
|
|
|
' #block code',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
' pos = #{posVar};',
|
|
|
|
|
'}',
|
|
|
|
|
{
|
|
|
|
|
code = fill("sequence.iteration", {
|
|
|
|
|
elementCode: emit(node.elements[i], context.delta(i, 1)),
|
|
|
|
|
elementResultVar: elementResultVars[i],
|
|
|
|
|
code: code,
|
|
|
|
|
posVar: posVar(context.posIndex),
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#{posVar} = pos;',
|
|
|
|
|
'#block code',
|
|
|
|
|
{
|
|
|
|
|
code: code,
|
|
|
|
|
posVar: posVar(context.posIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
return fill("sequence", { code: code, posVar: posVar(context.posIndex) });
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
labeled: function(node, context) {
|
|
|
|
@ -654,110 +769,56 @@ PEG.compiler.emitter = function(ast) {
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
simple_and: function(node, context) {
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#{posVar} = pos;',
|
|
|
|
|
'reportFailures++;',
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'reportFailures--;',
|
|
|
|
|
'if (#{resultVar} !== null) {',
|
|
|
|
|
' #{resultVar} = "";',
|
|
|
|
|
' pos = #{posVar};',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
'}',
|
|
|
|
|
{
|
|
|
|
|
return fill("simple_and", {
|
|
|
|
|
expressionCode: emit(node.expression, context.delta(0, 1)),
|
|
|
|
|
posVar: posVar(context.posIndex),
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
simple_not: function(node, context) {
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#{posVar} = pos;',
|
|
|
|
|
'reportFailures++;',
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'reportFailures--;',
|
|
|
|
|
'if (#{resultVar} === null) {',
|
|
|
|
|
' #{resultVar} = "";',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
' pos = #{posVar};',
|
|
|
|
|
'}',
|
|
|
|
|
{
|
|
|
|
|
return fill("simple_not", {
|
|
|
|
|
expressionCode: emit(node.expression, context.delta(0, 1)),
|
|
|
|
|
posVar: posVar(context.posIndex),
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
semantic_and: function(node, context) {
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#{resultVar} = (function() {#{node.code}})() ? "" : null;',
|
|
|
|
|
{
|
|
|
|
|
return fill("semantic_and", {
|
|
|
|
|
node: node,
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
semantic_not: function(node, context) {
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#{resultVar} = (function() {#{node.code}})() ? null : "";',
|
|
|
|
|
{
|
|
|
|
|
return fill("semantic_not", {
|
|
|
|
|
node: node,
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
optional: function(node, context) {
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'#{resultVar} = #{resultVar} !== null ? #{resultVar} : "";',
|
|
|
|
|
{
|
|
|
|
|
return fill("optional", {
|
|
|
|
|
expressionCode: emit(node.expression, context),
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
zero_or_more: function(node, context) {
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#{resultVar} = [];',
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'while (#{expressionResultVar} !== null) {',
|
|
|
|
|
' #{resultVar}.push(#{expressionResultVar});',
|
|
|
|
|
' #block expressionCode',
|
|
|
|
|
'}',
|
|
|
|
|
{
|
|
|
|
|
return fill("zero_or_more", {
|
|
|
|
|
expressionCode: emit(node.expression, context.delta(1, 0)),
|
|
|
|
|
expressionResultVar: resultVar(context.resultIndex + 1),
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
one_or_more: function(node, context) {
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'if (#{expressionResultVar} !== null) {',
|
|
|
|
|
' #{resultVar} = [];',
|
|
|
|
|
' while (#{expressionResultVar} !== null) {',
|
|
|
|
|
' #{resultVar}.push(#{expressionResultVar});',
|
|
|
|
|
' #block expressionCode',
|
|
|
|
|
' }',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
'}',
|
|
|
|
|
{
|
|
|
|
|
return fill("one_or_more", {
|
|
|
|
|
expressionCode: emit(node.expression, context.delta(1, 0)),
|
|
|
|
|
expressionResultVar: resultVar(context.resultIndex + 1),
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
action: function(node, context) {
|
|
|
|
@ -793,75 +854,32 @@ PEG.compiler.emitter = function(ast) {
|
|
|
|
|
actualParams = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#{posVar} = pos;',
|
|
|
|
|
'#block expressionCode',
|
|
|
|
|
'if (#{resultVar} !== null) {',
|
|
|
|
|
' #{resultVar} = (function(#{formalParams.join(", ")}) {#{node.code}})(#{actualParams.join(", ")});',
|
|
|
|
|
'}',
|
|
|
|
|
'if (#{resultVar} === null) {',
|
|
|
|
|
' pos = #{posVar};',
|
|
|
|
|
'}',
|
|
|
|
|
{
|
|
|
|
|
return fill("action", {
|
|
|
|
|
node: node,
|
|
|
|
|
expressionCode: emit(node.expression, context.delta(0, 1)),
|
|
|
|
|
formalParams: formalParams,
|
|
|
|
|
actualParams: actualParams,
|
|
|
|
|
posVar: posVar(context.posIndex),
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
rule_ref: function(node, context) {
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#{resultVar} = parse_#{node.name}();',
|
|
|
|
|
{
|
|
|
|
|
return fill("rule_ref", {
|
|
|
|
|
node: node,
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
literal: function(node, context) {
|
|
|
|
|
return formatCode(
|
|
|
|
|
'#if node.value.length === 0',
|
|
|
|
|
' #{resultVar} = "";',
|
|
|
|
|
'#else',
|
|
|
|
|
' #if node.value.length === 1',
|
|
|
|
|
' if (input.charCodeAt(pos) === #{node.value.charCodeAt(0)}) {',
|
|
|
|
|
' #else',
|
|
|
|
|
' if (input.substr(pos, #{node.value.length}) === #{string(node.value)}) {',
|
|
|
|
|
' #end',
|
|
|
|
|
' #{resultVar} = #{string(node.value)};',
|
|
|
|
|
' pos += #{node.value.length};',
|
|
|
|
|
' } else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
' if (reportFailures === 0) {',
|
|
|
|
|
' matchFailed(#{string(string(node.value))});',
|
|
|
|
|
' }',
|
|
|
|
|
' }',
|
|
|
|
|
'#end',
|
|
|
|
|
{
|
|
|
|
|
return fill("literal", {
|
|
|
|
|
node: node,
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
any: function(node, context) {
|
|
|
|
|
return formatCode(
|
|
|
|
|
'if (input.length > pos) {',
|
|
|
|
|
' #{resultVar} = input.charAt(pos);',
|
|
|
|
|
' pos++;',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
' if (reportFailures === 0) {',
|
|
|
|
|
' matchFailed("any character");',
|
|
|
|
|
' }',
|
|
|
|
|
'}',
|
|
|
|
|
{ resultVar: resultVar(context.resultIndex) }
|
|
|
|
|
);
|
|
|
|
|
return fill("any", { resultVar: resultVar(context.resultIndex) });
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
"class": function(node, context) {
|
|
|
|
@ -886,22 +904,11 @@ PEG.compiler.emitter = function(ast) {
|
|
|
|
|
regexp = node.inverted ? '/^[\\S\\s]/' : '/^(?!)/';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return formatCode(
|
|
|
|
|
'if (#{regexp}.test(input.charAt(pos))) {',
|
|
|
|
|
' #{resultVar} = input.charAt(pos);',
|
|
|
|
|
' pos++;',
|
|
|
|
|
'} else {',
|
|
|
|
|
' #{resultVar} = null;',
|
|
|
|
|
' if (reportFailures === 0) {',
|
|
|
|
|
' matchFailed(#{string(node.rawText)});',
|
|
|
|
|
' }',
|
|
|
|
|
'}',
|
|
|
|
|
{
|
|
|
|
|
return fill("class", {
|
|
|
|
|
node: node,
|
|
|
|
|
regexp: regexp,
|
|
|
|
|
resultVar: resultVar(context.resultIndex)
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|