Example #1
0
        public override void Parse(string input, int charIndex)
        {
            if (string.IsNullOrWhiteSpace(input))
            {
                throw new AST_EmptyInputException("Provided string is empty", charIndex);
            }
            int i = 0;

            //Read function access level
            while (i < input.Length && AST_Program.separator_ast.Contains(input[i]))
            {
                ++i;
            }
            if (i >= input.Length)
            {
                throw new AST_BadFormatException("Failed to parse function access level",
                                                 new ArgumentOutOfRangeException("input", "Reached the end of input"), charIndex + input.Length - 1);
            }
            if (input.IndexOf("shared", i) == i)
            {
                accessLevel = AccessLevel.Shared;
                i          += "shared".Length;
            }
            else if (input.IndexOf("private", i) == i)
            {
                accessLevel = AccessLevel.Private;
                i          += "private".Length;
            }
            else
            {
                accessLevel = AccessLevel.Private;
            }
            //Read path
            while (i < input.Length && AST_Program.separator_ast.Contains(input[i]))
            {
                ++i;
            }
            if (i >= input.Length)
            {
                throw new AST_BadFormatException("Failed to parse function path",
                                                 new ArgumentOutOfRangeException("input", "Reached the end of input"), charIndex + input.Length - 1);
            }
            if (input[i] != '\"')
            {
                throw new AST_BadFormatException("Failed to parse function path",
                                                 new ArgumentException("Function path not found"), charIndex + i);
            }
            int pathStart = i;

            ++i;
            while (input[i] != '\"' || input[i - 1] == '\\')
            {
                ++i;
            }
            path = input.Substring(pathStart + 1, i - pathStart - 1);
            ++i;
            //Read function type
            //TODO - add more function types
            while (i < input.Length && AST_Program.separator_ast.Contains(input[i]))
            {
                ++i;
            }
            if (i >= input.Length)
            {
                throw new AST_BadFormatException("Failed to parse function type",
                                                 new ArgumentOutOfRangeException("input", "Reached the end of input"), charIndex + input.Length - 1);
            }
            if (input.IndexOf("cdecl", i) == i)
            {
                functionType = FunctionType.cdecl;
                i           += "cdecl".Length;
            }
            else if (input.IndexOf("stdcall", i) == i)
            {
                functionType = FunctionType.stdcall;
                i           += "stdcall".Length;
            }
            else
            {
                throw new AST_BadFormatException("Unknown function format", charIndex + i);
            }
            //Read name
            while (i < input.Length && AST_Program.separator_ast.Contains(input[i]))
            {
                ++i;
            }
            if (i >= input.Length)
            {
                throw new AST_BadFormatException("Failed to parse function name",
                                                 new ArgumentOutOfRangeException("input", "Reached the end of input"), charIndex + input.Length - 1);
            }
            if (!(char.IsLetter(input[i]) || AST_Expression.naming_ast.Contains(input[i])))
            {
                throw new AST_BadFormatException("Function name not allowed",
                                                 new FormatException("Function name should start with a letter or " + AST_Expression.naming_ast),
                                                 charIndex + i);
            }
            string nm = "";

            while (char.IsLetterOrDigit(input[i]) || AST_Expression.naming_ast.Contains(input[i]))
            {
                nm += input[i];
                ++i;
                if (i >= input.Length)
                {
                    break;
                }
            }
            name = nm;
            //Read parameters
            while (i < input.Length && AST_Program.separator_ast.Contains(input[i]))
            {
                ++i;
            }
            if (i >= input.Length)
            {
                throw new AST_BadFormatException("Failed to parse function parameters, return value or code",
                                                 new ArgumentOutOfRangeException("input", "Reached the end of input"), charIndex + input.Length - 1);
            }
            if (input.IndexOf("takes", i) == i)
            {
                int end = input.IndexOf("ends", i);
                if (end == -1)
                {
                    throw new AST_BadFormatException("Failed to find a corresponding end to parameters start",
                                                     new FormatException("No corresponding ends for takes"), charIndex + i);
                }
                i += "takes".Length;
                string   inputparameters = input.Substring(i, end - i);
                string[] vars            = inputparameters.Split(AST_Program.separator_ast_nospace.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                int      varStart        = i;
                if (vars.Length > 0)
                {
                    parameters = new LinkedList <AST_Variable>();
                }
                foreach (string s in vars)
                {
                    if (!string.IsNullOrWhiteSpace(s))
                    {
                        parameters.AddLast(new AST_Variable(this, s, charIndex + varStart));
                        varStart += s.Length;
                    }
                    else
                    {
                        varStart += 1;
                    }
                }
                i = end + "ends".Length;
            }
            //Read output
            while (i < input.Length && AST_Program.separator_ast.Contains(input[i]))
            {
                ++i;
            }
            if (i >= input.Length)
            {
                throw new AST_BadFormatException("Failed to parse function return value or code",
                                                 new ArgumentOutOfRangeException("input", "Reached the end of input"), charIndex + input.Length - 1);
            }
            if (input.IndexOf("gives", i) == i)
            {
                int end = input.IndexOf("ends", i);
                if (end == -1)
                {
                    throw new AST_BadFormatException("Failed to find a corresponding end to return value start",
                                                     new FormatException("No corresponding ends for gives"), charIndex + input.Length - 1);
                }
                i += "gives".Length;
                string   inputreturn = input.Substring(i, end - i);
                string[] outputVars  = inputreturn.Split(AST_Program.separator_ast.ToCharArray(),
                                                         StringSplitOptions.RemoveEmptyEntries);
                if (outputVars.Length != 1)
                {
                    throw new AST_BadFormatException("Too many or too few return values. Try using a structure instead",
                                                     new FormatException("Wrong return values count. Should be 1"), charIndex + i);
                }
                retValue = new AST_Type(this, outputVars[0], charIndex + i + inputreturn.IndexOf(outputVars[0]));

                i = end + "ends".Length;
            }
            //Read expressions
            while (i < input.Length && AST_Program.separator_ast.Contains(input[i]))
            {
                ++i;
            }
            if (i >= input.Length)
            {
                throw new AST_BadFormatException("Failed to parse function code",
                                                 new ArgumentOutOfRangeException("input", "Reached the end of input"), charIndex + input.Length - 1);
            }
            //TODO - function declarations
            //TODO - nested ends and does
            if (input.IndexOf("does", i) == i)
            {
                Stack <string> segments = new Stack <string>();
                segments.Push("does");

                int endsIndex = i + "does".Length;
                while (segments.Count > 0)
                {
                    if (input.IndexOf("ends", endsIndex) == endsIndex)
                    {
                        segments.Pop();
                        if (segments.Count > 0)
                        {
                            endsIndex += "ends".Length;
                        }
                    }
                    else if (input.IndexOf("does", endsIndex) == endsIndex)
                    {
                        segments.Push("does");
                        endsIndex += "does".Length;
                    }
                    else
                    {
                        endsIndex++;
                    }
                    if (endsIndex >= input.Length)
                    {
                        throw new AST_BadFormatException("Failed to parse function code",
                                                         new ArgumentOutOfRangeException("input", "Reached the end of input"),
                                                         charIndex + input.Length - 1);
                    }
                }

                //int end = input.IndexOf("ends", i);
                int end = endsIndex;
                if (end == -1)
                {
                    throw new AST_BadFormatException("Failed to find a corresponding end to code start",
                                                     new FormatException("No corresponding ends for does"), charIndex + i);
                }
                if (input.IndexOf(name, end + "ends".Length + 1) == end + "ends".Length + 1)
                {
                    throw new AST_BadFormatException("Failed to find a corresponding end to code start",
                                                     new FormatException("No corresponding ends for does"), charIndex + end);
                }
                i += "does".Length;
                string   inputcode = input.Substring(i, end - i);
                string[] exps      = Split(inputcode, charIndex);//inputcode.Split(new char[] { ';' }/*, StringSplitOptions.RemoveEmptyEntries*/);
                if (exps.Length > 0)
                {
                    expressions = new LinkedList <AST_Expression>();
                }
                int exLength = 0;
                foreach (string ex in exps)
                {
                    bool hasActualExpression = false;
                    for (int p = 0; p < ex.Length; ++p)
                    {
                        if (!AST_Program.separator_ast.Contains(ex[p]))
                        {
                            hasActualExpression = true;
                            break;
                        }
                    }
                    if (hasActualExpression)
                    {
                        string nat = ex.Trim();
                        if (nat.StartsWith("native does") && nat.EndsWith("ends native"))
                        {
                            expressions.AddLast(new AST_Native(this, nat, charIndex + exLength));
                        }
                        else if (nat.StartsWith("if") && nat.EndsWith("ends if"))
                        {
                            expressions.AddLast(new AST_If(this, nat, charIndex + exLength));
                        }
                        else if (nat.StartsWith("while") && nat.EndsWith("ends while"))
                        {
                            expressions.AddLast(new AST_While(this, nat, charIndex + exLength));
                        }
                        else if (nat.StartsWith("for") && nat.EndsWith("ends for"))
                        {
                            expressions.AddLast(new AST_For(this, nat, charIndex + exLength));
                        }
                        else
                        {
                            //Try to find local variable
                            bool     isVariable = false;
                            string[] pieces     = nat.Split(AST_Program.separator_ast.ToCharArray(),
                                                            StringSplitOptions.RemoveEmptyEntries);
                            if (pieces.Length == 2)
                            {
                                //We may have a variable declaration
                                isVariable = true;
                                try
                                {
                                    //Do a simple parameter check beforehand not to waste time just in case
                                    var localType = ParameterType.GetParameterType(pieces[0]);
                                    AST_LocalVariable localVariable = new AST_LocalVariable(this, nat, charIndex + exLength);
                                    expressions.AddLast(localVariable);
                                }
                                catch (Exception)
                                {
                                    //It is not
                                    isVariable = false;
                                }
                            }
                            if (!isVariable)
                            {
                                //Parse as an expression
                                expressions.AddLast(new AST_Expression(this, ex + ";", charIndex + exLength));
                            }
                        }
                    }
                    exLength += ex.Length + 1;
                }
                i = end + "ends".Length;
            }
            else
            {
                throw new AST_BadFormatException("Failed to find function code", charIndex + i);
            }
        }
Example #2
0
        public override void Parse(string input, int charIndex)
        {
            input = input.Trim();
            if (string.IsNullOrWhiteSpace(input))
            {
                throw new AST_EmptyInputException("Provided string is empty", charIndex);
            }
            if (!input.StartsWith("if") || !input.EndsWith("ends if"))
            {
                throw new AST_EmptyInputException("Provided string is not an if code piece", charIndex);
            }

            int insideIndexStart = "if".Length;

            while (AST_Program.separator_ast.IndexOf(input[insideIndexStart]) != -1)
            {
                //We are skipping white-spaces
                ++insideIndexStart;
            }
            if (input[insideIndexStart] != '(')
            {
                throw new AST_BadFormatException("Failed to find conditional expression inside if", charIndex + insideIndexStart);
            }

            Stack <string> brackets       = new Stack <string>();
            int            insideIndexEnd = insideIndexStart + 1;

            brackets.Push("(");
            while (brackets.Count > 0)
            {
                if (input[insideIndexEnd] == '(')
                {
                    brackets.Push("(");
                    insideIndexEnd++;
                }
                else if (input[insideIndexEnd] == ')')
                {
                    if (brackets.Peek() == "(")
                    {
                        brackets.Pop();
                        insideIndexEnd++;
                    }
                    else
                    {
                        throw new AST_BadFormatException("Failed to parse conditional expression inside if",
                                                         new AST_BadFormatException("Encountered unexpected tokens in bracket stack",
                                                                                    charIndex + insideIndexEnd), charIndex + insideIndexEnd);
                    }
                }
                else
                {
                    insideIndexEnd++;
                }
                if (input.Length <= insideIndexEnd)
                {
                    throw new AST_BadFormatException("Reached end of input while parsing if brackets",
                                                     charIndex + insideIndexEnd);
                }
            }
            //insideIndexEnd points at closing bracket + 1
            string conditionalExpression = input.Substring(insideIndexStart + 1, insideIndexEnd - insideIndexStart - 2);

            inside = new AST_Expression(this, conditionalExpression + " ;", charIndex + insideIndexStart + 1);
            int localInput = insideIndexEnd;

            while (AST_Program.separator_ast.IndexOf(input[localInput]) != -1)
            {
                localInput++;
            }
            if (input.IndexOf("does", localInput) != localInput)
            {
                //We failed to find if body
                throw new AST_BadFormatException("Conditional statement body was not found", charIndex + localInput);
            }
            Stack <string> codeSegments = new Stack <string>();

            codeSegments.Push("does");
            int codeSegmentStart = localInput;

            localInput++;
            while (codeSegments.Count > 0)
            {
                if (input.IndexOf("does", localInput) == localInput)
                {
                    codeSegments.Push("does");
                }
                else if (input.IndexOf("ends", localInput) == localInput)
                {
                    if (codeSegments.Peek() != "does")
                    {
                        throw new AST_BadFormatException("Failed to parse conditional expression inside if",
                                                         new AST_BadFormatException("Encountered unexpected tokens in bracket stack",
                                                                                    charIndex + localInput), charIndex + localInput);
                    }
                    codeSegments.Pop();
                }
                localInput++;
                if (input.Length <= localInput && codeSegments.Count > 0)
                {
                    throw new AST_BadFormatException("Reached end of input while parsing if body",
                                                     charIndex + localInput);
                }
            }
            //localInput points at letter n from "ends"
            string codeBody = input.Substring(codeSegmentStart + "does".Length, localInput
                                              - 1 - "does".Length - codeSegmentStart);

            int elseIndex = localInput + "ends".Length;

            while (AST_Program.separator_ast.IndexOf(input[elseIndex]) != -1 &&
                   elseIndex < input.Length)
            {
                ++elseIndex;
            }
            if (input.IndexOf("if", elseIndex) != elseIndex)
            {
                if (input.IndexOf("else", elseIndex) != elseIndex)
                {
                    throw new AST_BadFormatException("Bad formatting of if statement", elseIndex);
                }
                else
                {
                    //We should parse "else"
                    elseIndex += "else".Length;
                    while (AST_Program.separator_ast_nosemicolon.IndexOf(input[elseIndex]) != -1)
                    {
                        elseIndex++;
                    }
                    if (input.IndexOf("does", elseIndex) != elseIndex)
                    {
                        throw new AST_BadFormatException("Couldn\'t find does part of else", elseIndex);
                    }
                    elseIndex += "does".Length;
                    int doesCount = 1, elseEndsIndex = elseIndex;
                    while (doesCount != 0)
                    {
                        if (input.IndexOf("does", elseEndsIndex) == elseEndsIndex)
                        {
                            doesCount++;
                            elseEndsIndex += "does".Length;
                        }
                        else if (input.IndexOf("ends", elseEndsIndex) == elseEndsIndex)
                        {
                            doesCount--;
                            elseEndsIndex += "ends".Length;
                        }
                        else
                        {
                            elseEndsIndex++;
                        }
                        if (input.Length <= elseEndsIndex && doesCount != 0)
                        {
                            throw new AST_BadFormatException("Reached end of input while parsing else body",
                                                             charIndex + elseEndsIndex);
                        }
                    }
                    string elseBody = input.Substring(elseIndex, elseEndsIndex - "ends".Length - elseIndex);

                    string[] elseExps = AST_Function.Split(elseBody, charIndex + codeSegmentStart + "does".Length);
                    if (elseExps.Length > 0)
                    {
                        else_expressions = new LinkedList <AST_Expression>();
                    }
                    int elseExLength = elseIndex;
                    foreach (string ex in elseExps)
                    {
                        bool hasActualExpression = false;
                        for (int p = 0; p < ex.Length; ++p)
                        {
                            if (!AST_Program.separator_ast.Contains(ex[p]))
                            {
                                hasActualExpression = true;
                                break;
                            }
                        }
                        if (hasActualExpression)
                        {
                            string nat = ex.Trim();
                            if (nat.StartsWith("native does") && nat.EndsWith("native ends"))
                            {
                                else_expressions.AddLast(new AST_Native(this, nat, charIndex + elseExLength));
                            }
                            else if (nat.StartsWith("if") && nat.EndsWith("ends if"))
                            {
                                else_expressions.AddLast(new AST_If(this, nat, charIndex + elseExLength));
                            }
                            else if (nat.StartsWith("while") && nat.EndsWith("ends while"))
                            {
                                else_expressions.AddLast(new AST_While(this, nat, charIndex + elseExLength));
                            }
                            else if (nat.StartsWith("for") && nat.EndsWith("ends for"))
                            {
                                else_expressions.AddLast(new AST_For(this, nat, charIndex + elseExLength));
                            }
                            else
                            {
                                //Try to find local variable
                                bool     isVariable = false;
                                string[] pieces     = nat.Split(AST_Program.separator_ast.ToCharArray(),
                                                                StringSplitOptions.RemoveEmptyEntries);
                                if (pieces.Length == 2)
                                {
                                    //We may have a variable declaration
                                    isVariable = true;
                                    try
                                    {
                                        //Do a simple parameter check beforehand not to waste time just in case
                                        var localType = CodeBlocks.ParameterType.GetParameterType(pieces[0]);
                                        AST_LocalVariable localVariable = new AST_LocalVariable(this, nat, charIndex + elseExLength);
                                        else_expressions.AddLast(localVariable);
                                    }
                                    catch (Exception)
                                    {
                                        //It is not
                                        isVariable = false;
                                    }
                                }
                                if (!isVariable)
                                {
                                    //Parse as an expression
                                    else_expressions.AddLast(new AST_Expression(this, ex + ";", charIndex + elseExLength));
                                }
                            }
                        }
                        elseExLength += ex.Length + 1;
                    }
                }
            }

            string[] exps = AST_Function.Split(codeBody, charIndex + codeSegmentStart + "does".Length);
            if (exps.Length > 0)
            {
                expressions = new LinkedList <AST_Expression>();
            }
            int exLength = codeSegmentStart + "does".Length;

            foreach (string ex in exps)
            {
                bool hasActualExpression = false;
                for (int p = 0; p < ex.Length; ++p)
                {
                    if (!AST_Program.separator_ast.Contains(ex[p]))
                    {
                        hasActualExpression = true;
                        break;
                    }
                }
                if (hasActualExpression)
                {
                    string nat = ex.Trim();
                    if (nat.StartsWith("native does") && nat.EndsWith("native ends"))
                    {
                        expressions.AddLast(new AST_Native(this, nat, charIndex + exLength));
                    }
                    else if (nat.StartsWith("if") && nat.EndsWith("ends if"))
                    {
                        expressions.AddLast(new AST_If(this, nat, charIndex + exLength));
                    }
                    else if (nat.StartsWith("while") && nat.EndsWith("ends while"))
                    {
                        expressions.AddLast(new AST_While(this, nat, charIndex + exLength));
                    }
                    else if (nat.StartsWith("for") && nat.EndsWith("ends for"))
                    {
                        expressions.AddLast(new AST_For(this, nat, charIndex + exLength));
                    }
                    else
                    {
                        //Try to find local variable
                        bool     isVariable = false;
                        string[] pieces     = nat.Split(AST_Program.separator_ast.ToCharArray(),
                                                        StringSplitOptions.RemoveEmptyEntries);
                        if (pieces.Length == 2)
                        {
                            //We may have a variable declaration
                            isVariable = true;
                            try
                            {
                                //Do a simple parameter check beforehand not to waste time just in case
                                var localType = CodeBlocks.ParameterType.GetParameterType(pieces[0]);
                                AST_LocalVariable localVariable = new AST_LocalVariable(this, nat, charIndex + exLength);
                                expressions.AddLast(localVariable);
                            }
                            catch (Exception)
                            {
                                //It is not
                                isVariable = false;
                            }
                        }
                        if (!isVariable)
                        {
                            //Parse as an expression
                            expressions.AddLast(new AST_Expression(this, ex + ";", charIndex + exLength));
                        }
                    }
                }
                exLength += ex.Length + 1;
            }
        }