/// <summary> /// Attempt to evaluate token as a bool, int, etc. /// Returns null if it fails /// </summary> internal static Value DoNoThrow(Token token) { string s = token.Value; // try as nil if (s == "nil") return new ValueNil(); // try as bool if (s == "true") return new ValueBool(true); if (s == "false") return new ValueBool(false); // try as int int i; if (Int32.TryParse(s, out i)) return new ValueInt(i); // try as float double d; if (Double.TryParse(s, out d)) return new ValueFloat(d); // try as string // todo: replace with a prefix definition in bootstrap if (s.StartsWith(":")) return new ValueString(s.Substring(1)); if (s.StartsWith("->")) return new ValueString(s.Substring(2)); // give up return null; }
/// <summary> /// Attempt to evaluate token as a bool, int, etc. May throw. /// </summary> internal static Value Do(Token token) { Value v = DoNoThrow(token); if (v == null) throw new Loki3Exception().AddBadToken(token); return v; }
public Value GetValue(Token token) { Value val; if (m_values.TryGetValue(token.Value, out val)) return val; return (m_parent != null ? m_parent.GetValue(token) : null); }
internal DelimiterNodeToken(Token token) { m_token = token; }
/// <summary>If :key is present, lookup value, else if :value is present, return value.</summary> internal static Value GetFromKeyOrValue(Map map, IScope scope) { // either lookup up value w/ specified key or just get specified value Value value = null; Value key = map["key"]; if (key != ValueNil.Nil) { Token token = new Token(key.AsString); value = scope.GetValue(token); if (value == null) throw new Loki3Exception().AddBadToken(token); } else if (map.ContainsKey("value")) { value = map["value"]; } if (value == null) // todo: better error throw new Loki3Exception().AddMissingKey(new ValueString("key or value required")); return value; }
/// <summary>Could not parse token</summary> internal Loki3Exception AddBadToken(Token token) { m_map[keyBadToken] = new ValueString(token.Value); return this; }
// simply search for end and stuff everything in the middle into a single token private static bool ParseString(int indent, string[] strs, int iStart, ValueDelimiter thisDelim, List<DelimiterNode> nodes, out int iEnd, out DelimiterList result) { iEnd = -1; bool bExtra = false; for (int i = iStart; i < strs.Length; i++) { string s = strs[i]; if (s == thisDelim.End) { iEnd = i; break; } else if (s.Substring(s.Length - 1, 1) == thisDelim.End) { iEnd = i + 1; bExtra = true; break; } } // no specified end delim means take the remainder of the line if (thisDelim.End == "") iEnd = strs.Length; // if we found end, wrap entire string in a single node if (iEnd != -1) { string subStr = GetSubStr(iStart, iEnd, strs); if (bExtra) { subStr = subStr.Substring(0, subStr.Length - 1); --iEnd; } Token token = new Token(subStr); DelimiterNode node = new DelimiterNodeToken(token); nodes.Add(node); result = new DelimiterList(thisDelim, nodes, indent, strs[iStart - 1], subStr, null); return true; } result = null; return false; }
// handle as individual tokens and nested lists private static bool ParseMisc(int indent, string original, string[] strs, int iStart, ValueDelimiter thisDelim, IParseLineDelimiters delims, ILineRequestor requestor, List<DelimiterNode> nodes, out int iEnd, out DelimiterList result) { result = null; iEnd = strs.Length; for (int i = iStart; i < strs.Length; i++) { string s = strs[i]; // is this the end of current set of delimited tokens? if (s == thisDelim.End) { // end delimiter iEnd = i; string subStr = GetSubStr(iStart, iEnd, strs); result = new DelimiterList(thisDelim, nodes, indent, strs[iStart - 1], subStr, null); return true; } // TODO: rework this so I don't need to check for : (e.g. for :}, when creating a delim) if (s.Substring(s.Length - 1, 1) == thisDelim.End && (s[0] != ':' || s.Length > 2)) { // end delimiter is part of final token iEnd = i + 1; string without = s.Substring(0, s.Length - 1); Token token = new Token(without); DelimiterNode node = new DelimiterNodeToken(token); nodes.Add(node); strs[i] = without; string subStr = GetSubStr(iStart, iEnd, strs); result = new DelimiterList(thisDelim, nodes, indent, strs[iStart - 1], subStr, null); strs[i] = s; --iEnd; return true; } // is it a stand alone starting delimiter? bool bAnyToken = false; ValueDelimiter subDelim = (delims == null ? null : delims.GetDelim(s, out bAnyToken)); string[] strsToUse = strs; bool bExtra = true; if (subDelim == null && !bAnyToken) { // whole thing wasn't a delimiter, function, etc., how about the 1st char? string s1 = s.Substring(0, 1); subDelim = (delims == null ? null : delims.GetDelim(s1, out bAnyToken)); if (subDelim != null) { // copy across array, but break iStart into delim & remainder bExtra = false; strsToUse = new string[strs.Length + 1]; for (int j = 0; j < i; j++) strsToUse[j] = strs[j]; strsToUse[i] = s1; strsToUse[i + 1] = s.Substring(1); for (int j = i + 1; j < strs.Length; j++) strsToUse[j + 1] = strs[j]; } } if (subDelim != null) { // start delimiter int end; DelimiterList sublist = Do(0, original, strsToUse, i + 1, subDelim, delims, requestor, out end); if (sublist != null) { DelimiterNodeList node = new DelimiterNodeList(sublist); nodes.Add(node); } // skip past the sublist i = (bExtra ? end : end - 1); } else { // stand alone token Token token = new Token(s); DelimiterNode node = new DelimiterNodeToken(token); nodes.Add(node); } } return false; }