Esempio n. 1
0
        public void TestParseClass()
        {
            var source =
                "class Test Deprecated Transient; \n" +
                "var private deprecated int X; \n" +
                "struct transient testStruct\n" +
                "{ var float a, b, c; };\n" +
                "private simulated function float MyFunc( out testStruct one, coerce optional float two ) \n" +
                "{\n" +
                "   return one.b + funcB(one, two);\n" +
                "}\n" +
                "auto state MyState\n" +
                "{\n" +
                "ignores MyFunc;\n" +
                "function StateFunc()\n" +
                "{\n" +
                "}\n" +
                "Begin:\n" +
                "       moredragons\n" +
                "}\n" +
                "final static operator(254) int >>>( coerce float left, coerce float right )\n" +
                "{\n" +
                "   all the dragons\n" +
                "}\n" +
                "\n";
            var parser = new ClassOutlineParser(new TokenStream <String>(new StringLexer(source)), log);

            var decl = parser.TryParseClass();

            Assert.IsNotNull(decl);
            Assert.AreEqual(decl.Name.ToLower(), "test");
            Assert.AreEqual(decl.Specifiers[1].Value.ToLower(), "transient");
            Assert.AreEqual(decl.VariableDeclarations[0].Variables[0].Name.ToLower(), "x");
            Assert.AreEqual(decl.TypeDeclarations[0].Name.ToLower(), "teststruct");
            Assert.AreEqual(decl.Functions[0].Name.ToLower(), "myfunc");
            Assert.AreEqual(decl.States[0].Name.ToLower(), "mystate");
            Assert.AreEqual(decl.Operators[0].OperatorKeyword.ToLower(), ">>>");
            Assert.AreEqual(log.Messages[log.Messages.Count - 1].Message.Substring(0, 10), "No parent ");

            source = "test ;\n";
            parser = new ClassOutlineParser(new TokenStream <String>(new StringLexer(source)), log);
            Assert.IsNull(parser.TryParseClass());
            Assert.AreEqual(log.AllErrors[log.AllErrors.Count - 1].Message, "Expected class declaration!");

            source = "class ;\n";
            parser = new ClassOutlineParser(new TokenStream <String>(new StringLexer(source)), log);
            Assert.IsNull(parser.TryParseClass());
            Assert.AreEqual(log.AllErrors[log.AllErrors.Count - 1].Message, "Expected class name!");

            source = "class Test deprecated\n var int local;";
            parser = new ClassOutlineParser(new TokenStream <String>(new StringLexer(source)), log);
            Assert.IsNull(parser.TryParseClass());
            Assert.AreEqual(log.AllErrors[log.AllErrors.Count - 1].Message, "Expected semi-colon!");

            source = "class Test deprecated; \n var int ;";
            parser = new ClassOutlineParser(new TokenStream <String>(new StringLexer(source)), log);
            Assert.IsNull(parser.TryParseClass());
            Assert.AreEqual(log.AllErrors[log.AllErrors.Count - 1].Message, "Malformed instance variable!");

            source = "class Test deprecated; \n struct fail;";
            parser = new ClassOutlineParser(new TokenStream <String>(new StringLexer(source)), log);
            Assert.IsNull(parser.TryParseClass());
            Assert.AreEqual(log.AllErrors[log.AllErrors.Count - 1].Message, "Malformed type declaration!");

            source = "class Test deprecated; \n struct fail { var int one; } struct next;";
            parser = new ClassOutlineParser(new TokenStream <String>(new StringLexer(source)), log);
            Assert.IsNull(parser.TryParseClass());
            Assert.AreEqual(log.AllErrors[log.AllErrors.Count - 1].Message, "Expected semi-colon!");

            source = "class Test deprecated; \n struct fail { var int one; }; function myfunc() {} var int fail;";
            parser = new ClassOutlineParser(new TokenStream <String>(new StringLexer(source)), log);
            Assert.IsNull(parser.TryParseClass());
            Assert.AreEqual(log.AllErrors[log.AllErrors.Count - 1].Message, "Expected function/state/operator declaration!");

            return;
        }
Esempio n. 2
0
        public static bool ResolveAllClassesInPackage(IMEPackage pcc, ref SymbolTable symbols)
        {
            string fileName = Path.GetFileNameWithoutExtension(pcc.FilePath);

#if DEBUGSCRIPT
            string dumpFolderPath = Path.Combine(ME3Directory.gamePath, "ScriptDump", fileName);
            Directory.CreateDirectory(dumpFolderPath);
#endif
            var log = new MessageLog();
            Debug.WriteLine($"{fileName}: Beginning Parse.");
            var classes = new List <(Class ast, string scriptText)>();
            foreach (ExportEntry export in pcc.Exports.Where(exp => exp.IsClass))
            {
                Class  cls        = ME3ObjectToASTConverter.ConvertClass(export.GetBinaryData <UClass>(), false);
                string scriptText = "";
                try
                {
#if DEBUGSCRIPT
                    var codeBuilder = new CodeBuilderVisitor();
                    cls.AcceptVisitor(codeBuilder);
                    scriptText = codeBuilder.GetCodeString();
                    File.WriteAllText(Path.Combine(dumpFolderPath, $"{cls.Name}.uc"), scriptText);
                    var parser = new ClassOutlineParser(new TokenStream <string>(new StringLexer(scriptText, log)), log);
                    cls = parser.TryParseClass();
                    if (cls == null || log.Content.Any())
                    {
                        DisplayError(scriptText, log.ToString());
                        return(false);
                    }
#endif

                    if (export.ObjectName == "Object")
                    {
                        symbols = SymbolTable.CreateIntrinsicTable(cls);
                    }
                    else
                    {
                        symbols.AddType(cls);
                    }

                    classes.Add(cls, scriptText);
                }
                catch (Exception e) when(!App.IsDebug)
                {
                    DisplayError(scriptText, log.ToString());
                    return(false);
                }
            }
            Debug.WriteLine($"{fileName}: Finished parse.");
            foreach (var validationPass in Enums.GetValues <ValidationPass>())
            {
                foreach ((Class ast, string scriptText) in classes)
                {
                    try
                    {
                        var validator = new ClassValidationVisitor(log, symbols, validationPass);
                        ast.AcceptVisitor(validator);
                        if (log.Content.Any())
                        {
                            DisplayError(scriptText, log.ToString());
                            return(false);
                        }
                    }
                    catch (Exception e) when(!App.IsDebug)
                    {
                        DisplayError(scriptText, log.ToString());
                        return(false);
                    }
                }
                Debug.WriteLine($"{fileName}: Finished validation pass {validationPass}.");
            }

            switch (fileName)
            {
            case "Core":
                symbols.InitializeOperators();
                break;

            case "Engine":
                symbols.ValidateIntrinsics();
                break;
            }

#if DEBUGSCRIPT
            //parse function bodies for testing purposes
            foreach ((Class ast, string scriptText) in classes)
            {
                symbols.RevertToObjectStack();
                if (!ast.Name.CaseInsensitiveEquals("Object"))
                {
                    symbols.GoDirectlyToStack(((Class)ast.Parent).GetInheritanceString());
                    symbols.PushScope(ast.Name);
                }

                foreach (Function function in ast.Functions.Where(func => !func.IsNative && func.IsDefined))
                {
                    CodeBodyParser.ParseFunction(function, scriptText, symbols, log);
                    if (log.Content.Any())
                    {
                        DisplayError(scriptText, log.ToString());
                    }
                }
            }
#endif


            symbols.RevertToObjectStack();

            return(true);
        }