diff --git a/lib/parser/nools/nool.parser.js b/lib/parser/nools/nool.parser.js index 71d4012..3b6b571 100644 --- a/lib/parser/nools/nool.parser.js +++ b/lib/parser/nools/nool.parser.js @@ -1,6 +1,6 @@ "use strict"; -var tokens = require("./tokens.js"), +var tokens = require("./tokens.js").topLevelTokens, extd = require("../../extended"), keys = extd.hash.keys, utils = require("./util.js"); diff --git a/lib/parser/nools/tokens.js b/lib/parser/nools/tokens.js index 3ac7080..2ead85f 100644 --- a/lib/parser/nools/tokens.js +++ b/lib/parser/nools/tokens.js @@ -5,7 +5,7 @@ var utils = require("./util.js"), extd = require("../../extended"), filter = extd.filter, indexOf = extd.indexOf, - predicates = ["not", "or", "exists"], + predicates = ["not", "or", "exists"], predicateRegExp = new RegExp("^(" + predicates.join("|") + ") *\\((.*)\\)$", "m"), predicateBeginExp = new RegExp(" *(" + predicates.join("|") + ") *\\(", "g"); @@ -38,8 +38,82 @@ var splitRuleLineByPredicateExpressions = function (ruleLine) { return ret.join(";"); }; -var ruleTokens = { +/** +*/ +var ruleRegExp = /^(\$?\w+)\s*:\s*(\w+)(.*)/; +var collectRuleRegExp = /^(\$?\w+)\s*:\s*(\w+)\s*(.*)from\s*collect\s*\((.*)\)/; +var hashRegExp = /(\{ *(?:["']?\$?\w+["']?\s*:\s*["']?\$?\w+["']? *(?:, *["']?\$?\w+["']?\s*:\s*["']?\$?\w+["']?)*)+ *\})/; +var fromRegExp = /(\bfrom\s+.*)/; +var parseRules = function (str) { + var rules = []; + var ruleLines = str.split(";"), l = ruleLines.length, ruleLine, alias, constraints, parts, collectRule; + for (var i = 0; i < l && (ruleLine = ruleLines[i].replace(/^\s*|\s*$/g, "").replace(/\n/g, "")); i++) { + if (!isWhiteSpace(ruleLine)) { + var rule = []; + if (predicateRegExp.test(ruleLine)) { + var m = ruleLine.match(predicateRegExp); + var pred = m[1].replace(/^\s*|\s*$/g, ""); + rule.push(pred); + ruleLine = m[2].replace(/^\s*|\s*$/g, ""); + if (pred === "or") { + rule = rule.concat(parseRules(splitRuleLineByPredicateExpressions(ruleLine))); + rules.push(rule); + continue; + } + } + else if( collectRuleRegExp.test(ruleLine) ) { + parts = ruleLine.match(collectRuleRegExp); + if(parts && parts.length ) { + rule.push('collect'); + rule.push(parts[2], parts[1]); + constraints = parts[3].trim(); + rule.push( (constraints && !isWhiteSpace(constraints)) ? constraints : undefined ); + collectRule = parseRules(parts[4]); + rule.push(collectRule[0]); + } + rules.push(rule); + continue; + } + parts = ruleLine.match(ruleRegExp); + if (parts && parts.length) { + rule.push(parts[2], parts[1]); + constraints = parts[3].replace(/^\s*|\s*$/g, ""); + var hashParts = constraints.match(hashRegExp), from = null, fromMatch; + if (hashParts) { + var hash = hashParts[1], constraint = constraints.replace(hash, ""); + if (fromRegExp.test(constraint)) { + fromMatch = constraint.match(fromRegExp); + from = fromMatch[0]; + constraint = constraint.replace(fromMatch[0], ""); + } + if (constraint) { + rule.push(constraint.replace(/^\s*|\s*$/g, "")); + } + if (hash) { + rule.push(eval("(" + hash.replace(/(\$?\w+)\s*:\s*(\$?\w+)/g, '"$1" : "$2"') + ")")); + } + } else if (constraints && !isWhiteSpace(constraints)) { + if (fromRegExp.test(constraints)) { + fromMatch = constraints.match(fromRegExp); + from = fromMatch[0]; + constraints = constraints.replace(fromMatch[0], ""); + } + rule.push(constraints); + } + if (from) { + rule.push(from); + } + rules.push(rule); + } else { + throw new Error("Invalid constraint " + ruleLine); + } + } + } + return rules; +}; +exports.parseRules = parseRules; +var ruleTokens = { salience: (function () { var salienceRegexp = /^(salience|priority)\s*:\s*(-?\d+)\s*[,;]?/; return function (src, context) { @@ -93,7 +167,7 @@ var ruleTokens = { } }; })(), - + "agenda-group": function () { return this.agendaGroup.apply(this, arguments); }, @@ -109,66 +183,6 @@ var ruleTokens = { when: (function () { /*jshint evil:true*/ - var ruleRegExp = /^(\$?\w+) *: *(\w+)(.*)/; - - var constraintRegExp = /(\{ *(?:["']?\$?\w+["']?\s*:\s*["']?\$?\w+["']? *(?:, *["']?\$?\w+["']?\s*:\s*["']?\$?\w+["']?)*)+ *\})/; - var fromRegExp = /(\bfrom\s+.*)/; - var parseRules = function (str) { - var rules = []; - var ruleLines = str.split(";"), l = ruleLines.length, ruleLine; - for (var i = 0; i < l && (ruleLine = ruleLines[i].replace(/^\s*|\s*$/g, "").replace(/\n/g, "")); i++) { - if (!isWhiteSpace(ruleLine)) { - var rule = []; - if (predicateRegExp.test(ruleLine)) { - var m = ruleLine.match(predicateRegExp); - var pred = m[1].replace(/^\s*|\s*$/g, ""); - rule.push(pred); - ruleLine = m[2].replace(/^\s*|\s*$/g, ""); - if (pred === "or") { - rule = rule.concat(parseRules(splitRuleLineByPredicateExpressions(ruleLine))); - rules.push(rule); - continue; - } - - } - var parts = ruleLine.match(ruleRegExp); - if (parts && parts.length) { - rule.push(parts[2], parts[1]); - var constraints = parts[3].replace(/^\s*|\s*$/g, ""); - var hashParts = constraints.match(constraintRegExp), from = null, fromMatch; - if (hashParts) { - var hash = hashParts[1], constraint = constraints.replace(hash, ""); - if (fromRegExp.test(constraint)) { - fromMatch = constraint.match(fromRegExp); - from = fromMatch[0]; - constraint = constraint.replace(fromMatch[0], ""); - } - if (constraint) { - rule.push(constraint.replace(/^\s*|\s*$/g, "")); - } - if (hash) { - rule.push(eval("(" + hash.replace(/(\$?\w+)\s*:\s*(\$?\w+)/g, '"$1" : "$2"') + ")")); - } - } else if (constraints && !isWhiteSpace(constraints)) { - if (fromRegExp.test(constraints)) { - fromMatch = constraints.match(fromRegExp); - from = fromMatch[0]; - constraints = constraints.replace(fromMatch[0], ""); - } - rule.push(constraints); - } - if (from) { - rule.push(from); - } - rules.push(rule); - } else { - throw new Error("Invalid constraint " + ruleLine); - } - } - } - return rules; - }; - return function (orig, context) { var src = orig.replace(/^when\s*/, "").replace(/^\s*|\s*$/g, ""); if (utils.findNextToken(src) === "{") { @@ -324,7 +338,7 @@ var topLevelTokens = { } }, - "rule": function (orig, context, parse) { + "rule": function (orig, context, parse) { var src = orig.replace(/^rule\s*/, ""); var name = src.match(/^([a-zA-Z_$][0-9a-zA-Z_$]*|"[^"]*"|'[^']*')/); if (name) { @@ -343,8 +357,7 @@ var topLevelTokens = { } else { throw new Error("missing name"); } - } }; -module.exports = topLevelTokens; +exports.topLevelTokens = topLevelTokens;