CodeStatement[] ParseFlow(List <CodeLine> lines, int index) { #region Variables var line = lines[index]; string code = line.Code.TrimStart(Spaces); string[] parts = { string.Empty, string.Empty }; var delimiters = new char[Spaces.Length + 1]; delimiters[0] = Multicast; Spaces.CopyTo(delimiters, 1); int[] d = { code.IndexOfAny(delimiters), code.IndexOfAny(new[] { BlockOpen, ParenOpen }) }; if (d[0] == -1 && d[1] == -1) { parts[0] = code; } else if (d[1] != -1 && (d[1] < d[0] || d[0] == -1)) { parts[0] = code.Substring(0, d[1]); parts[1] = code.Substring(d[1], code.Length - d[1]).TrimStart(Spaces); } else { parts[0] = code.Substring(0, d[0]); parts[1] = code.Substring(d[0] + 1, code.Length - d[0] - 1).TrimStart(Spaces); } if (parts.Length > 1 && IsEmptyStatement(parts[1])) { parts = new[] { parts[0] } } ; #endregion switch (parts[0].ToLowerInvariant()) { #region If/Else case FlowIf: { if (parts.Length < 1) { throw new ParseException("If requires a parameter"); } bool blockOpen = false; CodeExpression condition = ParseFlowParameter(parts[1], true, out blockOpen, false); var ifelse = new CodeConditionStatement { Condition = condition }; var block = new CodeBlock(line, Scope, ifelse.TrueStatements, CodeBlock.BlockKind.IfElse, blocks.Count == 0 ? null : blocks.Peek()); block.Type = blockOpen ? CodeBlock.BlockType.Within : CodeBlock.BlockType.Expect; CloseTopSingleBlock(); blocks.Push(block); elses.Push(ifelse.FalseStatements); return(new CodeStatement[] { ifelse }); } case FlowElse: { if (elses.Count == 0) { throw new ParseException("Else with no preceeding if block"); } string next = line.Code.TrimStart(Spaces).Substring(FlowElse.Length).TrimStart(Spaces); if (!IsEmptyStatement(next)) { lines.Insert(index + 1, new CodeLine(lines[index].FileName, lines[index].LineNumber, next)); } var type = parts.Length > 1 && parts[1][0] == BlockOpen ? CodeBlock.BlockType.Within : CodeBlock.BlockType.Expect; var block = new CodeBlock(lines[index], Scope, elses.Pop(), CodeBlock.BlockKind.IfElse, blocks.Count == 0 ? null : blocks.Peek()) { Type = type }; CloseTopSingleBlock(); blocks.Push(block); } break; #endregion #region Goto case FlowGosub: { if (parts.Length < 1) { throw new ParseException("No label specified"); } return(new CodeStatement[] { new CodeExpressionStatement(LocalLabelInvoke(parts[1])) }); } case FlowGoto: { if (parts.Length < 1) { throw new ParseException("No label specified"); } return(new CodeStatement[] { new CodeExpressionStatement(LocalLabelInvoke(parts[1])), new CodeMethodReturnStatement() }); } #endregion #region Loops case FlowLoop: { bool blockOpen = false; CodeMethodInvokeExpression iterator; bool skip = true; bool checkBrace = true; bool byref = false; #region Loop types if (parts.Length > 1) { string[] sub = parts[1].Split(new[] { Multicast }, 2); sub = new[] { sub[0].Trim(), sub.Length > 1 ? sub[1].Trim() : string.Empty }; switch (sub[0].ToUpperInvariant()) { case "READ": byref = true; iterator = (CodeMethodInvokeExpression)InternalMethods.LoopRead; break; case "PARSE": checkBrace = false; byref = true; iterator = (CodeMethodInvokeExpression)InternalMethods.LoopParse; break; case "HKEY_LOCAL_MACHINE": case "HKLM": case "HKEY_USERS": case "HKU": case "HKEY_CURRENT_USER": case "HKCU": case "HKEY_CLASSES_ROOT": case "HKCR": case "HKEY_CURRENT_CONFIG": case "HKCC": iterator = (CodeMethodInvokeExpression)InternalMethods.LoopRegistry; break; case "EACH": byref = true; iterator = (CodeMethodInvokeExpression)InternalMethods.LoopEach; break; default: { var file = false; if (parts[1].IndexOf(Multicast) != -1) { file = true; } // TODO: check file/iteration loop types skip = false; iterator = (CodeMethodInvokeExpression)(file ? InternalMethods.LoopFile : InternalMethods.Loop); } break; } if (skip) { parts[1] = sub[1]; } if (checkBrace) { // TODO: check expression parameters before stripping comments int x = parts.Length == 1 ? 0 : 1; string part = StripComment(parts[x]).TrimEnd(Spaces); int l = part.Length - 1; if (part.Length > 0 && part[l] == BlockOpen) { blockOpen = true; parts[x] = part.Substring(0, l); } } if (skip && parts[1].Length == 0) { throw new ParseException("Loop type must have an argument"); } foreach (var arg in SplitCommandParameters(parts[1])) { iterator.Parameters.Add(ParseCommandParameter(arg)); } if (LegacyLoop && byref) { iterator.Parameters[0] = VarId(iterator.Parameters[0]); } } else { iterator = (CodeMethodInvokeExpression)InternalMethods.Loop; iterator.Parameters.Add(new CodePrimitiveExpression(int.MaxValue)); } #endregion string id = InternalID; var init = new CodeVariableDeclarationStatement(); init.Name = id; init.Type = new CodeTypeReference(typeof(IEnumerable)); init.InitExpression = new CodeMethodInvokeExpression(iterator, "GetEnumerator", new CodeExpression[] { }); var condition = new CodeMethodInvokeExpression(); condition.Method.TargetObject = new CodeVariableReferenceExpression(id); condition.Method.MethodName = "MoveNext"; var loop = new CodeIterationStatement(); loop.InitStatement = init; loop.IncrementStatement = new CodeCommentStatement(string.Empty); // for C# display loop.TestExpression = condition; var block = new CodeBlock(line, Scope, loop.Statements, CodeBlock.BlockKind.Loop, blocks.Count == 0 ? null : blocks.Peek(), InternalID, InternalID); block.Type = blockOpen ? CodeBlock.BlockType.Within : CodeBlock.BlockType.Expect; CloseTopSingleBlock(); blocks.Push(block); return(new CodeStatement[] { loop, new CodeLabeledStatement(block.ExitLabel) }); } case FlowWhile: { bool blockOpen = false; CodeExpression condition = parts.Length > 1 ? ParseFlowParameter(parts[1], true, out blockOpen, true) : new CodePrimitiveExpression(true); var loop = new CodeIterationStatement(); loop.TestExpression = condition; loop.InitStatement = new CodeCommentStatement(string.Empty); var block = new CodeBlock(line, Scope, loop.Statements, CodeBlock.BlockKind.Loop, blocks.Count == 0 ? null : blocks.Peek(), InternalID, InternalID); block.Type = blockOpen ? CodeBlock.BlockType.Within : CodeBlock.BlockType.Expect; CloseTopSingleBlock(); blocks.Push(block); return(new CodeStatement[] { loop, new CodeLabeledStatement(block.ExitLabel) }); } case FlowBreak: int b = 1; if (parts.Length > 1) { parts[1] = StripCommentSingle(parts[1]); if (!int.TryParse(parts[1], out b) || b < 1) { throw new ParseException("Break parameter must be a static integer greater than zero."); } } string exit = PeekLoopLabel(true, b); if (exit == null) { throw new ParseException("Cannot break outside a loop"); } return(new CodeStatement[] { new CodeGotoStatement(exit) }); case FlowContinue: int c = 1; if (parts.Length > 1) { parts[1] = StripCommentSingle(parts[1]); if (!int.TryParse(parts[1], out c) || c < 1) { throw new ParseException("Continue parameter must be a static integer greater than zero."); } } string cont = PeekLoopLabel(false, c); if (cont == null) { throw new ParseException("Cannot continue outside a loop"); } return(new CodeStatement[] { new CodeGotoStatement(cont) }); #endregion #region Return case FlowReturn: if (Scope == mainScope) { if (parts.Length > 1) { throw new ParseException("Cannot have return parameter for entry point method"); } return(new CodeStatement[] { new CodeMethodReturnStatement() }); } else { var result = parts.Length > 1 ? ParseSingleExpression(parts[1]) : new CodePrimitiveExpression(null); return(new CodeStatement[] { new CodeMethodReturnStatement(result) }); } #endregion #region Function case FunctionLocal: case FunctionGlobal: case FunctionStatic: // TODO: function local/global/static scoping modifiers break; #endregion default: throw new ParseException(ExUnexpected); } return(null); } #region Parameters CodeExpression ParseFlowParameter(string code, bool inequality, out bool blockOpen, bool expr) { blockOpen = false; code = code.Trim(Spaces); if (code.Length == 0) { return(new CodePrimitiveExpression(false)); } if (LaxExpressions && IsLegacyIf(code)) { return(ParseLegacyIf(code)); } else if (expr || IsExpressionIf(code)) { code = StripComment(code).TrimEnd(Spaces); int l = code.Length - 1; if (code.Length > 0 && code[l] == BlockOpen) { blockOpen = true; code = code.Substring(0, l); } this.blockOpen = false; var result = ParseSingleExpression(code); blockOpen = blockOpen || this.blockOpen; var iftest = (CodeMethodInvokeExpression)InternalMethods.IfElse; iftest.Parameters.Add(result); return(iftest); } else if (LegacyIf) { code = StripCommentSingle(code); if (inequality) { return(ParseInequality(code)); } object result; if (IsPrimativeObject(code, out result)) { return(new CodePrimitiveExpression(result)); } else { throw new ParseException(ExUnexpected); } } else { throw new ParseException("Invalid arguments for if statement"); } } CodeExpression ParseInequality(string code) { var buf = new StringBuilder(code.Length); int i = 0; while (i < code.Length && IsSpace(code[i])) { i++; } while (i < code.Length && (IsIdentifier(code[i]) || code[i] == Resolve)) { buf.Append(code[i++]); } while (i < code.Length && IsSpace(code[i])) { i++; } if (i != code.Length) // if test argument is not a lone identifier then it is an expression { var op = new[] { Equal, Not, Greater, Less }; if (Array.IndexOf(op, code[i]) == -1) { throw new ParseException(ExUnexpected); } buf.Append(code[i++]); if (i < code.Length && Array.IndexOf(op, code[i]) != -1) { buf.Append(code[i++]); } buf.Append(StringBound); while (i < code.Length && IsSpace(code[i])) { i++; } if (i < code.Length) { string str = code.Substring(i); str = str.Replace(StringBound.ToString(), new string(StringBound, 2)); buf.Append(str); } while (i < code.Length && IsSpace(code[i])) { i++; } buf.Append(StringBound); } var iftest = (CodeMethodInvokeExpression)InternalMethods.IfElse; var expr = ParseSingleExpression(buf.ToString()); iftest.Parameters.Add(expr); return(iftest); } CodeExpression ParseLegacyIf(string code) { string[] parts = code.TrimStart(Spaces).Split(Spaces, 3); if (parts.Length != 3) { throw new ArgumentOutOfRangeException(); } if (!IsIdentifier(parts[0])) { throw new ArgumentException(); } bool not = false; if (parts[1].Equals(NotTxt, StringComparison.OrdinalIgnoreCase)) { not = false; string[] sub = parts[2].Split(Spaces, 2); parts[1] = sub[0]; parts[2] = sub[1]; } var invoke = (CodeMethodInvokeExpression)InternalMethods.IfLegacy; invoke.Parameters.Add(VarId(parts[0])); parts[1] = parts[1].ToLowerInvariant(); switch (parts[1]) { case BetweenTxt: case InTxt: case ContainsTxt: case IsTxt: invoke.Parameters.Add(new CodePrimitiveExpression(parts[1])); break; default: throw new ArgumentOutOfRangeException(); } invoke.Parameters.Add(ParseCommandParameter(parts[2])); if (not) { var flip = (CodeMethodInvokeExpression)InternalMethods.OperateUnary; flip.Parameters.Add(OperatorAsFieldReference(Script.Operator.BitwiseNot)); flip.Parameters.Add(invoke); invoke = flip; } return(invoke); } #endregion }
void Translate(ref string code) { #region Variables var delim = new char[Spaces.Length + 1]; delim[0] = Multicast; Spaces.CopyTo(delim, 1); int z = code.IndexOfAny(delim); string cmd, param; if (z == -1) { cmd = code; param = string.Empty; } else { cmd = code.Substring(0, z); param = code.Substring(z).TrimStart(delim); } var replaced = new StringBuilder(code.Length); #endregion #region Parameters string[] parts = SplitCommandParameters(param); if (parts.Length > 0) { parts[parts.Length - 1] = StripCommentSingle(parts[parts.Length - 1]); } for (int i = 0; i < parts.Length; i++) { if (IsExpressionParameter(parts[i])) { int e = parts[i].IndexOf(Resolve) + 1; if (e < parts[i].Length) { parts[i] = parts[i].Substring(e); } else { parts[i] = new string(StringBound, 2); } } else { parts[i] = parts[i].TrimStart(Spaces); int l = parts[i].Length; if (l > 1 && parts[i][0] == Resolve && parts[i][l - 1] == Resolve) { parts[i] = parts[i].Substring(1, l - 2); } else { string str = StringBound.ToString(); parts[i] = string.Concat(str, parts[i], str); } } } #endregion switch (cmd.ToLowerInvariant()) { #region Repeat case "repeat": param = StripCommentSingle(param); if (param.Length > 0 && !IsPrimativeObject(param)) { param = string.Empty; } replaced.Append("Loop "); replaced.Append(param); replaced.Append(SingleSpace); replaced.Append(BlockOpen); break; case "endrepeat": replaced.Append(BlockClose); replaced.Append(param); break; #endregion #region Setters case "setbatchlines": case "setcontroldelay": case "setdefaultmousespeed": case "setkeydelay": case "setmousedelay": case "setstorecapslockmode": case "settitlematchmode": case "setwindelay": case "setworkingdir": replaced.Append("A_"); replaced.Append(cmd, 3, cmd.Length - 3); replaced.Append(Equal); replaced.Append(param); break; case "setenv": replaced.Append(parts[0].Substring(1, parts[0].Length - 2)); replaced.Append(AssignPre); replaced.Append(Equal); if (parts.Length > 1) { replaced.Append(parts[1]); } else { replaced.Append(NullTxt); } break; case "setformat": if (parts.Length != 2) { throw new ParseException(ExTooFewParams); } replaced.Append("A_Format"); const string fast = "fast"; parts[0] = parts[0].Substring(1, parts[0].Length - 2); if (parts[0].EndsWith(fast, System.StringComparison.OrdinalIgnoreCase)) { parts[0] = parts[0].Substring(0, parts[0].Length - fast.Length); } replaced.Append(parts[0]); replaced.Append(AssignPre); replaced.Append(Equal); replaced.Append(parts[1]); break; case "autotrim": case "detecthiddentext": case "detecthiddenwindows": case "stringcasesense": replaced.Append("A_"); replaced.Append(cmd); replaced.Append(Equal); replaced.Append(param); break; #endregion #region If #region Equality // TODO: push single conditional command on same line as legacy converted equality-if statements case "ifequal": if (parts.Length < 1) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(parts[0]); replaced.Append(Equal); if (parts.Length > 1) { replaced.Append(parts[1]); } break; case "ifnotequal": if (parts.Length < 1) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(parts[0]); replaced.Append(Not); replaced.Append(Equal); if (parts.Length > 1) { replaced.Append(parts[1]); } break; case "ifgreater": if (parts.Length < 1) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(parts[0]); replaced.Append(Greater); if (parts.Length > 1) { replaced.Append(parts[1]); } break; case "ifgreaterorequal": if (parts.Length < 1) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(parts[0]); replaced.Append(Greater); replaced.Append(Equal); if (parts.Length > 1) { replaced.Append(parts[1]); } break; case "ifless": if (parts.Length < 1) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(parts[0]); replaced.Append(Less); if (parts.Length > 1) { replaced.Append(parts[1]); } break; case "iflessorequal": if (parts.Length < 1) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(parts[0]); replaced.Append(Less); replaced.Append(Equal); if (parts.Length > 1) { replaced.Append(parts[1]); } break; #endregion case "ifexist": if (parts.Length < 1) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(ParenOpen); replaced.Append("FileExist"); replaced.Append(ParenOpen); replaced.Append(parts[0]); replaced.Append(ParenClose, 2); break; case "ifnotexist": if (parts.Length < 1) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(ParenOpen); replaced.Append(Not); replaced.Append("FileExist"); replaced.Append(ParenOpen); replaced.Append(parts[0]); replaced.Append(ParenClose, 2); break; case "ifinstring": if (parts.Length < 2) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(ParenOpen); replaced.Append("InStr"); replaced.Append(ParenOpen); replaced.Append(parts[0]); replaced.Append(Multicast); replaced.Append(parts[1]); replaced.Append(ParenClose, 2); break; case "ifnotinstring": if (parts.Length < 2) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(ParenOpen); replaced.Append(Not); replaced.Append("InStr"); replaced.Append(ParenOpen); replaced.Append(parts[0]); replaced.Append(Multicast); replaced.Append(parts[1]); replaced.Append(ParenClose, 2); break; case "ifmsgbox": if (parts.Length < 1) { throw new ParseException(ExTooFewParams); } replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(ParenOpen); replaced.Append("A_MsgBox"); replaced.Append(Equal); replaced.Append(parts[0]); replaced.Append(ParenClose); break; case "ifwinactive": replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(ParenOpen); replaced.Append("WinActive"); replaced.Append(ParenOpen); foreach (var part in parts) { replaced.Append(part); replaced.Append(Multicast); } if (parts.Length > 1) { replaced.Remove(replaced.Length - 1, 1); } replaced.Append(ParenClose, 2); break; case "ifwinexist": replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(ParenOpen); replaced.Append("WinExist"); replaced.Append(ParenOpen); foreach (var part in parts) { replaced.Append(part); replaced.Append(Multicast); } if (parts.Length > 1) { replaced.Remove(replaced.Length - 1, 1); } replaced.Append(ParenClose, 2); break; case "ifwinnotactive": replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(ParenOpen); replaced.Append(Not); replaced.Append("WinActive"); replaced.Append(ParenOpen); foreach (var part in parts) { replaced.Append(part); replaced.Append(Multicast); } if (parts.Length > 1) { replaced.Remove(replaced.Length - 1, 1); } replaced.Append(ParenClose, 2); break; case "ifwinnotexist": replaced.Append(FlowIf); replaced.Append(SingleSpace); replaced.Append(ParenOpen); replaced.Append(Not); replaced.Append("WinExist"); replaced.Append(ParenOpen); foreach (var part in parts) { replaced.Append(part); replaced.Append(Multicast); } if (parts.Length > 1) { replaced.Remove(replaced.Length - 1, 1); } replaced.Append(ParenClose, 2); break; #endregion #region Strings // HACK: convert L/R paramter for legacy StringGetPos command case "stringgetpos": if (parts.Length < 3) { throw new ParseException(ExTooFewParams); } replaced.Append(parts[0].Trim(StringBound)); replaced.Append(AssignPre); replaced.Append(Equal); replaced.Append("InStr"); replaced.Append(ParenOpen); replaced.Append(parts[1]); replaced.Append(Multicast); replaced.Append(parts[2]); replaced.Append(Multicast); replaced.Append(FalseTxt); replaced.Append(Multicast); replaced.Append(parts.Length > 4 ? parts[4] : "0"); replaced.Append(ParenClose); break; case "stringleft": if (parts.Length < 3) { throw new ParseException(ExTooFewParams); } replaced.Append(parts[0]); replaced.Append(AssignPre); replaced.Append(Equal); replaced.Append("SubStr"); replaced.Append(ParenOpen); replaced.Append(parts[1]); replaced.Append(Multicast); replaced.Append("1"); replaced.Append(Multicast); replaced.Append(parts[2]); replaced.Append(ParenClose); break; case "stringlen": if (parts.Length < 2) { throw new ParseException(ExTooFewParams); } replaced.Append(parts[0]); replaced.Append(AssignPre); replaced.Append(Equal); replaced.Append("StrLen"); replaced.Append(ParenOpen); replaced.Append(parts[1]); replaced.Append(ParenClose); break; case "stringmid": if (parts.Length < 3) { throw new ParseException(ExTooFewParams); } replaced.Append(parts[0]); replaced.Append(AssignPre); replaced.Append(Equal); replaced.Append("SubStr"); replaced.Append(ParenOpen); replaced.Append(parts[1]); replaced.Append(Multicast); replaced.Append(parts[2]); if (parts.Length > 3) { replaced.Append(Multicast); replaced.Append(parts[3]); } if (parts.Length > 4) { replaced.Append(Multicast); replaced.Append(parts[4]); } replaced.Append(ParenClose); break; case "stringright": if (parts.Length < 3) { throw new ParseException(ExTooFewParams); } replaced.Append(parts[0]); replaced.Append(AssignPre); replaced.Append(Equal); replaced.Append("SubStr"); replaced.Append(ParenOpen); replaced.Append(parts[1]); replaced.Append(Multicast); replaced.Append("1"); replaced.Append(Add); replaced.Append(Minus); replaced.Append(ParenOpen); replaced.Append(parts[2]); replaced.Append(ParenClose); replaced.Append(ParenClose); break; case "stringtrimleft": if (parts.Length < 3) { throw new ParseException(ExTooFewParams); } replaced.Append(parts[0]); replaced.Append(AssignPre); replaced.Append(Equal); replaced.Append("SubStr"); replaced.Append(ParenOpen); replaced.Append(parts[1]); replaced.Append(Multicast); replaced.Append("1"); replaced.Append(Add); replaced.Append(parts[2]); replaced.Append(ParenClose); break; case "stringtrimright": if (parts.Length < 3) { throw new ParseException(ExTooFewParams); } replaced.Append(parts[0]); replaced.Append(AssignPre); replaced.Append(Equal); replaced.Append("SubStr"); replaced.Append(ParenOpen); replaced.Append(parts[1]); replaced.Append(Multicast); replaced.Append("1"); replaced.Append(Multicast); replaced.Append(Minus); replaced.Append(ParenOpen); replaced.Append(parts[2]); replaced.Append(ParenClose); replaced.Append(ParenClose); break; #endregion #region Arithmetic // TODO: translate legacy EnvMult, EnvDiv etc #endregion #region Send case "sendevent": case "sendinput": case "sendplay": replaced.Append("Send"); replaced.Append(Multicast); replaced.Append(SingleSpace); replaced.Append(param); break; case "sendraw": replaced.Append("Send"); replaced.Append(Multicast); replaced.Append(SingleSpace); ParameterPrepend(ref param, "{Raw}"); replaced.Append(param); break; case "controlsendraw": replaced.Append("ControlSend"); replaced.Append(Multicast); replaced.Append(SingleSpace); ParameterPrepend(ref param, "{Raw}"); replaced.Append(param); break; case "sendmode": code = string.Empty; break; case "setcapslockstate": case "setnumlockstate": case "setscrolllockstate": replaced.Append("SetLockState"); replaced.Append(Multicast); replaced.Append(SingleSpace); replaced.Append(cmd, 3, cmd.Length - 3 - 5); replaced.Append(Multicast); replaced.Append(SingleSpace); replaced.Append(param); break; #endregion #region Mouse case "leftclick": case "mouseclick": replaced.Append("Click"); replaced.Append(Multicast); replaced.Append(param); break; case "leftclickdrag": replaced.Append("MouseClickDrag"); replaced.Append(Multicast); replaced.Append("Left"); replaced.Append(Multicast); replaced.Append(param); break; case "mousemove": replaced.Append("Click"); replaced.Append(Multicast); replaced.Append(param); replaced.Append(Multicast); replaced.Append("0"); break; #endregion #region Debug case "edit": case "listlines": case "listvars": replaced = null; break; #endregion #region Other case "filegetattrib": if (parts.Length != 2) { replaced = null; } else { replaced.Append(parts[0].Substring(1, parts[0].Length - 2)); replaced.Append(AssignPre); replaced.Append(Equal); replaced.Append("FileExist"); replaced.Append(ParenOpen); replaced.Append(parts[1]); replaced.Append(ParenClose); } break; #endregion } if (replaced == null) { code = string.Empty; } else if (replaced.Length > 0) { code = replaced.ToString(); } }
List <object> SplitTokens(string code) { var list = new List <object>(); bool json = false; for (int i = 0; i < code.Length; i++) { char sym = code[i]; #region Spaces if (IsSpace(sym)) { continue; } #endregion #region Comments else if (IsCommentAt(code, i)) { MoveToEOL(code, ref i); } #endregion #region Identifiers else if (IsIdentifier(sym) || sym == Resolve || (sym == Concatenate && i + 1 < code.Length && IsIdentifier(code[i + 1]))) { var id = new StringBuilder(code.Length); id.Append(sym); i++; // UNDONE: optimise split tokens for (; i < code.Length; i++) { sym = code[i]; if ((sym == 'e' || sym == 'E') && IsPrimativeObject(id.ToString()) && id.ToString().IndexOf("0x") != 0 && i + 1 < code.Length) { id.Append(sym); sym = code[++i]; if (!(sym == '+' || sym == '-' || char.IsDigit(sym))) { throw new ParseException(ExInvalidExponent); } id.Append(sym); } else if (IsIdentifier(sym) || sym == Resolve || (sym == Concatenate && (i + 1 < code.Length ? code[i + 1] != Equal : true))) { id.Append(sym); } else { if (sym == ParenOpen && !IsKeyword(id.ToString()) && !id.ToString().Contains(Concatenate.ToString())) { id.Append(ParenOpen); } else { i--; } break; } } string seq = id.ToString(); var parts = IsPrimativeObject(seq) ? new[] { seq } : seq.Split(Concatenate); if (parts[0].Length != 0) { list.Add(parts[0]); } for (int n = 1; n < parts.Length; n++) { list.Add(ArrayOpen.ToString()); string str = StringBound.ToString(); list.Add(string.Concat(str, parts[n], str)); list.Add(ArrayClose.ToString()); } } #endregion #region Strings else if (sym == StringBound) { var str = new StringBuilder(code.Length); str.Append(StringBound); i++; for (int max = code.Length + 1; i < max; i++) { if (i == code.Length) { throw new ParseException(ExUntermStr); } sym = code[i]; str.Append(sym); if (sym == StringBound) { int n = i + 1; if (n < code.Length && code[n] == StringBound) { i = n; } else { break; } } } list.Add(str.ToString()); } #endregion #region Operators else { var op = new StringBuilder(3); int n = i + 1; char symNext = n < code.Length ? code[n] : Reserved; bool tri = false; #region 3x if (sym == symNext) { bool peekAssign = false; switch (sym) { case Divide: case Greater: case Less: peekAssign = true; goto case Add; case Add: case Minus: case Multiply: case BitOR: case BitAND: op.Append(sym); op.Append(symNext); i++; tri = true; if (peekAssign) { n = i + 1; if (n < code.Length && code[n] == Equal) { op.Append(code[n]); i = n; } } break; } } #endregion if (!tri) { #region 2x if (symNext == Equal) { switch (sym) { case AssignPre: case Add: case Minus: case Multiply: case Divide: case Concatenate: case BitAND: case BitXOR: case BitOR: case Not: case Equal: case Greater: case Less: op.Append(sym); op.Append(symNext); i++; break; } } else if ((sym == Less && symNext == Greater) || (sym == TernaryA && symNext == TernaryA)) { op.Append(sym); op.Append(symNext); i++; } #endregion #region 1x else { switch (sym) { case Add: case Minus: case Multiply: case Not: case BitNOT: case BitAND: case Greater: case Less: case BitXOR: case BitOR: case ParenOpen: case ParenClose: case Equal: case Concatenate: case TernaryB: case Divide: case ArrayOpen: case ArrayClose: op.Append(sym); break; case BlockOpen: if (json) { op.Append(sym); break; } blockOpen = true; int j = i + 2; if (j < code.Length && !IsCommentAt(code, j)) { blockOpen = false; json = true; goto case BlockOpen; } j--; if (j < code.Length) { if (code[j] == BlockClose) { json = true; goto case BlockClose; } else if (!IsSpace(code[j])) { throw new ParseException(ExUnexpected); } } return(list); case BlockClose: if (!json) { goto default; } op.Append(sym); break; default: if (sym == Resolve || sym == Multicast) { goto case Add; } throw new ParseException(ExUnexpected); } } #endregion } if (op.Length == 0) { op.Append(sym); } list.Add(op.ToString()); } #endregion } return(list); }
private CodeExpression ParseInequality(string code) { var buf = new StringBuilder(code.Length); int i = 0; while (i < code.Length && IsSpace(code[i])) { i++; } while (i < code.Length && (IsIdentifier(code[i]) || code[i] == Resolve)) { buf.Append(code[i++]); } while (i < code.Length && IsSpace(code[i])) { i++; } if (i != code.Length) // if test argument is not a lone identifier then it is an expression { var op = new[] { Equal, Not, Greater, Less }; if (Array.IndexOf(op, code[i]) == -1) { throw new ParseException(ExUnexpected); } buf.Append(code[i++]); if (i < code.Length && Array.IndexOf(op, code[i]) != -1) { buf.Append(code[i++]); } buf.Append(StringBound); while (i < code.Length && IsSpace(code[i])) { i++; } if (i < code.Length) { string str = code.Substring(i); str = str.Replace(StringBound.ToString(), new string(StringBound, 2)); buf.Append(str); } while (i < code.Length && IsSpace(code[i])) { i++; } buf.Append(StringBound); } var iftest = (CodeMethodInvokeExpression)InternalMethods.IfElse; var expr = ParseSingleExpression(buf.ToString()); iftest.Parameters.Add(expr); return(iftest); }