Exemple #1
0
        private static void WriteFieldSwitch(IndentedWriter output, Block block, string variable)
        {
            output.
            Line("switch (assignment.Name.ToLower())").
            OpenParen();


            foreach (var field in block.Fields)
            {
                output.
                Line($"case \"{field.FormatName.ToLowerInvariant()}\":").
                IncreaseIndent().
                Line($"{variable}.{field.PropertyName} = Read{field.PropertyType.ToPascalCase()}Value(assignment, \"{block.CodeName}.{field.PropertyName}\");").
                Line("break;").
                DecreaseIndent();
            }

            output.
            Line("default:").
            IncreaseIndent().
            Line($"{variable}.UnknownProperties.Add(new UnknownProperty(assignment.Name, assignment.ValueAsString()));").
            Line("break;").
            DecreaseIndent().
            CloseParen();
        }
        private static void WriteProperties(Block block, IndentedWriter sb)
        {
            foreach (var property in block.Fields.Where(_ => _.IsRequired))
            {
                sb.Line($"private bool {property.FieldName}HasBeenSet = false;").
                Line($"private {property.PropertyType} {property.FieldName};").
                Line($"public {property.PropertyType} {property.PropertyName}").
                OpenParen().
                Line($"get {{ return {property.FieldName}; }}").
                Line($"set").
                OpenParen().
                Line($"{property.FieldName}HasBeenSet = true;").
                Line($"{property.FieldName} = value;").
                CloseParen().
                CloseParen();
            }

            foreach (var field in block.Fields.Where(_ => !_.IsRequired))
            {
                sb.Line($"public {field.PropertyType} {field.PropertyName} {{ get; set; }} = {field.DefaultValue};");
            }

            foreach (var subBlock in block.SubBlocks)
            {
                sb.Line(
                    $"public {subBlock.PropertyType} {subBlock.PropertyName} {{ get; }} = new {subBlock.PropertyType}();");
            }
        }
Exemple #3
0
        public static void WriteTo(StreamWriter stream)
        {
            using (var output = new IndentedWriter(stream))
            {
                output.Line(
                    $@"// Copyright (c) {DateTime.Today.Year}, David Aramant
// Distributed under the 3-clause BSD license.  For full terms see the file LICENSE. 

using System.CodeDom.Compiler;
using UdmfParsing.Udmf.Parsing.SuperpowerVersion.AbstractSyntaxTree;

namespace UdmfParsing.Udmf.Parsing.SuperpowerVersion").OpenParen()
                .Line($"[GeneratedCode(\"{CurrentLibraryInfo.Name}\", \"{CurrentLibraryInfo.Version}\")]")
                .Line("public static partial class UdmfSemanticAnalyzer").OpenParen();

                WriteGlobalFieldParsing(output);

                output.Line();

                WriteBlockParsing(output);

                output.Line();

                foreach (var block in UdmfDefinitions.Blocks.Where(b => b.IsSubBlock))
                {
                    WriteBlockParser(block, output);
                }

                output.CloseParen();
                output.CloseParen();
            }
        }
Exemple #4
0
        private static void WriteBlockParsing(IndentedWriter output)
        {
            output.
            Line("static partial void ProcessBlock(MapData map, Block block)").
            OpenParen().
            Line("switch (block.Name.ToLower())").
            OpenParen();

            foreach (var block in UdmfDefinitions.Blocks.Single(b => b.CodeName.ToPascalCase() == "MapData").SubBlocks
                     .Where(b => b.IsRequired))
            {
                output.
                Line($"case \"{block.FormatName.ToLowerInvariant()}\":").
                IncreaseIndent().
                Line($"map.{block.PropertyName}.Add(Process{block.FormatName.ToPascalCase()}(block));").
                Line("break;").
                DecreaseIndent();
            }

            output.
            Line("default:").
            IncreaseIndent().
            Line($"map.UnknownBlocks.Add(ProcessUnknownBlock(block));").
            Line("break;").
            DecreaseIndent().
            CloseParen().
            CloseParen();
        }
        public static void WriteToPath(string basePath)
        {
            if (!Directory.Exists(basePath))
            {
                Directory.CreateDirectory(basePath);
            }

            using var stream = File.CreateText(Path.Combine(basePath, "MapDeclarationParser.Generated.cs"));
            using var output = new IndentedWriter(stream);

            var includes = new[]
            {
                "System.CodeDom.Compiler",
                "System.Linq",
                "Tiledriver.Core.FormatModels.Common",
                "Tiledriver.Core.FormatModels.MapInfo.Reading.AbstractSyntaxTree",
            };

            output
            .Line("#nullable enable")
            .WriteHeader("Tiledriver.Core.FormatModels.MapInfo.Reading", includes)
            .Line($"[GeneratedCode(\"{CurrentLibraryInfo.Name}\", \"{CurrentLibraryInfo.Version}\")]")
            .Line($"public static partial class MapDeclarationParser")
            .OpenParen();

            WriteParser(output, MapInfoDefinitions.Blocks.Single(b => b.ClassName == "DefaultMap"));
            output.Line();
            WriteParser(output, MapInfoDefinitions.Blocks.Single(b => b.ClassName == "AddDefaultMap"));
            output.Line();
            WriteMapParser(output, MapInfoDefinitions.Blocks.Single(b => b.ClassName == "Map"));
            output.Line();
            WriteDefaultMapUpdater(output, MapInfoDefinitions.Blocks.Single(b => b.ClassName == "DefaultMap"));

            output.CloseParen();
        }
        static void WriteRecord(string basePath, Block block)
        {
            using var blockStream =
                      File.CreateText(Path.Combine(basePath, block.ClassName + ".Generated.cs"));
            using var output = new IndentedWriter(blockStream);

            var  containsCollection = block.Properties.Any(p => p is CollectionProperty);
            bool includeConverter   = block.ClassName == "TileTemplate";

            var includes = new List <string> {
                "System.CodeDom.Compiler"
            };

            if (containsCollection)
            {
                includes.Add("System.Collections.Immutable");
            }

            if (includeConverter)
            {
                includes.Add("Tiledriver.Core.FormatModels.Uwmf");
            }

            output
            .WriteHeader("Tiledriver.Core.FormatModels.Xlat", includes)
            .Line($"[GeneratedCode(\"{CurrentLibraryInfo.Name}\", \"{CurrentLibraryInfo.Version}\")]")
            .Line($"public sealed partial record {block.ClassName}(")
            .IncreaseIndent()
            .JoinLines(",", block.OrderedProperties.Select(GetPropertyDefinition))
            .DecreaseIndent();

            if (includeConverter)
            {
                output
                .Line(")")
                .OpenParen()
                .Line("public Tile ToTile() =>")
                .IncreaseIndent()
                .Line("new Tile(")
                .IncreaseIndent()
                .JoinLines(",",
                           block
                           .OrderedProperties
                           .Where(p => p.PropertyName != "OldNum")
                           .Select(p => $"{p.PropertyName}: {p.PropertyName}"))
                .DecreaseIndent()
                .Line(");")
                .DecreaseIndent()
                .CloseParen();
            }
            else
            {
                output.Line(");");
            }
        }
        static void WriteRecord(string basePath, IBlock block)
        {
            using var blockStream =
                      File.CreateText(Path.Combine(basePath, block.ClassName + ".Generated.cs"));
            using var output = new IndentedWriter(blockStream);

            var containsCollection = block.OrderedProperties.Any(p => p is CollectionProperty);
            var containsIdentifier = block.OrderedProperties.Any(p => p is IdentifierProperty);

            List <string> includes = new() { "System.CodeDom.Compiler" };

            if (containsCollection)
            {
                includes.Add("System.Collections.Immutable");
            }

            if (containsIdentifier)
            {
                includes.Add("Tiledriver.Core.FormatModels.Common");
            }

            var qualifier         = block is AbstractBlock ? "abstract" : "sealed";
            var includesNullables = block.OrderedProperties.OfType <ScalarProperty>().Any(sp => sp.IsNullable);

            if (includesNullables)
            {
                output.Line("#nullable enable");
            }

            output
            .WriteHeader("Tiledriver.Core.FormatModels.MapInfo", includes)
            .Line($"[GeneratedCode(\"{CurrentLibraryInfo.Name}\", \"{CurrentLibraryInfo.Version}\")]")
            .Line($"public {qualifier} partial record {block.ClassName}(")
            .IncreaseIndent()
            .JoinLines(",", block.OrderedProperties.Select(GetPropertyDefinition))
            .DecreaseIndent();

            if (block is InheritedBlock ib)
            {
                output
                .Line($") : {ib.BaseClass.ClassName}(")
                .IncreaseIndent()
                .JoinLines(",", ib.BaseClass.OrderedProperties.Select(p => p.PropertyName))
                .DecreaseIndent();
            }

            output
            .Line(");");
        }
        private static void WriteSemanticValidityMethods(IndentedWriter output, Block block)
        {
            output.Line(@"public void CheckSemanticValidity()").
            OpenParen();

            // CHECK THAT ALL REQUIRED PROPERTIES HAVE BEEN SET
            foreach (var field in block.Fields.Where(_ => _.IsRequired))
            {
                output.Line(
                    $"if (!{field.FieldName}HasBeenSet) throw new InvalidUdmfException(\"Did not set {field.PropertyName} on {block.CodeName.ToPascalCase()}\");");
            }

            output.Line(@"AdditionalSemanticChecks();").
            CloseParen().
            Line().
            Line("partial void AdditionalSemanticChecks();");
        }
        private static void WriteWriteToMethod(Block block, IndentedWriter sb)
        {
            sb.Line(@"public Stream WriteTo(Stream stream)").
            OpenParen().
            Line("CheckSemanticValidity();");

            var indent = block.IsSubBlock ? "true" : "false";

            if (block.IsSubBlock)
            {
                sb.Line($"stream.WriteLine(\"{block.FormatName}\");");
                sb.Line("stream.WriteLine(\"{\");");
            }

            // WRITE ALL REQUIRED PROPERTIES
            foreach (var field in block.Fields.Where(_ => _.IsRequired))
            {
                sb.Line(
                    $"stream.WriteProperty(\"{field.FormatName}\", {field.FieldName}, indent: {indent});");
            }
            // WRITE OPTIONAL PROPERTIES
            foreach (var field in block.Fields.Where(_ => !_.IsRequired))
            {
                sb.Line(
                    $"if ({field.PropertyName} != {field.DefaultValue}) stream.WriteProperty(\"{field.FormatName}\", {field.PropertyName}, indent: {indent});");
            }

            // WRITE UNKNOWN PROPERTIES
            sb.Line($"foreach (var property in UnknownProperties)").
            OpenParen().
            Line($"stream.WritePropertyVerbatim((string)property.Name, property.Value, indent: {indent});").
            CloseParen();

            // WRITE SUB-BLOCKS
            foreach (var subBlock in block.SubBlocks.Where(b => !(b is UnknownPropertiesList)))
            {
                var variable = subBlock.FormatName;
                sb.Line($"foreach(var {variable} in {subBlock.PropertyName})").
                OpenParen().
                Line($"{variable}.WriteTo(stream);").
                CloseParen();
            }

            if (block.IsSubBlock)
            {
                sb.Line("stream.WriteLine(\"}\");");
            }
            sb.Line("return stream;").
            CloseParen();
        }
    static void WriteActorFile(string basePath, IReadOnlyList <Actor> actors)
    {
        using var blockStream = File.CreateText(Path.Combine(basePath, "Actor.Generated.cs"));
        using var output      = new IndentedWriter(blockStream);

        output
        .WriteHeader("Tiledriver.Core.GameInfo.Doom", new[] { "System.Collections.Generic", "System.CodeDom.Compiler" })
        .Line($"[GeneratedCode(\"{CurrentLibraryInfo.Name}\", \"{CurrentLibraryInfo.Version}\")]")
        .Line($"public sealed partial record Actor")
        .OpenParen();

        foreach (var actor in actors)
        {
            output
            .Line($"/// <summary>{actor.Description}</summary>")
            .Line($"public static readonly Actor {actor.SafeName} = new(")
            .IncreaseIndent()
            .JoinLines(",", new[] {
                $"Id: {actor.Id}",
                $"Description: \"{actor.Description}\"",
                $"Width: {actor.Width}",
                $"Height: {actor.Height}"
            })
            .DecreaseIndent()
            .Line(");")
            .Line();
        }

        foreach (var category in actors.GroupBy(c => c.CategoryName))
        {
            output
            .Line($"public static class {category.Key}")
            .OpenParen()
            .Lines(category.Select(actor => $"public static Actor {actor.SafeName} => Actor.{actor.SafeName};"))
            .Line("public static IEnumerable<Actor> GetAll()")
            .OpenParen()
            .Lines(category.Select(actor => $"yield return {actor.SafeName};"))
            .CloseParen()
            .CloseParen();
        }

        output
        .CloseParen();
    }
 private static void WriteParser(IndentedWriter output, IBlock block)
 {
     output
     .Line($"private static partial {block.ClassName} Parse{block.ClassName}(ILookup<Identifier, VariableAssignment> assignmentLookup)")
     .IncreaseIndent()
     .Line($"=> new {block.ClassName}(")
     .IncreaseIndent()
     .JoinLines(",", block.OrderedProperties.Select(GetPropertyReader))
     .DecreaseIndent()
     .Line(");")
     .DecreaseIndent();
 }
Exemple #12
0
        private static void CreateBlockWriter(IndentedWriter output, Block block)
        {
            output
            .Line($"private static void Write(StreamWriter writer, {block.ClassName} {block.Name})")
            .OpenParen();

            if (block.Serialization == SerializationType.Normal)
            {
                output
                .Line($"writer.WriteLine(\"{block.Name}\");")
                .Line("writer.WriteLine(\"{\");");
            }

            foreach (var p in block.Properties)
            {
                if (p is ScalarProperty sp)
                {
                    var defaultValue = sp.DefaultString;
                    if (sp is TextureProperty {
                        IsOptional: true
                    })
Exemple #13
0
        private static void WriteGlobalFieldParsing(IndentedWriter output)
        {
            output.
            Line("static partial void ProcessGlobalAssignment(MapData map, Assignment assignment)").
            OpenParen();

            var block = UdmfDefinitions.Blocks.Single(b => b.CodeName.ToPascalCase() == "MapData");

            WriteFieldSwitch(output, block, "map");

            output.
            CloseParen();
        }
        private static void CreateBlockWriter(IndentedWriter output, Block block)
        {
            output
            .Line($"private static void Write(StreamWriter writer, {block.ClassName} {block.Name})")
            .OpenParen();

            if (block.Serialization == SerializationType.Normal)
            {
                output
                .Line($"writer.WriteLine(\"{block.Name}\");")
                .Line("writer.WriteLine(\"{\");");
            }

            foreach (var p in block.Properties)
            {
                if (p is ScalarProperty sp)
                {
                    var defaultValue = sp.DefaultString;

                    string optionalDefault = defaultValue != null ? ", " + defaultValue : string.Empty;
                    string indent          = block.Serialization == SerializationType.Normal ? string.Empty : ", indent:false";

                    output.Line($"WriteProperty(writer, \"{sp.FormatName}\", {block.Name}.{sp.PropertyName}{optionalDefault}{indent});");
                }
                else if (p is CollectionProperty cp)
                {
                    output.Line($"foreach(var block in {block.Name}.{cp.PropertyName})")
                    .OpenParen()
                    .Line($"Write(writer, block);")
                    .CloseParen();
                }
            }

            if (block.Serialization == SerializationType.Normal)
            {
                output.Line("writer.WriteLine(\"}\");");
            }
            output.CloseParen();
        }
        private static void WriteCloneMethod(IndentedWriter output, Block block)
        {
            output.
            Line().
            Line($"public {block.CodeName} Clone()").
            OpenParen().
            Line($"return new {block.CodeName}(").IncreaseIndent();

            foreach (var indexed in block.OrderedProperties().Select((param, index) => new { param, index }))
            {
                var postfix = indexed.index == block.Properties.Count() - 1 ? ");" : ",";

                if (indexed.param is BlockList)
                {
                    postfix = ".Select(item => item.Clone())" + postfix;
                }
                output.Line(indexed.param.ConstructorArgumentName + ": " + indexed.param.PropertyName + postfix);
            }

            output.
            DecreaseIndent().
            CloseParen();
        }
 private static void WriteMapParser(IndentedWriter output, IBlock block)
 {
     output.Line("private static partial Map ParseMap(")
     .IncreaseIndent()
     .Line("ILookup<Identifier, VariableAssignment> assignmentLookup,")
     .Line("string mapLump,")
     .Line("string? mapName,")
     .Line("bool isMapNameLookup,")
     .Line("DefaultMap defaultMap) =>")
     .Line("new Map(")
     .IncreaseIndent()
     .JoinLines(",", block.OrderedProperties.Select(GetMapPropertyReader))
     .DecreaseIndent()
     .Line(");")
     .DecreaseIndent();
 }
        public static void WriteToPath(string basePath)
        {
            foreach (var block in UdmfDefinitions.Blocks)
            {
                using (var blockStream = File.CreateText(Path.Combine(basePath, block.CodeName.ToPascalCase() + ".Generated.cs")))
                    using (var output = new IndentedWriter(blockStream))
                    {
                        output.Line(
                            $@"// Copyright (c) {DateTime.Today.Year}, David Aramant
// Distributed under the 3-clause BSD license.  For full terms see the file LICENSE. 

using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UdmfParsing.Udmf.WritingExtensions;

namespace UdmfParsing.Udmf");

                        output.OpenParen();
                        output.Line(
                            $"[GeneratedCode(\"{CurrentLibraryInfo.Name}\", \"{CurrentLibraryInfo.Version}\")]");
                        output.Line(
                            $"public sealed partial class {block.CodeName}");
                        output.OpenParen();

                        WriteProperties(block, output);

                        output.Line();

                        WriteConstructors(output, block);

                        output.Line();

                        WriteWriteToMethod(block, output);

                        output.Line();

                        WriteSemanticValidityMethods(output, block);
                        WriteCloneMethod(output, block);

                        output.CloseParen();
                        output.Line();
                        output.CloseParen(); // End namespace
                    }
            }
        }
Exemple #18
0
        private static void WriteBlockParser(Block block, IndentedWriter output)
        {
            var variable = block.CodeName.ToCamelCase();

            output.
            Line($"static {block.CodeName} Process{block.CodeName}(Block block)").
            OpenParen().
            Line($"var {variable} = new {block.CodeName}();").
            Line("foreach (var assignment in block.Fields)").
            OpenParen();

            WriteFieldSwitch(output, block, variable);

            output.
            CloseParen().
            Line($"return {variable};").
            CloseParen().
            Line();
        }
        private static void WriteConstructors(IndentedWriter sb, Block block)
        {
            sb.Line($"public {block.CodeName}() {{ }}");
            sb.Line($"public {block.CodeName}(");
            sb.IncreaseIndent();

            foreach (var indexed in block.OrderedProperties().Select((param, index) => new { param, index }))
            {
                var property = indexed.param;
                var argument = $"{property.ConstructorArgumentType} {property.ConstructorArgumentName}" +
                               (property.IsRequired ? string.Empty : $" = {property.DefaultValue}");
                sb.Line(argument + (indexed.index == block.Properties.Count() - 1 ? ")" : ","));
            }

            sb.DecreaseIndent();
            sb.OpenParen();

            foreach (var property in block.OrderedProperties())
            {
                switch (property)
                {
                case Field field:
                    sb.Line($"{field.PropertyName} = {field.ConstructorArgumentName};");
                    break;

                case BlockList requiredBlockList when requiredBlockList.IsRequired:
                    sb.Line($"{requiredBlockList.PropertyName}.AddRange({requiredBlockList.ConstructorArgumentName});");
                    break;

                case BlockList blockList:
                    sb.Line($"{blockList.PropertyName}.AddRange({blockList.ConstructorArgumentName} ?? Enumerable.Empty<{blockList.SingularName}>());");
                    break;
                }
            }

            sb.Line(@"AdditionalSemanticChecks();");
            sb.CloseParen();
        }