changed out a stack based filter parser for a operator/operand k-ary tree based parser.
This commit is contained in:
parent
1690a3f3f1
commit
d09a2ee711
|
@ -96,6 +96,229 @@ function _filterStringToStack(str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//expression parsing
|
||||||
|
//returns the index of the closing parenthesis matching the open paren specified by openParenIndex
|
||||||
|
function matchParens(str, openParenIndex){
|
||||||
|
var stack = [];
|
||||||
|
|
||||||
|
for(var i=openParenIndex || 0;i<str.length;i++){
|
||||||
|
if(str.charAt(i)=='('){
|
||||||
|
stack.push(1);
|
||||||
|
}else if(str.charAt(i) == ')'){
|
||||||
|
stack.pop();
|
||||||
|
if(stack.length === 0){
|
||||||
|
//console.log('[_findMatchingParenthesis]: returning ', i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//console.log('[_findMatchingParenthesis]: returning ', str.length-1);
|
||||||
|
return str.length-1;
|
||||||
|
};
|
||||||
|
//recursive function that builds a filter tree from a string expression
|
||||||
|
//the filter tree is an intermediary step between the incoming expression and the outgoing Dsml.
|
||||||
|
//see the comments of store.fetch concerning the filter argument for more info
|
||||||
|
function _buildFilterTree(expr){
|
||||||
|
console.log('[buildFilterTree]: expression: ',expr);
|
||||||
|
var tree = {};
|
||||||
|
if(expr.length === 0){
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
console.log(expr);
|
||||||
|
|
||||||
|
//remove leading and trailing parenthesis if they are there
|
||||||
|
if (expr.charAt(0) == '('){
|
||||||
|
expr = expr.substring(1,expr.length-1);
|
||||||
|
console.log('substring: '+expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//store prefix op
|
||||||
|
if(expr.charAt(0) == '&'){
|
||||||
|
tree.op = 'and';
|
||||||
|
expr = expr.substring(1);
|
||||||
|
}else if (expr.charAt(0) == '|'){
|
||||||
|
tree.op = 'or';
|
||||||
|
expr = expr.substring(1);
|
||||||
|
}else if(expr.charAt(0) == '!'){
|
||||||
|
tree.op = 'not';
|
||||||
|
expr = expr.substring(1);
|
||||||
|
}else{
|
||||||
|
tree.op = 'expr';
|
||||||
|
}
|
||||||
|
//if its a logical operator
|
||||||
|
if(tree.op != 'expr'){
|
||||||
|
var child,i=0;
|
||||||
|
tree.children = [];
|
||||||
|
|
||||||
|
//logical operators are k-ary, so we go until our expression string runs out
|
||||||
|
//(at least for this recursion level)
|
||||||
|
var endParen;
|
||||||
|
while (expr.length !== 0){
|
||||||
|
endParen = matchParens(expr);
|
||||||
|
if (endParen == expr.length-1){
|
||||||
|
tree.children[i] = _buildFilterTree(expr);
|
||||||
|
expr = "";
|
||||||
|
}else{
|
||||||
|
child = expr.slice(0,endParen+1);
|
||||||
|
expr = expr.substring(endParen+1);
|
||||||
|
tree.children[i] = _buildFilterTree(child);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
//else its equality expression, parse and return as such
|
||||||
|
var operatorStr = "";
|
||||||
|
var valueOffset=0;
|
||||||
|
tree.name = "";
|
||||||
|
tree.value = '';
|
||||||
|
if(expr.indexOf('~=') !=-1 ){
|
||||||
|
operatorStr = '~=';
|
||||||
|
tree.tag = 'approxMatch';
|
||||||
|
valueOffset = 2;
|
||||||
|
}else if(expr.indexOf('>=') != -1){
|
||||||
|
operatorStr = '>=';
|
||||||
|
tree.tag = 'greaterOrEqual';
|
||||||
|
valueOffset = 2;
|
||||||
|
}else if(expr.indexOf('<=') != -1){
|
||||||
|
operatorStr = '<=';
|
||||||
|
tree.tag = 'lessOrEqual';
|
||||||
|
valueOffset = 2;
|
||||||
|
}else if(expr.indexOf("=") != -1){
|
||||||
|
operatorStr = '=';
|
||||||
|
tree.tag = 'equalityMatch';
|
||||||
|
valueOffset = 1;
|
||||||
|
}else {
|
||||||
|
tree.tag = 'present';
|
||||||
|
}
|
||||||
|
console.log('operatorStr: ' + operatorStr + '; valueOffset: ' + valueOffset);
|
||||||
|
if (operatorStr == ""){
|
||||||
|
tree.name = expr;
|
||||||
|
}else{
|
||||||
|
//pull out lhs and rhs of equality operator
|
||||||
|
//var index = expr.indexOf('=');
|
||||||
|
|
||||||
|
var splitAry = expr.split(operatorStr,2);
|
||||||
|
tree.name =splitAry[0];
|
||||||
|
tree.value = splitAry[1];
|
||||||
|
|
||||||
|
if (tree.value.indexOf('*') != -1 && tree.tag == 'equalityMatch'){
|
||||||
|
tree.tag = 'substrings';
|
||||||
|
var split = tree.value.split("*");
|
||||||
|
if(tree.value.indexOf("*") != 0){
|
||||||
|
tree.initial = split.shift();
|
||||||
|
}else{
|
||||||
|
split.shift();
|
||||||
|
}
|
||||||
|
if(tree.value.lastIndexOf("*") != tree.value.length-1){
|
||||||
|
tree['final'] = split.pop();
|
||||||
|
}else{
|
||||||
|
split.pop();
|
||||||
|
}
|
||||||
|
tree.any = split;
|
||||||
|
}
|
||||||
|
if(tree.value.length == 0){
|
||||||
|
tree.tag = 'present';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
};
|
||||||
|
|
||||||
|
var treeToObjs = function(tree,filterObj){
|
||||||
|
console.log("in treeToObjs");
|
||||||
|
if(tree === undefined){
|
||||||
|
return filterObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tree.length === 0){
|
||||||
|
return filterObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentFilter = filterObj;
|
||||||
|
if(tree.op != "expr"){
|
||||||
|
console.log("adding "+tree.op+" to filters");
|
||||||
|
switch (tree.op){
|
||||||
|
case "and":
|
||||||
|
filterObj.addFilter(currentFilter = new AndFilter({filters:[]}));
|
||||||
|
break;
|
||||||
|
case "or":
|
||||||
|
filterObj.addFilter(currentFilter = new OrFilter({filters:[]}));
|
||||||
|
break;
|
||||||
|
case "not":
|
||||||
|
filterObj.addFilter(currentFilter = new NotFilter({filters:[]}));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for(var i = 0,tempFilter,child;i<tree.children.length;i++){
|
||||||
|
child = tree.children[i];
|
||||||
|
treeToObjs(child,currentFilter);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
var tempFilter;
|
||||||
|
//console.log("adding "+tree.tag+" to filters");
|
||||||
|
switch(tree.tag){
|
||||||
|
case "approxMatch":
|
||||||
|
tempFilter = new ApproximateFilter({
|
||||||
|
attribute: tree.name,
|
||||||
|
value: tree.value
|
||||||
|
});
|
||||||
|
console.log("adding "+tree.tag+"; attr: "+tree.name+"; value: "+tree.value);
|
||||||
|
break;
|
||||||
|
case "greaterOrEqual":
|
||||||
|
tempFilter = new GreaterThanEqualsFilter({
|
||||||
|
attribute: tree.name,
|
||||||
|
value: tree.value
|
||||||
|
});
|
||||||
|
console.log("adding "+tree.tag+"; attr: "+tree.name+"; value: "+tree.value);
|
||||||
|
break;
|
||||||
|
case "lessOrEqual":
|
||||||
|
tempFilter = new LessThanEqualsFilter({
|
||||||
|
attribute: tree.name,
|
||||||
|
value: tree.value
|
||||||
|
});
|
||||||
|
console.log("adding "+tree.tag+"; attr: "+tree.name+"; value: "+tree.value);
|
||||||
|
break;
|
||||||
|
case "equalityMatch":
|
||||||
|
tempFilter = new EqualityFilter({
|
||||||
|
attribute: tree.name,
|
||||||
|
value: tree.value
|
||||||
|
});
|
||||||
|
console.log("adding "+tree.tag+"; attr: "+tree.name+"; value: "+tree.value);
|
||||||
|
break;
|
||||||
|
case "substrings":
|
||||||
|
tempFilter = new SubstringFilter({
|
||||||
|
attribute: tree.name,
|
||||||
|
initial: tree.initial,
|
||||||
|
any: tree.any,
|
||||||
|
"final": tree["final"]
|
||||||
|
});
|
||||||
|
console.log("adding "+tree.tag+"; attr: "+tree.name+"; initial: "+tree.initial+"; any: "+JSON.stringify(tree.any) + "; final: "+tree['final']);
|
||||||
|
break;
|
||||||
|
case "present":
|
||||||
|
tempFilter = new PresenceFilter({
|
||||||
|
attribute: tree.name
|
||||||
|
});
|
||||||
|
console.log("adding "+tree.tag+"; attr: "+tree.name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
filterObj.addFilter(tempFilter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function _parseString(str){
|
||||||
|
assert.ok(str);
|
||||||
|
var filterObj = new AndFilter({
|
||||||
|
filters:[]
|
||||||
|
});
|
||||||
|
|
||||||
|
var tree = _buildFilterTree(str);
|
||||||
|
console.log("tree built: ",JSON.stringify(tree));
|
||||||
|
treeToObjs(tree,filterObj);
|
||||||
|
return filterObj.filters[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
function _parseString(str) {
|
function _parseString(str) {
|
||||||
assert.ok(str);
|
assert.ok(str);
|
||||||
|
|
||||||
|
@ -207,7 +430,7 @@ function _parseString(str) {
|
||||||
|
|
||||||
return filters.pop();
|
return filters.pop();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A filter looks like this coming in:
|
* A filter looks like this coming in:
|
||||||
|
|
Loading…
Reference in New Issue