/// <summary> /// Captures an element left from the starting index. /// </summary> private ElementCapture CaptureLeft(string exp, int index) { if (string.IsNullOrWhiteSpace(exp)) return new ElementCapture() { Length = 0, StartIndex = 0, Identifier = "", Depth = 0 }; string identifier = ""; bool foundSeperatorChar = false; int depth = 0; StringEscapeHelper escaper = new RightToLeftStringEscapeHelper(exp, index); while (index >= 0 && !foundSeperatorChar) { char t = exp[index]; escaper.CheckStartAt(index); if (!escaper.IsString) { if (t == ')' || t == ']' || t == '}') { depth++; } else if (t == '(' || t == '[' || t == '{') { depth--; } } if (depth < 0) { // this is when we walk out of the capture area because we are inside some area and a )]} appeared. foundSeperatorChar = true; } else { if (!escaper.IsString && depth == 0) { if (t == '.') { // Check if the '.' is not a decimal seperator: if (!Regex.IsMatch(identifier.Trim(), REGEX_NUMRIGHTDOT)) { foundSeperatorChar = true; } } else if (IDENTIFIER_SEPERATORS.Contains(t)) { foundSeperatorChar = true; } } // Append the char to the identifier: if (!foundSeperatorChar) { identifier = t + identifier; } } index--; } // Check for a minus in front of the identifier to indicate a negative number: if (index >= -1 && exp[index + 1] == '-' && !string.IsNullOrWhiteSpace(identifier)) { identifier = "-" + identifier; index--; } if (foundSeperatorChar) return new ElementCapture() { StartIndex = index + 2, Length = identifier.Length, Identifier = identifier, Depth = depth }; else return new ElementCapture() { StartIndex = index + 1, Length = identifier.Length, Identifier = identifier, Depth = depth }; }
private SObject ToScriptObject(string exp) { exp = exp.Trim(); // This means it's either an indexer or an array if (exp.EndsWith("]")) { if (!(exp.StartsWith("[") && !exp.Remove(0, 1).Contains("["))) // When there's no "[" besides the start, and it starts with [, then it is an array. Otherwise, do real check. { // It is possible that we are having a simple array declaration here. // We check that by looking if we can find a "[" before the expression ends: int depth = 0; int index = exp.Length - 2; int indexerStartIndex = 0; bool hasIndexer = false; StringEscapeHelper escaper = new RightToLeftStringEscapeHelper(exp, index); while (index > 0 && !hasIndexer) { char t = exp[index]; escaper.CheckStartAt(index); if (!escaper.IsString) { if (t == ')' || t == '}' || t == ']') { depth++; } else if (t == '(' || t == '{') { depth--; } else if (t == '[') { if (depth == 0) { if (index > 0) { indexerStartIndex = index; hasIndexer = true; } } else { depth--; } } } } if (hasIndexer) { string indexerCode = exp.Remove(0, indexerStartIndex + 1); indexerCode = indexerCode.Remove(indexerCode.Length - 1, 1); string identifier = exp.Remove(indexerStartIndex); SObject statementResult = ExecuteStatement(new ScriptStatement(indexerCode)); return ToScriptObject(identifier).GetMember(this, statementResult, true); } } } // Normal object return procedure: // Negative number: bool isNegative = false; if (exp.StartsWith("-")) { exp = exp.Remove(0, 1); isNegative = true; } double dblResult; SObject returnObject; if (exp == SObject.LITERAL_NULL) { returnObject = Null; } else if (exp == SObject.LITERAL_UNDEFINED) { returnObject = Undefined; } else if (exp == SObject.LITERAL_BOOL_FALSE) { returnObject = CreateBool(false); } else if (exp == SObject.LITERAL_BOOL_TRUE) { returnObject = CreateBool(true); } else if (exp == SObject.LITERAL_NAN) { returnObject = CreateNumber(double.NaN); } else if (exp == SObject.LITERAL_THIS) { returnObject = Context.This; } else if (SNumber.TryParse(exp, out dblResult)) { returnObject = CreateNumber(dblResult); } else if (exp.StartsWith("\"") && exp.EndsWith("\"") || exp.StartsWith("\'") && exp.EndsWith("\'")) { returnObject = CreateString(exp.Remove(exp.Length - 1, 1).Remove(0, 1), true); } else if (exp.StartsWith("@\"") && exp.EndsWith("\"") || exp.StartsWith("@\'") && exp.EndsWith("\'")) { returnObject = CreateString(exp.Remove(exp.Length - 1, 1).Remove(0, 2), false); } else if (exp.StartsWith("{") && exp.EndsWith("}")) { returnObject = SProtoObject.Parse(this, exp); } else if (exp.StartsWith("[") && exp.EndsWith("]")) { returnObject = SArray.Parse(this, exp); } else if (exp.StartsWith("function") && Regex.IsMatch(exp, REGEX_FUNCTION)) { returnObject = new SFunction(this, exp); } else if (Context.IsAPIUsing(exp)) { returnObject = Context.GetAPIUsing(exp); } else if (Context.IsVariable(exp)) { returnObject = Context.GetVariable(exp); } else if (Context.This.HasMember(this, exp)) { returnObject = Context.This.GetMember(this, CreateString(exp), false); } else if (Context.IsPrototype(exp)) { returnObject = Context.GetPrototype(exp); } else if (exp.StartsWith("new ")) { returnObject = Context.CreateInstance(exp); } else if (exp.StartsWith("$")) { string strId = exp.Remove(0, 1); int id = 0; if (int.TryParse(strId, out id) && ObjectBuffer.HasObject(id)) { returnObject = (SObject)ObjectBuffer.GetObject(id); } else { returnObject = ErrorHandler.ThrowError(ErrorType.SyntaxError, ErrorHandler.MESSAGE_SYNTAX_INVALID_TOKEN, new object[] { exp }); } } else { returnObject = ErrorHandler.ThrowError(ErrorType.ReferenceError, ErrorHandler.MESSAGE_REFERENCE_NOT_DEFINED, new object[] { exp }); } if (isNegative) returnObject = ObjectOperators.NegateNumber(this, returnObject); return returnObject; }