public async Task <PapyrusAssemblyObject> Parse(string file) { return(await Task.Run(() => { PapyrusAssemblyObject obj = null; var ext = Path.GetExtension(file); if (!string.IsNullOrEmpty(ext)) { // StatusCallback.WriteLine("... " + Path.GetFileNameWithoutExtension(file)); obj = ext.ToLower().EndsWith("pas") ? PapyrusAssemblyParser.ParseAssembly(file) : PapyrusScriptParser.ParseScript(file); } filesParsed++; StatusCallback.Title = "PapyrusDotNet - Parsing Papyrus: " + filesParsed + "/" + totalFilesToParse; return obj; })); }
public PapyrusAssemblyObject ParseScript(string file) { var obj = new PapyrusAssemblyObject(); var scriptObject = Parse(file); var objName = scriptObject.Name; obj.Name = objName; foreach (var s in scriptObject.StateFunctions) { var state = new PapyrusAssemblyState(); state.Name = s.Name; foreach (var f in s.Functions) { var sourceFunction = f; if (!string.IsNullOrEmpty(sourceFunction.StateName) && string.IsNullOrEmpty(state.Name)) { state.Name = sourceFunction.StateName; } var function = new PapyrusAssemblyFunction(); function.Name = functionNameResolver.Resolve(sourceFunction.Name); function.ReturnType = sourceFunction.ReturnType.VarType; function.ReturnArray = sourceFunction.ReturnType.IsArray; var inputNameIndex = 0; foreach (var p in sourceFunction.Parameters) { function.Params.Add(new PapyrusAssemblyVariable(p.Name, p.VarType)); inputNameIndex++; } function.IsStatic = sourceFunction.IsGlobal; function.IsNative = sourceFunction.IsNative; function.IsEvent = sourceFunction.IsEvent; // Since we are only generating "dummy" classes, // the function scope is not necessary at this point. // var fs = sourceFunction.FunctionScope; state.Functions.Add(function); } obj.States.Add(state); } // Ignore Non Overridable Functions for now. // We will need to handle these later to make sure that a user // does not override them. GetState, SetState are both common. //var nof = scriptObject.kNonOverridableFunctions; //var instanceVars = scriptObject.kInstanceVariables; //var propertyVars = scriptObject.kProperties; // If the script is extended by another script // The script will have a parent. if (scriptObject.Extends != null) { obj.ExtendsName = scriptObject.Extends; } foreach (var prop in scriptObject.Properties) { obj.PropertyTable.Add(new PapyrusAssemblyVariable(prop.Name, prop.VarType)); } foreach (var field in scriptObject.InstanceVariables) { // Most likely an auto- property // And we have already added them above. if (field.Name.StartsWith("::")) { continue; } } // throw new NotImplementedException("Parsing from .psc/ Skyrim Papyrus Scripts are not yet supported."); // TypeDefinition def = new TypeDefinition("","", TypeAttributes.); return(obj); }
public TypeDefinition Resolve(ModuleDefinition mainModule, PapyrusAssemblyObject input) { var newType = new TypeDefinition(assemblyNameResolver.BaseNamespace, input.Name, TypeAttributes.Class) { IsPublic = true }; // newType.DeclaringType = newType; if (!string.IsNullOrEmpty(input.ExtendsName)) { newType.BaseType = new TypeReference(assemblyNameResolver.BaseNamespace, input.ExtendsName, mainModule, mainModule); // newType.DeclaringType = MainModule.Types.FirstOrDefault(t => t.FullName == newType.BaseType.FullName); newType.Scope = mainModule; } else { newType.BaseType = mainModule.TypeSystem.Object; newType.Scope = mainModule; } statusCallback.WriteLine("Generating Type '" + assemblyNameResolver.BaseNamespace + "." + input.Name + "'..."); foreach (var prop in input.PropertyTable) { var typeRef = referenceResolver.Resolve(mainModule, null, prop.Type); var pro = new PropertyDefinition(prop.Name, PropertyAttributes.HasDefault, typeRef); newType.Properties.Add(pro); } // newType.AddDefaultConstructor(); builder.AddEmptyConstructor(newType); builder.AddVirtualOnInit(newType); foreach (var papyrusAsmState in input.States) { foreach (var papyrusAsmFunction in papyrusAsmState.Functions) { var typeReference = referenceResolver.Resolve(mainModule, null, papyrusAsmFunction.ReturnType); // var typeRef = MainModule.TypeSystem.Void; var function = new MethodDefinition(papyrusAsmFunction.Name, MethodAttributes.Public, typeReference) { IsStatic = papyrusAsmFunction.IsStatic }; if (function.IsStatic) { function.HasThis = false; } if (!function.IsStatic && papyrusAsmFunction.Name.StartsWith("On") || papyrusAsmFunction.IsEvent) { function.IsVirtual = true; } else { function.IsVirtual = false; } builder.CreateEmptyFunctionBody(ref function); foreach (var par in papyrusAsmFunction.Params) { var resolvedTypeReference = referenceResolver.Resolve(mainModule, null, par.Type); // var typeRefp = MainModule.TypeSystem.Object; var nPar = new ParameterDefinition(par.Name, ParameterAttributes.None, resolvedTypeReference); function.Parameters.Add(nPar); } var skipAdd = false; foreach (var m in newType.Methods) { if (m.Name == function.Name) { if (m.Parameters.Count == function.Parameters.Count) { skipAdd = true; for (var pi = 0; pi < m.Parameters.Count; pi++) { if (m.Parameters[pi].ParameterType.FullName != function.Parameters[pi].ParameterType.FullName) { skipAdd = false; } } break; } } } if (!skipAdd) { newType.Methods.Add(function); } } } return(newType); }