//private static bool IsDot(Parser.ParseContext context, out OperatorType operatorType, out int offset) //{ // offset = 0; // operatorType = OperatorType.None; // string c = context.Expression.Substring(context.TokenPosition, 1); // if (c == "."){ // operatorType = OperatorType.Dot; // offset = 1; // return true; // } // return false; //} internal static bool ParseBinary(Parser.ParseContext context) { int offset = 0; OperatorType operatorType = OperatorType.None; bool isBinary = IsNumeric(context, out operatorType, out offset); if (!isBinary) { isBinary = IsEquality(context, out operatorType, out offset); } if (!isBinary) { isBinary = IsComparator(context, out operatorType, out offset); } if (!isBinary) { isBinary = IsLogical(context, out operatorType, out offset); } if (!isBinary) { return(false); } ValidateTokenOrder(context, TokenType.BinaryOperator); ElementOperator element = new ElementBinaryOperator(operatorType); ProcessOperator(context, element); context.TokenPosition += offset; return(true); }
internal static void ProcessOperator(Parser.ParseContext context, ElementOperator element) { Operator.AssignmentEnum assigment = element.Operator.Assigment; int precedence = element.Operator.Precedence; while (context.Stack.Count > 0) { Element lastElement = context.Stack.Pop(); if (lastElement.Type == TokenType.BinaryOperator || lastElement.Type == TokenType.UnitaryOperator || lastElement.Type == TokenType.Function) { Operator prevOperator = ((ElementOperator)lastElement).Operator; if ((assigment == Operator.AssignmentEnum.Left && precedence >= prevOperator.Precedence) || (assigment == Operator.AssignmentEnum.Right && precedence > prevOperator.Precedence)) { context.Ouput.Push(lastElement); } else { context.Stack.Push(lastElement); break; } } else { context.Stack.Push(lastElement); break; } } context.Stack.Push(element); }
internal static bool Parse(Parser.ParseContext context) { char c = context.Expression[context.TokenPosition]; if (c == '@') { ValidateTokenOrder(context, TokenType.Selector); StringBuilder selectorStr = new StringBuilder(); while (context.TokenPosition < context.Expression.Length) { c = context.Expression[context.TokenPosition]; //if (!VariableValidCharsRegExp.IsMatch(c)){ if (c == ']') { break; } selectorStr.Append(c); context.TokenPosition++; } ElementSelector element = new ElementSelector(selectorStr.ToString()); context.Ouput.Push(element); return(true); } return(false); }
private static bool ParseTernaryElse(Parser.ParseContext context) { if (context.BpOrder.Count == 0 || context.BpOrder.Pop() != TokenType.TernaryIf) { throw new ELException("Invalid token at position " + context.TokenPosition); } ValidateTokenOrder(context, TokenType.TernaryElse); Element element = new ElementTernaryOperator(TokenType.TernaryElse); while (context.Stack.Count > 0) { Element lastElement = context.Stack.Pop(); if (lastElement.Type == TokenType.TernaryIf) { break; } else { context.Ouput.Push(lastElement); } } context.Ouput.Push(element); context.TokenPosition++; return(true); }
private static bool ParseTenaryIf(Parser.ParseContext context) { context.BpOrder.Push(TokenType.TernaryIf); ValidateTokenOrder(context, TokenType.TernaryIf); Element element = new ElementTernaryOperator(TokenType.TernaryIf); context.LastTokenType = TokenType.TernaryIf; while (context.Stack.Count > 0) { Element lastElement = context.Stack.Pop(); if (lastElement.Type == TokenType.OpenParenthesis) { context.Stack.Push(lastElement); break; } else { context.Ouput.Push(lastElement); } } context.Stack.Push(element); context.Ouput.Push(element); context.TokenPosition++; return(true); }
private static bool ParseBool(Parser.ParseContext context, out TokenType tokenType, out object value) { tokenType = TokenType.None; value = null; string subStr = context.Expression.Substring(context.TokenPosition, Math.Min(5, context.Expression.Length - context.TokenPosition)); if (testTrue.IsMatch(subStr)) { //We validate first that way we don't need to process the rest of the string if not needed. ValidateTokenOrder(context, TokenType.BooleanLiteral); tokenType = TokenType.BooleanLiteral; value = true; context.TokenPosition += 4; return(true); } subStr = context.Expression.Substring(context.TokenPosition, Math.Min(6, context.Expression.Length - context.TokenPosition)); if (testFalse.IsMatch(subStr)) { //We validate first that way we don't need to process the rest of the string if not needed. ValidateTokenOrder(context, TokenType.BooleanLiteral); tokenType = TokenType.BooleanLiteral; value = false; context.TokenPosition += 5; return(true); } return(false); }
private static bool ParseString(Parser.ParseContext context, out TokenType tokenType, out object value) { char c = context.Expression[context.TokenPosition]; value = null; tokenType = TokenType.None; if (c == '"' || c == '\'') { //We validate first that way we don't need to process the rest of the string if not needed. ValidateTokenOrder(context, TokenType.StringLiteral); StringBuilder content = new StringBuilder(); char encloseChar = c; context.TokenPosition++; while (context.TokenPosition < context.Expression.Length) { c = context.Expression[context.TokenPosition]; if (c == encloseChar) { tokenType = TokenType.StringLiteral; value = content.ToString(); context.TokenPosition++; return(true); } else if (c == '\\') { if (context.Expression.Length <= context.TokenPosition + 1) { throw new ELException("Invalid token at position " + context.TokenPosition); } else { context.TokenPosition++; c = context.Expression[context.TokenPosition]; switch (c) { case '\'': case '"': content.Append(c); break; //TODO add extra excape handling //http://ftp.icm.edu.pl/packages/tucows/html/programmer/jstut/jsTabChars.html default: throw new ELException("Invalid token at position " + context.TokenPosition); } context.TokenPosition++; } } else { content.Append(c); context.TokenPosition++; } } throw new ELException("Invalid expression string not closed"); } return(false); }
private static bool ParseOpenParenthesis(Parser.ParseContext context) { context.BpOrder.Push(TokenType.OpenParenthesis); ValidateTokenOrder(context, TokenType.OpenParenthesis); Element element = new ElementGrouping(TokenType.OpenParenthesis); context.Ouput.Push(element); context.Stack.Push(element); context.TokenPosition++; return(true); }
internal static bool ParseUnitary(Parser.ParseContext context) { char c = context.Expression[context.TokenPosition]; int offset = 0; string subStr; OperatorType operationType = OperatorType.None; TokenType lastTokenType = context.LastTokenType; switch (c) { case '-': if (lastTokenType == TokenType.OpenBracket || lastTokenType == TokenType.OpenParenthesis || lastTokenType == TokenType.UnitaryOperator || lastTokenType == TokenType.Start || lastTokenType == TokenType.BinaryOperator) { offset = 1; operationType = OperatorType.Negative; break; } return(false); case '!': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(2, context.Expression.Length - context.TokenPosition)); if (!subStr.Equals("!=")) { offset = 1; operationType = OperatorType.Not; break; } return(false); case 'n': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(4, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("not ") || subStr.Equals("not(")) { operationType = OperatorType.Not; offset = 3; break; } return(false); default: return(false); } ValidateTokenOrder(context, TokenType.UnitaryOperator); ElementOperator element = new ElementUnitaryOperator(operationType); ProcessOperator(context, element); context.TokenPosition += offset; return(true); }
internal static bool ParseDot(Parser.ParseContext context) { char c = context.Expression[context.TokenPosition]; if (c == '.') { ValidateTokenOrder(context, TokenType.Dot); ElementDot element = new ElementDot(); context.Ouput.Push(element); context.TokenPosition++; return(true); } return(false); }
internal static bool Parse(Parser.ParseContext context) { char c = context.Expression[context.TokenPosition]; if (c.Equals('?')) { return(ParseTenaryIf(context)); } else if (c.Equals(':')) { return(ParseTernaryElse(context)); } return(false); }
//private static bool IsObjectElement(Parser.ParseContext context, out OperatorType operatorType, out int offset){ // operatorType = OperatorType.None; // offset = 0; // string c = context.Expression.Substring(context.TokenPosition, 1); // if (c.Equals(".")){ // operatorType = OperatorType.Dot; // offset = 1; // return true; // } // return false; //} private static bool IsEquality(Parser.ParseContext context, out OperatorType operatorType, out int offset) { operatorType = OperatorType.None; offset = 0; string c = context.Expression.Substring(context.TokenPosition, Math.Min(2, context.Expression.Length - context.TokenPosition)); switch (c) { case "==": operatorType = OperatorType.Equals; offset = 2; return(true); case "!=": operatorType = OperatorType.NotEquals; offset = 2; return(true); } c = context.Expression.Substring(context.TokenPosition, Math.Min(3, context.Expression.Length - context.TokenPosition)); switch (c) { case "eq ": operatorType = OperatorType.Equals; offset = 3; return(true); case "eq(": operatorType = OperatorType.Equals; offset = 2; return(true); case "ne ": operatorType = OperatorType.NotEquals; offset = 3; return(true); case "ne(": operatorType = OperatorType.NotEquals; offset = 2; return(true); } return(false); }
internal static void ValidateTokenOrder(Parser.ParseContext context, TokenType tokenType) { bool hasToken = false; for (int i = 0; i < tokenOrder[context.LastTokenType].Length; i++) { if (tokenOrder[context.LastTokenType][i] == tokenType) { hasToken = true; break; } } if (!hasToken) { throw new ELException("Invalid token at position " + context.TokenPosition); } context.LastTokenType = tokenType; }
internal static bool Parse(Parser.ParseContext context) { if (ElementBinaryOperator.ParseBinary(context)) { return(true); } else if (ElementUnitaryOperator.ParseUnitary(context)) { return(true); } else if (ElementDot.ParseDot(context)) { return(true); } else if (ElementFunction.ParseFunction(context)) { return(true); } return(false); }
internal static bool Parse(Parser.ParseContext context) { string c = context.Expression.Substring(context.TokenPosition, 1); if (VariableStartRegExp.IsMatch(c)) { ValidateTokenOrder(context, TokenType.Variable); StringBuilder variableStr = new StringBuilder(); while (context.TokenPosition < context.Expression.Length) { c = context.Expression.Substring(context.TokenPosition, 1); //if (c == ".") //{ // variableStr.Append(c); // context.TokenPosition++; // c = context.Expression.Substring(context.TokenPosition, 1); // if (VariableStartRegExp.IsMatch(c)) // { // variableStr.Append(c); // context.TokenPosition++; // continue; // } // else // { // throw new ELException("Invalid token at position " + context.TokenPosition); // } //} if (!VariableValidCharsRegExp.IsMatch(c)) { break; } variableStr.Append(c); context.TokenPosition++; } ElementVariable element = new ElementVariable(variableStr.ToString()); context.Ouput.Push(element); return(true); } return(false); }
internal static bool Parse(Parser.ParseContext context) { char c = context.Expression[context.TokenPosition]; switch (c) { case ')': return(ParseCloseParenthesis(context)); case '(': return(ParseOpenParenthesis(context)); case ']': return(ParseCloseBracket(context)); case '[': return(ParseOpenBracket(context)); default: return(false); } }
private static bool ParseCloseParenthesis(Parser.ParseContext context) { if (context.BpOrder.Count == 0 || context.BpOrder.Pop() != TokenType.OpenParenthesis) { throw new ELException("Invalid token at " + context.TokenPosition); } ValidateTokenOrder(context, TokenType.CloseParenthesis); Element element = new ElementGrouping(TokenType.CloseParenthesis); while (context.Stack.Count > 0) { Element lastElement = context.Stack.Pop(); if (lastElement.Type.Equals(TokenType.OpenParenthesis)) { break; } context.Ouput.Push(lastElement); } context.Ouput.Push(element); context.TokenPosition++; return(true); }
internal static bool Parse(Parser.ParseContext context) { TokenType tokenType = TokenType.None; object value = null; bool isLiteral = ParseString(context, out tokenType, out value); if (!isLiteral) { isLiteral = ParseNumeric(context, out tokenType, out value); } if (!isLiteral) { isLiteral = ParseBool(context, out tokenType, out value); } if (!isLiteral) { return(false); } ElementLiteral element = new ElementLiteral(tokenType, value); context.Ouput.Push(element); return(true); }
internal static bool ParseFunction(Parser.ParseContext context) { char c = context.Expression[context.TokenPosition]; int offset = 0; string subStr; OperatorType operationType = OperatorType.None; TokenType lastTokenType = context.LastTokenType; switch (c) { case 'e': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(6, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("empty ") || subStr.Equals("empty(")) { offset = 4; operationType = OperatorType.Empty; break; } return(false); case 't': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(9, context.Expression.Length - context.TokenPosition)); if (subStr == "toNumber " || subStr == "toNumber(") { offset = 7; operationType = OperatorType.ToNumber; break; } else if (subStr == "toString " || subStr == "toString(") { offset = 7; operationType = OperatorType.ToString; break; } subStr = context.Expression.Substring(context.TokenPosition, Math.Min(10, context.Expression.Length - context.TokenPosition)); if (subStr == "toBoolean " || subStr == "toBoolean(") { offset = 8; operationType = OperatorType.ToBoolean; break; } return(false); case 'm': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(10, context.Expression.Length - context.TokenPosition)); if (subStr == "mathRound " || subStr == "mathRound(") { offset = 8; operationType = OperatorType.MathRound; break; } else if (subStr == "mathFloor " || subStr == "mathFloor(") { offset = 8; operationType = OperatorType.MathFloor; break; } subStr = context.Expression.Substring(context.TokenPosition, Math.Min(9, context.Expression.Length - context.TokenPosition)); if (subStr == "mathCeil " || subStr == "mathCeil(") { offset = 7; operationType = OperatorType.MathCeil; break; } return(false); case 'o': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(14, context.Expression.Length - context.TokenPosition)); if (subStr == "os:htmlEncode " || subStr == "os:htmlEncode(") { offset = 12; operationType = OperatorType.HtmlEncode; break; } if (subStr == "os:htmlDecode " || subStr == "os:htmlDecode(") { offset = 12; operationType = OperatorType.HtmlDecode; break; } subStr = context.Expression.Substring(context.TokenPosition, Math.Min(13, context.Expression.Length - context.TokenPosition)); if (subStr == "os:urlEncode " || subStr == "os:urlEncode(") { offset = 11; operationType = OperatorType.UrlEncode; break; } if (subStr == "os:urlDecode " || subStr == "os:urlDecode(") { offset = 11; operationType = OperatorType.UrlDecode; break; } subStr = context.Expression.Substring(context.TokenPosition, Math.Min(18, context.Expression.Length - context.TokenPosition)); if (subStr == "os:jsStringEscape " || subStr == "os:jsStringEscape(") { offset = 16; operationType = OperatorType.JsStringEscape; break; } return(false); case 'h': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(11, context.Expression.Length - context.TokenPosition)); if (subStr == "htmlEncode " || subStr == "htmlEncode(") { offset = 9; operationType = OperatorType.HtmlEncode; break; } if (subStr == "htmlDecode " || subStr == "htmlDecode(") { offset = 9; operationType = OperatorType.HtmlDecode; break; } return(false); case 'u': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(10, context.Expression.Length - context.TokenPosition)); if (subStr == "urlEncode " || subStr == "urlEncode(") { offset = 8; operationType = OperatorType.UrlEncode; break; } if (subStr == "urlDecode " || subStr == "urlDecode(") { offset = 8; operationType = OperatorType.UrlDecode; break; } return(false); case 'j': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(15, context.Expression.Length - context.TokenPosition)); if (subStr == "jsStringEscape " || subStr == "jsStringEscape(") { offset = 13; operationType = OperatorType.JsStringEscape; break; } return(false); default: return(false); } ValidateTokenOrder(context, TokenType.Function); context.TokenPosition += offset; IList <IList <Element> > parameters = GetParameters(context); ElementOperator element = new ElementFunction(operationType, parameters); ProcessOperator(context, element); return(true); }
private static IList <IList <Element> > GetParameters(Parser.ParseContext context) { char c; while (true) { context.TokenPosition++; c = context.Expression[context.TokenPosition]; if (c == ' ' || c == '\t' || c == '\n' || c == '\r') { continue; } else if (c != '(') { throw new ELException("Invalid token"); } else { break; } } if (c != '(') { throw new ELException("Invalid token"); } context.TokenPosition++; int parentesisCount = 1; StringBuilder param = new StringBuilder(); IList <IList <Element> > parms = new List <IList <Element> >(); string paramVal; while (parentesisCount > 0 && context.TokenPosition < context.Expression.Length) { c = context.Expression[context.TokenPosition]; switch (c) { case ')': parentesisCount--; context.TokenPosition++; if (parentesisCount == 0) { paramVal = param.ToString().Trim(); if (string.IsNullOrEmpty(paramVal)) { throw new ELException("Invalid token parameter"); } else { parms.Add(Parser.Parse(paramVal)); } continue; } break; case '(': parentesisCount++; break; case ',': paramVal = param.ToString().Trim(); if (string.IsNullOrEmpty(paramVal)) { throw new EL.ELException("Invalid parameter"); } else { parms.Add(Parser.Parse(paramVal)); } context.TokenPosition++; param.Remove(0, param.Length); continue; } param.Append(c); context.TokenPosition++; } return(parms); }
private static bool IsNumeric(Parser.ParseContext context, out OperatorType operatorType, out int offset) { operatorType = OperatorType.None; offset = 0; string subStr; char c = context.Expression[context.TokenPosition]; switch (c) { case '+': operatorType = OperatorType.Addition; offset = 1; return(true); case '/': operatorType = OperatorType.Division; offset = 1; return(true); case '%': operatorType = OperatorType.Modulo; offset = 1; return(true); case '*': operatorType = OperatorType.Multiplication; offset = 1; return(true); case '-': TokenType lastTokenType = context.LastTokenType; if (lastTokenType == TokenType.CloseParenthesis || lastTokenType == TokenType.StringLiteral || lastTokenType == TokenType.DecimalLiteral || lastTokenType == TokenType.IntegerLiteral || lastTokenType == TokenType.BooleanLiteral || lastTokenType == TokenType.Variable || lastTokenType == TokenType.CloseBracket) { operatorType = OperatorType.Substraction; offset = 1; return(true); } return(false); case 'm': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(4, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("mod ")) { operatorType = OperatorType.Modulo; offset = 4; return(true); } return(false); case 'd': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(4, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("div ")) { operatorType = OperatorType.Division; offset = 4; return(true); } return(false); } return(false); }
private static bool IsComparator(Parser.ParseContext context, out OperatorType operatorType, out int offset) { offset = 0; operatorType = OperatorType.None; char c = context.Expression[context.TokenPosition]; string subStr; switch (c) { case 'l': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(3, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("lt ")) { operatorType = OperatorType.LessThan; offset = 3; return(true); } else if (subStr.Equals("lt(")) { operatorType = OperatorType.LessThan; offset = 2; return(true); } else if (subStr.Equals("le ")) { operatorType = OperatorType.LessThanEquals; offset = 3; return(true); } else if (subStr.Equals("le(")) { operatorType = OperatorType.LessThanEquals; offset = 2; return(true); } return(false); case 'g': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(3, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("gt ")) { operatorType = OperatorType.GreaterThan; offset = 3; return(true); } else if (subStr.Equals("gt(")) { operatorType = OperatorType.GreaterThan; offset = 2; return(true); } else if (subStr.Equals("ge ")) { operatorType = OperatorType.GreaterThanEquals; offset = 3; return(true); } else if (subStr.Equals("ge(")) { operatorType = OperatorType.GreaterThanEquals; offset = 2; return(true); } return(false); case '>': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(2, context.Expression.Length - context.TokenPosition)); if (subStr.Equals(">=")) { operatorType = OperatorType.GreaterThanEquals; offset = 2; return(true); } else { operatorType = OperatorType.GreaterThan; offset = 1; return(true); } case '<': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(2, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("<=")) { operatorType = OperatorType.LessThanEquals; offset = 2; return(true); } else { operatorType = OperatorType.LessThan; offset = 1; return(true); } } return(false); }
private static bool IsLogical(Parser.ParseContext context, out OperatorType operatorType, out int offset) { offset = 0; operatorType = OperatorType.None; char c = context.Expression[context.TokenPosition]; string subStr; switch (c) { case '&': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(2, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("&&")) { operatorType = OperatorType.And; offset = 2; return(true); } return(false); case '|': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(2, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("||")) { operatorType = OperatorType.Or; offset = 2; return(true); } return(false); case 'a': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(4, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("and ")) { operatorType = OperatorType.And; offset = 4; return(true); } else if (subStr.Equals("and(")) { operatorType = OperatorType.And; offset = 3; return(true); } return(false); case 'o': subStr = context.Expression.Substring(context.TokenPosition, Math.Min(3, context.Expression.Length - context.TokenPosition)); if (subStr.Equals("or ")) { operatorType = OperatorType.Or; offset = 3; return(true); } else if (subStr.Equals("or(")) { operatorType = OperatorType.Or; offset = 2; return(true); } return(false); } return(false); }
private static bool ParseNumeric(Parser.ParseContext context, out TokenType tokenType, out object value) { tokenType = TokenType.None; value = null; char c = context.Expression[context.TokenPosition]; if (IsNumeric(c)) { //We validate first that way we don't need to process the rest of the string if not needed. ValidateTokenOrder(context, TokenType.DecimalLiteral); bool point = false; bool scientific = false; StringBuilder strValue = new StringBuilder(); while (context.TokenPosition < context.Expression.Length) { c = context.Expression[context.TokenPosition]; if (c.Equals('.')) { if (point || scientific) { throw new ELException("Invalid Token at position " + context.TokenPosition); } point = true; strValue.Append(c); context.TokenPosition++; } else if (IsNumber(c)) { strValue.Append(c); context.TokenPosition++; } else if (c == 'e' || c == 'E') { if (scientific) { throw new ELException("Invalid Token at position " + context.TokenPosition); } if (context.TokenPosition + 1 >= context.Expression.Length) { throw new ELException("Invalid Token at position " + context.TokenPosition); } scientific = true; strValue.Append('e'); context.TokenPosition++; c = context.Expression[context.TokenPosition]; if (c == '-' || c == '+') { strValue.Append(c); if (context.TokenPosition + 1 >= context.Expression.Length) { throw new ELException("Invalid Token at position " + context.TokenPosition); } context.TokenPosition++; c = context.Expression[context.TokenPosition]; } if (!IsNumber(c)) { throw new ELException("Invalid Token at position " + context.TokenPosition); } strValue.Append(c); context.TokenPosition++; } else { break; } } if (point || scientific) { double doubleValue = Double.Parse(strValue.ToString(), System.Globalization.NumberStyles.Float); if (doubleValue == Math.Floor(doubleValue)) { tokenType = TokenType.IntegerLiteral; value = (int)doubleValue; } else { tokenType = TokenType.DecimalLiteral; value = doubleValue; } } else { tokenType = TokenType.IntegerLiteral; value = Int32.Parse(strValue.ToString()); } return(true); } return(false); }