An expression parser
Hi, while using JSON Select i had a requirement of being able to access a JSON object with expression like [uuid="123"].account_info.[full_name="Test"].city_state_zip which would select any node that had UUID as 123 and a object in that node with full_name as Test and then the value of city_state_zip in that object, so the sake of simplicity i took a simple example. For the above requirement i have written a parser, which will convert an expression as above to a JSON Select expression. Below is the code for the same.
var Parser = function () { var SIMPLE_EXPRESSION = 0; var COMPLEX_EXPRESSION = 1; var SELECT_ALL_EXPRESSION = 2; var ATTRIBUTE_SEPERATOR = "="; var SQUARE_OPENER = "["; var SQUARE_CLOSER = "]"; var EXPRESSION_SEPERATOR = "."; var GLOBAL_SELECTOR = "*";
function Expression(objName, attribute, exprType) {
this.exprType = exprType;
this.objName = objName;
if(exprType != SIMPLE_EXPRESSION){
var attributeArr = attribute.split(ATTRIBUTE_SEPERATOR);
this.attributeName = attributeArr[0];
this.attributeVal = attributeArr[1];
}
this.cssExpression = this.generateCSSExpression();
}
Expression.prototype = {
generateCSSExpression: function(){
if(this.cssExpression == undefined || this.cssExpression == null){
var cssExpression = null;
switch(this.exprType){
case COMPLEX_EXPRESSION:
cssExpression = "."+this.objName+" :has(."+this.attributeName+":expr(x="+this.attributeVal+"))";
break;
case SELECT_ALL_EXPRESSION:
cssExpression = ":has(:root > ."+ this.attributeName+ ":expr(x="+this.attributeVal+"))";
break;
case SIMPLE_EXPRESSION:
cssExpression = "."+this.objName;
break;
}
this.cssExpression = cssExpression;
}
return this.cssExpression;
}
}
function Parser() {
}
Parser.parse = function (expr) {
return new Parser().parse(expr);
};
Parser.getExpressionStack = function (expr) {
return new Parser().getExpressionStack(expr);
};
Parser.prototype = {
getExpressionStack: function(expr){
return this.parseExpression(expr, false);
},
parse: function (expr) {
return this.parseExpression(expr, true);
},
parseExpression: function(expr, isString){
this.expression = expr;
this.expressionStack = [];
this.pos = 0;
var objectArray = this.expression.split(EXPRESSION_SEPERATOR);
var self = this;
/**
* This function is used to parse a expression and generate a CSS expression out of it
* Example expressions are
* name_address[type='PRI'].email_address would generate a CSS Expression .name_address .type:val('PRI') ~ .email_address
*/
$.each(objectArray, function(index, expr){
var expression = null;
var expressionType = self.getExpressionType(expr);
switch(expressionType){
case COMPLEX_EXPRESSION:
case SELECT_ALL_EXPRESSION:
var exprArray = expr.replace(SQUARE_OPENER,"").split(SQUARE_CLOSER);
if(exprArray[1] === "" && exprArray.length == 2){
exprArray[1] = exprArray[0].replace("*","");
}
expression = new Expression(exprArray[0], exprArray[1], expressionType);
break;
case SIMPLE_EXPRESSION:
expression = new Expression(expr, null, expressionType);
break;
}
if(isString){
self.expressionStack.push(expression.cssExpression);
} else {
self.expressionStack.push(expression);
}
});
if(isString){
return self.expressionStack.join(" ");
}
return this.expressionStack;
},
getExpressionType: function(expr){
if(expr.indexOf(GLOBAL_SELECTOR) >= 0)
return SELECT_ALL_EXPRESSION;
if(expr.indexOf(SQUARE_OPENER) >= 0 && expr.indexOf(SQUARE_CLOSER) >= 0)
return COMPLEX_EXPRESSION;
return SIMPLE_EXPRESSION;
}
}
return Parser;
}();
I am a newbie to Javascript, Please let me know if the above can be improved