public Variable(string markup) { _markup = markup; Name = null; Filters = new List <Filter>(); Match match = MyRegex.Match(markup, string.Format(R.Q(@"\s*({0})(.*)"), Liquid.QuotedAssignFragment)); if (match.Success) { Name = match.Groups[1].Value; Match filterMatch = MyRegex.Match(match.Groups[2].Value, string.Format(R.Q(@"{0}\s*(.*)"), Liquid.FilterSeparator)); if (filterMatch.Success) { foreach (string f in R.Scan(filterMatch.Value, FilterParser)) { Match filterNameMatch = MyRegex.Match(f, R.Q(@"\s*(\w+)")); if (filterNameMatch.Success) { string filterName = filterNameMatch.Groups[1].Value; List <string> filterArgs = R.Scan(f, string.Format(R.Q(@"(?:{0}|{1})\s*({2})"), Liquid.FilterArgumentSeparator, Liquid.ArgumentSeparator, Liquid.QuotedFragment)); Filters.Add(new Filter(filterName, filterArgs.ToArray())); } } } } }
/// <summary> /// Look up variable, either resolve directly after considering the name. We can directly handle /// Strings, digits, floats and booleans (true,false). If no match is made we lookup the variable in the current scope and /// later move up to the parent blocks to see if we can resolve the variable somewhere up the tree. /// Some special keywords return symbols. Those symbols are to be called on the rhs object in expressions /// /// Example: /// /// products == empty #=> products.empty? /// </summary> /// <param name="key"></param> /// <returns></returns> private object Resolve(string key) { switch (key) { case null: case "nil": case "null": case "": return(null); case "true": return(true); case "false": return(false); case "blank": return(new Symbol(o => o is IEnumerable && !((IEnumerable)o).Cast <object>().Any())); case "empty": return(new Symbol(o => o is IEnumerable && !((IEnumerable)o).Cast <object>().Any())); } // Single quoted strings. Match match = MyRegex.Match(key, R.Q(@"^'(.*)'$")); if (match.Success) { return(match.Groups[1].Value); } // Double quoted strings. match = MyRegex.Match(key, R.Q(@"^""(.*)""$")); if (match.Success) { return(match.Groups[1].Value); } // Integer. match = MyRegex.Match(key, R.Q(@"^([+-]?\d+)$")); if (match.Success) { return(Convert.ToInt32(match.Groups[1].Value)); } // Ranges. match = MyRegex.Match(key, R.Q(@"^\((\S+)\.\.(\S+)\)$")); if (match.Success) { return(Range.Inclusive(Convert.ToInt32(Resolve(match.Groups[1].Value)), Convert.ToInt32(Resolve(match.Groups[2].Value)))); } // Floats. match = MyRegex.Match(key, R.Q(@"^([+-]?\d[\d\.|\,]+)$")); if (match.Success) { // For cultures with "," as the decimal separator, allow // both "," and "." to be used as the separator. // First try to parse using current culture. float result; if (float.TryParse(match.Groups[1].Value, out result)) { return(result); } // If that fails, try to parse using invariant culture. return(float.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture)); } return(Variable(key)); }