static List <Variable> Split(ParsingScript script, char[] to) { List <Variable> listToMerge = new List <Variable>(16); if (!script.StillValid() || to.Contains(script.Current)) { listToMerge.Add(Variable.EmptyInstance); script.Forward(); return(listToMerge); } int arrayIndexDepth = 0; bool inQuotes = false; int negated = 0; char ch; string action; do { // Main processing cycle of the first part. string token = ExtractNextToken(script, to, ref inQuotes, ref arrayIndexDepth, ref negated, out ch, out action); bool ternary = UpdateIfTernary(script, token, ch, listToMerge, (List <Variable> newList) => { listToMerge = newList; }); if (ternary) { return(listToMerge); } bool negSign = CheckConsistencyAndSign(script, listToMerge, action, ref token); // We are done getting the next token. The GetValue() call below may // recursively call SplitAndMerge(). This will happen if extracted // item is a function or if the next item is starting with a START_ARG '('. ParserFunction func = new ParserFunction(script, token, ch, ref action); Variable current = func.GetValue(script); if (UpdateResult(script, to, listToMerge, token, negSign, ref current, ref negated, ref action)) { return(listToMerge); } } while (script.StillValid() && (inQuotes || arrayIndexDepth > 0 || !to.Contains(script.Current))); // This happens when called recursively inside of the math expression: script.MoveForwardIf(Constants.END_ARG); return(listToMerge); }
public static void CheckNotEnd(ParsingScript script, string name) { if (!script.StillValid()) { string realName = Constants.GetRealName(name); throw new ArgumentException("Incomplete arguments for [" + realName + "]"); } }
public static void CheckNotEmpty(ParsingScript script, string varName, string name) { if (!script.StillValid() || string.IsNullOrWhiteSpace(varName)) { string realName = Constants.GetRealName(name); ThrowErrorMsg("Incomplete arguments for [" + realName + "].", script, name); } }
public static void CheckNotEnd(ParsingScript script, string name) { if (!script.StillValid()) { string realName = Constants.GetRealName(name); ThrowErrorMsg("Incomplete arguments for [" + realName + "]", script, script.Prev.ToString()); } }
public static string GetBodyBetween(ParsingScript script, char open = Constants.START_ARG, char close = Constants.END_ARG) { // We are supposed to be one char after the beginning of the string, i.e. // we must not have the opening char as the first one. StringBuilder sb = new StringBuilder(script.Size()); int braces = 0; bool inQuotes = false; bool inQuotes1 = false; bool inQuotes2 = false; bool checkBraces = true; char prev = Constants.EMPTY; char prevprev = Constants.EMPTY; for (; script.StillValid(); script.Forward()) { char ch = script.Current; if (close != Constants.QUOTE) { checkBraces = !inQuotes; if (ch == Constants.QUOTE && !inQuotes1 && (prev != '\\' || prevprev == '\\')) { inQuotes = inQuotes2 = !inQuotes2; } if (ch == Constants.QUOTE1 && !inQuotes2 && (prev != '\\' || prevprev == '\\')) { inQuotes = inQuotes1 = !inQuotes1; } } if (string.IsNullOrWhiteSpace(ch.ToString()) && sb.Length == 0) { continue; } else if (checkBraces && ch == open) { braces++; } else if (checkBraces && ch == close) { braces--; } sb.Append(ch); prevprev = prev; prev = ch; if (braces < 0) { if (ch == close) { sb.Remove(sb.Length - 1, 1); } break; } } return(sb.ToString()); }
private void SkipBlock(ParsingScript script) { int blockStart = script.Pointer; int startCount = 0; int endCount = 0; bool inQuotes = false; bool inQuotes1 = false; bool inQuotes2 = false; char previous = Constants.EMPTY; char prevprev = Constants.EMPTY; while (startCount == 0 || startCount > endCount) { if (!script.StillValid()) { throw new ArgumentException("Couldn't skip block [" + script.Substr(blockStart, Constants.MAX_CHARS_TO_SHOW) + "]"); } char currentChar = script.CurrentAndForward(); switch (currentChar) { case Constants.QUOTE1: if (!inQuotes2 && (previous != '\\' || prevprev == '\\')) { inQuotes = inQuotes1 = !inQuotes1; } break; case Constants.QUOTE: if (!inQuotes1 && (previous != '\\' || prevprev == '\\')) { inQuotes = inQuotes2 = !inQuotes2; } break; case Constants.START_GROUP: if (!inQuotes) { startCount++; } break; case Constants.END_GROUP: if (!inQuotes) { endCount++; } break; } prevprev = previous; previous = currentChar; } if (startCount != endCount) { throw new ArgumentException("Mismatched parentheses"); } }
static async Task <List <Variable> > SplitAsync(ParsingScript script, char[] to) { List <Variable> listToMerge = new List <Variable>(16); if (!script.StillValid() || to.Contains(script.Current)) { listToMerge.Add(Variable.EmptyInstance); script.Forward(); return(listToMerge); } int arrayIndexDepth = 0; bool inQuotes = false; int negated = 0; char ch; string action; do { // Main processing cycle of the first part. string token = ExtractNextToken(script, to, ref inQuotes, ref arrayIndexDepth, ref negated, out ch, out action); bool ternary = await UpdateIfTernaryAsync(script, token, ch, listToMerge, (List <Variable> newList) => { listToMerge = newList; }); if (ternary) { return(listToMerge); } bool negSign = CheckConsistencyAndSign(script, listToMerge, action, ref token); ParserFunction func = new ParserFunction(script, token, ch, ref action); Variable current = await func.GetValueAsync(script); if (UpdateResult(script, to, listToMerge, token, negSign, ref current, ref negated, ref action)) { return(listToMerge); } } while (script.StillValid() && (inQuotes || arrayIndexDepth > 0 || !to.Contains(script.Current))); // This happens when called recursively inside of the math expression: script.MoveForwardIf(Constants.END_ARG); return(listToMerge); }
public static string ExtractNextToken(ParsingScript script, char[] to, ref bool inQuotes, ref int arrayIndexDepth, ref int negated, out char ch, out string action, bool throwExc = true) { StringBuilder item = new StringBuilder(); ch = Constants.EMPTY; action = null; do { string negateSymbol = Utils.IsNotSign(script.Rest); if (negateSymbol != null && !inQuotes) { negated++; script.Forward(negateSymbol.Length); continue; } ch = script.CurrentAndForward(); CheckQuotesIndices(script, ch, ref inQuotes, ref arrayIndexDepth); bool keepCollecting = inQuotes || arrayIndexDepth > 0 || StillCollecting(item.ToString(), to, script, ref action); if (keepCollecting) { // The char still belongs to the previous operand. item.Append(ch); bool goForMore = script.StillValid() && (inQuotes || arrayIndexDepth > 0 || !to.Contains(script.Current)); if (goForMore) { continue; } } if (SkipOrAppendIfNecessary(item, ch, to)) { continue; } break; }while (true); string result = item.ToString(); result = result.Replace("\\\\", "\\"); result = result.Replace("\\\"", "\""); result = result.Replace("\\'", "'"); if (throwExc && string.IsNullOrWhiteSpace(result) && action != "++" && action != "--" && Utils.IsAction(script.Prev) && Utils.IsAction(script.PrevPrev)) { Utils.ThrowErrorMsg("Can't process token [" + script.PrevPrev + script.Prev + script.Current + "].", script, script.Current.ToString()); } return(result); }
// A "virtual" Constructor public ParserFunction(ParsingScript script, string item, char ch, ref string action) { if (item.Length == 0 && (ch == Constants.START_ARG || !script.StillValid())) { // There is no function, just an expression in parentheses m_impl = s_idFunction; return; } if (item.Length > 1 && ((item[0] == Constants.QUOTE && item[item.Length - 1] == Constants.QUOTE) || (item[0] == Constants.QUOTE1 && item[item.Length - 1] == Constants.QUOTE1))) { // We are dealing with a string. s_strOrNumFunction.Item = item; m_impl = s_strOrNumFunction; return; } item = Constants.ConvertName(item); m_impl = GetRegisteredAction(item, ref action); if (m_impl != null) { return; } m_impl = GetArrayFunction(item, script, action); if (m_impl != null) { return; } m_impl = GetObjectFunction(item, script); if (m_impl != null) { return; } m_impl = GetVariable(item, script); if (m_impl != null) { return; } if (m_impl == s_strOrNumFunction && string.IsNullOrWhiteSpace(item)) { string problem = (!string.IsNullOrWhiteSpace(action) ? action : ch.ToString()); string restData = ch.ToString() + script.Rest; throw new ArgumentException("Couldn't parse [" + problem + "] in " + restData + "..."); } // Function not found, will try to parse this as a string in quotes or a number. s_strOrNumFunction.Item = item; m_impl = s_strOrNumFunction; }
public static void SkipRestExpr(ParsingScript script) { int argRead = 0; bool inQuotes = false; char previous = Constants.EMPTY; while (script.StillValid()) { char currentChar = script.Current; if (inQuotes && currentChar != Constants.QUOTE) { script.Forward(); continue; } switch (currentChar) { case Constants.QUOTE: if (previous != '\\') { inQuotes = !inQuotes; } break; case Constants.START_ARG: argRead++; break; case Constants.END_ARG: argRead--; if (argRead < 0) { return; } break; case Constants.END_STATEMENT: return; case Constants.TERNARY_OPERATOR: case Constants.NEXT_ARG: if (argRead <= 0) { return; } break; default: break; } script.Forward(); previous = currentChar; } }
public static List <Variable> GetArgs(ParsingScript script, char start, char end, out bool isList) { List <Variable> args = new List <Variable>(); isList = script.StillValid() && script.Current == Constants.START_GROUP; if (!script.StillValid() || script.Current == Constants.END_STATEMENT) { return(args); } ParsingScript tempScript = new ParsingScript(script.String, script.Pointer); string body = Utils.GetBodyBetween(tempScript, start, end); string rest = script.Rest; // After the statement above tempScript.Parent will point to the last // character belonging to the body between start and end characters. while (script.Pointer < tempScript.Pointer) { Variable item = Utils.GetItem(script); args.Add(item); rest = script.Rest; if (script.Pointer == tempScript.Pointer) { rest = script.Rest; } script.MoveForwardIf(Constants.NEXT_ARG); } if (script.Pointer <= tempScript.Pointer) { // Eat closing parenthesis, if there is one, but only if it closes // the current argument list, not one after it. script.MoveForwardIf(Constants.END_ARG); } script.MoveForwardIf(Constants.SPACE); //script.MoveForwardIf(Constants.SPACE, Constants.END_STATEMENT); return(args); }
int GetCurrentLineNumber(ParsingScript script) { if (script == m_debugging && !m_debugging.StillValid()) { #if UNITY_EDITOR == false && UNITY_STANDALONE == false && __ANDROID__ == false && __IOS__ == false return(-1); #else return(-2); #endif } return(script.GetOriginalLineNumber()); }
private Variable ProcessBlock(ParsingScript script) { int blockStart = script.Pointer; Variable result = null; if (script.Debugger != null) { bool done = false; result = script.Debugger.DebugBlockIfNeeded(script, ref done); if (done) { return(result); } } while (script.StillValid()) { int endGroupRead = script.GoToNextStatement(); if (endGroupRead > 0 || !script.StillValid()) { return(result != null ? result : new Variable()); } /*if (!script.StillValid()) * { * throw new ArgumentException("Couldn't process block [" + * script.Substr(blockStart, Constants.MAX_CHARS_TO_SHOW) + "]"); * }*/ result = script.ExecuteTo(); if (result.IsReturn || result.Type == Variable.VarType.BREAK || result.Type == Variable.VarType.CONTINUE) { return(result); } } return(result); }
static Variable ExtractArray(ParsingScript script) { Variable newValue = new Variable(Variable.VarType.ARRAY); while (script.StillValid() && (newValue.Count == 0 || script.Current == ',')) { script.Forward(); Variable addVariable = ExtractValue(script); newValue.AddVariable(addVariable); } script.MoveForwardIf(']'); return(newValue); }
public static string ReplaceSpaces(ParsingScript script, char replaceChar = ',', char end = Constants.END_STATEMENT) { StringBuilder sb = new StringBuilder(); while (script.StillValid() && script.TryCurrent() != end) { var token = GetBodyBetween(script, '\0', ' ', end); sb.Append(token + replaceChar); } if (sb.Length > 0 && sb[sb.Length - 1] == replaceChar) { sb.Remove(sb.Length - 1, 1); } return(sb.ToString()); }
private Variable ProcessBlock(ParsingScript script) { int blockStart = script.Pointer; Variable result = null; while (script.StillValid()) { int endGroupRead = script.GoToNextStatement(); if (endGroupRead > 0 || !script.StillValid()) { return(result != null ? result : new Variable()); } result = script.Execute(); if (result.IsReturn || result.Type == Variable.VarType.BREAK || result.Type == Variable.VarType.CONTINUE) { return(result); } } return(result); }
private void SkipRestBlocks(ParsingScript script) { while (script.StillValid()) { int endOfToken = script.Pointer; ParsingScript nextData = new ParsingScript(script); string nextToken = Utils.GetNextToken(nextData); if (Constants.ELSE_IF != nextToken && Constants.ELSE != nextToken) { return; } script.Pointer = nextData.Pointer; SkipBlock(script); } }
static Variable ExtractObject(ParsingScript script) { Variable newValue = new Variable(Variable.VarType.ARRAY); while (script.StillValid() && (newValue.Count == 0 || script.Current == ',')) { script.Forward(); string key = Utils.GetToken(script, SEP); script.MoveForwardIf(':'); Variable valueVar = ExtractValue(script); newValue.SetHashVariable(key, valueVar); } script.MoveForwardIf('}'); return(newValue); }
public static string GetNextToken(ParsingScript script) { if (!script.StillValid()) { return(""); } int end = script.FindFirstOf(Constants.TOKEN_SEPARATION); if (end < 0) { return(""); } string var = script.Substr(script.Pointer, end - script.Pointer); script.Pointer = end; return(var); }
internal Variable ProcessSwitch(ParsingScript script) { Variable switchValue = Utils.GetItem(script); script.Forward(); Variable result = Variable.EmptyInstance; var caseSep = ":".ToCharArray(); bool caseDone = false; while (script.StillValid()) { var nextToken = Utils.GetBodySize(script, Constants.CASE, Constants.DEFAULT); if (string.IsNullOrEmpty(nextToken)) { break; } if (nextToken == Constants.DEFAULT && !caseDone) { result = ProcessBlock(script); break; } if (!caseDone) { Variable caseValue = script.Execute(caseSep); script.Forward(); if (switchValue.Type == caseValue.Type && switchValue.Equals(caseValue)) { caseDone = true; result = ProcessBlock(script); if (script.Prev == '}') { break; } script.Forward(); } } } script.MoveForwardIfNotPrevious('}'); script.GoToNextStatement(); return(result); }
private static string UpdateAction(ParsingScript script, char[] to) { // We search a valid action till we get to the End of Argument ')' // or pass the end of string. if (!script.StillValid() || script.Current == Constants.END_ARG || to.Contains(script.Current)) { return(Constants.NULL_ACTION); } string action = Utils.ValidAction(script.Rest); // We need to advance forward not only the action length but also all // the characters we skipped before getting the action. int advance = action == null ? 0 : action.Length; script.Forward(advance); return(action == null ? Constants.NULL_ACTION : action); }
public static string GetBodyBetween(ParsingScript script, char open, char close) { // We are supposed to be one char after the beginning of the string, i.e. // we must not have the opening char as the first one. StringBuilder sb = new StringBuilder(script.Size()); int braces = 0; for (; script.StillValid(); script.Forward()) { char ch = script.Current; if (string.IsNullOrWhiteSpace(ch.ToString()) && sb.Length == 0) { continue; } else if (ch == open) { braces++; } else if (ch == close) { braces--; } sb.Append(ch); if (braces == -1) { if (ch == close) { sb.Remove(sb.Length - 1, 1); } break; } } return(sb.ToString()); }
bool Completed(ParsingScript debugging) { return((LastResult != null && LastResult.IsReturn) || !debugging.StillValid()); }
public static void PreprocessScript(ParsingScript script) { script.Pointer = 0; int nestedLevel = 0; int functionNestedLevel = 0; int pointerOffset = 0; string currentFunction = ""; string prevToken = ""; bool inQuotes = false; int negated = 0; int arrayIndexDepth = 0; if (script.AllLabels == null) { script.AllLabels = new Dictionary <string, Dictionary <string, int> >(); } if (script.LabelToFile == null) { script.LabelToFile = new Dictionary <string, string>(); } while (script.StillValid()) { char ch = script.Current; if (ch == '{') { nestedLevel++; script.Forward(); continue; } else if (ch == '}') { nestedLevel--; if (nestedLevel <= functionNestedLevel) { currentFunction = ""; pointerOffset = 0; } script.Forward(); continue; } else if (ch == ':' && !string.IsNullOrWhiteSpace(prevToken)) { script.Forward(); Dictionary <string, int> labels; if (!script.AllLabels.TryGetValue(currentFunction, out labels)) { labels = new Dictionary <string, int>(); } labels[prevToken] = script.Pointer + 1 - pointerOffset; script.AllLabels[currentFunction] = labels; script.LabelToFile[prevToken] = script.Filename; continue; } try { string token = Parser.ExtractNextToken(script, Constants.TOKEN_SEPARATION, ref inQuotes, ref arrayIndexDepth, ref negated, out _, out _, false); if (token == Constants.FUNCTION) { script.Forward(); currentFunction = Utils.GetToken(script, Constants.TOKEN_SEPARATION); currentFunction = Constants.ConvertName(currentFunction); functionNestedLevel = nestedLevel; var sig = Utils.GetFunctionSignature(script); pointerOffset = script.Pointer + (currentFunction == "" ? 1 : 2); } prevToken = token; } catch (Exception exc) { Console.WriteLine(exc.Message); script.Forward(); } } script.Pointer = 0; }
protected override Variable Evaluate(ParsingScript script) { string dirname = (!script.StillValid() || script.Current == Constants.END_STATEMENT) ? Directory.GetCurrentDirectory() : Utils.GetToken(script, Constants.NEXT_OR_END_ARRAY); //List<Variable> results = Utils.GetPathnames(dirname); List <Variable> results = new List <Variable>(); int index = dirname.IndexOf('*'); if (index < 0 && !Directory.Exists(dirname) && !File.Exists(dirname)) { throw new ArgumentException("Directory [" + dirname + "] doesn't exist"); } string pattern = Constants.ALL_FILES; try { string dir = index < 0 ? Path.GetFullPath(dirname) : dirname; if (File.Exists(dir)) { FileInfo fi = new FileInfo(dir); Interpreter.Instance.AppendOutput(Utils.GetPathDetails(fi, fi.Name), true); results.Add(new Variable(fi.Name)); return(new Variable(results)); } // Special dealing if there is a pattern (only * is supported at the moment) if (index >= 0) { pattern = Path.GetFileName(dirname); if (index > 0) { string prefix = dirname.Substring(0, index); DirectoryInfo di = Directory.GetParent(prefix); dirname = di.FullName; } else { dirname = "."; } } dir = Path.GetFullPath(dirname); // First get contents of the directory (unless there is a pattern) DirectoryInfo dirInfo = new DirectoryInfo(dir); if (pattern == Constants.ALL_FILES) { Interpreter.Instance.AppendOutput(Utils.GetPathDetails(dirInfo, "."), true); if (dirInfo.Parent != null) { Interpreter.Instance.AppendOutput(Utils.GetPathDetails(dirInfo.Parent, ".."), true); } } // Then get contents of all of the files in the directory FileInfo[] fileNames = dirInfo.GetFiles(pattern); foreach (FileInfo fi in fileNames) { try { Interpreter.Instance.AppendOutput(Utils.GetPathDetails(fi, fi.Name), true); results.Add(new Variable(fi.Name)); } catch (Exception) { continue; } } // Then get contents of all of the subdirs in the directory DirectoryInfo[] dirInfos = dirInfo.GetDirectories(pattern); foreach (DirectoryInfo di in dirInfos) { try { Interpreter.Instance.AppendOutput(Utils.GetPathDetails(di, di.Name), true); results.Add(new Variable(di.Name)); } catch (Exception) { continue; } } } catch (Exception exc) { throw new ArgumentException("Couldn't list directory: " + exc.Message); } return(new Variable(results)); }
private static List <Variable> Split(ParsingScript script, char[] to) { List <Variable> listToMerge = new List <Variable>(16); if (!script.StillValid() || to.Contains(script.Current)) { listToMerge.Add(Variable.EmptyInstance); script.Forward(); return(listToMerge); } StringBuilder item = new StringBuilder(); int arrayIndexDepth = 0; bool inQuotes = false; int negated = 0; string rest = script.Rest; //if (rest == "b[a[0]];") { // int stop = 1; //} do // Main processing cycle of the first part. { string negateSymbol = Utils.IsNotSign(script.Rest); if (negateSymbol != null && !inQuotes) { negated++; script.Forward(negateSymbol.Length); continue; } char ch = script.CurrentAndForward(); CheckQuotesIndices(script, ch, ref inQuotes, ref arrayIndexDepth); string action = null; bool keepCollecting = inQuotes || arrayIndexDepth > 0 || StillCollecting(item.ToString(), to, script, ref action); if (keepCollecting) { // The char still belongs to the previous operand. item.Append(ch); bool goForMore = script.StillValid() && (inQuotes || arrayIndexDepth > 0 || !to.Contains(script.Current)); if (goForMore) { continue; } } if (SkipOrAppendIfNecessary(item, ch, to)) { continue; } string token = item.ToString(); bool ternary = UpdateIfTernary(script, token, ch, ref listToMerge); if (ternary) { return(listToMerge); } CheckConsistency(token, listToMerge, script); script.MoveForwardIf(Constants.SPACE); if (action != null && action.Length > 1) { script.Forward(action.Length - 1); } // We are done getting the next token. The getValue() call below may // recursively call loadAndCalculate(). This will happen if extracted // item is a function or if the next item is starting with a START_ARG '('. ParserFunction func = new ParserFunction(script, token, ch, ref action); Variable current = func.GetValue(script); current.ParsingToken = token; if (negated > 0 && current.Type == Variable.VarType.NUMBER) { // If there has been a NOT sign, this is a boolean. // Use XOR (true if exactly one of the arguments is true). bool neg = !((negated % 2 == 0) ^ Convert.ToBoolean(current.Value)); current = new Variable(Convert.ToDouble(neg)); negated = 0; } if (action == null) { action = UpdateAction(script, to); } else { script.MoveForwardIf(action[0]); } char next = script.TryCurrent(); // we've already moved forward bool done = listToMerge.Count == 0 && (next == Constants.END_STATEMENT || (action == Constants.NULL_ACTION && current.Type != Variable.VarType.NUMBER) || current.IsReturn); if (done) { if (action != null && action != Constants.END_ARG_STR) { throw new ArgumentException("Action [" + action + "] without an argument."); } // If there is no numerical result, we are not in a math expression. listToMerge.Add(current); return(listToMerge); } Variable cell = current.Clone(); cell.Action = action; bool addIt = UpdateIfBool(script, ref cell, ref listToMerge); if (addIt) { listToMerge.Add(cell); } item.Clear(); } while (script.StillValid() && (inQuotes || arrayIndexDepth > 0 || !to.Contains(script.Current))); // This happens when called recursively inside of the math expression: script.MoveForwardIf(Constants.END_ARG); return(listToMerge); }