Example #1
0
        public ASTNode ParseBody()
        {
            do
            {
                if (Tokens.CurrentItem.StartPosition.Equals(Body.StartPos))
                {
                    break;
                }
                Tokens.Advance();
            } while (!Tokens.AtEnd());

            if (Tokens.AtEnd())
            {
                return(Error("Could not find the code body for the current node, please contact the maintainers of this compiler!"));
            }

            var body = TryParseBody(false);

            if (body == null)
            {
                return(null);
            }
            Body.Statements = body.Statements;

            if (!Tokens.CurrentItem.StartPosition.Equals(Body.EndPos))
            {
                return(Error("Could not parse a valid statement, even though the current code body has supposedly not ended yet.",
                             CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
            }

            return(Body);
        }
Example #2
0
        /// <summary>
        /// Skip tokens until we reach what we assume to be the end of a statement
        /// </summary>
        // TODO does this belong on a statement parser or something
        private void SkipToEndOfStatement()
        {
            while (!Tokens.AtEnd <ISemicolonToken>())
            {
                Tokens.Next();
            }

            // Consume the semicolon is we aren't at the end of the file.
            var _ = Tokens.Accept <ISemicolonToken>();
        }
Example #3
0
        public FixedList <T> ParseMany <T, TTerminator>(Func <T> parseItem)
            where T : class
            where TTerminator : IToken
        {
            var items = new List <T>();

            while (!Tokens.AtEnd <TTerminator>())
            {
                items.Add(parseItem());
            }

            return(items.ToFixedList());
        }
Example #4
0
        /// <summary>
        /// Requires that the open paren has already been consumed
        /// </summary>
        /// <returns></returns>
        private FixedList <ParameterSyntax> ParseRestOfParameters()
        {
            var parameters = new List <ParameterSyntax>();

            while (!Tokens.AtEnd <ICloseParenToken>())
            {
                parameters.Add(ParseParameter());
                if (Tokens.Current is ICommaToken)
                {
                    Tokens.Expect <ICommaToken>();
                }
            }

            Tokens.Expect <ICloseParenToken>();
            return(parameters.ToFixedList());
        }
Example #5
0
        private FixedList <EnumVariantSyntax> ParseEnumVariants()
        {
            var variants = new List <EnumVariantSyntax>();

            while (Tokens.Current is IIdentifierToken)
            {
                variants.Add(ParseEnumVariant());
            }

            // Semicolon is optional if there are no members
            if (!Tokens.AtEnd <ICloseBraceToken>())
            {
                Tokens.Expect <ISemicolonToken>();
            }

            return(variants.ToFixedList());
        }
Example #6
0
        public Struct TryParseStruct()
        {
            Func <ASTNode> structParser = () =>
            {
                if (Tokens.ConsumeToken(TokenType.Struct) == null)
                {
                    return(null);
                }

                var specs = ParseSpecifiers(GlobalLists.StructSpecifiers);

                var name = Tokens.ConsumeToken(TokenType.Word);
                if (name == null)
                {
                    return(Error("Expected struct name!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var parent = TryParseParent();

                if (Tokens.ConsumeToken(TokenType.LeftBracket) == null)
                {
                    return(Error("Expected '{'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var vars = new List <VariableDeclaration>();
                do
                {
                    var variable = TryParseVarDecl();
                    if (variable == null)
                    {
                        return(Error("Malformed struct content!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }

                    vars.Add(variable);
                } while (CurrentTokenType != TokenType.RightBracket && !Tokens.AtEnd());

                if (Tokens.ConsumeToken(TokenType.RightBracket) == null)
                {
                    return(Error("Expected '}'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                return(new Struct(name.Value, specs, vars, name.StartPosition, name.EndPosition, parent));
            };

            return((Struct)Tokens.TryGetTree(structParser));
        }
Example #7
0
        public FixedList <T> ParseMany <T, TSeparator, TTerminator>(Func <T> parseItem)
            where T : class
            where TSeparator : class, IToken
            where TTerminator : IToken
        {
            var items = new List <T>();

            while (!Tokens.AtEnd <TTerminator>())
            {
                items.Add(parseItem());
                if (!Tokens.Accept <TSeparator>())
                {
                    break;
                }
            }

            return(items.ToFixedList());
        }
Example #8
0
        public FixedList <DeclarationSyntax> ParseDeclarations()
        {
            var declarations = new List <DeclarationSyntax>();

            // Stop at end of file or close brace that contains these declarations
            while (!Tokens.AtEnd <ICloseBraceToken>())
            {
                try
                {
                    declarations.AddRange(ParseDeclaration());
                }
                catch (ParseFailedException)
                {
                    // Ignore: we would have consumed something before failing, try to get the next declaration
                }
            }

            return(declarations.ToFixedList());
        }
Example #9
0
        public FixedList <DeclarationSyntax> ParseTopLevelDeclarations()
        {
            var declarations = new List <DeclarationSyntax>();

            // Keep going to the end of the file
            while (!Tokens.AtEnd <IEndOfFileToken>())
            {
                try
                {
                    declarations.AddRange(ParseDeclaration());
                }
                catch (ParseFailedException)
                {
                    // Ignore: we would have consumed something before failing, try to get the next declaration
                }
            }

            return(declarations.ToFixedList());
        }
        public FixedList <INonMemberDeclarationSyntax> ParseNonMemberDeclarations <T>()
            where T : IToken
        {
            var declarations = new List <INonMemberDeclarationSyntax>();

            // Stop at end of file or some token that contains these declarations
            while (!Tokens.AtEnd <T>())
            {
                try
                {
                    declarations.Add(ParseNonMemberDeclaration());
                }
                catch (ParseFailedException)
                {
                    // Ignore: we would have consumed something before failing, try to get the next declaration
                }
            }

            return(declarations.ToFixedList());
        }
Example #11
0
        public State TryParseState()
        {
            Func <ASTNode> stateSkeletonParser = () =>
            {
                var specs = ParseSpecifiers(GlobalLists.StateSpecifiers);

                if (Tokens.ConsumeToken(TokenType.State) == null)
                {
                    return(null);
                }

                var name = Tokens.ConsumeToken(TokenType.Word);
                if (name == null)
                {
                    return(Error("Expected state name!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var parent = TryParseParent();

                if (Tokens.ConsumeToken(TokenType.LeftBracket) == null)
                {
                    return(Error("Expected '{'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                List <Function> ignores = new List <Function>();
                if (Tokens.ConsumeToken(TokenType.Ignores) != null)
                {
                    do
                    {
                        VariableIdentifier variable = TryParseVariable();
                        if (variable == null)
                        {
                            return(Error("Malformed ignore statement!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                        }

                        ignores.Add(new Function(variable.Name, null, null, null, null, variable.StartPos, variable.EndPos));
                    } while (Tokens.ConsumeToken(TokenType.Comma) != null);

                    if (Tokens.ConsumeToken(TokenType.SemiColon) == null)
                    {
                        return(Error("Expected semi-colon!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }
                }

                var      funcs = new List <Function>();
                Function func  = TryParseFunction();
                while (func != null)
                {
                    funcs.Add(func);
                    func = TryParseFunction();
                }

                var bodyStart = Tokens.CurrentItem.StartPosition;
                while (Tokens.CurrentItem.Type != TokenType.RightBracket && !Tokens.AtEnd())
                {
                    Tokens.Advance();
                }
                var bodyEnd = Tokens.CurrentItem.StartPosition;

                if (Tokens.ConsumeToken(TokenType.RightBracket) == null)
                {
                    return(Error("Expected '}'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var body        = new CodeBody(new List <Statement>(), bodyStart, bodyEnd);
                var parentState = parent != null ? new State(parent.Name, null, null, null, null, null, null, parent.StartPos, parent.EndPos) : null;
                return(new State(name.Value, body, specs, parentState, funcs, ignores, null, name.StartPosition, name.EndPosition));
            };

            return((State)Tokens.TryGetTree(stateSkeletonParser));
        }
Example #12
0
        public Class TryParseClass()
        {
            Func <ASTNode> classParser = () =>
            {
                if (Tokens.ConsumeToken(TokenType.Class) == null)
                {
                    return(Error("Expected class declaration!"));
                }

                var name = Tokens.ConsumeToken(TokenType.Word);
                if (name == null)
                {
                    return(Error("Expected class name!"));
                }

                var parentClass = TryParseParent();
                if (parentClass == null)
                {
                    Log.LogMessage("No parent class specified for " + name.Value + ", interiting from Object");
                    parentClass = new VariableType("Object", null, null);
                }

                var outerClass = TryParseOuter();

                var specs = ParseSpecifiers(GlobalLists.ClassSpecifiers);

                if (Tokens.ConsumeToken(TokenType.SemiColon) == null)
                {
                    return(Error("Expected semi-colon!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var variables = new List <VariableDeclaration>();
                var types     = new List <VariableType>();
                while (CurrentTokenType == TokenType.InstanceVariable ||
                       CurrentTokenType == TokenType.Struct ||
                       CurrentTokenType == TokenType.Enumeration)
                {
                    if (CurrentTokenType == TokenType.InstanceVariable)
                    {
                        var variable = TryParseVarDecl();
                        if (variable == null)
                        {
                            return(Error("Malformed instance variable!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                        }

                        variables.Add(variable);
                    }
                    else
                    {
                        var type = TryParseEnum() ?? TryParseStruct() ?? new VariableType("INVALID", null, null);
                        if (type.Name == "INVALID")
                        {
                            return(Error("Malformed type declaration!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                        }

                        types.Add(type);

                        if (Tokens.ConsumeToken(TokenType.SemiColon) == null)
                        {
                            return(Error("Expected semi-colon!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                        }
                    }
                }

                List <Function>            funcs  = new List <Function>();
                List <State>               states = new List <State>();
                List <OperatorDeclaration> ops    = new List <OperatorDeclaration>();
                ASTNode declaration;
                do
                {
                    declaration = (ASTNode)TryParseFunction() ??
                                  (ASTNode)TryParseOperatorDecl() ??
                                  (ASTNode)TryParseState() ??
                                  (ASTNode)null;
                    if (declaration == null && !Tokens.AtEnd())
                    {
                        return(Error("Expected function/state/operator declaration!",
                                     CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }

                    if (declaration.Type == ASTNodeType.Function)
                    {
                        funcs.Add((Function)declaration);
                    }
                    else if (declaration.Type == ASTNodeType.State)
                    {
                        states.Add((State)declaration);
                    }
                    else
                    {
                        ops.Add((OperatorDeclaration)declaration);
                    }
                } while (!Tokens.AtEnd());

                // TODO: should AST-nodes accept null values? should they make sure they dont present any?
                return(new Class(name.Value, specs, variables, types, funcs, states, parentClass, outerClass, ops, name.StartPosition, name.EndPosition));
            };

            return((Class)Tokens.TryGetTree(classParser));
        }