Esempio n. 1
0
        // Single-command parser
        // Rules:
        // Ends with ; - is a signal where one command ends.
        public static object Process(string Command)
        {
            /* Input examples:
             * string a = "b";
             * bool x = false;
             * int ttt = 5555;
             * Test("a", b(5, c(true)));
             * TODO:
             * string b = "test";
             * string a = b;
             */

            Command = Command.Trim(SpacesAndTabs); // Remove spaces and tabs at the end and start

            if (!Command.EndsWith(";"))
            {
                throw new Exceptions.ParserException("Ending character is not found.");
            }

            var CommandType = GetCommandType(Command);

            if (CommandType == CommandTypes.Unknown)
            {
                throw new Exceptions.ParserException("Parser can't understand the type of this command (Unknown)");
            }
            else if (CommandType == CommandTypes.VariableInitializer)
            {
                // something like: string a = "b";

                /* Rules:
                 * space must split variable type and variable name
                 * = is the signal to start write variable's value and ; is the signal to stop parsing
                 */
                var CommandSplit = Command.Split(' ');

                if (CommandSplit.Length < 1)
                {
                    throw new Exceptions.VariableInitializerException("Variable type or variable name is not found");
                }

                string VariableType = CommandSplit[0];
                string VariableName = "";

                string ParsingName = CommandSplit[1];
                for (int i = 0; i < ParsingName.Length; i++)
                {
                    char c = ParsingName[i];

                    if (c == ';' || c == '=')
                    {
                        break;
                    }

                    foreach (var bad in SpacesAndTabs)
                    {
                        if (c == bad)
                        {
                            break;
                        }
                    }

                    VariableName += c;
                }

                if (VariableType.Length <= 0)
                {
                    throw new Exceptions.VariableInitializerException("Invalid variable type");
                }

                if (VariableName.Length <= 0)
                {
                    throw new Exceptions.VariableInitializerException("Invalid variable name");
                }

                // Moving on, now we must check for value somehow.
                // It can be: "bool a;" or "bool a = null" which is null or bool a = true;
                // So, simply read everything to end. By the rules, there are no more spaces/tabes at the start or between var name/value
                // so we can get length and start from that point
                int PositionAfterVarInit = (VariableType + " " + VariableName).Length;

                if (PositionAfterVarInit > Command.Length)
                {
                    throw new Exceptions.VariableInitializerException("Something wrong");
                }

                string valueString = "";

                bool writeValue = false;
                for (int i = PositionAfterVarInit; i < Command.Length; i++)
                {
                    char c = Command[i];

                    if (c == ';')
                    {
                        break; // stop at ;
                    }
                    if (writeValue)
                    {
                        valueString += c;
                    }

                    if (c == '=')
                    {
                        if (!writeValue)
                        {
                            writeValue = true;
                        }
                        else
                        {
                            throw new Exceptions.VariableInitializerException("Unexpected '='");
                        }
                    }
                }

                valueString = valueString.Trim(SpacesAndTabs);

                var type = GetCommandType(valueString);

                if (IsCommandTypeCompatibleWith(type, CommandTypes.Method))
                {
                    // something like: string a = Return("a");
                    var invokeType = GetCompatibleTypeByName(VariableType);
                    if (VariableType != "var" && invokeType == null)
                    {
                        throw new Exceptions.VariableSetException($"Type {VariableType} is not compatible with ESCRIPT");
                    }

                    var invokeResult = Cmd.Process(valueString + ";", false);
                    if (invokeResult != null && VariableType != "var" && invokeResult.GetType() != invokeType.Type)
                    {
                        throw new Exceptions.VariableSetException($"{invokeType.Name} expected, but {invokeResult.GetType().Name} received");
                    }

                    Variables.SetVariableObject(VariableName, invokeResult);

                    return(new ParseResult(ParseResult.ParserNativeResults.ParserNativeOK, "VariableInitialzer, value is Method-compatible"));
                }
                else if (type == CommandTypes.CastValue)
                {
                    // something like: IntPtr x = (IntPtr)5;
                    var invokeType = GetCompatibleTypeByName(VariableType);
                    if (VariableType != "var" && invokeType == null)
                    {
                        throw new Exceptions.VariableSetException($"Type {VariableType} is not compatible with ESCRIPT");
                    }

                    var invokeResult = ConvertStringToVar(valueString);
                    if (invokeResult != null && VariableType != "var" && invokeResult.GetType() != invokeType.Type)
                    {
                        throw new Exceptions.VariableSetException($"{invokeType.Name} expected, but {invokeResult.GetType().Name} received");
                    }

                    Variables.SetVariableObject(VariableName, invokeResult);

                    return(new ParseResult(ParseResult.ParserNativeResults.ParserNativeOK, "VariableInitialzer, value is cast"));
                }
                else
                {
                    // something like: string a = "a";
                    return(VariableSetValueHandler(VariableType, VariableName, valueString));
                }
            }
            else if (CommandType == CommandTypes.VariableSet)
            {
                // something like: a = true;

                /* Rules:
                 * = must split variable name and variable value
                 */

                // I'm lazy, so temporary solution is to add "var" to the start:
                return(Process("var " + Command));

#if NOT_LAZY_AUTHOR // TODO
                string VariableName = Command.Split('=')[0].Trim(SpacesAndTabs);

                string valueString = "";

                bool writeValue = false;
                for (int i = VariableName.Length; i < Command.Length; i++)
                {
                    char c = Command[i];

                    if (c == ';')
                    {
                        break; // stop at ;
                    }
                    if (writeValue)
                    {
                        valueString += c;
                    }

                    if (c == '=')
                    {
                        if (!writeValue)
                        {
                            writeValue = true;
                        }
                        else
                        {
                            throw new Exceptions.VariableInitializerException("Unexpected '='");
                        }
                    }
                }

                valueString = valueString.Trim(SpacesAndTabs);

                if (valueString.Length == 0)
                {
                    throw new Exceptions.VariableSetException("Value is not found");
                }

                for (int i = 0; i < Variables.VarList.Count; i++)
                {
                    var var = Variables.VarList[i];
                    if (var.Name == VariableName)
                    {
                        return(VariableSetValueHandler(var.Value.GetType().Name, VariableName, valueString));
                    }
                }

                throw new Exceptions.VariableSetException($"Variable {VariableName} is not found");
#endif
            }
            else if (CommandType == CommandTypes.Typeof)
            {
                // rules:

                /*
                 * arguments container with only one value which is Class name
                 * returns Type of value
                 */
                string ClassName = "";

                // Check for CAST
                string CastTo = CheckForCast(Command);

                var Pair = ConvertStringToArgumentsContainer(Command);
                ClassName = Pair.Value;

                foreach (var t in CompatibleTypes)
                {
                    if (t.Names.Contains(ClassName))
                    {
                        return(t.Type);
                    }
                }

                throw new Exception($"Class '{ClassName}' not found.");
            }
            else if (CommandType == CommandTypes.Method)
            {
                // something like: Test(); Test(true); Test("a", 2); Test("a", 2, GetTrue());

                /* Rules:
                 * Arguments container must be started with ( and ended with )
                 */
                // First of all, we need to split arguments containt and method name:

                string MethodName         = "";
                string ArgumentsContainer = "";

                // Check for CAST
                string CastTo = CheckForCast(Command);

                var Pair = ConvertStringToArgumentsContainer(Command);
                MethodName         = Pair.Key;
                ArgumentsContainer = Pair.Value;

                if (MethodName.Length <= 0)
                {
                    throw new Exceptions.ParserException("Invalid method name");
                }


                // This method must resolve invokes inside of a container and convert it to an array
                object[] Args = StaticArgsToArray(ArgumentsContainer);

                List <object> FutureArguments = new List <object>();

                foreach (var argument in Args)
                {
                    // unknown argument type is string by default
                    if (argument != null)
                    {
                        if (argument.GetType() == typeof(string))
                        {
                            FutureArguments.Add(ConvertStringToVar((string)argument));
                        }
                        else
                        {
                            FutureArguments.Add(argument);
                        }
                    }
                    else
                    {
                        throw new NullReferenceException("Argument is null for some reason :/");
                    }
                }

                var invokeResult = Cmd.InvokeMethod(MethodName, FutureArguments.ToArray());
                if (CastTo.Length >= 1)
                {
                    if (invokeResult == null)
                    {
                        throw new NullReferenceException($"Trying to cast method's result to {CastTo}, but result is null");
                    }

                    invokeResult = ConvertStringToVar($"({CastTo}){CommandNormalizer.ConvertObjectToStringCode(invokeResult)}");
                }
                return(invokeResult);
            }
            else if (CommandType == CommandTypes.UsingHeader)
            {
                string Namespace         = "";
                string NamespaceOriginal = Command.Split(' ')[1].Trim(SpacesAndTabs);
                for (int i = 0; i < NamespaceOriginal.Length; i++)
                {
                    char c = NamespaceOriginal[i];

                    if (c == ';')
                    {
                        break;
                    }

                    Namespace += c;
                }

                Namespace = Namespace.Trim(SpacesAndTabs);

                if (Namespace.Length <= 0)
                {
                    throw new Exceptions.ParserException($"Namespace is invalid");
                }

                EnvironmentManager.AddNamespace(Namespace);

                return(new ParseResult(ParseResult.ParserNativeResults.ParserNativeOK, $"Namespace '{Namespace}' imported"));
            }
            else if (CommandType == CommandTypes.ObjectInitializer)
            {
                /* RULES:
                 * Type name is after "new " (4 len)
                 * Contains argument container!
                 */

                string TypeName           = "";
                string ArgumentsContainer = "";

                // Check for CAST
                string CastTo = CheckForCast(Command);

                var Pair = ConvertStringToArgumentsContainer(Command);
                TypeName           = Pair.Key.Remove(0, 4); // remove from string starting "new " (4 chars)
                ArgumentsContainer = Pair.Value;

                if (TypeName.Length <= 0)
                {
                    throw new Exceptions.ParserException("Invalid type name");
                }

                // This method must resolve invokes inside of a container and convert it to an array
                object[] Args = StaticArgsToArray(ArgumentsContainer);

                List <object> FutureArguments = new List <object>();

                foreach (var argument in Args)
                {
                    // unknown argument type is string by default
                    if (argument != null)
                    {
                        if (argument.GetType() == typeof(string))
                        {
                            FutureArguments.Add(ConvertStringToVar((string)argument));
                        }
                        else
                        {
                            FutureArguments.Add(argument);
                        }
                    }
                    else
                    {
                        throw new NullReferenceException("Argument is null for some reason :/");
                    }
                }

                var invokeResult = Cmd.CreateInstance(TypeName, FutureArguments.ToArray());

                if (CastTo.Length >= 1)
                {
                    if (invokeResult == null)
                    {
                        throw new NullReferenceException($"Trying to cast {invokeResult.GetType().Name} to {CastTo}, but result is null");
                    }

                    invokeResult = ConvertStringToVar($"({CastTo}){CommandNormalizer.ConvertObjectToStringCode(invokeResult)}");
                }
                return(invokeResult);
            }
            else
            {
                throw new NotImplementedException("Type " + CommandType.GetType().Name + "." + CommandType.ToString() + " is not implemented!!!");
            }
        }