Beispiel #1
0
        private void BuildDefine(UnknownPreprocessor unknPreprocessor)
        {
            string ppValue = unknPreprocessor.Value;

            string[] elements = ppValue.Split().Where(element => !string.IsNullOrEmpty(element)).ToArray();
            if (elements.Length == 3)
            {
                string instruction = elements[0];
                string macro       = elements[1];
                string value       = elements[2];

                if (instruction == "#define")
                {
                    if (macro == "ENGINE_NUM_STRUCTURES")
                    {
                        stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}public const int {macro} = {value};");
                        return;
                    }

                    const string structurePrefix = "ENGINE_STRUCTURE_";
                    if (macro.StartsWith(structurePrefix))
                    {
                        string structureName  = value.ToUpperInvariant();
                        int    structureValue = int.Parse(macro.Substring(structurePrefix.Length));
                        stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}public const int {structurePrefix}{structureName} = {structureValue};");
                        return;
                    }
                }
            }

            stringBuilder.AppendLine($"// {ppValue}");
        }
        private void BuildMethod(FunctionImplementation implementation)
        {
            string name    = VMTranslations.RemovePrefixes(pluginNameVar, implementation.Name.Identifier, false);
            string retType = VMTranslations.RemovePrefixes(pluginNameVar, implementation.ReturnType.Declaration);

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

            foreach (FunctionParameter param in implementation.Parameters)
            {
                string paramType = VMTranslations.RemovePrefixes(pluginNameVar, param.m_Type.Declaration);
                string paramName = Output_CSharp.GetSafeVariableName(param.m_Lvalue.Identifier);

                string paramStr = paramType + " " + paramName;

                if (param is FunctionParameterWithDefault def)
                {
                    string defaultAsStr = Output_CSharp.GetValueAsString(def.m_Default, true);
                    paramStr += " = " + defaultAsStr;
                }

                funcParams.Add(paramStr);
            }

            string parameters = funcParams.Count == 0 ? "" : funcParams.Aggregate((a, b) => a + ", " + b);

            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}public static {retType} {name}({parameters})");
            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}{{");

            BuildImplementation(implementation);

            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}}}");
            stringBuilder.AppendLine();
        }
Beispiel #3
0
        private void BuildConstant(LvalueDeclSingleWithAssignment lvalueDecl)
        {
            string type  = lvalueDecl.m_Type.Declaration;
            string name  = lvalueDecl.m_Lvalue.Identifier;
            string value = lvalueDecl.m_Expression.m_Expression;

            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}public const {type} {name} = {value}{(lvalueDecl.m_Type.GetType() == typeof(FloatType) && !value.EndsWith("f") ? "f" : "")};");
        }
Beispiel #4
0
        private void ProcessCustomConstants()
        {
            foreach (string constant in customConstants)
            {
                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}{constant}");
            }

            stringBuilder.AppendLine();
        }
Beispiel #5
0
        private void BuildMethod(FunctionDeclaration funcDecl)
        {
            string name = funcDecl.Name.Identifier;

            if (customImplementations.ContainsKey(name))
            {
                stringBuilder.AppendLine(customImplementations[name]);
                internalCallId++;
                stringBuilder.AppendLine();
                return;
            }

            string retType = funcDecl.ReturnType.Declaration;

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

            foreach (FunctionParameter param in funcDecl.Parameters)
            {
                string paramType = param.m_Type.Declaration;
                string paramName = param.m_Lvalue.Identifier;
                string paramStr  = paramType + " " + paramName;

                if (param is FunctionParameterWithDefault def)
                {
                    string defaultAsStr = Output_CSharp.GetValueAsString(def.m_Default, false);
                    paramStr += " = " + defaultAsStr;
                }

                funcParams.Add(paramStr);
            }

            string parameters = funcParams.Count == 0 ? "" : funcParams.Aggregate((a, b) => a + ", " + b);

            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}public static {retType} {name}({parameters})");
            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}{{");

            for (int i = funcDecl.Parameters.Count - 1; i >= 0; --i)
            {
                FunctionParameter param = funcDecl.Parameters[i];
                stringBuilder.AppendLine(Output_CSharp.GetIndent(3) + Output_CSharp.GetStackPush(param.m_Type, param.m_Lvalue, false) + ";");
            }

            stringBuilder.AppendLine(Output_CSharp.GetIndent(3) + Output_CSharp.GetInternalCall(internalCallId++) + ";");

            if (funcDecl.ReturnType.GetType() != typeof(VoidType))
            {
                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(3)}return " + Output_CSharp.GetStackPop(funcDecl.ReturnType) + ";");
            }

            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}}}");
            stringBuilder.AppendLine();
        }
Beispiel #6
0
        public int GetFromCU(CompilationUnit cu, string className, out string data)
        {
            stringBuilder.Clear();
            internalCallId = 0;

            stringBuilder.AppendLine("namespace NWN.Core");
            stringBuilder.AppendLine("{");
            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}public static partial class NWScript");
            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}{{");

            ProcessCustomConstants();

            for (int index = 0; index < cu.m_Nodes.Count; index++)
            {
                NSSNode node     = cu.m_Nodes[index];
                NSSNode nextNode = index < cu.m_Nodes.Count - 1 ? cu.m_Nodes[index + 1] : null;

                if (node is LineComment lineComment)
                {
                    string xmlEscapedComment = lineComment.Comment
                                               .Replace("\"", "&quot;")
                                               .Replace("'", "&apos;")
                                               .Replace("<", "&lt;")
                                               .Replace(">", "&gt;")
                                               .Replace("&", "&amp;");

                    stringBuilder.Append($"{Output_CSharp.GetIndent(2)}/// " + xmlEscapedComment);
                    if (nextNode is Comment)
                    {
                        stringBuilder.Append("<br/>");
                    }

                    stringBuilder.AppendLine();
                }

                if (node is BlockComment blockComment)
                {
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}/*");
                    foreach (string line in blockComment.CommentLines)
                    {
                        stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}" + line);
                    }

                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}*/");
                }

                if (node is LvalueDeclSingleWithAssignment lvalueDecl)
                {
                    BuildConstant(lvalueDecl);
                    if (cu.m_Nodes.Count > index + 2 && !(cu.m_Nodes[index + 1] is LvalueDeclSingleWithAssignment))
                    {
                        stringBuilder.AppendLine();
                    }
                }

                if (node is UnknownPreprocessor unknPreprocessor)
                {
                    BuildDefine(unknPreprocessor);
                }

                if (node is FunctionDeclaration funcDecl)
                {
                    BuildMethod(funcDecl);
                }
            }

            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}}}");
            stringBuilder.AppendLine("}");

            data = stringBuilder.ToString();
            return(0);
        }
        private void ProcessImplementationNode(FunctionImplementation implementation, List <string> vectorDecls, NSSNode node, int depth)
        {
            string expression;

            switch (node)
            {
            case LvalueDeclSingleWithAssignment declAssignment:
                expression = VMTranslations.TryTranslate(pluginNameVar, declAssignment.m_Expression.m_Expression);

                if (declAssignment.m_Lvalue.Identifier == "sFunc")
                {
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}const {declAssignment.m_Type.Declaration} {declAssignment.m_Lvalue.Identifier} = {expression};");
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}VM.NWNX.SetFunction({pluginNameVar}, sFunc);");
                    break;
                }

                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{declAssignment.m_Type.Declaration} {declAssignment.m_Lvalue.Identifier} = {expression};");
                break;

            case LvalueAssignment assignment:
                string[] identifier = assignment.m_Lvalue.Identifier.Split('.', 2);
                if (identifier.Length > 1 && vectorDecls.Contains(identifier[0]))
                {
                    identifier[1] = identifier[1].ToUpper();
                }

                expression = VMTranslations.TryTranslate(pluginNameVar, assignment.m_Expression.m_Expression);
                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{string.Join('.', identifier)} = {expression};");
                break;

            case LvalueDeclSingle declaration:
                if (declaration.m_Type.GetType() == typeof(StringType))
                {
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{VMTranslations.RemovePrefixes(pluginNameVar, declaration.m_Type.Declaration)} {declaration.m_Lvalue.Identifier} = \"\";");
                }
                else if (declaration.m_Type is StructType)
                {
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{VMTranslations.RemovePrefixes(pluginNameVar, declaration.m_Type.Declaration)} {declaration.m_Lvalue.Identifier} = default;");
                }
                else if (declaration.m_Type is VectorType)
                {
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{VMTranslations.RemovePrefixes(pluginNameVar, declaration.m_Type.Declaration)} {declaration.m_Lvalue.Identifier} = default;");
                    vectorDecls.Add(declaration.m_Lvalue.Identifier);
                }
                else
                {
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{VMTranslations.RemovePrefixes(pluginNameVar, declaration.m_Type.Declaration)} {declaration.m_Lvalue.Identifier};");
                }
                break;

            case FunctionCall functionCall:
                expression = VMTranslations.TranslateCall(pluginNameVar, functionCall.m_Name.Identifier, functionCall.m_Arguments);
                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{expression};");
                break;

            case ReturnStatement returnStatement:
                if (implementation.ReturnType is StructType || implementation.ReturnType is VectorType)
                {
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}return {returnStatement.m_Expression.m_Expression};");
                    break;
                }

                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}return {implementation.ReturnType.NWNXPopFormat};");
                break;

            case IfStatement ifStatement:
                expression = VMTranslations.TryTranslate(pluginNameVar, ifStatement.m_Expression.m_Expression);

                if (!expression.Contains("==") && !expression.Contains("!=") && !expression.Contains("<") && !expression.Contains(">"))
                {
                    if (expression.StartsWith("!"))
                    {
                        expression = $"{expression.Substring(1)} == FALSE";
                    }
                    else
                    {
                        expression = $"{expression} == TRUE";
                    }
                }

                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}if ({expression})");
                ProcessImplementationNode(implementation, vectorDecls, ifStatement.m_Action, depth);
                break;

            case ElseStatement elseStatement:
                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}else");
                ProcessImplementationNode(implementation, vectorDecls, elseStatement.m_Action, depth);
                break;

            case ForLoop forLoop:
                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}for ({forLoop.m_Pre.m_Expression}; {forLoop.m_Condition.m_Expression}; {forLoop.m_Post.m_Expression})");
                ProcessImplementationNode(implementation, vectorDecls, forLoop.m_Action, depth);
                break;

            case Block block:
                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{{");
                foreach (NSSNode childNode in block.m_Nodes)
                {
                    ProcessImplementationNode(implementation, vectorDecls, childNode, depth + 1);
                }

                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}}}");
                break;
            }
        }
        public int GetFromCU(CompilationUnit cu, string className, out string data)
        {
            stringBuilder.Clear();
            pluginNameVar = null;

            stringBuilder.AppendLine("using static NWN.Core.NWScript;");
            stringBuilder.AppendLine();

            stringBuilder.AppendLine("namespace NWN.Core.NWNX");
            stringBuilder.AppendLine("{");

            int attributePos = stringBuilder.Length;

            stringBuilder.AppendLine();
            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}public class {className}");
            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}{{");

            HashSet <FunctionImplementation> implementedMethods = new HashSet <FunctionImplementation>();

            for (int index = 0; index < cu.m_Nodes.Count; index++)
            {
                NSSNode node = cu.m_Nodes[index];
                if (node is LineComment lineComment)
                {
                    string xmlEscapedComment = lineComment.Comment
                                               .Replace("&", "&amp;")
                                               .Replace("\"", "&quot;")
                                               .Replace("'", "&apos;")
                                               .Replace("<", "&lt;")
                                               .Replace(">", "&gt;")
                                               .Replace("/ @}", " @}");

                    if (xmlEscapedComment.Contains("@param"))
                    {
                        string paramName = xmlEscapedComment.Split(' ')[2];
                        stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}//{xmlEscapedComment.Replace($"@param {paramName} ", $"<param name=\"{paramName}\">").Replace($"@param {paramName}", $"<param name=\"{paramName}\">")}</param>");
                    }
                    else if (xmlEscapedComment.Contains("@return"))
                    {
                        stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}//{xmlEscapedComment.Replace("@return ", $"<returns>").Replace("@return", $"<returns>")}</returns>");
                    }
                    else
                    {
                        stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}//" + xmlEscapedComment.Replace("@brief ", ""));
                    }
                }

                if (node is BlockComment blockComment)
                {
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}/*");
                    foreach (string line in blockComment.CommentLines)
                    {
                        stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}" + line);
                    }

                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}*/");
                }

                if (node is LvalueDeclSingleWithAssignment lvalueDecl)
                {
                    // First entry is always the plugin name.
                    if (pluginNameVar == null)
                    {
                        if (lvalueDecl.m_Type.GetType() != typeof(StringType))
                        {
                            data = null;
                            return(-1);
                        }

                        pluginNameVar = lvalueDecl.m_Lvalue.Identifier;
                    }

                    string type  = lvalueDecl.m_Type.Declaration;
                    string name  = lvalueDecl.m_Lvalue.Identifier;
                    string value = lvalueDecl.m_Expression.m_Expression;
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}public const {type} {name} = {value}{(lvalueDecl.m_Type.GetType() == typeof(FloatType) && !value.EndsWith("f") ? "f" : "")};");
                    if (cu.m_Nodes.Count > index + 2 && !(cu.m_Nodes[index + 1] is LvalueDeclSingleWithAssignment))
                    {
                        stringBuilder.AppendLine();
                    }
                }

                if (pluginNameVar == null)
                {
                    continue;
                }

                if (node is FunctionDeclaration funcDecl)
                {
                    FunctionImplementation funcImpl = GetFunction(cu, funcDecl);
                    if (implementedMethods.Contains(funcImpl))
                    {
                        continue;
                    }

                    BuildMethod(funcImpl);
                    implementedMethods.Add(funcImpl);
                }

                if (node is FunctionImplementation func)
                {
                    if (implementedMethods.Contains(func))
                    {
                        continue;
                    }

                    BuildMethod(func);
                    implementedMethods.Add(func);
                }
            }

            stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}}}");

            // Structures
            foreach (StructDeclaration structDeclaration in cu.m_Nodes.OfType <StructDeclaration>())
            {
                stringBuilder.AppendLine();
                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}public struct {VMTranslations.RemovePrefixes(pluginNameVar, structDeclaration.m_Name.Identifier)}");
                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}{{");

                foreach (LvalueDeclSingle dec in structDeclaration.m_Members.OfType <LvalueDeclSingle>())
                {
                    string type = dec.m_Type.Declaration;
                    string name = dec.m_Lvalue.Identifier;
                    stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}public {type} {name};");
                }

                stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}}}");
            }

            stringBuilder.Append("}");
            stringBuilder.AppendLine();

            if (pluginNameVar == null)
            {
                data = null;
                return(-1);
            }

            stringBuilder.Insert(attributePos, $"{Output_CSharp.GetIndent(1)}[NWNXPlugin({pluginNameVar})]");
            data = stringBuilder.ToString();
            return(0);
        }