imicros-feel-interpreter
Version:
DMN decisions and FEEL language interpreter
331 lines (317 loc) • 31.6 kB
JavaScript
// Generated automatically by nearley, version 2.20.1
// http://github.com/Hardmath123/nearley
(function () {
function id(x) { return x[0]; }
/**
* @license MIT, imicros.de (c) 2022 Andreas Leinen
*
*/
;
const moo = require("moo");
const Node = require("./ast.js");
const lexer = moo.compile({
singlelinecomment : { match: /\/\/.*/ },
multilinecomment : { match: /\/\*[.\s\S]+?\*+\//, lineBreaks: true },
string : { match: /"(?:\\"|[^"])*?"/, value: s => s.slice(1, -1) },
dayandtime : /date[ ]+and[ ]+time/,
fn : /put[ ]+all|string[ ]+length|string[ ]+join|week[ ]+of[ ]+year|month[ ]+of[ ]+year|day[ ]+of[ ]+year|month[ ]+of[ ]+year|day[ ]+of[ ]+week|years[ ]+and[ ]+months[ ]+duration/,
types : /day-time-duration|year-month-duration/,
instance : /instance[ ]+of/,
whitespace : { match: /[ \t\n\r\u00A0\uFEFF\u000D\u000A]+/, lineBreaks: true },
word : { match: /[\?_'A-Za-z\u00c4\u00e4\u00d6\u00f6\u00dc\u00fc\u00df]+/, type: moo.keywords({
keywords : ['for','return','if','true','false','in','and','or','between','some','every','then','else'],
not : ['not'],
types : ['string','number','boolean'],
null : ['null'],
dayandtime : ['date','time','duration'],
fn : ['even','abs','length','all','any']
}) },
number : /[0-9]+/,
comparator : /!=|==|<=|>=|<{1}|>{1}|={1}/,
operator : /-|\+|\.\.|\/|\*{1,2}/,
punctuator : /@|[.,:;[\](){}]/
});
// store context keys to check names with special characters
var keys = [];
var locations = [];
function addToContext(key) {
if (key?.value && keys.indexOf(key.value) < 0) keys.push(key.value);
}
function concat(e) {
if (Array.isArray(e)) return e.reduce((prev,curr) => prev.concat(concat(curr)), [] ).join('');
return e;
}
function reduce(data) {
if (Array.isArray(data) && data.length === 1) return reduce(data[0]);
return data
}
function extract(data, i) {
if (Array.isArray(data)) return data.reduce((prev,curr) => prev.concat(concat(curr[i])), [] );
return [];
}
function extractObj(data, i) {
if (Array.isArray(data)) return data.reduce((prev,curr) => prev.concat(reduce(curr[i])), [] );
return [];
}
/*
function checkSpecialName(data, location) {
// console.log("check",data, keys, keys.indexOf(data));
if (keys.indexOf(data) >= 0) locations.push(location);
if (keys.indexOf(data) >= 0) return true;
return false;
}
*/
function checkLocation(location,data) {
/*
console.log("check", location,locations,reduce([data]));
return false;
if (locations.indexOf(location) >= 0) {
if (data?.node == Node.NAME && keys.indexOf(data?.value) >= 0) return false;
return true;
}
return false;
return locations.indexOf(location) >= 0 ? true : false;
function check(obj, reject) {
Object.keys(obj).forEach(function(key,index) {
if (typeof obj[key] == 'object' && obj[key] instanceof Node) {
if (obj[key].node == Node.NAME && obj[key].location == location && keys.indexOf(obj[key].value) < 0) reject = true;
check(obj[key]);
}
});
return reject;
};
// return locations.indexOf(location) >= 0 ? true : false;
// console.log(location,locations,reduce([data]),locations.indexOf(location));
if (locations.indexOf(location) >= 0 && typeof data == 'object') {
const result = check(data, false);
// console.log("checked", location,locations,reduce([data]),result);
return result;
// console.log("reject", location,locations,reduce([data]),locations.indexOf(location));
// return false;
}
// console.log("accept", location,locations,reduce([data]),locations.indexOf(location));
*/
return false;
}
var grammar = {
Lexer: lexer,
ParserRules: [
{"name": "main", "symbols": ["UnaryTests"], "postprocess": (data) => reduce([data[0]])},
{"name": "main", "symbols": ["_", "Expression", "_"], "postprocess": (data) => reduce([data[1]])},
{"name": "Expression", "symbols": ["BoxedExpression"]},
{"name": "Expression", "symbols": ["TextualExpression"], "postprocess": (data) => reduce([data])},
{"name": "TextualExpression", "symbols": ["ForExpression"]},
{"name": "TextualExpression", "symbols": ["IfExpression"]},
{"name": "TextualExpression", "symbols": ["QuantifiedExpression"]},
{"name": "TextualExpression", "symbols": ["LogicalExpression"], "postprocess": (data,location,reject) => { if (checkLocation(location,data)) return reject; return data; }},
{"name": "NonArithmeticExpression", "symbols": ["InstanceOf"]},
{"name": "NonArithmeticExpression", "symbols": ["PathExpression"]},
{"name": "NonArithmeticExpression", "symbols": ["FilterExpression"]},
{"name": "NonArithmeticExpression", "symbols": ["SimplePositiveUnaryTest"]},
{"name": "NonArithmeticExpression", "symbols": [{"literal":"("}, "_", "Expression", "_", {"literal":")"}], "postprocess": (data) => { return new Node({ node: Node.EVAL, expression: data[2] }); }},
{"name": "SimplePositiveUnaryTest$subexpression$1", "symbols": [{"literal":"!="}]},
{"name": "SimplePositiveUnaryTest$subexpression$1", "symbols": [{"literal":"<"}]},
{"name": "SimplePositiveUnaryTest$subexpression$1", "symbols": [{"literal":"<="}]},
{"name": "SimplePositiveUnaryTest$subexpression$1", "symbols": [{"literal":">"}]},
{"name": "SimplePositiveUnaryTest$subexpression$1", "symbols": [{"literal":">="}]},
{"name": "SimplePositiveUnaryTest", "symbols": ["SimplePositiveUnaryTest$subexpression$1", "_", "Endpoint"], "postprocess": (data) => { return new Node({ node: Node.UNARY, operator: reduce(data[0]).value, value: reduce(data[2]) }); }},
{"name": "SimplePositiveUnaryTest", "symbols": ["Interval"]},
{"name": "SimplePositiveUnaryTest", "symbols": [{"literal":"("}, "_", {"literal":"-"}, "_", {"literal":")"}], "postprocess": (data) => { return new Node({ node: Node.DASH }); }},
{"name": "Interval$subexpression$1", "symbols": [{"literal":"("}]},
{"name": "Interval$subexpression$1", "symbols": [{"literal":"]"}]},
{"name": "Interval$subexpression$1", "symbols": [{"literal":"["}]},
{"name": "Interval$subexpression$2", "symbols": [{"literal":")"}]},
{"name": "Interval$subexpression$2", "symbols": [{"literal":"["}]},
{"name": "Interval$subexpression$2", "symbols": [{"literal":"]"}]},
{"name": "Interval", "symbols": ["Interval$subexpression$1", "_", "Endpoint", "_", {"literal":".."}, "_", "Endpoint", "_", "Interval$subexpression$2"], "postprocess": (data) => { return new Node({ node: Node.INTERVAL, open: reduce(data[0]).value, from: reduce(data[2]), to: reduce(data[6]), close: reduce(data[8]).value }) }},
{"name": "Interval", "symbols": ["FunctionInvocation"]},
{"name": "Interval", "symbols": ["Literal"]},
{"name": "PositiveUnarytest", "symbols": ["Expression"]},
{"name": "PositiveUnarytests$ebnf$1$subexpression$1", "symbols": [{"literal":","}, "_", "PositiveUnarytest"]},
{"name": "PositiveUnarytests$ebnf$1", "symbols": ["PositiveUnarytests$ebnf$1$subexpression$1"]},
{"name": "PositiveUnarytests$ebnf$1$subexpression$2", "symbols": [{"literal":","}, "_", "PositiveUnarytest"]},
{"name": "PositiveUnarytests$ebnf$1", "symbols": ["PositiveUnarytests$ebnf$1", "PositiveUnarytests$ebnf$1$subexpression$2"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "PositiveUnarytests", "symbols": ["PositiveUnarytest", "_", "PositiveUnarytests$ebnf$1"], "postprocess": (data) => { return new Node({ node:Node.LIST, entries: [].concat(data[0]).concat(extractObj(data[2],2)) }) ;}},
{"name": "UnaryTests", "symbols": ["PositiveUnarytests"], "postprocess": (data) => { return new Node({ node: Node.UNARYTESTS, list: reduce([data]) }); }},
{"name": "UnaryTests", "symbols": ["Expression", "_", {"literal":"in"}, "_", "List"], "postprocess": (data) => { return new Node({ node:Node.IN_LIST, input: reduce(data[0]), list: reduce(data[4]) });}},
{"name": "UnaryTests", "symbols": ["UnaryNot"]},
{"name": "UnaryTests", "symbols": ["UnaryDash"]},
{"name": "UnaryNot", "symbols": [(lexer.has("not") ? {type: "not"} : not), "_", {"literal":"("}, "_", "PositiveUnarytests", "_", {"literal":")"}], "postprocess": (data) => { return new Node({ node: Node.UNARY_NOT, test: reduce(data[4]) }); }},
{"name": "UnaryDash", "symbols": ["_", {"literal":"-"}, "_"], "postprocess": (data) => { return new Node({ node: Node.DASH }); }},
{"name": "Endpoint", "symbols": ["SimpleValue"]},
{"name": "SimpleValue", "symbols": ["QualifiedName"]},
{"name": "SimpleValue", "symbols": ["SimpleLiteral"]},
{"name": "ArithmeticNegation", "symbols": [{"literal":"-"}, "_", "NonArithmeticExpression"], "postprocess": (data) => { return new Node({ node: Node.NEGATION, expression: reduce(data[2]) });}},
{"name": "ArithmeticNegation", "symbols": ["NonArithmeticExpression"]},
{"name": "Sum$subexpression$1", "symbols": [{"literal":"+"}]},
{"name": "Sum$subexpression$1", "symbols": [{"literal":"-"}]},
{"name": "Sum", "symbols": ["Sum", "_", "Sum$subexpression$1", "_", "Product"], "postprocess": (data) => { return new Node({ node: Node.SUM, left: reduce(data[0]), operator: reduce(data[2]).value, right: reduce(data[4]) }); }},
{"name": "Sum", "symbols": ["Product"]},
{"name": "Product$subexpression$1", "symbols": [{"literal":"*"}]},
{"name": "Product$subexpression$1", "symbols": [{"literal":"/"}]},
{"name": "Product", "symbols": ["Product", "_", "Product$subexpression$1", "_", "Exponentation"], "postprocess": (data) => { return new Node({ node: Node.PRODUCT, left: reduce(data[0]), operator: reduce(data[2]).value, right: reduce(data[4]) }); }},
{"name": "Product", "symbols": ["Exponentation"]},
{"name": "Exponentation$subexpression$1", "symbols": [{"literal":"**"}]},
{"name": "Exponentation", "symbols": ["Exponentation", "_", "Exponentation$subexpression$1", "_", "ArithmeticNegation"], "postprocess": (data, location, reject) => { return new Node({ node: Node.EXPONENTATION, left: reduce(data[0]), operator: reduce(data[2]).value, right: reduce(data[4]) }); }},
{"name": "Exponentation", "symbols": ["ArithmeticNegation"]},
{"name": "QualifiedName", "symbols": ["Name", "_", {"literal":"."}, "_", "Name"], "postprocess": (data) => { return new Node({ node: Node.PATH, object:data[0], property:data[4]}); }},
{"name": "QualifiedName", "symbols": ["Name"]},
{"name": "Name", "symbols": ["PotentialName"], "postprocess": (data, location, reject) => { return new Node({ node: Node.NAME, value: concat([data]) }); }},
{"name": "PotentialName$ebnf$1", "symbols": []},
{"name": "PotentialName$ebnf$1$subexpression$1", "symbols": ["__", "NamePart"]},
{"name": "PotentialName$ebnf$1", "symbols": ["PotentialName$ebnf$1", "PotentialName$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "PotentialName", "symbols": ["NameStart", "PotentialName$ebnf$1"], "postprocess": (data) => { return concat([data]); }},
{"name": "NameStart$ebnf$1", "symbols": [(lexer.has("number") ? {type: "number"} : number)], "postprocess": id},
{"name": "NameStart$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
{"name": "NameStart", "symbols": [(lexer.has("word") ? {type: "word"} : word), "NameStart$ebnf$1"], "postprocess": (data) => { return concat(data)}},
{"name": "NamePart$ebnf$1", "symbols": [(lexer.has("number") ? {type: "number"} : number)], "postprocess": id},
{"name": "NamePart$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
{"name": "NamePart", "symbols": [(lexer.has("word") ? {type: "word"} : word), "NamePart$ebnf$1"], "postprocess": (data) => { return concat(data)}},
{"name": "NamePart", "symbols": [(lexer.has("types") ? {type: "types"} : types)], "postprocess": (data) => { return concat(data)}},
{"name": "Literal", "symbols": ["SimpleLiteral"]},
{"name": "Literal", "symbols": [(lexer.has("null") ? {type: "null"} : null)], "postprocess": (data) => { return new Node({ node: Node.NULL }); }},
{"name": "SimpleLiteral", "symbols": ["NumericLiteral"]},
{"name": "SimpleLiteral", "symbols": ["BooleanLiteral"]},
{"name": "SimpleLiteral", "symbols": ["StringLiteral"]},
{"name": "SimpleLiteral", "symbols": ["DateTimeLiteral"]},
{"name": "StringLiteral", "symbols": [(lexer.has("string") ? {type: "string"} : string)], "postprocess": (data) => { return new Node({ node: Node.STRING, value: String.raw`${ data }` }); }},
{"name": "BooleanLiteral$subexpression$1", "symbols": [{"literal":"true"}]},
{"name": "BooleanLiteral$subexpression$1", "symbols": [{"literal":"false"}]},
{"name": "BooleanLiteral", "symbols": ["BooleanLiteral$subexpression$1"], "postprocess": (data) => { return new Node({ node: Node.BOOLEAN, value: concat([data]) === "true" ? true : false });}},
{"name": "NumericLiteral$ebnf$1$subexpression$1", "symbols": [{"literal":"."}, "Digits"]},
{"name": "NumericLiteral$ebnf$1", "symbols": ["NumericLiteral$ebnf$1$subexpression$1"], "postprocess": id},
{"name": "NumericLiteral$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
{"name": "NumericLiteral", "symbols": ["Digits", "NumericLiteral$ebnf$1"], "postprocess": (data) => { return new Node({ node:Node.NUMBER, integer: parseInt(data[0]), decimals: parseInt(data[1] ? data[1][1] : null), float: parseFloat(concat([data])) }); }},
{"name": "NumericLiteral", "symbols": [{"literal":"."}, "Digits"], "postprocess": (data) => { return new Node({ node: Node.NUMBER, decimals: parseInt(concat(data[1])), float: parseFloat("."+concat([data[1]])) }); }},
{"name": "Digits", "symbols": [(lexer.has("number") ? {type: "number"} : number)], "postprocess": (data) => { return concat([data]); }},
{"name": "FunctionInvocation", "symbols": ["FunctionName", "_", "Parameters"], "postprocess": (data, location, reject) => { return new Node({ node: Node.FUNCTION_CALL, name: reduce(data[0]), parameters: reduce(data[2]) });}},
{"name": "FunctionInvocation", "symbols": [(lexer.has("not") ? {type: "not"} : not), "_", {"literal":"("}, "_", "Expression", "_", {"literal":")"}], "postprocess": (data, location, reject) => { return new Node({ node: Node.NOT, parameters: reduce(data[4]) });}},
{"name": "FunctionName", "symbols": [(lexer.has("fn") ? {type: "fn"} : fn)], "postprocess": (data) => { return new Node({ node: Node.NAME, value: concat([data]) }); }},
{"name": "FunctionName", "symbols": ["PotentialName"], "postprocess": (data) => { return new Node({ node: Node.NAME, value: concat([data]) }); }},
{"name": "FunctionName", "symbols": [{"literal":"number"}], "postprocess": (data) => { return new Node({ node: Node.NAME, value: concat([data]) }); }},
{"name": "FunctionName", "symbols": [{"literal":"string"}], "postprocess": (data) => { return new Node({ node: Node.NAME, value: concat([data]) }); }},
{"name": "FunctionName", "symbols": [{"literal":"context"}], "postprocess": (data) => { return new Node({ node: Node.NAME, value: concat([data]) }); }},
{"name": "Parameters$ebnf$1$subexpression$1", "symbols": ["NamedParameterList"]},
{"name": "Parameters$ebnf$1$subexpression$1", "symbols": ["PositionalParameterList"]},
{"name": "Parameters$ebnf$1", "symbols": ["Parameters$ebnf$1$subexpression$1"], "postprocess": id},
{"name": "Parameters$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
{"name": "Parameters", "symbols": [{"literal":"("}, "_", "Parameters$ebnf$1", "_", {"literal":")"}], "postprocess": (data) => reduce(data[2])},
{"name": "NamedParameterList$ebnf$1", "symbols": []},
{"name": "NamedParameterList$ebnf$1$subexpression$1", "symbols": [{"literal":","}, "_", "NamedParameter"]},
{"name": "NamedParameterList$ebnf$1", "symbols": ["NamedParameterList$ebnf$1", "NamedParameterList$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "NamedParameterList", "symbols": ["NamedParameter", "_", "NamedParameterList$ebnf$1"], "postprocess": (data) => { return new Node({ node: Node.LIST, entries: [].concat(data[0]).concat(extractObj(data[2],2)) });}},
{"name": "NamedParameter", "symbols": ["Name", "_", {"literal":":"}, "_", "Expression"], "postprocess": (data) => { return new Node({ node: Node.NAMED_PARAMETER, name: concat(data[0]), expression: reduce(data[4]) });}},
{"name": "PositionalParameterList$ebnf$1", "symbols": []},
{"name": "PositionalParameterList$ebnf$1$subexpression$1", "symbols": [{"literal":","}, "_", "Expression"]},
{"name": "PositionalParameterList$ebnf$1", "symbols": ["PositionalParameterList$ebnf$1", "PositionalParameterList$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "PositionalParameterList", "symbols": ["Expression", "_", "PositionalParameterList$ebnf$1"], "postprocess": (data) => { return new Node({ node: Node.LIST, entries: [].concat(reduce(data[0])).concat(reduce(extractObj(data[2],2))) });}},
{"name": "PathExpression", "symbols": ["NonArithmeticExpression", {"literal":"."}, "Name"], "postprocess": (data) => { return new Node({ node: Node.PATH, object:reduce(data[0]), property:data[2]});}},
{"name": "PathExpression", "symbols": ["BoxedExpression", {"literal":"."}, "Name"], "postprocess": (data) => { return new Node({ node: Node.PATH, object:reduce(data[0]), property:data[2]});}},
{"name": "PathExpression", "symbols": ["Name"]},
{"name": "ForExpression", "symbols": [{"literal":"for"}, "__", "Name", "__", {"literal":"in"}, "__", "Expression", "__", {"literal":"return"}, "__", "Expression"], "postprocess": (data) => { return new Node({ node: Node.FOR, var: data[2], context: reduce(data[6]), return: reduce(data[10])}); }},
{"name": "IfExpression", "symbols": [{"literal":"if"}, "__", "Expression", "__", {"literal":"then"}, "__", "Expression", "__", {"literal":"else"}, "__", "Expression", "_"], "postprocess": (data) => { return new Node({ node: Node.IF, condition: data[2], then: data[6], else: data[10]}); }},
{"name": "QuantifiedExpression$subexpression$1", "symbols": [{"literal":"some"}]},
{"name": "QuantifiedExpression$subexpression$1", "symbols": [{"literal":"every"}]},
{"name": "QuantifiedExpression", "symbols": ["QuantifiedExpression$subexpression$1", "__", "Name", "__", {"literal":"in"}, "__", "Expression", "__", {"literal":"satisfies"}, "__", "Expression"], "postprocess": (data) => { return new Node({ node: Node.QUANTIFIED, operator: reduce(data[0]).value, variable: data[2], context: data[6], satisfy: data[10]}); }},
{"name": "LogicalExpression$subexpression$1", "symbols": [{"literal":"and"}]},
{"name": "LogicalExpression$subexpression$1", "symbols": [{"literal":"or"}]},
{"name": "LogicalExpression", "symbols": ["LogicalExpression", "__", "LogicalExpression$subexpression$1", "__", "Comparison"], "postprocess": (data) => { return new Node({ node: Node.LOGICAL, left: reduce(data[0]), operator: reduce(data[2]).value, right: reduce(data[4])}); }},
{"name": "LogicalExpression", "symbols": ["Comparison"]},
{"name": "Comparison$subexpression$1", "symbols": [{"literal":"="}]},
{"name": "Comparison$subexpression$1", "symbols": [{"literal":"!="}]},
{"name": "Comparison$subexpression$1", "symbols": [{"literal":"<"}]},
{"name": "Comparison$subexpression$1", "symbols": [{"literal":"<="}]},
{"name": "Comparison$subexpression$1", "symbols": [{"literal":">"}]},
{"name": "Comparison$subexpression$1", "symbols": [{"literal":">="}]},
{"name": "Comparison", "symbols": ["Comparison", "_", "Comparison$subexpression$1", "_", "Sum"], "postprocess": (data) => { return new Node({ node: Node.COMPARISON, operator: reduce(data[2]).value, left: reduce(data[0]), right: reduce(data[4])});}},
{"name": "Comparison", "symbols": ["Expression", "__", {"literal":"between"}, "__", "Expression", "__", {"literal":"and"}, "__", "Expression"], "postprocess": (data) => { return new Node({ node: Node.BETWEEN, expression: reduce(data[0]), left: reduce(data[4]), right: reduce(data[8])});}},
{"name": "Comparison", "symbols": ["Expression", "__", {"literal":"in"}, "__", "PositiveUnarytest"], "postprocess": (data) => { return new Node({ node: Node.IN, input: reduce(data[0]), test: reduce(data[4])});}},
{"name": "Comparison", "symbols": ["Expression", "__", {"literal":"in"}, "__", "UnaryNot"], "postprocess": (data) => { return new Node({ node: Node.IN, input: reduce(data[0]), test: reduce(data[4])});}},
{"name": "Comparison", "symbols": ["Expression", "__", {"literal":"in"}, "__", "UnaryDash"], "postprocess": (data) => { return new Node({ node: Node.IN, input: reduce(data[0]), test: reduce(data[4])});}},
{"name": "Comparison", "symbols": ["Expression", "__", {"literal":"in"}, "_", {"literal":"("}, "_", "PositiveUnarytests", "_", {"literal":")"}], "postprocess": (data) => { return new Node({ node: Node.IN_LIST, input: reduce(data[0]), list: reduce(data[6])});}},
{"name": "Comparison", "symbols": ["Sum"]},
{"name": "FilterExpression", "symbols": ["Expression", "_", {"literal":"["}, "_", "Expression", "_", {"literal":"]"}], "postprocess": (data) => { return new Node({ node: Node.FILTER, list: reduce(data[0]), filter: reduce(data[4])});}},
{"name": "InstanceOf", "symbols": ["Expression", "_", (lexer.has("instance") ? {type: "instance"} : instance), "_", "Type"], "postprocess": (data) => { return new Node({ node: Node.INSTANCE_OF, instance: reduce(data[0]), of: reduce(data[4])}); }},
{"name": "Type", "symbols": ["QualifiedName"]},
{"name": "Type", "symbols": [{"literal":"list"}, "_", {"literal":"<"}, "_", "Type", "_", {"literal":">"}], "postprocess": (data) => { return new Node({ node: Node.LIST_OF, single: reduce(data[4]) }); }},
{"name": "Type", "symbols": [{"literal":"context"}, "_", {"literal":"<"}, "_", "ContextElements", "_", {"literal":">"}], "postprocess": (data) => { return new Node({ node: Node.CONTEXT_TYPE, elements: reduce(data[4]) }); }},
{"name": "Type$ebnf$1$subexpression$1$ebnf$1", "symbols": []},
{"name": "Type$ebnf$1$subexpression$1$ebnf$1$subexpression$1", "symbols": [{"literal":","}, "_", "Type"]},
{"name": "Type$ebnf$1$subexpression$1$ebnf$1", "symbols": ["Type$ebnf$1$subexpression$1$ebnf$1", "Type$ebnf$1$subexpression$1$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "Type$ebnf$1$subexpression$1", "symbols": ["Type", "_", "Type$ebnf$1$subexpression$1$ebnf$1"]},
{"name": "Type$ebnf$1", "symbols": ["Type$ebnf$1$subexpression$1"], "postprocess": id},
{"name": "Type$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
{"name": "Type", "symbols": [{"literal":"function"}, "_", {"literal":"<"}, "_", "Type$ebnf$1", "_", {"literal":">"}, "_", {"literal":"->"}, "_", "Type"]},
{"name": "Type", "symbols": ["BasicType"], "postprocess": (data) => reduce(data)},
{"name": "ContextElements$ebnf$1", "symbols": []},
{"name": "ContextElements$ebnf$1$subexpression$1", "symbols": [{"literal":","}, "_", "ContextElement"]},
{"name": "ContextElements$ebnf$1", "symbols": ["ContextElements$ebnf$1", "ContextElements$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "ContextElements", "symbols": ["ContextElement", "_", "ContextElements$ebnf$1"], "postprocess": (data) => { return new Node({ node: Node.LIST, entries: [].concat(data[0]).concat(extract(data[2],2)) });}},
{"name": "ContextElement", "symbols": ["Name", "_", {"literal":":"}, "_", "Type"], "postprocess": (data) => { return new Node({ node: Node.CONTEXT_ELEMENT, name: concat(data[0]), type: reduce(data[4]) });}},
{"name": "BasicType$subexpression$1", "symbols": [{"literal":"boolean"}]},
{"name": "BasicType$subexpression$1", "symbols": [{"literal":"number"}]},
{"name": "BasicType$subexpression$1", "symbols": [{"literal":"string"}]},
{"name": "BasicType$subexpression$1", "symbols": [{"literal":"date"}]},
{"name": "BasicType$subexpression$1", "symbols": [{"literal":"time"}]},
{"name": "BasicType$subexpression$1", "symbols": [{"literal":"date and time"}]},
{"name": "BasicType$subexpression$1", "symbols": [{"literal":"day-time-duration"}]},
{"name": "BasicType$subexpression$1", "symbols": [{"literal":"year-month-duration"}]},
{"name": "BasicType", "symbols": ["BasicType$subexpression$1"], "postprocess": (data) => reduce(data).value},
{"name": "BasicType", "symbols": [{"literal":"date"}, "__", {"literal":"time"}], "postprocess": (data) => concat(data)},
{"name": "BoxedExpression", "symbols": ["List"]},
{"name": "BoxedExpression", "symbols": ["FunctionDefintion"], "postprocess": (data) => { return reduce(data);}},
{"name": "BoxedExpression", "symbols": ["Context", "__", "Expression"], "postprocess": (data) => { return new Node({ node: Node.BOXED, context: reduce(data[0]), result: reduce(data[2]) }); }},
{"name": "BoxedExpression", "symbols": ["Context"], "postprocess": (data) => { return reduce(data);}},
{"name": "List", "symbols": [{"literal":"["}, "_", "ListEntries", "_", {"literal":"]"}], "postprocess": (data) => { return new Node({ node: Node.LIST, entries: data[2] }); }},
{"name": "List", "symbols": [{"literal":"["}, "_", {"literal":"]"}], "postprocess": (data) => { return new Node({ node: Node.LIST, entries: [] }); }},
{"name": "ListEntries$ebnf$1", "symbols": []},
{"name": "ListEntries$ebnf$1$subexpression$1", "symbols": [{"literal":","}, "_", "ListEntry"]},
{"name": "ListEntries$ebnf$1", "symbols": ["ListEntries$ebnf$1", "ListEntries$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "ListEntries", "symbols": ["ListEntry", "_", "ListEntries$ebnf$1"], "postprocess": (data) => { return [].concat(data[0]).concat(extractObj(data[2],2)); }},
{"name": "ListEntry", "symbols": ["Expression"], "postprocess": (data) => reduce(data)},
{"name": "ListEntry", "symbols": ["UnaryDash"]},
{"name": "ListEntry", "symbols": ["UnaryNot"]},
{"name": "FunctionDefintion$ebnf$1", "symbols": ["FormalParameterList"], "postprocess": id},
{"name": "FunctionDefintion$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
{"name": "FunctionDefintion", "symbols": [{"literal":"function"}, "_", {"literal":"("}, "_", "FunctionDefintion$ebnf$1", "_", {"literal":")"}, "_", "Expression"], "postprocess": (data) => { return new Node({ node: Node.FUNCTION_DEFINITION, parameters: reduce(data[4]), expression: reduce(data[8]) });}},
{"name": "FormalParameterList$ebnf$1", "symbols": []},
{"name": "FormalParameterList$ebnf$1$subexpression$1", "symbols": [{"literal":","}, "_", "FormalParameter"]},
{"name": "FormalParameterList$ebnf$1", "symbols": ["FormalParameterList$ebnf$1", "FormalParameterList$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "FormalParameterList", "symbols": ["FormalParameter", "_", "FormalParameterList$ebnf$1"], "postprocess": (data) => { return new Node({ node: Node.LIST, entries: [].concat(reduce(data[0])).concat(reduce(extractObj(data[2],2))) });}},
{"name": "FormalParameter$ebnf$1", "symbols": ["FormalParameterType"], "postprocess": id},
{"name": "FormalParameter$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
{"name": "FormalParameter", "symbols": ["Name", "_", "FormalParameter$ebnf$1"], "postprocess": (data) => { return new Node({ node: Node.FORMAL_PARAMETER, name: concat(data[0]), type: reduce(data[2]) });}},
{"name": "FormalParameterType", "symbols": [{"literal":":"}, "_", "Type"], "postprocess": (data) => { return reduce(data[2]); }},
{"name": "Context$ebnf$1$subexpression$1", "symbols": ["ContextEntries"]},
{"name": "Context$ebnf$1", "symbols": ["Context$ebnf$1$subexpression$1"], "postprocess": id},
{"name": "Context$ebnf$1", "symbols": [], "postprocess": function(d) {return null;}},
{"name": "Context", "symbols": [{"literal":"{"}, "_", "Context$ebnf$1", "_", {"literal":"}"}], "postprocess": (data) => { return new Node({ node: Node.CONTEXT, data: reduce(data[2]) }); }},
{"name": "ContextEntries$ebnf$1", "symbols": []},
{"name": "ContextEntries$ebnf$1$subexpression$1", "symbols": [{"literal":","}, "_", "ContextEntry"]},
{"name": "ContextEntries$ebnf$1", "symbols": ["ContextEntries$ebnf$1", "ContextEntries$ebnf$1$subexpression$1"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "ContextEntries", "symbols": ["ContextEntry", "_", "ContextEntries$ebnf$1"], "postprocess": (data) => { return new Node({ node: Node.LIST, entries: [].concat(data[0]).concat(extractObj(data[2],2)) });}},
{"name": "ContextEntry", "symbols": ["Key", "_", {"literal":":"}, "_", "Expression"], "postprocess": (data) => { addToContext(reduce(data[0])); return new Node({ node: Node.CONTEXT_ENTRY, key: reduce(data[0]), expression: reduce(data[4]) });}},
{"name": "Key", "symbols": ["Name"]},
{"name": "Key", "symbols": ["StringLiteral"]},
{"name": "DateTimeLiteral", "symbols": ["AtLiteral"]},
{"name": "DateTimeLiteral", "symbols": ["DateTimeFunction"]},
{"name": "DateTimeFunction", "symbols": [(lexer.has("dayandtime") ? {type: "dayandtime"} : dayandtime), "_", "Parameters"], "postprocess": (data) => { return new Node({ node: Node.DATE_AND_TIME, name: data[0].value, parameters: reduce(data[2]) });}},
{"name": "WhiteSpace", "symbols": [(lexer.has("whitespace") ? {type: "whitespace"} : whitespace)]},
{"name": "WhiteSpace", "symbols": [(lexer.has("singlelinecomment") ? {type: "singlelinecomment"} : singlelinecomment)]},
{"name": "WhiteSpace", "symbols": [(lexer.has("multilinecomment") ? {type: "multilinecomment"} : multilinecomment)]},
{"name": "_$ebnf$1", "symbols": []},
{"name": "_$ebnf$1", "symbols": ["_$ebnf$1", "WhiteSpace"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "_", "symbols": ["_$ebnf$1"], "postprocess": () => { return " "; }},
{"name": "__$ebnf$1", "symbols": ["WhiteSpace"]},
{"name": "__$ebnf$1", "symbols": ["__$ebnf$1", "WhiteSpace"], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}},
{"name": "__", "symbols": ["__$ebnf$1"], "postprocess": () => { return " "; }},
{"name": "AtLiteral", "symbols": [{"literal":"@"}, "StringLiteral"], "postprocess": (data) => {return new Node({ node: Node.AT_LITERAL, expression: reduce(data[1]) });}}
]
, ParserStart: "main"
}
if (typeof module !== 'undefined'&& typeof module.exports !== 'undefined') {
module.exports = grammar;
} else {
window.grammar = grammar;
}
})();