Example #1
0
        private static Executable ParseStruct(TokenStream tokens, Executable owner)
        {
            Token structToken     = tokens.PopExpected("struct");
            Token structNameToken = tokens.Pop();

            Parser.VerifyIdentifier(structNameToken);

            tokens.PopExpected("{");

            List <Token>      fieldTokens     = new List <Token>();
            List <Annotation> typeAnnotations = new List <Annotation>();
            bool nextForbidden = false;

            while (!tokens.PopIfPresent("}"))
            {
                if (nextForbidden)
                {
                    tokens.PopExpected("}");                // crash
                }
                Annotation annotation = tokens.IsNext("@") ? AnnotationParser.ParseAnnotation(tokens) : null;

                Token fieldToken = tokens.Pop();
                Parser.VerifyIdentifier(fieldToken);
                nextForbidden = !tokens.PopIfPresent(",");
                fieldTokens.Add(fieldToken);
                typeAnnotations.Add(annotation);
            }

            return(new StructDefinition(structToken, structNameToken, fieldTokens, typeAnnotations, owner));
        }
Example #2
0
        private static Executable ParseEnumDefinition(Parser parser, TokenStream tokens, Executable owner)
        {
            Token enumToken = tokens.PopExpected("enum");
            Token nameToken = tokens.Pop();

            Parser.VerifyIdentifier(nameToken);
            string name = nameToken.Value;

            tokens.PopExpected("{");
            bool              nextForbidden = false;
            List <Token>      items         = new List <Token>();
            List <Expression> values        = new List <Expression>();

            while (!tokens.PopIfPresent("}"))
            {
                if (nextForbidden)
                {
                    tokens.PopExpected("}");                // crash
                }
                Token enumItem = tokens.Pop();
                Parser.VerifyIdentifier(enumItem);
                if (tokens.PopIfPresent("="))
                {
                    values.Add(ExpressionParser.Parse(tokens, owner));
                }
                else
                {
                    values.Add(null);
                }
                nextForbidden = !tokens.PopIfPresent(",");
                items.Add(enumItem);
            }

            return(new EnumDefinition(enumToken, nameToken, parser.CurrentNamespace, items, values, owner));
        }
Example #3
0
        public Annotation ParseAnnotation(TokenStream tokens)
        {
            Token annotationToken = tokens.PopExpected("@");
            Token typeToken       = tokens.Pop();

            // TODO: refactor this. All built-in annotations should be exempt from the VerifyIdentifier check in an extensible way.
            if (typeToken.Value != this.parser.Keywords.PRIVATE)
            {
                parser.VerifyIdentifier(typeToken);
            }

            List <Expression> args = new List <Expression>();

            if (tokens.PopIfPresent("("))
            {
                while (!tokens.PopIfPresent(")"))
                {
                    if (args.Count > 0)
                    {
                        tokens.PopExpected(",");
                    }

                    args.Add(this.parser.ExpressionParser.Parse(tokens, null));
                }
            }
            return(new Annotation(annotationToken, typeToken, args));
        }
Example #4
0
        private static Executable ParseConstructor(Parser parser, TokenStream tokens, Executable owner)
        {
            Token constructorToken = tokens.PopExpected("constructor");

            tokens.PopExpected("(");
            List <Token>      argNames  = new List <Token>();
            List <Expression> argValues = new List <Expression>();
            bool optionalArgFound       = false;

            while (!tokens.PopIfPresent(")"))
            {
                if (argNames.Count > 0)
                {
                    tokens.PopExpected(",");
                }

                Token argName = tokens.Pop();
                Parser.VerifyIdentifier(argName);
                Expression defaultValue = null;
                if (tokens.PopIfPresent("="))
                {
                    defaultValue     = ExpressionParser.Parse(tokens, owner);
                    optionalArgFound = true;
                }
                else if (optionalArgFound)
                {
                    throw new ParserException(argName, "All optional arguments must come at the end of the argument list.");
                }

                argNames.Add(argName);
                argValues.Add(defaultValue);
            }

            List <Expression> baseArgs  = new List <Expression>();
            Token             baseToken = null;

            if (tokens.PopIfPresent(":"))
            {
                baseToken = tokens.PopExpected("base");
                tokens.PopExpected("(");
                while (!tokens.PopIfPresent(")"))
                {
                    if (baseArgs.Count > 0)
                    {
                        tokens.PopExpected(",");
                    }

                    baseArgs.Add(ExpressionParser.Parse(tokens, owner));
                }
            }

            IList <Executable> code = Parser.ParseBlock(parser, tokens, true, owner);

            return(new ConstructorDefinition(constructorToken, argNames, argValues, baseArgs, code, baseToken, owner));
        }
Example #5
0
        private static string PopClassName(TokenStream tokens, Token firstToken)
        {
            Parser.VerifyIdentifier(firstToken);
            string name = firstToken.Value;

            while (tokens.PopIfPresent("."))
            {
                Token nameNext = tokens.Pop();
                Parser.VerifyIdentifier(nameNext);
                name += "." + nameNext.Value;
            }
            return(name);
        }
Example #6
0
        private static Executable ParseConst(Parser parser, TokenStream tokens, Executable owner)
        {
            Token constToken = tokens.PopExpected("const");
            Token nameToken  = tokens.Pop();

            Parser.VerifyIdentifier(nameToken);
            tokens.PopExpected("=");
            Expression expression = ExpressionParser.Parse(tokens, owner);

            tokens.PopExpected(";");

            return(new ConstStatement(constToken, nameToken, parser.CurrentNamespace, expression, owner));
        }
Example #7
0
        private static Executable ParseNamespace(Parser parser, TokenStream tokens, Executable owner)
        {
            Token namespaceToken = tokens.PopExpected("namespace");
            Token first          = tokens.Pop();

            Parser.VerifyIdentifier(first);
            List <Token> namespacePieces = new List <Token>()
            {
                first
            };

            while (tokens.PopIfPresent("."))
            {
                Token nsToken = tokens.Pop();
                Parser.VerifyIdentifier(nsToken);
                namespacePieces.Add(nsToken);
            }

            string name = string.Join(".", namespacePieces.Select <Token, string>(t => t.Value));

            parser.PushNamespacePrefix(name);

            Namespace namespaceInstance = new Namespace(namespaceToken, name, owner);

            tokens.PopExpected("{");
            List <Executable> namespaceMembers = new List <Executable>();

            while (!tokens.PopIfPresent("}"))
            {
                Executable executable = ExecutableParser.Parse(parser, tokens, false, false, true, namespaceInstance);
                if (executable is FunctionDefinition ||
                    executable is ClassDefinition ||
                    executable is EnumDefinition ||
                    executable is ConstStatement ||
                    executable is Namespace)
                {
                    namespaceMembers.Add(executable);
                }
                else
                {
                    throw new ParserException(executable.FirstToken, "Only function, class, and nested namespace declarations may exist as direct members of a namespace.");
                }
            }

            namespaceInstance.Code = namespaceMembers.ToArray();

            parser.PopNamespacePrefix();

            return(namespaceInstance);
        }
Example #8
0
        private static FieldDeclaration ParseField(TokenStream tokens, ClassDefinition owner)
        {
            bool  isStatic   = tokens.PopIfPresent("static");
            Token fieldToken = tokens.PopExpected("field");
            Token nameToken  = tokens.Pop();

            Parser.VerifyIdentifier(nameToken);
            FieldDeclaration fd = new FieldDeclaration(fieldToken, nameToken, owner, isStatic);

            if (tokens.PopIfPresent("="))
            {
                fd.DefaultValue = ExpressionParser.Parse(tokens, owner);
            }
            tokens.PopExpected(";");
            return(fd);
        }
Example #9
0
        public static Annotation ParseAnnotation(TokenStream tokens)
        {
            Token annotationToken = tokens.PopExpected("@");
            Token typeToken       = tokens.Pop();

            Parser.VerifyIdentifier(typeToken);
            List <Expression> args = new List <Expression>();

            if (tokens.PopIfPresent("("))
            {
                while (!tokens.PopIfPresent(")"))
                {
                    if (args.Count > 0)
                    {
                        tokens.PopExpected(",");
                    }

                    args.Add(ExpressionParser.Parse(tokens, null));
                }
            }
            return(new Annotation(annotationToken, typeToken, args));
        }
Example #10
0
        public TopLevelConstruct ParseTopLevel(
            TokenStream tokens,
            TopLevelConstruct owner,
            FileScope fileScope)
        {
            string value = tokens.PeekValue();

            Token staticToken = null;
            Token finalToken  = null;

            while (value == this.parser.Keywords.STATIC || value == this.parser.Keywords.FINAL)
            {
                if (value == this.parser.Keywords.STATIC && staticToken == null)
                {
                    staticToken = tokens.Pop();
                    value       = tokens.PeekValue();
                }
                if (value == this.parser.Keywords.FINAL && finalToken == null)
                {
                    finalToken = tokens.Pop();
                    value      = tokens.PeekValue();
                }
            }

            if (staticToken != null || finalToken != null)
            {
                if (value != this.parser.Keywords.CLASS)
                {
                    if (staticToken != null)
                    {
                        throw new ParserException(staticToken, "Only classes, methods, and fields may be marked as static");
                    }
                    else
                    {
                        throw new ParserException(finalToken, "Only classes may be marked as final.");
                    }
                }

                if (staticToken != null && finalToken != null)
                {
                    throw new ParserException(staticToken, "Classes cannot be both static and final.");
                }
            }

            if (value == parser.Keywords.IMPORT)
            {
                Token         importToken       = tokens.PopExpected(parser.Keywords.IMPORT);
                List <string> importPathBuilder = new List <string>();
                while (!tokens.PopIfPresent(";"))
                {
                    if (importPathBuilder.Count > 0)
                    {
                        tokens.PopExpected(".");
                    }

                    Token pathToken = tokens.Pop();
                    parser.VerifyIdentifier(pathToken);
                    importPathBuilder.Add(pathToken.Value);
                }
                string importPath = string.Join(".", importPathBuilder);

                return(new ImportStatement(importToken, importPath, parser.CurrentLibrary, fileScope));
            }

            if (value == this.parser.Keywords.ENUM)
            {
                return(this.ParseEnumDefinition(tokens, owner, fileScope));
            }

            if (value == this.parser.Keywords.NAMESPACE)
            {
                return(this.ParseNamespace(tokens, owner, fileScope));
            }

            if (value == this.parser.Keywords.CONST)
            {
                return(this.ParseConst(tokens, owner, fileScope));
            }
            if (value == this.parser.Keywords.FUNCTION)
            {
                return(this.ParseFunction(tokens, owner, fileScope));
            }
            if (value == this.parser.Keywords.CLASS)
            {
                return(this.ParseClassDefinition(tokens, owner, staticToken, finalToken, fileScope));
            }
            if (value == this.parser.Keywords.ENUM)
            {
                return(this.ParseEnumDefinition(tokens, owner, fileScope));
            }
            if (value == this.parser.Keywords.CONSTRUCTOR)
            {
                return(this.ParseConstructor(tokens, owner));
            }

            throw new ParserException(tokens.Peek(), "Unrecognized token.");
        }
Example #11
0
        private static Expression ParseEntity(TokenStream tokens, Executable owner)
        {
            Expression root;

            if (tokens.PopIfPresent("("))
            {
                root = Parse(tokens, owner);
                tokens.PopExpected(")");
            }
            else
            {
                root = ParseEntityWithoutSuffixChain(tokens, owner);
            }
            bool anySuffixes = true;

            while (anySuffixes)
            {
                if (tokens.IsNext("."))
                {
                    Token dotToken  = tokens.Pop();
                    Token stepToken = tokens.Pop();
                    Parser.VerifyIdentifier(stepToken);
                    root = new DotStep(root, dotToken, stepToken, owner);
                }
                else if (tokens.IsNext("["))
                {
                    Token             openBracket     = tokens.Pop();
                    List <Expression> sliceComponents = new List <Expression>();
                    if (tokens.IsNext(":"))
                    {
                        sliceComponents.Add(null);
                    }
                    else
                    {
                        sliceComponents.Add(Parse(tokens, owner));
                    }

                    for (int i = 0; i < 2; ++i)
                    {
                        if (tokens.PopIfPresent(":"))
                        {
                            if (tokens.IsNext(":") || tokens.IsNext("]"))
                            {
                                sliceComponents.Add(null);
                            }
                            else
                            {
                                sliceComponents.Add(Parse(tokens, owner));
                            }
                        }
                    }

                    tokens.PopExpected("]");

                    if (sliceComponents.Count == 1)
                    {
                        Expression index = sliceComponents[0];
                        root = new BracketIndex(root, openBracket, index, owner);
                    }
                    else
                    {
                        root = new ListSlice(root, sliceComponents, openBracket, owner);
                    }
                }
                else if (tokens.IsNext("("))
                {
                    Token             openParen = tokens.Pop();
                    List <Expression> args      = new List <Expression>();
                    while (!tokens.PopIfPresent(")"))
                    {
                        if (args.Count > 0)
                        {
                            tokens.PopExpected(",");
                        }

                        args.Add(Parse(tokens, owner));
                    }
                    root = new FunctionCall(root, openParen, args, owner);
                }
                else if (tokens.IsNext("is"))
                {
                    Token  isToken    = tokens.Pop();
                    Token  classToken = tokens.Pop();
                    string className  = PopClassName(tokens, classToken);
                    root = new IsComparison(root, isToken, classToken, className, owner);
                }
                else
                {
                    anySuffixes = false;
                }
            }
            return(root);
        }
Example #12
0
        public Executable Parse(
            TokenStream tokens,
            bool simpleOnly,
            bool semicolonPresent,
            bool isRoot,
            Executable owner)
        {
            string value = tokens.PeekValue();

            if (!simpleOnly)
            {
                Token staticToken = null;
                Token finalToken  = null;
                while (value == this.parser.Keywords.STATIC || value == this.parser.Keywords.FINAL)
                {
                    if (value == this.parser.Keywords.STATIC && staticToken == null)
                    {
                        staticToken = tokens.Pop();
                        value       = tokens.PeekValue();
                    }
                    if (value == this.parser.Keywords.FINAL && finalToken == null)
                    {
                        finalToken = tokens.Pop();
                        value      = tokens.PeekValue();
                    }
                }

                if (staticToken != null || finalToken != null)
                {
                    if (value != this.parser.Keywords.CLASS)
                    {
                        if (staticToken != null)
                        {
                            throw new ParserException(staticToken, "Only classes, methods, and fields may be marked as static");
                        }
                        else
                        {
                            throw new ParserException(finalToken, "Only classes may be marked as final.");
                        }
                    }

                    if (staticToken != null && finalToken != null)
                    {
                        throw new ParserException(staticToken, "Classes cannot be both static and final.");
                    }
                }

                if (!isRoot &&
                    (value == this.parser.Keywords.FUNCTION || value == this.parser.Keywords.CLASS))
                {
                    throw new ParserException(
                              tokens.Peek(),
                              (value == this.parser.Keywords.FUNCTION ? "Function" : "Class") +
                              " definition cannot be nested in another construct.");
                }


                if (value == parser.Keywords.IMPORT)
                {
                    Token importToken = tokens.PopExpected(parser.Keywords.IMPORT);

                    if (!isRoot)
                    {
                        throw new ParserException(tokens.Peek(), "Imports can only be made from the root of a file and cannot be nested inside other constructs.");
                    }

                    List <string> importPathBuilder = new List <string>();
                    while (!tokens.PopIfPresent(";"))
                    {
                        if (importPathBuilder.Count > 0)
                        {
                            tokens.PopExpected(".");
                        }

                        Token pathToken = tokens.Pop();
                        parser.VerifyIdentifier(pathToken);
                        importPathBuilder.Add(pathToken.Value);
                    }
                    string importPath = string.Join(".", importPathBuilder);

                    return(new ImportStatement(importToken, importPath));
                }

                if (value == this.parser.Keywords.ENUM)
                {
                    if (!isRoot)
                    {
                        throw new ParserException(tokens.Peek(), "Enums can only be defined from the root of a file and cannot be nested inside functions/loops/etc.");
                    }

                    return(this.ParseEnumDefinition(tokens, owner));
                }

                if (value == this.parser.Keywords.NAMESPACE)
                {
                    if (!isRoot)
                    {
                        throw new ParserException(tokens.Peek(), "Namespace declarations cannot be nested in other constructs.");
                    }
                    return(this.ParseNamespace(tokens, owner));
                }

                if (value == this.parser.Keywords.CONST)
                {
                    return(this.ParseConst(tokens, owner));
                }
                if (value == this.parser.Keywords.FUNCTION)
                {
                    return(this.ParseFunction(tokens, owner));
                }
                if (value == this.parser.Keywords.CLASS)
                {
                    return(this.ParseClassDefinition(tokens, owner, staticToken, finalToken));
                }
                if (value == this.parser.Keywords.ENUM)
                {
                    return(this.ParseEnumDefinition(tokens, owner));
                }
                if (value == this.parser.Keywords.FOR)
                {
                    return(this.ParseFor(tokens, owner));
                }
                if (value == this.parser.Keywords.WHILE)
                {
                    return(this.ParseWhile(tokens, owner));
                }
                if (value == this.parser.Keywords.DO)
                {
                    return(this.ParseDoWhile(tokens, owner));
                }
                if (value == this.parser.Keywords.SWITCH)
                {
                    return(this.ParseSwitch(tokens, owner));
                }
                if (value == this.parser.Keywords.IF)
                {
                    return(this.ParseIf(tokens, owner));
                }
                if (value == this.parser.Keywords.TRY)
                {
                    return(this.ParseTry(tokens, owner));
                }
                if (value == this.parser.Keywords.RETURN)
                {
                    return(this.ParseReturn(tokens, owner));
                }
                if (value == this.parser.Keywords.BREAK)
                {
                    return(this.ParseBreak(tokens, owner));
                }
                if (value == this.parser.Keywords.CONTINUE)
                {
                    return(this.ParseContinue(tokens, owner));
                }
                if (value == this.parser.Keywords.CONSTRUCTOR)
                {
                    return(this.ParseConstructor(tokens, owner));
                }
                if (value == this.parser.Keywords.THROW)
                {
                    return(this.ParseThrow(tokens, owner));
                }
            }

            Expression expr = this.parser.ExpressionParser.Parse(tokens, owner);

            value = tokens.PeekValue();
            if (ASSIGNMENT_OPS.Contains(value))
            {
                Token      assignment      = tokens.Pop();
                Expression assignmentValue = this.parser.ExpressionParser.Parse(tokens, owner);
                if (semicolonPresent)
                {
                    tokens.PopExpected(";");
                }
                return(new Assignment(expr, assignment, assignment.Value, assignmentValue, owner));
            }

            if (semicolonPresent)
            {
                tokens.PopExpected(";");
            }

            return(new ExpressionAsExecutable(expr, owner));
        }
Example #13
0
        private static Executable ParseFunction(Parser parser, TokenStream tokens, Executable nullableOwner)
        {
            bool isStatic =
                nullableOwner != null &&
                nullableOwner is ClassDefinition &&
                tokens.PopIfPresent("static");

            Token functionToken = tokens.PopExpected("function");

            List <Annotation> functionAnnotations = new List <Annotation>();

            while (tokens.IsNext("@"))
            {
                functionAnnotations.Add(AnnotationParser.ParseAnnotation(tokens));
            }

            Token functionNameToken = tokens.Pop();

            Parser.VerifyIdentifier(functionNameToken);

            FunctionDefinition fd = new FunctionDefinition(functionToken, nullableOwner, isStatic, functionNameToken, functionAnnotations, parser.CurrentNamespace);

            tokens.PopExpected("(");
            List <Token>      argNames       = new List <Token>();
            List <Expression> defaultValues  = new List <Expression>();
            List <Annotation> argAnnotations = new List <Annotation>();
            bool optionalArgFound            = false;

            while (!tokens.PopIfPresent(")"))
            {
                if (argNames.Count > 0)
                {
                    tokens.PopExpected(",");
                }

                Annotation annotation   = tokens.IsNext("@") ? AnnotationParser.ParseAnnotation(tokens) : null;
                Token      argName      = tokens.Pop();
                Expression defaultValue = null;
                Parser.VerifyIdentifier(argName);
                if (tokens.PopIfPresent("="))
                {
                    optionalArgFound = true;
                    defaultValue     = ExpressionParser.Parse(tokens, fd);
                }
                else if (optionalArgFound)
                {
                    throw new ParserException(argName, "All optional arguments must come at the end of the argument list.");
                }
                argAnnotations.Add(annotation);
                argNames.Add(argName);
                defaultValues.Add(defaultValue);
            }

            IList <Executable> code = Parser.ParseBlock(parser, tokens, true, fd);

            fd.ArgNames       = argNames.ToArray();
            fd.DefaultValues  = defaultValues.ToArray();
            fd.ArgAnnotations = argAnnotations.ToArray();
            fd.Code           = code.ToArray();

            return(fd);
        }
Example #14
0
        private static Executable ParseClassDefinition(Parser parser, TokenStream tokens, Executable owner, Token staticToken, Token finalToken)
        {
            Token classToken     = tokens.PopExpected("class");
            Token classNameToken = tokens.Pop();

            Parser.VerifyIdentifier(classNameToken);
            List <Token>  baseClassTokens  = new List <Token>();
            List <string> baseClassStrings = new List <string>();

            if (tokens.PopIfPresent(":"))
            {
                if (baseClassTokens.Count > 0)
                {
                    tokens.PopExpected(",");
                }

                Token  baseClassToken = tokens.Pop();
                string baseClassName  = baseClassToken.Value;

                Parser.VerifyIdentifier(baseClassToken);
                while (tokens.PopIfPresent("."))
                {
                    Token baseClassTokenNext = tokens.Pop();
                    Parser.VerifyIdentifier(baseClassTokenNext);
                    baseClassName += "." + baseClassTokenNext.Value;
                }

                baseClassTokens.Add(baseClassToken);
                baseClassStrings.Add(baseClassName);
            }

            ClassDefinition cd = new ClassDefinition(
                classToken,
                classNameToken,
                baseClassTokens,
                baseClassStrings,
                parser.CurrentNamespace,
                owner,
                staticToken,
                finalToken);

            tokens.PopExpected("{");
            List <FunctionDefinition> methods              = new List <FunctionDefinition>();
            List <FieldDeclaration>   fields               = new List <FieldDeclaration>();
            ConstructorDefinition     constructorDef       = null;
            ConstructorDefinition     staticConstructorDef = null;

            while (!tokens.PopIfPresent("}"))
            {
                Dictionary <string, List <Annotation> > annotations = null;

                while (tokens.IsNext("@"))
                {
                    annotations = annotations ?? new Dictionary <string, List <Annotation> >();
                    Annotation annotation = AnnotationParser.ParseAnnotation(tokens);
                    if (!annotations.ContainsKey(annotation.Type))
                    {
                        annotations[annotation.Type] = new List <Annotation>();
                    }

                    annotations[annotation.Type].Add(annotation);
                }

                if (tokens.IsNext("function") || tokens.AreNext("static", "function"))
                {
                    methods.Add((FunctionDefinition)ExecutableParser.ParseFunction(parser, tokens, cd));
                }
                else if (tokens.IsNext("constructor"))
                {
                    if (constructorDef != null)
                    {
                        throw new ParserException(tokens.Pop(), "Multiple constructors are not allowed. Use optional arguments.");
                    }

                    constructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd);

                    if (annotations != null && annotations.ContainsKey("private"))
                    {
                        constructorDef.PrivateAnnotation = annotations["private"][0];
                        annotations["private"].RemoveAt(0);
                    }
                }
                else if (tokens.AreNext("static", "constructor"))
                {
                    tokens.Pop(); // static token
                    if (staticConstructorDef != null)
                    {
                        throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed.");
                    }

                    staticConstructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd);
                }
                else if (tokens.IsNext("field") || tokens.AreNext("static", "field"))
                {
                    fields.Add(ExecutableParser.ParseField(tokens, cd));
                }
                else
                {
                    tokens.PopExpected("}");
                }

                if (annotations != null)
                {
                    foreach (List <Annotation> annotationsOfType in annotations.Values)
                    {
                        if (annotationsOfType.Count > 0)
                        {
                            throw new ParserException(annotationsOfType[0].FirstToken, "Unused or extra annotation.");
                        }
                    }
                }
            }

            cd.Methods           = methods.ToArray();
            cd.Constructor       = constructorDef;
            cd.StaticConstructor = staticConstructorDef;
            cd.Fields            = fields.ToArray();

            return(cd);
        }
Example #15
0
        public static Executable Parse(Parser parser, TokenStream tokens, bool simpleOnly, bool semicolonPresent, bool isRoot, Executable owner)
        {
            string value = tokens.PeekValue();

            if (!simpleOnly)
            {
                Token staticToken = null;
                Token finalToken  = null;
                while (value == "static" || value == "final")
                {
                    if (value == "static" && staticToken == null)
                    {
                        staticToken = tokens.Pop();
                        value       = tokens.PeekValue();
                    }
                    if (value == "final" && finalToken == null)
                    {
                        finalToken = tokens.Pop();
                        value      = tokens.PeekValue();
                    }
                }

                if (staticToken != null || finalToken != null)
                {
                    if (value != "class")
                    {
                        if (staticToken != null)
                        {
                            throw new ParserException(staticToken, "Only classes, methods, and fields may be marked as static");
                        }
                        else
                        {
                            throw new ParserException(finalToken, "Only classes may be marked as final.");
                        }
                    }

                    if (staticToken != null && finalToken != null)
                    {
                        throw new ParserException(staticToken, "Classes cannot be both static and final.");
                    }
                }

                if (!isRoot && (value == "function" || value == "class"))
                {
                    throw new ParserException(tokens.Peek(), (value == "function" ? "Function" : "Class") + " definition cannot be nested in another construct.");
                }

                if (parser.IsTranslateMode && value == "struct")
                {
                    if (!isRoot)
                    {
                        throw new ParserException(tokens.Peek(), "structs cannot be nested into any other construct.");
                    }

                    return(ParseStruct(tokens, owner));
                }

                if (value == "import")
                {
                    Token importToken = tokens.PopExpected("import");

                    bool inline = parser.IsTranslateMode && tokens.PopIfPresent("inline");

                    if (inline)
                    {
                        Token fileToken = tokens.Pop();
                        char  c         = fileToken.Value[0];
                        if (c != '\'' && c != '"')
                        {
                            throw new ParserException(fileToken, "Inline imports are supposed to be strings.");
                        }
                        tokens.PopExpected(";");
                        string inlineImportFileName = fileToken.Value.Substring(1, fileToken.Value.Length - 2);
                        string inlineImportFileContents;
                        if (inlineImportFileName.StartsWith("LIB:"))
                        {
                            string[] parts       = inlineImportFileName.Split(':');
                            string   libraryName = parts[1];
                            string   filename    = FileUtil.JoinPath(parts[2].Split('/'));
                            Library  library     = parser.SystemLibraryManager.GetLibraryFromKey(libraryName.ToLower());
                            inlineImportFileContents = library.ReadFile(filename, false);
                        }
                        else
                        {
                            inlineImportFileContents = Util.ReadInterpreterFileInternally(inlineImportFileName);
                        }
                        // TODO: Anti-pattern alert. Clean this up.
                        if (inlineImportFileContents.Contains("%%%"))
                        {
                            Dictionary <string, string> replacements = parser.NullablePlatform.InterpreterCompiler.BuildReplacementsDictionary();
                            inlineImportFileContents = Constants.DoReplacements(inlineImportFileContents, replacements);
                        }
                        Token[] inlineTokens = Tokenizer.Tokenize(inlineImportFileName, inlineImportFileContents, 0, true);

                        tokens.InsertTokens(inlineTokens);

                        return(ExecutableParser.Parse(parser, tokens, simpleOnly, semicolonPresent, isRoot, owner)); // start exectuable parser anew.
                    }

                    if (!isRoot)
                    {
                        throw new ParserException(tokens.Peek(), "Imports can only be made from the root of a file and cannot be nested inside other constructs.");
                    }

                    List <string> importPathBuilder = new List <string>();
                    while (!tokens.PopIfPresent(";"))
                    {
                        if (importPathBuilder.Count > 0)
                        {
                            tokens.PopExpected(".");
                        }

                        Token pathToken = tokens.Pop();
                        Parser.VerifyIdentifier(pathToken);
                        importPathBuilder.Add(pathToken.Value);
                    }
                    string importPath = string.Join(".", importPathBuilder);

                    return(new ImportStatement(importToken, importPath));
                }

                if (value == "enum")
                {
                    if (!isRoot)
                    {
                        throw new ParserException(tokens.Peek(), "Enums can only be defined from the root of a file and cannot be nested inside functions/loops/etc.");
                    }

                    return(ParseEnumDefinition(parser, tokens, owner));
                }

                if (value == "namespace")
                {
                    if (!isRoot)
                    {
                        throw new ParserException(tokens.Peek(), "Namespace declarations cannot be nested in other constructs.");
                    }
                }

                switch (value)
                {
                case "namespace": return(ParseNamespace(parser, tokens, owner));

                case "function": return(ParseFunction(parser, tokens, owner));

                case "class": return(ParseClassDefinition(parser, tokens, owner, staticToken, finalToken));

                case "enum": return(ParseEnumDefinition(parser, tokens, owner));

                case "for": return(ParseFor(parser, tokens, owner));

                case "while": return(ParseWhile(parser, tokens, owner));

                case "do": return(ParseDoWhile(parser, tokens, owner));

                case "switch": return(ParseSwitch(parser, tokens, owner));

                case "if": return(ParseIf(parser, tokens, owner));

                case "try": return(ParseTry(parser, tokens, owner));

                case "return": return(ParseReturn(tokens, owner));

                case "break": return(ParseBreak(tokens, owner));

                case "continue": return(ParseContinue(tokens, owner));

                case "const": return(ParseConst(parser, tokens, owner));

                case "constructor": return(ParseConstructor(parser, tokens, owner));

                default: break;
                }
            }

            Expression expr = ExpressionParser.Parse(tokens, owner);

            value = tokens.PeekValue();
            if (ASSIGNMENT_OPS.Contains(value))
            {
                Token      assignment      = tokens.Pop();
                Expression assignmentValue = ExpressionParser.Parse(tokens, owner);
                if (semicolonPresent)
                {
                    tokens.PopExpected(";");
                }
                return(new Assignment(expr, assignment, assignment.Value, assignmentValue, owner));
            }

            if (semicolonPresent)
            {
                tokens.PopExpected(";");
            }

            return(new ExpressionAsExecutable(expr, owner));
        }