コード例 #1
0
        private void ReadStringTable(BinaryReader reader)
        {
            int stringCount = reader.ReadInt32();

            stringTable = new List <string>(stringCount);

            StringBound[] bounds = new StringBound[stringCount];
            for (int i = 0; i < stringCount; i++)
            {
                var bound = new StringBound();
                bound.Offset = reader.ReadInt32();
                bound.Length = reader.ReadInt32();
                bounds[i]    = bound;
            }

            var builder    = new StringBuilder();
            var decoder    = Encoding.UTF8.GetDecoder();
            var byteBuffer = new byte[1024];
            var charBuffer = new char[1024];

            int stringDataLength = reader.ReadInt32();
            int lastEndOffset    = 0;

            for (int i = 0; i < stringCount; i++)
            {
                var bound = bounds[i];

                if (bound.Offset < lastEndOffset)
                {
                    // don't allow overlap
                    throw new IndexOutOfRangeException("Two string ranges overlapped.");
                }
                else if (bound.Offset > lastEndOffset)
                {
                    // skip padding (?) bytes
                    reader.BaseStream.Position += bound.Offset - lastEndOffset;
                }

                int thisEndOffset = bound.Offset + bound.Length;
                if (thisEndOffset > stringDataLength)
                {
                    throw new IndexOutOfRangeException("String end exceded data length.");
                }

                // The string length is in bytes, so we can't use StreamReader
                // We need to control how many bytes are read.
                int remainingBytes = bound.Length;
                if (remainingBytes > 0)
                {
                    int  readBytes       = 0;
                    bool completedString = false;
                    while ((readBytes = reader.Read(byteBuffer, 0, Math.Min(byteBuffer.Length, remainingBytes))) != 0)
                    {
                        remainingBytes -= readBytes;

                        int charCount, byteCount;
                        decoder.Convert(byteBuffer, 0, readBytes, charBuffer, 0, charBuffer.Length, remainingBytes == 0, out byteCount, out charCount, out completedString);
                        builder.Append(charBuffer, 0, charCount);

                        if (remainingBytes == 0)
                        {
                            break;
                        }
                    }

                    if (remainingBytes != 0 || !completedString)
                    {
                        throw new InvalidDataException("Failed to fully read a string.");
                    }

                    decoder.Reset();
                    string str = builder.ToString();
                    builder.Length = 0;

                    stringTable.Add(str);
                }
                else
                {
                    stringTable.Add(string.Empty);
                }

                lastEndOffset = thisEndOffset;
            }
        }
コード例 #2
0
        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
    }
コード例 #3
0
ファイル: Translate.cs プロジェクト: 1j01/node-ahk
        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();
            }
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }