示例#1
0
文件: Parser.cs 项目: falun/crayon
        internal static IList <Executable> ParseBlock(Parser parser, TokenStream tokens, bool bracketsRequired, Executable owner)
        {
            List <Executable> output = new List <Executable>();

            if (tokens.PopIfPresent("{"))
            {
                while (!tokens.PopIfPresent("}"))
                {
                    output.Add(ExecutableParser.Parse(parser, tokens, false, true, false, owner));
                }
            }
            else
            {
                if (bracketsRequired)
                {
                    tokens.PopExpected("{"); // throws with reasonable exception message.
                }

                if (tokens.PopIfPresent(";"))
                {
                    return(output);
                }

                output.Add(ExecutableParser.Parse(parser, tokens, false, true, false, owner));
            }
            return(output);
        }
示例#2
0
文件: Parser.cs 项目: falun/crayon
        public Executable[] ParseInterpretedCode(string filename, string code, string libraryName)
        {
            int fileId = this.GetNextFileId();

            this.RegisterFileUsed(filename, code, fileId);
            Token[]     tokenList = Tokenizer.Tokenize(filename, code, fileId, true);
            TokenStream tokens    = new TokenStream(tokenList);

            List <Executable> executables = new List <Executable>();

            List <string> namespaceImportsBuilder = new List <string>();

            tokens.InsertTokens(implicitCoreImport);

            while (tokens.HasMore && tokens.IsNext("import"))
            {
                ImportStatement importStatement = ExecutableParser.Parse(this, tokens, false, true, true, null) as ImportStatement;
                if (importStatement == null)
                {
                    throw new Exception();
                }
                namespaceImportsBuilder.Add(importStatement.ImportPath);
                Executable[] libraryEmbeddedCode = this.SystemLibraryManager.ImportLibrary(this, importStatement.FirstToken, importStatement.ImportPath);
                executables.AddRange(libraryEmbeddedCode);
            }

            string[] namespaceImports = namespaceImportsBuilder.ToArray();

            while (tokens.HasMore)
            {
                Executable executable;
                try
                {
                    executable = ExecutableParser.Parse(this, tokens, false, true, true, null);
                }
                catch (EofException)
                {
                    throw new ParserException(null, "Unexpected EOF encountered while parsing " + filename + ". Did you forget a closing curly brace?");
                }

                if (executable is ImportStatement)
                {
                    throw new ParserException(executable.FirstToken, "All imports must occur at the beginning of the file.");
                }

                executable.NamespacePrefixSearch = namespaceImports;
                executable.LibraryName           = libraryName;

                if (executable is Namespace)
                {
                    ((Namespace)executable).GetFlattenedCode(executables, namespaceImports, libraryName);
                }
                else
                {
                    executables.Add(executable);
                }
            }

            return(executables.ToArray());
        }
示例#3
0
文件: Parser.cs 项目: falun/crayon
        public Executable[] ParseInterpreterCode(string filename, string contents)
        {
            TokenStream       tokens = new TokenStream(Tokenizer.Tokenize(filename, contents, 0, true));
            List <Executable> output = new List <Executable>();

            while (tokens.HasMore)
            {
                output.Add(ExecutableParser.Parse(this, tokens, false, true, true, null));
            }
            return(new Resolver(this, output).ResolveTranslatedCode());
        }
示例#4
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);
        }
示例#5
0
        private static Executable ParseSwitch(Parser parser, TokenStream tokens, Executable owner)
        {
            Token switchToken = tokens.PopExpected("switch");

            Expression explicitMax      = null;
            Token      explicitMaxToken = null;

            if (tokens.IsNext("{"))
            {
                explicitMaxToken = tokens.Pop();
                explicitMax      = ExpressionParser.Parse(tokens, owner);
                tokens.PopExpected("}");
            }

            tokens.PopExpected("(");
            Expression condition = ExpressionParser.Parse(tokens, owner);

            tokens.PopExpected(")");
            tokens.PopExpected("{");
            List <List <Expression> > cases = new List <List <Expression> >();
            List <Token> firstTokens        = new List <Token>();
            List <List <Executable> > code  = new List <List <Executable> >();
            char state = '?'; // ? - first, O - code, A - case
            bool defaultEncountered = false;

            while (!tokens.PopIfPresent("}"))
            {
                if (tokens.IsNext("case"))
                {
                    if (defaultEncountered)
                    {
                        throw new ParserException(tokens.Peek(), "default condition in a switch statement must be the last condition.");
                    }

                    Token caseToken = tokens.PopExpected("case");
                    if (state != 'A')
                    {
                        cases.Add(new List <Expression>());
                        firstTokens.Add(caseToken);
                        code.Add(null);
                        state = 'A';
                    }
                    cases[cases.Count - 1].Add(ExpressionParser.Parse(tokens, owner));
                    tokens.PopExpected(":");
                }
                else if (tokens.IsNext("default"))
                {
                    Token defaultToken = tokens.PopExpected("default");
                    if (state != 'A')
                    {
                        cases.Add(new List <Expression>());
                        firstTokens.Add(defaultToken);
                        code.Add(null);
                        state = 'A';
                    }
                    cases[cases.Count - 1].Add(null);
                    tokens.PopExpected(":");
                    defaultEncountered = true;
                }
                else
                {
                    if (state != 'O')
                    {
                        cases.Add(null);
                        firstTokens.Add(null);
                        code.Add(new List <Executable>());
                        state = 'O';
                    }
                    code[code.Count - 1].Add(ExecutableParser.Parse(parser, tokens, false, true, false, owner));
                }
            }

            return(new SwitchStatement(switchToken, condition, firstTokens, cases, code, explicitMax, explicitMaxToken, owner));
        }
示例#6
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));
        }