Remove old ZoneCodeGenerator implementation in c#

This commit is contained in:
Jan 2021-03-01 14:30:10 +01:00
parent 5290d3a768
commit f85c82f487
174 changed files with 0 additions and 15421 deletions

View File

@ -133,7 +133,6 @@ include "src/Linker.lua"
include "src/Unlinker.lua"
include "src/Utils.lua"
include "src/ZoneCode.lua"
include "src/ZoneCodeGenerator.lua"
include "src/ZoneCodeGeneratorLib.lua"
include "src/ZoneCodeGeneratorNew.lua"
include "src/ZoneCommon.lua"
@ -149,7 +148,6 @@ group "Components"
Crypto:project()
Utils:project()
ZoneCode:project()
ZoneCodeGenerator:project()
ZoneCodeGeneratorLib:project()
ZoneCommon:project()
ZoneLoading:project()
@ -170,14 +168,12 @@ group ""
-- Tests
-- ========================
include "test/ObjCommonTests.lua"
include "test/ZoneCodeGeneratorTests.lua"
include "test/ZoneCodeGeneratorLibTests.lua"
include "test/ZoneCommonTests.lua"
-- Tests group: Unit test and other tests projects
group "Tests"
ObjCommonTests:project()
ZoneCodeGeneratorTests:project()
ZoneCodeGeneratorLibTests:project()
ZoneCommonTests:project()
group ""

View File

@ -1,50 +0,0 @@
ZoneCodeGenerator = {}
function ZoneCodeGenerator:include()
end
function ZoneCodeGenerator:link()
if References:link("ZoneCodeGenerator") then
links "ZoneCodeGenerator"
end
end
function ZoneCodeGenerator:use()
dependson "ZoneCodeGenerator"
end
function ZoneCodeGenerator:project()
References:reset()
local folder = ProjectFolder();
project "ZoneCodeGenerator"
targetdir(TargetDirectoryLib)
location "%{wks.location}/src/%{prj.name}"
kind "ConsoleApp"
language "C#"
dotnetframework "4.5"
namespace "ZoneCodeGenerator"
files {
path.join(folder, "ZoneCodeGenerator/**.cs"),
path.join(folder, "ZoneCodeGenerator/**.stg")
}
filter "files:**.stg"
buildaction "Embed"
filter {}
vpaths { ["*"] = "src/ZoneCodeGenerator" }
nuget {
"Antlr3.Runtime:3.5.1",
"StringTemplate4:4.0.8"
}
links {
"System",
"System.Core",
"System.Data"
}
end

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
namespace ZoneCodeGenerator.Domain
{
class CustomAction
{
public string ActionName { get; }
public IList<DataType> ParameterTypes { get; }
public CustomAction(string actionName, IEnumerable<DataType> parameterTypes)
{
ActionName = actionName;
ParameterTypes = new List<DataType>(parameterTypes);
}
}
}

View File

@ -1,9 +0,0 @@
namespace ZoneCodeGenerator.Domain
{
class DataException : LoadingException
{
public DataException(string message) : base(message)
{
}
}
}

View File

@ -1,21 +0,0 @@
namespace ZoneCodeGenerator.Domain
{
abstract class DataType
{
public string Namespace { get; }
public string Name { get; }
public DataTypeType Type { get; }
public string FullName => string.IsNullOrEmpty(Namespace) ? Name : $"{Namespace}::{Name}";
public abstract int Alignment { get; }
public abstract bool ForceAlignment { get; }
public abstract int Size { get; }
protected DataType(string _namespace, string name, DataTypeType type)
{
Namespace = _namespace;
Name = name;
Type = type;
}
}
}

View File

@ -1,46 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ZoneCodeGenerator.Domain
{
class DataTypeBaseType : DataType
{
public static readonly DataTypeBaseType FLOAT = new DataTypeBaseType("float", 4);
public static readonly DataTypeBaseType DOUBLE = new DataTypeBaseType("double", 8);
public static readonly DataTypeBaseType BOOL = new DataTypeBaseType("bool", 1);
public static readonly DataTypeBaseType CHAR = new DataTypeBaseType("char", 1);
public static readonly DataTypeBaseType UNSIGNED_CHAR = new DataTypeBaseType("unsigned char", 1);
public static readonly DataTypeBaseType SHORT = new DataTypeBaseType("short", 2);
public static readonly DataTypeBaseType UNSIGNED_SHORT = new DataTypeBaseType("unsigned short", 2);
public static readonly DataTypeBaseType INT = new DataTypeBaseType("int", 4);
public static readonly DataTypeBaseType UNSIGNED_INT = new DataTypeBaseType("unsigned int", 4);
public static readonly DataTypeBaseType LONG = new DataTypeBaseType("long", 4);
public static readonly DataTypeBaseType UNSIGNED_LONG = new DataTypeBaseType("unsigned long", 4);
public static readonly DataTypeBaseType LONG_LONG = new DataTypeBaseType("long long", 8);
public static readonly DataTypeBaseType UNSIGNED_LONG_LONG = new DataTypeBaseType("unsigned long long", 8);
public static readonly DataTypeBaseType VOID = new DataTypeBaseType("void", 0);
public static readonly IEnumerable<DataTypeBaseType> BASE_TYPES = typeof(DataTypeBaseType)
.GetFields(BindingFlags.Public | BindingFlags.Static)
.Where(info => info.FieldType == typeof(DataTypeBaseType))
.Select(info => info.GetValue(null))
.Cast<DataTypeBaseType>()
.ToList();
public override bool ForceAlignment => false;
public override int Size { get; }
public override int Alignment => Size;
private DataTypeBaseType(string name, int size) : base("", name, DataTypeType.BaseType)
{
Size = size;
}
public override string ToString()
{
return $"BaseType {FullName}";
}
}
}

View File

@ -1,26 +0,0 @@
using System.Collections.Generic;
namespace ZoneCodeGenerator.Domain
{
class DataTypeEnum : DataType
{
public DataTypeBaseType ParentType { get; }
public List<EnumMember> Members { get; }
public override bool ForceAlignment => ParentType.ForceAlignment;
public override int Size => ParentType.Size;
public override int Alignment => ParentType.Alignment;
public DataTypeEnum(string _namespace, string name, DataTypeBaseType parentType) : base(_namespace, name, DataTypeType.Enum)
{
Members = new List<EnumMember>();
ParentType = parentType;
}
public override string ToString()
{
return $"enum {FullName}";
}
}
}

View File

@ -1,51 +0,0 @@
using System;
using ZoneCodeGenerator.Utils;
namespace ZoneCodeGenerator.Domain
{
class DataTypeStruct : DataTypeWithMembers
{
public DataTypeStruct(string _namespace, string name, int pack) : base(_namespace, name, pack, DataTypeType.Struct)
{
}
protected override int CalculateSize()
{
var currentSize = 0;
var currentBitOffset = 0;
foreach (var member in Members)
{
if (member.VariableType.HasCustomBitSize)
{
currentBitOffset += member.VariableType.CustomBitSize.GetValueOrDefault(0);
}
else
{
if (currentBitOffset > 0)
{
currentBitOffset = currentBitOffset.Align(8);
currentSize += currentBitOffset / 8;
currentBitOffset = 0;
}
currentSize = currentSize.Align(member.ForceAlignment ? member.Alignment : Math.Min(member.Alignment, Pack));
currentSize += member.VariableType.Size;
}
}
if (currentBitOffset > 0)
{
currentBitOffset = currentBitOffset.Align(8);
currentSize += currentBitOffset / 8;
}
return currentSize.Align(Alignment);
}
public override string ToString()
{
return $"struct {FullName}";
}
}
}

View File

@ -1,11 +0,0 @@
namespace ZoneCodeGenerator.Domain
{
enum DataTypeType
{
Struct,
Union,
Enum,
Typedef,
BaseType
}
}

View File

@ -1,22 +0,0 @@
namespace ZoneCodeGenerator.Domain
{
class DataTypeTypedef : DataType
{
public TypeDeclaration TypeDefinition { get; }
public DataTypeTypedef(string _namespace, string name, TypeDeclaration typeDefinitionDeclaration) : base(_namespace, name, DataTypeType.Typedef)
{
TypeDefinition = typeDefinitionDeclaration;
}
public int? AlignmentOverride { get; set; }
public override int Alignment => AlignmentOverride ?? TypeDefinition.Alignment;
public override bool ForceAlignment => AlignmentOverride != null || TypeDefinition.ForceAlignment;
public override int Size => TypeDefinition.Size;
public override string ToString()
{
return $"typedef {FullName}";
}
}
}

View File

@ -1,25 +0,0 @@
using System.Linq;
using ZoneCodeGenerator.Utils;
namespace ZoneCodeGenerator.Domain
{
class DataTypeUnion : DataTypeWithMembers
{
public DataTypeUnion(string _namespace, string name, int pack) : base(_namespace, name, pack, DataTypeType.Union)
{
}
protected override int CalculateSize()
{
return Members
.Select(variable => variable.VariableType.Size)
.Max()
.Align(Alignment);
}
public override string ToString()
{
return $"union {FullName}";
}
}
}

View File

@ -1,72 +0,0 @@
using System.Collections.Generic;
using System.Linq;
namespace ZoneCodeGenerator.Domain
{
abstract class DataTypeWithMembers : DataType
{
public int? AlignmentOverride { get; set; }
private int alignment;
public override int Alignment => AlignmentOverride ?? alignment;
public override bool ForceAlignment => AlignmentOverride != null;
private int size;
public override int Size => size;
public int Pack { get; }
public List<Variable> Members { get; }
public bool IsAnonymous { get; set; }
private bool finalized;
public void FinalizeDataType()
{
if (finalized) return;
finalized = true;
CalculateProperties();
}
protected DataTypeWithMembers(string _namespace, string name, int pack, DataTypeType type) : base(_namespace, name, type)
{
Members = new List<Variable>();
Pack = pack;
finalized = false;
IsAnonymous = false;
}
private void CalculateProperties()
{
foreach (var member in Members
.Select(variable => variable.VariableType.Type))
{
switch (member)
{
case DataTypeWithMembers dataTypeWithMembers:
dataTypeWithMembers.FinalizeDataType();
break;
case DataTypeTypedef typeDef:
{
while (typeDef.TypeDefinition.Type is DataTypeTypedef typeDef2)
{
typeDef = typeDef2;
}
if(typeDef.TypeDefinition.Type is DataTypeWithMembers dataTypeWithMembers)
{
dataTypeWithMembers.FinalizeDataType();
}
break;
}
}
}
alignment = Members.Select(variable => variable.Alignment).Max();
size = CalculateSize();
}
protected abstract int CalculateSize();
}
}

View File

@ -1,14 +0,0 @@
namespace ZoneCodeGenerator.Domain
{
class EnumMember
{
public string Name { get; }
public long Value { get; }
public EnumMember(string name, long value)
{
Name = name;
Value = value;
}
}
}

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ZoneCodeGenerator.Domain.Evaluation
{
interface IEvaluation
{
bool IsStatic { get; }
int EvaluateNumeric();
}
}

View File

@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain.Information;
namespace ZoneCodeGenerator.Domain.Evaluation
{
class OperandDynamic : IEvaluation
{
public StructureInformation Structure { get; }
public IList<MemberInformation> ReferencedMemberChain { get; }
public IList<IEvaluation> ArrayIndices { get; }
public bool IsStatic => false;
public OperandDynamic(StructureInformation structure, IEnumerable<MemberInformation> memberChain)
{
Structure = structure;
ReferencedMemberChain = new List<MemberInformation>(memberChain);
ArrayIndices = new List<IEvaluation>();
}
public int EvaluateNumeric()
{
throw new Exception("A dynamic operand cannot be evaluated.");
}
public override string ToString()
{
return $"{Structure.Type.FullName}::{string.Join("::", ReferencedMemberChain.Select(information => information.Member.Name))}{string.Concat(ArrayIndices.Select(i => $"[{i}]"))}";
}
}
}

View File

@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ZoneCodeGenerator.Domain.Evaluation
{
class OperandStatic : IEvaluation
{
public int Value { get; }
public EnumMember EnumMemberValue { get; }
public bool IsStatic => true;
public int EvaluateNumeric()
{
return Value;
}
public OperandStatic(int value)
{
Value = value;
EnumMemberValue = null;
}
public OperandStatic(EnumMember enumMember)
{
Value = (int) enumMember.Value;
EnumMemberValue = enumMember;
}
public override string ToString()
{
return Value.ToString();
}
}
}

View File

@ -1,63 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ZoneCodeGenerator.Domain.Evaluation
{
class Operation : IEvaluation
{
public IEvaluation Operand1 { get; }
public bool Operand1NeedsParenthesis => Operand1 is Operation operation1 &&
operation1.OperationType.Precedence > OperationType.Precedence;
public IEvaluation Operand2 { get; }
public bool Operand2NeedsParenthesis => Operand2 is Operation operation2 &&
operation2.OperationType.Precedence >= OperationType.Precedence;
public OperationType OperationType { get; }
public bool IsStatic => Operand1.IsStatic && Operand2.IsStatic;
public int EvaluateNumeric()
{
return OperationType.Function(Operand1.EvaluateNumeric(), Operand2.EvaluateNumeric());
}
public Operation(IEvaluation operand1, IEvaluation operand2, OperationType type)
{
Operand1 = operand1;
Operand2 = operand2;
OperationType = type;
}
public override string ToString()
{
string operand1String;
string operand2String;
if (Operand1 is Operation operation1
&& operation1.OperationType.Precedence > OperationType.Precedence)
{
operand1String = $"({Operand1})";
}
else
{
operand1String = Operand1.ToString();
}
if (Operand2 is Operation operation2
&& operation2.OperationType.Precedence > OperationType.Precedence)
{
operand2String = $"({Operand2})";
}
else
{
operand2String = Operand2.ToString();
}
return $"{operand1String} {OperationType} {operand2String}";
}
}
}

View File

@ -1,159 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ZoneCodeGenerator.Domain.Evaluation
{
sealed class OperationType
{
// https://en.cppreference.com/w/cpp/language/operator_precedence
public enum OperationPrecedence
{
MultiplicationDivisionRemainder = 1,
AdditionSubtraction = 2,
BitwiseShift = 3,
RelationalGreaterLessThan = 4,
RelationalEquals = 5,
BitwiseAnd = 6,
BitwiseXor = 7,
BitwiseOr = 8,
LogicalAnd = 9,
LogicalOr = 10
}
public delegate int EvaluationFunction(int operand1, int operand2);
public string Syntax { get; }
public OperationPrecedence Precedence { get; }
public EvaluationFunction Function { get; }
public override string ToString()
{
return Syntax;
}
private OperationType(string syntax, OperationPrecedence precedence, EvaluationFunction function)
{
Syntax = syntax;
Precedence = precedence;
Function = function;
}
public static OperationType OperationAdd = new OperationType(
"+",
OperationPrecedence.AdditionSubtraction,
(operand1, operand2) => operand1 + operand2
);
public static OperationType OperationSubtract = new OperationType(
"-",
OperationPrecedence.AdditionSubtraction,
(operand1, operand2) => operand1 - operand2
);
public static OperationType OperationMultiply = new OperationType(
"*",
OperationPrecedence.MultiplicationDivisionRemainder,
(operand1, operand2) => operand1 * operand2
);
public static OperationType OperationDivide = new OperationType(
"/",
OperationPrecedence.MultiplicationDivisionRemainder,
(operand1, operand2) => operand1 / operand2
);
public static OperationType OperationRemainder = new OperationType(
"%",
OperationPrecedence.MultiplicationDivisionRemainder,
(operand1, operand2) => operand1 % operand2
);
public static OperationType OperationBitwiseAnd = new OperationType(
"&",
OperationPrecedence.BitwiseAnd,
(operand1, operand2) => operand1 & operand2
);
public static OperationType OperationBitwiseXor = new OperationType(
"^",
OperationPrecedence.BitwiseXor,
(operand1, operand2) => operand1 ^ operand2
);
public static OperationType OperationBitwiseOr = new OperationType(
"|",
OperationPrecedence.BitwiseOr,
(operand1, operand2) => operand1 | operand2
);
public static OperationType OperationShiftLeft = new OperationType(
"<<",
OperationPrecedence.BitwiseShift,
(operand1, operand2) => operand1 << operand2
);
public static OperationType OperationShiftRight = new OperationType(
">>",
OperationPrecedence.BitwiseShift,
(operand1, operand2) => operand1 >> operand2
);
public static OperationType OperationGreaterThan = new OperationType(
">",
OperationPrecedence.RelationalGreaterLessThan,
(operand1, operand2) => operand1 > operand2 ? 1 : 0
);
public static OperationType OperationGreaterEqualsThan = new OperationType(
">=",
OperationPrecedence.RelationalGreaterLessThan,
(operand1, operand2) => operand1 >= operand2 ? 1 : 0
);
public static OperationType OperationLessThan = new OperationType(
"<",
OperationPrecedence.RelationalGreaterLessThan,
(operand1, operand2) => operand1 < operand2 ? 1 : 0
);
public static OperationType OperationLessEqualsThan = new OperationType(
"<=",
OperationPrecedence.RelationalGreaterLessThan,
(operand1, operand2) => operand1 <= operand2 ? 1 : 0
);
public static OperationType OperationEquals = new OperationType(
"==",
OperationPrecedence.RelationalEquals,
(operand1, operand2) => operand1 == operand2 ? 1 : 0
);
public static OperationType OperationNotEquals = new OperationType(
"!=",
OperationPrecedence.RelationalEquals,
(operand1, operand2) => operand1 != operand2 ? 1 : 0
);
public static OperationType OperationAnd = new OperationType(
"&&",
OperationPrecedence.LogicalAnd,
(operand1, operand2) => operand1 > 0 && operand2 > 0 ? 1 : 0
);
public static OperationType OperationOr = new OperationType(
"||",
OperationPrecedence.LogicalOr,
(operand1, operand2) => operand1 > 0 || operand2 > 0 ? 1 : 0
);
public static List<OperationType> Types => typeof(OperationType)
.GetFields(BindingFlags.Static | BindingFlags.Public)
.Select(info => info.GetValue(null))
.OfType<OperationType>()
.ToList();
}
}

View File

@ -1,30 +0,0 @@
namespace ZoneCodeGenerator.Domain.FastFileStructure
{
class FastFileBlock
{
public enum Type
{
Temp,
Runtime,
Delay,
Normal
}
public string Name { get; }
public long Index { get; }
public Type BlockType { get; }
public bool IsDefault { get; }
public bool IsTemp => BlockType == Type.Temp;
public bool IsRuntime => BlockType == Type.Runtime;
public bool IsDelay => BlockType == Type.Delay;
public bool IsNormal => BlockType == Type.Normal;
public FastFileBlock(string name, long index, Type blockType, bool isDefault)
{
Name = name;
Index = index;
BlockType = blockType;
IsDefault = isDefault;
}
}
}

View File

@ -1,49 +0,0 @@
using System;
namespace ZoneCodeGenerator.Domain
{
class ForwardDeclaration : DataType
{
private DataType forwardedType;
public DataType ForwardedType
{
get => forwardedType;
set
{
if (forwardedType == null)
{
if(value.Type != Type)
throw new DataException($"Type of forwarded type '{Name}' does not match previous declaration");
forwardedType = value;
}
else if(forwardedType != value)
{
throw new DataException($"Tried to set forwarded type '{Name}' multiple times with different types");
}
}
}
public ForwardDeclaration(string _namespace, string name, DataTypeType dataTypeType) : base(_namespace, name, dataTypeType)
{
switch (dataTypeType)
{
case DataTypeType.Enum:
case DataTypeType.Struct:
case DataTypeType.Union:
break;
default:
throw new ArgumentException($"Cannot create forward declaration for type '{dataTypeType}'");
}
forwardedType = null;
}
public override int Alignment => 0;
public override bool ForceAlignment => false;
public override int Size => 0;
}
}

View File

@ -1,41 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain.Evaluation;
using ZoneCodeGenerator.Domain.FastFileStructure;
using ZoneCodeGenerator.Generating.Computations;
namespace ZoneCodeGenerator.Domain.Information
{
class MemberInformation
{
public StructureInformation Parent { get; }
public StructureInformation StructureType { get; }
public Variable Member { get; set; }
public bool IsString { get; set; }
public bool IsScriptString { get; set; }
public bool IsReusable { get; set; }
public bool IsLeaf { get; set; }
public IEvaluation Condition { get; set; }
public FastFileBlock Block { get; set; }
public MemberComputations Computations => new MemberComputations(this);
public MemberInformation(StructureInformation parent, Variable member, StructureInformation structureType)
{
Parent = parent;
Member = member;
StructureType = structureType;
IsString = false;
IsScriptString = false;
IsReusable = false;
IsLeaf = false;
Condition = null;
Block = null;
}
public override string ToString()
{
return $"info for {Member.Name}";
}
}
}

View File

@ -1,60 +0,0 @@
using System.Collections.Generic;
using ZoneCodeGenerator.Domain.FastFileStructure;
using ZoneCodeGenerator.Generating.Computations;
namespace ZoneCodeGenerator.Domain.Information
{
class StructureInformation
{
public DataTypeWithMembers Type { get; }
public bool IsUnion => Type is DataTypeUnion;
public EnumMember AssetEnumEntry { get; set; }
public bool IsAsset => AssetEnumEntry != null;
private int? fastFileAlign;
public bool HasNonDefaultAlign => fastFileAlign != null;
public int FastFileAlign
{
get => fastFileAlign ?? Type.Alignment;
set => fastFileAlign = value;
}
public List<StructureInformation> Usages { get; }
public List<MemberInformation> OrderedMembers { get; set; }
public bool NonEmbeddedReferenceExists { get; set; }
public bool SinglePointerReferenceExists { get; set; }
public bool ArrayPointerReferenceExists { get; set; }
public bool ArrayReferenceExists { get; set; }
public bool ReferenceFromNonDefaultNormalBlockExists { get; set; }
public CustomAction PostLoadAction { get; set; }
public FastFileBlock Block { get; set; }
public bool IsLeaf { get; set; }
public List<MemberInformation> NameChain { get; set; }
public StructureComputations Computations => new StructureComputations(this);
public StructureInformation(DataTypeWithMembers type)
{
AssetEnumEntry = null;
fastFileAlign = null;
Type = type;
NonEmbeddedReferenceExists = false;
SinglePointerReferenceExists = false;
ArrayReferenceExists = false;
ReferenceFromNonDefaultNormalBlockExists = false;
Usages = new List<StructureInformation>();
OrderedMembers = new List<MemberInformation>();
PostLoadAction = null;
IsLeaf = true;
NameChain = null;
}
public override string ToString()
{
return $"info for {Type}";
}
}
}

View File

@ -1,59 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace ZoneCodeGenerator.Domain
{
class Namespace
{
private static readonly Regex nameRegex = new Regex(@"^[a-zA-Z_$][a-zA-Z0-9_$]*$");
private readonly Stack<string> namespaceStack;
public Namespace()
{
namespaceStack = new Stack<string>();
}
public void Push(string _namespace)
{
if(!nameRegex.IsMatch(_namespace))
throw new ArgumentException("Namespace name invalid");
namespaceStack.Push(_namespace);
}
public string Pop()
{
return namespaceStack.Pop();
}
public string GetName()
{
if (namespaceStack.Count == 0)
return "";
var result = "";
var stackSnapshot = namespaceStack.ToArray();
// The stack is read from top to bottom. Therefore we need to access it in reverse order here.
for(var i = stackSnapshot.Length - 1; i >= 0; i--)
{
if (!string.IsNullOrEmpty(result))
result += "::";
result += stackSnapshot[i];
}
return result;
}
public override string ToString()
{
return GetName();
}
public static string Combine(Namespace _namespace, string typename)
{
return $"{_namespace}::{typename}";
}
}
}

View File

@ -1,7 +0,0 @@
namespace ZoneCodeGenerator.Domain
{
abstract class ReferenceType
{
}
}

View File

@ -1,19 +0,0 @@
using ZoneCodeGenerator.Domain.Evaluation;
namespace ZoneCodeGenerator.Domain
{
class ReferenceTypeArray : ReferenceType
{
public int ArraySize { get; }
public IEvaluation DynamicSize { get; set; }
public IEvaluation DynamicCount { get; set; }
public ReferenceTypeArray(int arraySize)
{
ArraySize = arraySize;
DynamicSize = null;
DynamicCount = null;
}
}
}

View File

@ -1,29 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain.Evaluation;
namespace ZoneCodeGenerator.Domain
{
class ReferenceTypePointer : ReferenceType
{
public static IEvaluation DefaultCount = new OperandStatic(1);
public IEvaluation Count { get; set; } = DefaultCount;
public IEvaluation[] CountByArrayIndex { get; set; }
public bool HasCountByArrayIndex => CountByArrayIndex != null;
private static bool EvaluationIsArray(IEvaluation eval)
{
return !eval.IsStatic || eval.EvaluateNumeric() > 1;
}
public bool IsArray(int index)
{
return EvaluationIsArray(HasCountByArrayIndex ? CountByArrayIndex[index] : Count);
}
public bool AnyIsArray =>
HasCountByArrayIndex ? CountByArrayIndex.Any(EvaluationIsArray) : EvaluationIsArray(Count);
}
}

View File

@ -1,55 +0,0 @@
using System.Collections.Generic;
using System.Linq;
namespace ZoneCodeGenerator.Domain
{
class TypeDeclaration
{
private const int PointerSize = 4;
public DataType Type { get; set; }
public int? CustomBitSize { get; set; }
public bool IsConst { get; set; }
public bool HasCustomBitSize => CustomBitSize != null;
private readonly List<ReferenceType> references;
public IReadOnlyList<ReferenceType> References => references.AsReadOnly();
public int Alignment => references.OfType<ReferenceTypePointer>().Any() ? PointerSize : Type.Alignment;
public bool ForceAlignment => !references.OfType<ReferenceTypePointer>().Any() && Type.ForceAlignment;
public int Size
{
get
{
var currentSize = Type.Size;
foreach (var reference in References.Reverse())
{
switch (reference)
{
case ReferenceTypePointer _:
currentSize = PointerSize;
break;
case ReferenceTypeArray array:
currentSize *= array.ArraySize;
break;
}
}
return currentSize;
}
}
public TypeDeclaration(DataType type, List<ReferenceType> references)
{
Type = type;
this.references = references ?? new List<ReferenceType>();
CustomBitSize = null;
}
}
}

View File

@ -1,20 +0,0 @@
namespace ZoneCodeGenerator.Domain
{
class Variable
{
public string Name { get; }
public int? AlignmentOverride { get; set; }
public int Alignment => AlignmentOverride ?? VariableType.Alignment;
public bool ForceAlignment => AlignmentOverride != null || VariableType.ForceAlignment;
public TypeDeclaration VariableType { get; }
public Variable(string name, TypeDeclaration type)
{
Name = name;
VariableType = type;
}
}
}

View File

@ -1,113 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Interface;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Generating
{
static class CodeGenerator
{
private class GeneratorPreset
{
public string FileName { get; }
public string TemplateName { get; }
public GeneratorPreset(string fileName, string templateName)
{
FileName = fileName;
TemplateName = templateName;
}
}
private static readonly Dictionary<string, GeneratorPreset> presets =
new Dictionary<string, GeneratorPreset>(StringComparer.CurrentCultureIgnoreCase)
{
{
"ZoneLoad", new GeneratorPreset("$asset/$asset_load_db", "ZoneLoad.stg")
},
{
"ZoneWrite", new GeneratorPreset("$asset/$asset_write_db", "ZoneWrite.stg")
},
{
"AssetStructTests", new GeneratorPreset("$asset/$asset_struct_test", "AssetStructTests.stg")
}
};
public static IEnumerable<string> Presets => presets.Keys;
public static bool GenerateCodeForPreset(string presetName, StructureInformation asset, CUISession session)
{
if (!presets.ContainsKey(presetName))
{
Console.WriteLine($"Unknown preset '{presetName}'");
return false;
}
var preset = presets[presetName];
try
{
if (!Directory.Exists(session.GeneratorOutputPath))
Directory.CreateDirectory(session.GeneratorOutputPath);
var codeTemplate = CodeTemplate.FromResources(preset.TemplateName);
if (codeTemplate == null)
{
Console.WriteLine($"Could not find template '{preset.TemplateName}'");
return false;
}
var resolvedFileName = preset.FileName.Replace("$asset", asset.Type.Name.ToLower());
var fullPath = Path.Combine(session.GeneratorOutputPath, resolvedFileName);
var folderOfFile = Path.GetDirectoryName(fullPath);
if (!Directory.Exists(folderOfFile))
Directory.CreateDirectory(folderOfFile);
var renderingContext = RenderingContext.BuildContext(session, asset);
if (renderingContext == null)
{
Console.WriteLine("Building rendering context failed");
return false;
}
if (!codeTemplate.HasHeaderTemplate && !codeTemplate.HasSourceTemplate)
{
Console.WriteLine($"Preset '{presetName}' does not have a header or a source! This is weird.");
return false;
}
if (codeTemplate.HasHeaderTemplate)
{
using (var fileStream = new FileStream(fullPath + ".h", FileMode.Create))
{
codeTemplate.RenderHeaderFile(fileStream, renderingContext);
fileStream.Close();
}
}
if (codeTemplate.HasSourceTemplate)
{
using (var fileStream = new FileStream(fullPath + ".cpp", FileMode.Create))
{
codeTemplate.RenderSourceFile(fileStream, renderingContext);
fileStream.Close();
}
}
return true;
}
catch (Exception e)
{
Console.WriteLine("An exception occured while trying to generate code");
Console.WriteLine(e.GetType().Name);
Console.WriteLine(e.Message);
return false;
}
}
}
}

View File

@ -1,56 +0,0 @@
using System.IO;
using Antlr4.StringTemplate;
using ZoneCodeGenerator.Domain;
namespace ZoneCodeGenerator.Generating
{
class CodeTemplate
{
private const string SourceTemplateName = "source";
private const string HeaderTemplateName = "header";
private readonly TemplateGroup templateGroup;
public bool HasSourceTemplate => templateGroup.IsDefined(SourceTemplateName);
public bool HasHeaderTemplate => templateGroup.IsDefined(HeaderTemplateName);
private CodeTemplate(TemplateGroup templateGroup)
{
this.templateGroup = templateGroup;
templateGroup.RegisterRenderer(typeof(string), new StringRenderer());
templateGroup.RegisterRenderer(typeof(DataType), new DataTypeAttributeRenderer());
}
public static CodeTemplate FromResources(string fileName)
{
var templateGroup = new TemplateGroupResources(fileName);
templateGroup.Load();
return new CodeTemplate(templateGroup);
}
public void RenderSourceFile(Stream stream, RenderingContext context)
{
RenderTemplate(stream, templateGroup.GetInstanceOf(SourceTemplateName), context);
}
public void RenderHeaderFile(Stream stream, RenderingContext context)
{
RenderTemplate(stream, templateGroup.GetInstanceOf(HeaderTemplateName), context);
}
private static void RenderTemplate(Stream stream, Template template, RenderingContext context)
{
if (template == null)
return;
template.Add("context", context);
using (var writer = new StreamWriter(stream))
{
template.Write(new AutoIndentWriter(writer));
}
}
}
}

View File

@ -1,108 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Evaluation;
using ZoneCodeGenerator.Domain.Information;
namespace ZoneCodeGenerator.Generating.Computations
{
class MemberComputations
{
private readonly MemberInformation information;
public bool ShouldIgnore => information.Condition != null
&& information.Condition.IsStatic
&& information.Condition.EvaluateNumeric() == 0;
public bool ContainsNonEmbeddedReference =>
information.Member.VariableType.References.OfType<ReferenceTypePointer>().Any();
public bool ContainsSinglePointerReference => information.Member.VariableType.References.Any()
&& information.Member.VariableType.References.Last() is
ReferenceTypePointer pointerReference
&& !pointerReference.AnyIsArray;
public bool ContainsArrayPointerReference => information.Member.VariableType.References.Any()
&& information.Member.VariableType.References.Last() is
ReferenceTypePointer pointerReference
&& pointerReference.AnyIsArray;
public bool ContainsPointerArrayReference => ContainsSinglePointerReference
&& (IsArray && PointerDepthIsOne || !IsArray && PointerDepthIsTwo);
public bool ContainsArrayReference => information.Member.VariableType.References.Any()
&& information.Member.VariableType.References
.Last() is ReferenceTypeArray;
public IEvaluation ArrayPointerCountEvaluation =>
information.Member.VariableType.References.Last() is ReferenceTypePointer pointerReference
? pointerReference.Count
: null;
public bool IsArray => information.Member.VariableType.References
.TakeWhile(type => type is ReferenceTypeArray)
.Any();
public IEnumerable<int> ArraySizes => information.Member.VariableType.References
.TakeWhile(type => type is ReferenceTypeArray)
.OfType<ReferenceTypeArray>()
.Select(array => array.ArraySize);
public int ArrayDimension => information.Member.VariableType.References
.TakeWhile(type => type is ReferenceTypeArray)
.Count();
public bool IsPointerToArray => information.Member.VariableType.References.OfType<ReferenceTypePointer>().Any()
&& information.Member.VariableType.References.Last() is ReferenceTypeArray;
public IEnumerable<int> PointerToArraySizes => information.Member.VariableType.References
.Reverse()
.TakeWhile(type => type is ReferenceTypeArray)
.OfType<ReferenceTypeArray>()
.Reverse()
.Select(array => array.ArraySize);
public int PointerDepth => information.Member.VariableType.References
.OfType<ReferenceTypePointer>()
.Count();
public bool PointerDepthIsOne => PointerDepth == 1;
public bool PointerDepthIsTwo => PointerDepth == 2;
public bool IsNotDefaultNormalBlock =>
information.Block != null && !(information.Block.IsNormal && information.Block.IsDefault);
public bool IsTempBlock => information.Block != null && information.Block.IsTemp;
public bool IsRuntimeBlock => information.Block != null && information.Block.IsRuntime;
private IEnumerable<MemberInformation> ParentUsedMembers =>
information.Parent.IsUnion && information.Parent.Computations.DynamicMember != null
? information.Parent.OrderedMembers.Where(member => !member.Computations.ShouldIgnore)
: information.Parent.OrderedMembers.Where(member =>
!member.IsLeaf && !member.Computations.ShouldIgnore);
public bool IsFirstMember => ParentUsedMembers.FirstOrDefault() == information;
public bool IsLastMember => ParentUsedMembers.LastOrDefault() == information;
public bool HasDynamicArraySize => information.Member.VariableType.References
.OfType<ReferenceTypeArray>()
.Any(array => array.DynamicSize != null);
public bool IsDynamicMember => HasDynamicArraySize ||
!ContainsNonEmbeddedReference &&
information.StructureType?.Computations.DynamicMember != null;
public bool IsAfterPartialLoad => IsDynamicMember ||
information.Parent.IsUnion &&
information.Parent.Computations.DynamicMember != null;
public MemberReferenceComputations References => new MemberReferenceComputations(information);
public MemberComputations(MemberInformation information)
{
this.information = information;
}
}
}

View File

@ -1,105 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Evaluation;
using ZoneCodeGenerator.Domain.Information;
namespace ZoneCodeGenerator.Generating.Computations
{
class MemberReferenceComputations
{
private readonly MemberInformation information;
private readonly List<int> referenceIndices;
private readonly int combinedIndex;
public ReferenceType Reference => referenceIndices.Count < information.Member.VariableType.References.Count
? information.Member.VariableType.References[referenceIndices.Count]
: null;
public ReferenceType NextReference =>
referenceIndices.Count + 1 < information.Member.VariableType.References.Count
? information.Member.VariableType.References[referenceIndices.Count + 1]
: null;
public IEnumerable<ReferenceType> FollowingReferences =>
information.Member.VariableType.References.Skip(referenceIndices.Count + 1);
public IEnumerable<int> ArrayIndices => referenceIndices;
public bool IsArray => Reference is ReferenceTypeArray;
public int ArraySize => Reference is ReferenceTypeArray array ? array.ArraySize : 0;
public bool HasDynamicArrayCount => Reference is ReferenceTypeArray array && array.DynamicCount != null;
public IEvaluation DynamicArrayCountEvaluation =>
Reference is ReferenceTypeArray array ? array.DynamicCount : null;
public IEnumerable<MemberReferenceComputations> ArrayEntries => Enumerable.Range(0, ArraySize)
.Select(i => new MemberReferenceComputations(information, referenceIndices.Concat(new[] {i})));
public bool IsSinglePointer => Reference is ReferenceTypePointer referenceTypePointer
&& !referenceTypePointer.IsArray(combinedIndex)
&& !FollowingReferences.OfType<ReferenceTypePointer>().Any();
public bool IsArrayPointer => Reference is ReferenceTypePointer referenceTypePointer
&& referenceTypePointer.IsArray(combinedIndex)
&& !FollowingReferences.OfType<ReferenceTypePointer>().Any();
public IEvaluation ArrayPointerCountEvaluation
{
get
{
if (!(Reference is ReferenceTypePointer pointer))
return null;
return pointer.HasCountByArrayIndex ? pointer.CountByArrayIndex[combinedIndex] : pointer.Count;
}
}
public bool IsPointerArray =>
(Reference is ReferenceTypePointer referenceTypePointer && referenceTypePointer.IsArray(combinedIndex) ||
Reference is ReferenceTypeArray)
&& NextReference is ReferenceTypePointer nextReferencePointer &&
!nextReferencePointer.IsArray(combinedIndex);
public IEvaluation PointerArrayCountEvaluation => NextReference is ReferenceTypePointer referenceTypePointer
? referenceTypePointer.Count
: null;
public bool IsDynamicArray =>
Reference is ReferenceTypeArray referenceTypeArray && referenceTypeArray.DynamicSize != null;
public IEvaluation DynamicArraySizeEvaluation => Reference is ReferenceTypeArray referenceTypeArray
? referenceTypeArray.DynamicSize
: null;
public MemberReferenceComputations(MemberInformation information)
{
this.information = information;
referenceIndices = new List<int>();
combinedIndex = 0;
}
private MemberReferenceComputations(MemberInformation information, IEnumerable<int> referenceIndices)
{
this.information = information;
this.referenceIndices = new List<int>(referenceIndices);
var arraySizes = information.Member.VariableType.References
.OfType<ReferenceTypeArray>()
.Select(array => array.ArraySize)
.ToList();
var indexDepth = 0;
combinedIndex = 0;
foreach (var referenceIndex in this.referenceIndices)
{
var sizePerIndexInCurrentDepth = arraySizes.Count <= indexDepth + 1
? 1
: arraySizes.Skip(indexDepth + 1).Aggregate((i1, i2) => i1 * i2);
combinedIndex += referenceIndex * sizePerIndexInCurrentDepth;
indexDepth++;
}
}
}
}

View File

@ -1,23 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Evaluation;
using ZoneCodeGenerator.Domain.Information;
namespace ZoneCodeGenerator.Generating.Computations
{
class StructureComputations
{
private readonly StructureInformation information;
public bool IsUsed => information.Usages.Any();
public MemberInformation DynamicMember =>
information.OrderedMembers.FirstOrDefault(memberInformation => memberInformation.Computations.IsDynamicMember);
public StructureComputations(StructureInformation information)
{
this.information = information;
}
}
}

View File

@ -1,29 +0,0 @@
using System.Globalization;
using Antlr4.StringTemplate;
using ZoneCodeGenerator.Domain;
namespace ZoneCodeGenerator.Generating
{
class DataTypeAttributeRenderer : IAttributeRenderer
{
public string ToString(object obj, string formatString, CultureInfo culture)
{
if (formatString == null)
return obj.ToString();
if (!(obj is DataType dataType))
{
return obj.ToString();
}
switch (formatString)
{
case "safe_name":
return dataType.Name.Replace(" ", "_");
default:
return obj.ToString();
}
}
}
}

View File

@ -1,162 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.FastFileStructure;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Interface;
namespace ZoneCodeGenerator.Generating
{
class RenderingContext
{
public class UsedType
{
public bool MembersLoaded { get; set; }
public DataType Type { get; }
public StructureInformation Information { get; }
public bool IsContextAsset { get; set; }
public bool NonRuntimeReferenceExists { get; set; }
public bool NonEmbeddedReferenceExists { get; set; }
public bool ArrayReferenceExists { get; set; }
public bool PointerArrayReferenceExists { get; set; }
public bool PointerArrayReferenceIsReusable { get; set; }
public UsedType(DataType type, StructureInformation information)
{
MembersLoaded = false;
Type = type;
Information = information;
IsContextAsset = false;
NonRuntimeReferenceExists = false;
NonEmbeddedReferenceExists = false;
ArrayReferenceExists = false;
PointerArrayReferenceExists = false;
PointerArrayReferenceIsReusable = false;
}
}
public string Game { get; set; }
public StructureInformation Asset { get; private set; }
private readonly IDictionary<DataType, UsedType> usedTypes;
public IEnumerable<UsedType> UsedTypes => usedTypes.Values;
public IEnumerable<UsedType> UsedStructures => UsedTypes
.Where(usedType => usedType.Information != null && usedType.Information.Type == usedType.Type);
public IEnumerable<UsedType> ReferencedAssets => UsedTypes.Where(type =>
type.Information != null && type.Information.IsAsset && type.Information != Asset);
public IList<FastFileBlock> Blocks { get; private set; }
public FastFileBlock DefaultNormalBlock => Blocks.FirstOrDefault(block => block.IsDefault && block.IsNormal) ??
Blocks.FirstOrDefault(block => block.IsNormal);
public FastFileBlock DefaultTempBlock => Blocks.FirstOrDefault(block => block.IsDefault && block.IsTemp) ??
Blocks.FirstOrDefault(block => block.IsTemp);
public bool HasActions => UsedTypes.Any(type =>
(type.Information == null || !type.Information.IsAsset || type.IsContextAsset) && type.NonRuntimeReferenceExists &&
type.Information?.PostLoadAction != null);
private RenderingContext()
{
usedTypes = new Dictionary<DataType, UsedType>();
}
private UsedType GetBaseType(UsedType usedType)
{
if (usedType.Type is DataTypeTypedef typeDef)
{
while (typeDef.TypeDefinition.Type is DataTypeTypedef anotherTypeDef)
{
typeDef = anotherTypeDef;
}
if (!usedTypes.ContainsKey(typeDef.TypeDefinition.Type))
{
var result = new UsedType(typeDef.TypeDefinition.Type, usedType.Information);
usedTypes.Add(typeDef.TypeDefinition.Type, result);
return result;
}
return usedTypes[typeDef.TypeDefinition.Type];
}
return null;
}
private void AddMembersToContext(StructureInformation structureInformation)
{
foreach (var member in structureInformation.OrderedMembers
.Where(member => !member.Computations.ShouldIgnore))
{
UsedType usedType;
if (!usedTypes.ContainsKey(member.Member.VariableType.Type))
{
usedType = new UsedType(member.Member.VariableType.Type, member.StructureType);
usedTypes.Add(usedType.Type, usedType);
}
else
{
usedType = usedTypes[member.Member.VariableType.Type];
}
var baseUsedType = GetBaseType(usedType);
if (!member.Computations.IsRuntimeBlock)
{
usedType.NonRuntimeReferenceExists = true;
if (baseUsedType != null)
baseUsedType.NonRuntimeReferenceExists = true;
}
if (member.Computations.ContainsNonEmbeddedReference)
usedType.NonEmbeddedReferenceExists = true;
if (member.Computations.ContainsArrayPointerReference || member.Computations.ContainsArrayReference)
usedType.ArrayReferenceExists = true;
if (member.Computations.ContainsPointerArrayReference && !member.IsString)
{
usedType.PointerArrayReferenceExists = true;
if (member.IsReusable)
usedType.PointerArrayReferenceIsReusable = true;
}
if (usedType.Information != null && !usedType.Information.IsAsset && !member.Computations.IsRuntimeBlock &&
!usedType.MembersLoaded)
{
usedType.MembersLoaded = true;
AddMembersToContext(usedType.Information);
}
}
}
private void MakeAsset(StructureInformation asset)
{
Asset = asset;
var usage = new UsedType(asset.Type, asset) {IsContextAsset = true};
usedTypes.Add(usage.Type, usage);
AddMembersToContext(asset);
}
public static RenderingContext BuildContext(CUISession session, StructureInformation asset)
{
var context = new RenderingContext
{
Game = session.Game,
Blocks = session.Repository.GetAllFastFileBlocks().ToList()
};
context.MakeAsset(asset);
return context;
}
}
}

View File

@ -1,126 +0,0 @@
using System;
using System.IO;
using System.Reflection;
using Antlr.Runtime;
using Antlr4.StringTemplate;
using Antlr4.StringTemplate.Compiler;
using Antlr4.StringTemplate.Misc;
namespace ZoneCodeGenerator.Generating
{
public class TemplateGroupResources : TemplateGroup
{
private const string ResourceBasePath = "ZoneCodeGenerator.Generating.Templates";
private const char DefaultDelimiterStart = '<';
private const char DefaultDelimiterStop = '>';
private bool alreadyLoaded;
private readonly string fileName;
public TemplateGroupResources(string fileName, char delimiterStartChar, char delimiterStopChar) : base(delimiterStartChar, delimiterStopChar)
{
this.fileName = fileName;
alreadyLoaded = false;
}
public TemplateGroupResources(string fileName) : this(fileName, DefaultDelimiterStart, DefaultDelimiterStop)
{
}
public override void ImportTemplates(IToken fileNameToken)
{
var text = Utility.Strip(fileNameToken.Text, 1);
TemplateGroup importingGroup = null;
if (text.EndsWith(GroupFileExtension))
{
importingGroup = new TemplateGroupResources(text, DelimiterStartChar, DelimiterStopChar);
}
else if (text.EndsWith(TemplateFileExtension))
{
importingGroup = new TemplateGroup(DelimiterStartChar, DelimiterStopChar);
using (var resourceStream = StreamFromResources(text))
{
if (resourceStream != null)
{
using (var textStream = new StreamReader(resourceStream))
{
var inputStream = new ANTLRReaderStream(textStream)
{
name = fileName
};
importingGroup.LoadTemplateFile("/", fileName, inputStream);
}
}
}
}
if (importingGroup != null)
{
importingGroup.Load();
ImportTemplates(importingGroup);
}
else
{
ErrorManager.CompiletimeError(ErrorType.CANT_IMPORT, null, fileNameToken, text);
}
}
public override void Load()
{
if (alreadyLoaded)
return;
alreadyLoaded = true;
if (Verbose)
Console.WriteLine($"loading group file '{fileName}'");
using (var resourceStream = StreamFromResources(fileName))
{
if (resourceStream == null)
{
Console.WriteLine($"Resource '{fileName}' doesn't exist");
Console.WriteLine("The following files do exist: " + string.Join(", ", Assembly.GetExecutingAssembly().GetManifestResourceNames()));
return;
}
using (var textStream = new StreamReader(resourceStream))
{
var inputStream = new ANTLRReaderStream(textStream)
{
name = fileName
};
try
{
var lexer = new GroupLexer(inputStream);
var tokenStream = new CommonTokenStream(lexer);
var parser = new GroupParser(tokenStream);
parser.group(this, "/");
}
catch (Exception ex)
{
ErrorManager.IOError(null, ErrorType.CANT_LOAD_GROUP_FILE, ex, FileName);
}
}
}
}
private static Stream StreamFromResources(string fileName)
{
var resourceName = $"{ResourceBasePath}.{fileName.Replace('\\', '.').Replace('/', '.')}";
var assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceStream(resourceName);
}
public override string Name => "TemplateGroupResources";
public override string FileName => Name;
}
}

View File

@ -1,41 +0,0 @@
delimiters "$", "$"
import "Common.stg"
TestMethod(structure) ::= <<
$if(structure.NonEmbeddedReferenceExists)$
TEST_METHOD(Test_$structure.Type.Name$)
{
Assert::AreEqual($structure.Type.Size$u, sizeof($structure.Type.FullName$));
Assert::AreEqual($structure.Type.Alignment$u, alignof($structure.Type.FullName$));
}
$endif$
>>
// =======================
// Source file entry point
// =======================
source(context) ::= <<
// ====================================================================
// This file has been generated by ZoneCodeGenerator.
// Do not modify.
// Any changes will be discarded when regenerating.
// ====================================================================
#include "CppUnitTest.h"
#include "Game/$context.Game$/$context.Game$.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace $context.Game$;
namespace ZoneCommonTests
{
TEST_CLASS(AssetStructTest_$context.Asset.Type.Name$)
{
public:
$TestMethod(context.Asset)$
$context.UsedStructures:{structure | $if(!structure.Information.Type.IsAnonymous && !structure.Information.IsAsset)$$TestMethod(structure)$
$endif$}$
};
}
>>

View File

@ -1,69 +0,0 @@
delimiters "$", "$"
Capital(name) ::= "$name; format=\"cap\"$"
Lower(name) ::= "$name; format=\"lower\"$"
TypeDeclaration(typeDecl) ::= "$if(typeDecl.IsConst)$const $endif$$typeDecl.Type.FullName$"
TypeVarName(type) ::= "var$SafeTypeName(type)$"
TypePtrVarName(type) ::= "var$SafeTypeName(type)$Ptr"
SafeTypeName(type) ::= "$type; format=\"safe_name\"$"
PrintFollowingReferences(references) ::= <%
$references:{ reference |
$if(reference.ArraySize)$
[$reference.ArraySize$]
$else$
*
$endif$
}$
%>
PrintArrayIndices(reference) ::= "$reference.ArrayIndices:{ index | [$index$]}$"
PrintOperandStatic(op) ::= <%
$if(op.EnumMemberValue)$
$op.EnumMemberValue.Name$
$else$
$op.Value$
$endif$
%>
PrintOperandDynamic(op) ::= <%
$TypeVarName(op.Structure.Type)$
$if(first(op.ReferencedMemberChain))$
->$trunc(op.ReferencedMemberChain):{member | $member.Member.Name$$if(member.Computations.ContainsNonEmbeddedReference)$->$else$.$endif$}$
$last(op.ReferencedMemberChain):{member | $member.Member.Name$}$
$op.ArrayIndices:{ arrayIndex | [$PrintEvaluation(arrayIndex)$]}$
$endif$
%>
PrintOperation(operation) ::= <%
$if(operation.Operand1NeedsParenthesis)$
($PrintEvaluation(operation.Operand1)$)
$else$
$PrintEvaluation(operation.Operand1)$
$endif$
$operation.OperationType.Syntax$
$if(operation.Operand2NeedsParenthesis)$
($PrintEvaluation(operation.Operand2)$)
$else$
$PrintEvaluation(operation.Operand2)$
$endif$
%>
PrintEvaluation(eval) ::= <%
$if(eval.OperationType)$
$PrintOperation(eval)$
$elseif(eval.IsStatic)$
$PrintOperandStatic(eval)$
$else$
$PrintOperandDynamic(eval)$
$endif$
%>

View File

@ -1,165 +0,0 @@
delimiters "$", "$"
// Everything related to loading a pointer with a count that can be larger than 1
LoadArrayPointer_Loading(context, structure, member, reference) ::= <<
$if(member.Computations.IsTempBlock)$
$member.Member.VariableType.Type.FullName$* ptr = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;
$endif$$\\$
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>(alignof($TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$)); $\\$
// $member.Member.VariableType.Type.Alignment$$\\$
$\\$
$\\$
$if(member.Computations.IsTempBlock)$
$member.Member.VariableType.Type.FullName$** toInsert = nullptr;
if(ptr == PTR_INSERT)
toInsert = m_stream->InsertPointer<$member.Member.VariableType.Type.FullName$>();
$endif$$\\$
$\\$
$\\$
$if(member.StructureType && !member.StructureType.IsLeaf && !member.Computations.IsRuntimeBlock)$
$TypeVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;
LoadArray_$member.Member.VariableType.Type.Name$(true, $PrintEvaluation(reference.ArrayPointerCountEvaluation)$);$\\$
$else$
m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $PrintEvaluation(reference.ArrayPointerCountEvaluation)$);$\\$
$endif$$\\$
$\\$
$if(member.Computations.IsTempBlock)$
if(toInsert != nullptr)
*toInsert = $TypeVarName(structure.Type)$->$member.Member.Name$;$\\$
$endif$
>>
LoadArrayPointer_ScriptString(context, structure, member, reference) ::= <%
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>(alignof($TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$));
// $member.Member.VariableType.Type.Alignment$
$\n$
varScriptString = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$
LoadScriptStringArray(true, $PrintEvaluation(reference.ArrayPointerCountEvaluation)$);
%>
LoadArrayPointer_TypeCheck(context, structure, member, reference) ::= <%
$if(member.IsScriptString)$
$LoadArrayPointer_ScriptString(context, structure, member, reference)$
$else$
$LoadArrayPointer_Loading(context, structure, member, reference)$
$endif$
%>
LoadArrayPointer_Reuse(context, structure, member, reference) ::= <<
$if(member.Computations.IsTempBlock)$
if($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ == PTR_FOLLOWING || $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ == PTR_INSERT)
{
$LoadArrayPointer_TypeCheck(context, structure, member, reference)$
}
else
{
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->ConvertOffsetToAlias($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$);
}$\\$
$else$
if($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ == PTR_FOLLOWING)
{
$LoadArrayPointer_TypeCheck(context, structure, member, reference)$
}
else
{
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->ConvertOffsetToPointer($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$);
}$\\$
$endif$
>>
LoadArrayPointer_PointerCheck(context, structure, member, reference) ::= <<
if ($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$)
{
$if(member.IsReusable)$
$LoadArrayPointer_Reuse(context, structure, member, reference)$
$else$
$LoadArrayPointer_TypeCheck(context, structure, member, reference)$
$endif$
}
>>
LoadArrayPointer_Block(context, structure, member, reference) ::= <%
$if(member.Computations.IsNotDefaultNormalBlock)$
m_stream->PushBlock($member.Block.Name$);$\n$
$endif$
$LoadArrayPointer_PointerCheck(context, structure, member, reference)$
$if(member.Computations.IsNotDefaultNormalBlock)$
$\n$m_stream->PopBlock();
$endif$
%>
LoadArrayPointer(context, structure, member, reference) ::= <%
$LoadArrayPointer_Block(context, structure, member, reference)$
%>
LoadPointerArrayMethod_Loading(context, type, structure) ::= <%
*$TypePtrVarName(type)$ = m_stream->Alloc<$type.FullName$>(alignof($type.FullName$));
// $type.Alignment$
$\n$
$if(structure && !structure.IsLeaf)$
$TypeVarName(structure.Type)$ = *$TypePtrVarName(type)$;$\n$
Load_$type.Name$(true);
$else$
m_stream->Load<$type.FullName$>(*$TypePtrVarName(type)$);
$endif$
%>
LoadPointerArrayMethod_Asset(context, type, structure) ::= <<
$LoaderClassName(structure)$ loader(m_zone, m_stream);
AddDependency(loader.Load($TypePtrVarName(type)$));
>>
LoadPointerArrayMethod_PointerCheck(context, type, structure, reusable) ::= <<
if (*$TypePtrVarName(type)$)
{
$if(structure && structure.IsAsset)$
$LoadPointerArrayMethod_Asset(context, type, structure)$
$else$
$if(reusable)$
if(*$TypePtrVarName(type)$ == PTR_FOLLOWING)
{
$LoadPointerArrayMethod_Loading(context, type, structure)$
}
else
{
*$TypePtrVarName(type)$ = m_stream->ConvertOffsetToPointer(*$TypePtrVarName(type)$);
}
$else$
$LoadPointerArrayMethod_Loading(context, type, structure)$
$endif$
$endif$
}
>>
LoadPointerArrayMethod(context, type, structure, reusable) ::= <<
void $LoaderClassName(context.Asset)$::LoadPtrArray_$SafeTypeName(type)$(const bool atStreamStart, const size_t count)
{
assert($TypePtrVarName(type)$ != nullptr);
if(atStreamStart)
m_stream->Load<$type.FullName$*>($TypePtrVarName(type)$, count);
$type.FullName$** var = $TypePtrVarName(type)$;
for(size_t index = 0; index < count; index++)
{
$TypePtrVarName(type)$ = var;
$LoadPointerArrayMethod_PointerCheck(context, type, structure, reusable)$
var++;
}
}
>>

View File

@ -1,8 +0,0 @@
delimiters "$", "$"
// Loading common
LoaderClassName(asset) ::= "Loader_$asset.Type.Name$"
CustomAction(action) ::= <<
m_actions.$action.ActionName$($first(action.ParameterTypes):{ param | $TypeVarName(param)$}$$rest(action.ParameterTypes):{ param | , $TypeVarName(param)$}$);
>>

View File

@ -1,20 +0,0 @@
delimiters "$", "$"
// Everything related to loading a dynamic array
LoadDynamicArray_Load(context, structure, member, reference) ::= <%
$if(member.StructureType && !member.StructureType.IsLeaf)$
$TypeVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$
LoadArray_$member.Member.VariableType.Type.Name$(true, $PrintEvaluation(reference.DynamicArraySizeEvaluation)$);
$else$
m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $PrintEvaluation(reference.DynamicArraySizeEvaluation)$);
$endif$
%>
LoadDynamicArray(context, structure, member, reference) ::= <%
$LoadDynamicArray_Load(context, structure, member, reference)$
%>

View File

@ -1,69 +0,0 @@
delimiters "$", "$"
// Everything related to loading an embedded reference
ArrayCount(reference) ::= <%
$if(reference.HasDynamicArrayCount)$
$PrintEvaluation(reference.DynamicArrayCountEvaluation)$
$else$
$reference.ArraySize$
$endif$
%>
LoadEmbedded_Load(context, structure, member, reference) ::= <<
$if(!member.IsLeaf)$
$TypeVarName(member.Member.VariableType.Type)$ = &$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;
Load_$member.Member.VariableType.Type.Name$($if(member.Computations.IsAfterPartialLoad)$true$else$false$endif$);$\\$
$if(member.StructureType.PostLoadAction)$
$CustomAction(member.StructureType.PostLoadAction)$
$endif$
$elseif(member.Computations.IsAfterPartialLoad)$
m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>(&$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$);$\\$
$endif$
>>
LoadEmbedded_TypeCheck(context, structure, member, reference) ::= <%
$if(member.IsScriptString)$
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = UseScriptString($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$);
$else$
$LoadEmbedded_Load(context, structure, member, reference)$
$endif$
%>
LoadEmbedded_Block(context, structure, member, reference) ::= <%
$if(member.Computations.IsNotDefaultNormalBlock)$
m_stream->PushBlock($member.Block.Name$);$\n$
$endif$
$LoadEmbedded_TypeCheck(context, structure, member, reference)$
$if(member.Computations.IsNotDefaultNormalBlock)$
$\n$m_stream->PopBlock();
$endif$
%>
LoadEmbedded(context, structure, member, reference) ::= <%
$LoadEmbedded_Block(context, structure, member, reference)$
%>
LoadEmbeddedArray_Load(context, structure, member, reference) ::= <<
$if(!member.IsLeaf)$
$TypeVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;
LoadArray_$member.Member.VariableType.Type.Name$($if(member.Computations.IsAfterPartialLoad)$true$else$false$endif$, $ArrayCount(reference)$);$\\$
$elseif(member.Computations.IsAfterPartialLoad)$
m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $ArrayCount(reference)$);$\\$
$endif$
>>
LoadEmbeddedArray_TypeCheck(context, structure, member, reference) ::= <%
$if(member.IsScriptString)$
varScriptString = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$
LoadScriptStringArray(false, $ArrayCount(reference)$);
$else$
$LoadEmbeddedArray_Load(context, structure, member, reference)$
$endif$
%>
LoadEmbeddedArray(context, structure, member, reference) ::= <<
$LoadEmbeddedArray_TypeCheck(context, structure, member, reference)$
>>

View File

@ -1,101 +0,0 @@
delimiters "$", "$"
LoadPointerArray_Loading_Array(context, structure, member, reference) ::= <%
$TypePtrVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$
LoadPtrArray_$SafeTypeName(member.Member.VariableType.Type)$(false, $reference.ArraySize$);
%>
LoadPointerArray_Loading_Pointer_Inner(context, structure, member, reference) ::= <%
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>(alignof($TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$));
// $member.Member.VariableType.Alignment$$\n$
$TypePtrVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$
LoadPtrArray_$SafeTypeName(member.Member.VariableType.Type)$(true, $PrintEvaluation(reference.ArrayPointerCountEvaluation)$);
%>
LoadPointerArray_Loading_Pointer(context, structure, member, reference) ::= <<
if($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$)
{
$if(member.IsReusable)$
if($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ == PTR_FOLLOWING)
{
$LoadPointerArray_Loading_Pointer_Inner(context, structure, member, reference)$
}
else
{
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->ConvertOffsetToPointer($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$);
}
$else$
$LoadPointerArray_Loading_Pointer_Inner(context, structure, member, reference)$
$endif$
}
>>
LoadPointerArray_Loading(context, structure, member, reference) ::= <%
$if(member.Computations.IsArray)$
$LoadPointerArray_Loading_Array(context, structure, member, reference)$
$else$
$LoadPointerArray_Loading_Pointer(context, structure, member, reference)$
$endif$
%>
LoadPointerArray_String_Array(context, structure, member, reference) ::= <<
varXString = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;
LoadXStringArray(false, $reference.ArraySize$);
>>
LoadPointerArray_String_Pointer_Inner(context, structure, member, reference) ::= <%
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>(alignof($TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$));
// $member.Member.VariableType.Alignment$$\n$
varXString = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$
LoadXStringArray(true, $PrintEvaluation(reference.ArrayPointerCountEvaluation)$);
%>
LoadPointerArray_String_Pointer(context, structure, member, reference) ::= <<
if($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$)
{
$if(member.IsReusable)$
if($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ == PTR_FOLLOWING)
{
$LoadPointerArray_String_Pointer_Inner(context, structure, member, reference)$
}
else
{
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->ConvertOffsetToPointer($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$);
}
$else$
$LoadPointerArray_String_Pointer_Inner(context, structure, member, reference)$
$endif$
}
>>
LoadPointerArray_String(context, structure, member, reference) ::= <%
$if(reference.IsArray)$
$LoadPointerArray_String_Array(context, structure, member, reference)$
$else$
$LoadPointerArray_String_Pointer(context, structure, member, reference)$
$endif$
%>
LoadPointerArray_TypeCheck(context, structure, member, reference) ::= <%
$if(member.IsString)$
$LoadPointerArray_String(context, structure, member, reference)$
$else$
$LoadPointerArray_Loading(context, structure, member, reference)$
$endif$
%>
LoadPointerArray_Block(context, structure, member, reference) ::= <%
$if(member.Computations.IsNotDefaultNormalBlock)$
m_stream->PushBlock($member.Block.Name$);$\n$
$endif$
$LoadPointerArray_TypeCheck(context, structure, member, reference)$
$if(member.Computations.IsNotDefaultNormalBlock)$
$\n$m_stream->PopBlock();
$endif$
%>
LoadPointerArray(context, structure, member, reference) ::= <%
$LoadPointerArray_Block(context, structure, member, reference)$
%>

View File

@ -1,115 +0,0 @@
delimiters "$", "$"
// Everything related to loading a pointer with a count that is statically 1
LoadSinglePointerInner(context, structure, member, reference) ::= <<
$if(member.Computations.IsTempBlock)$
$member.Member.VariableType.Type.FullName$* ptr = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;
$endif$$\\$
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->Alloc<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>(alignof($TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$)); // $member.Member.VariableType.Type.Alignment$$\\$
$\\$
$\\$
$if(member.Computations.IsTempBlock)$
$member.Member.VariableType.Type.FullName$** toInsert = nullptr;
if(ptr == PTR_INSERT)
toInsert = m_stream->InsertPointer<$member.Member.VariableType.Type.FullName$>();
$endif$$\\$
$\\$
$\\$
$if(member.StructureType && !member.StructureType.IsLeaf && !member.Computations.IsRuntimeBlock)$
$TypeVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;
Load_$member.Member.VariableType.Type.Name$(true);$\\$
$if(member.StructureType.PostLoadAction)$
$CustomAction(member.StructureType.PostLoadAction)$
$endif$
$else$
m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$);$\\$
$endif$$\\$
$\\$
$if(member.Computations.IsTempBlock)$
if(toInsert != nullptr)
*toInsert = $TypeVarName(structure.Type)$->$member.Member.Name$;$\\$
$endif$
>>
LoadSinglePointerAsset(context, structure, member, reference) ::= <<
$LoaderClassName(member.StructureType)$ loader(m_zone, m_stream);
AddDependency(loader.Load(&$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$));
>>
LoadSinglePointer_Reuse(context, structure, member, reference) ::= <<
$if(member.Computations.IsTempBlock)$
if($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ == PTR_FOLLOWING || $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ == PTR_INSERT)
{
$LoadSinglePointerInner(context, structure, member, reference)$
}
else
{
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->ConvertOffsetToAlias($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$);
}$\\$
$else$
if($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ == PTR_FOLLOWING)
{
$LoadSinglePointerInner(context, structure, member, reference)$
}
else
{
$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$ = m_stream->ConvertOffsetToPointer($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$);
}$\\$
$endif$
>>
LoadSinglePointer_PointerCheck(context, structure, member, reference) ::= <<
if ($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$)
{
$if(member.StructureType && member.StructureType.IsAsset)$
$LoadSinglePointerAsset(context, structure, member, reference)$
$else$
$if(member.IsReusable)$
$LoadSinglePointer_Reuse(context, structure, member, reference)$
$else$
$LoadSinglePointerInner(context, structure, member, reference)$
$endif$
$endif$
}
>>
LoadSinglePointer_String(context, structure, member, reference) ::= <%
$if(member.Member.VariableType.IsConst)$
varXString = &$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$
$else$
varXString = const_cast<const char**>(&$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$);$\n$
$endif$
LoadXString(false);
%>
LoadSinglePointer_TypeCheck(context, structure, member, reference) ::= <%
$if(member.IsString)$
$LoadSinglePointer_String(context, structure, member, reference)$
$elseif(member.IsScriptString)$
// ScriptString $member.Member.Name$
$else$
$LoadSinglePointer_PointerCheck(context, structure, member, reference)$
$endif$
%>
LoadSinglePointer_Block(context, structure, member, reference) ::= <%
$if(member.Computations.IsNotDefaultNormalBlock)$
m_stream->PushBlock($member.Block.Name$);$\n$
$endif$
$LoadSinglePointer_TypeCheck(context, structure, member, reference)$
$if(member.Computations.IsNotDefaultNormalBlock)$
$\n$m_stream->PopBlock();
$endif$
%>
LoadSinglePointer(context, structure, member, reference) ::= <%
$LoadSinglePointer_Block(context, structure, member, reference)$
%>

View File

@ -1,382 +0,0 @@
delimiters "$", "$"
import "Common.stg"
import "Loading/Common.stg"
import "Loading/ArrayPointer.stg"
import "Loading/DynamicArray.stg"
import "Loading/Embedded.stg"
import "Loading/SinglePointer.stg"
import "Loading/PointerArray.stg"
// Loading common
LoaderClassName(asset) ::= "Loader_$asset.Type.Name$"
HeaderConstructor(context) ::= "$LoaderClassName(context.Asset)$(Zone* zone, IZoneInputStream* stream);"
HeaderTempPtrLoadMethodDeclaration(structure) ::= "void LoadPtr_$structure.Type.Name$(bool atStreamStart);"
HeaderArrayLoadMethodDeclaration(type) ::= "void LoadArray_$SafeTypeName(type)$(bool atStreamStart, size_t count);"
HeaderPtrArrayLoadMethodDeclaration(type) ::= "void LoadPtrArray_$SafeTypeName(type)$(bool atStreamStart, size_t count);"
HeaderLoadMethodDeclaration(structure) ::= "void Load_$structure.Type.Name$(bool atStreamStart);"
HeaderGetNameMethodDeclaration(asset) ::= "static std::string GetAssetName($asset.Type.FullName$* pAsset);"
HeaderAssetLoadMethodDeclaration(asset) ::= "void LoadAsset_$asset.Type.Name$($asset.Type.FullName$** pAsset);"
HeaderMainLoadMethodDeclaration(asset) ::= "XAssetInfo<$asset.Type.FullName$>* Load($asset.Type.FullName$** pAsset);"
VariableDeclaration(type) ::= <<
$type.FullName$* var$SafeTypeName(type)$;
>>
PointerVariableDeclaration(type) ::= <<
$type.FullName$** var$SafeTypeName(type)$Ptr;
>>
// =======================
// Header file entry point
// =======================
header(context) ::= <<
// ====================================================================
// This file has been generated by ZoneCodeGenerator.
// Do not modify.
// Any changes will be discarded when regenerating.
// ====================================================================
#pragma once
#include "Loading/AssetLoader.h"
#include "Game/$context.Game$/$context.Game$.h"
$if(context.HasActions)$
#include "Game/$context.Game$/XAssets/$Lower(context.Asset.Type.Name)$/$Lower(context.Asset.Type.Name)$_actions.h"
$endif$
#include <string>
namespace $context.Game$
{
class $LoaderClassName(context.Asset)$ final : public AssetLoader
{
XAssetInfo<$context.Asset.Type.FullName$>* m_asset_info;
$if(context.HasActions)$
Actions_$context.Asset.Type.Name$ m_actions;
$endif$
$VariableDeclaration(context.Asset.Type)$
$PointerVariableDeclaration(context.Asset.Type)$
$context.UsedTypes:{type | $if(type.Information && !type.Information.Type.IsAnonymous && !type.Information.IsLeaf && !type.Information.IsAsset)$$VariableDeclaration(type.Type)$
$endif$}$
$context.UsedTypes:{type | $if(type.PointerArrayReferenceExists && !type.IsContextAsset)$$PointerVariableDeclaration(type.Type)$
$endif$}$$\\$
$context.UsedTypes:{usedType | $if(usedType.PointerArrayReferenceExists)$$HeaderPtrArrayLoadMethodDeclaration(usedType.Type)$$\n$$endif$}$
$context.UsedTypes:{usedType | $if(usedType.ArrayReferenceExists && usedType.Information && !usedType.Information.IsLeaf && usedType.NonRuntimeReferenceExists)$$HeaderArrayLoadMethodDeclaration(usedType.Type)$$\n$$endif$}$
$context.UsedStructures:{usedStructure | $if(usedStructure.NonRuntimeReferenceExists && !usedStructure.Information.IsLeaf && !usedStructure.Information.IsAsset)$$HeaderLoadMethodDeclaration(usedStructure.Information)$$\n$$endif$}$
$HeaderLoadMethodDeclaration(context.Asset)$
$HeaderTempPtrLoadMethodDeclaration(context.Asset)$
$HeaderAssetLoadMethodDeclaration(context.Asset)$
public:
$HeaderConstructor(context)$
$HeaderMainLoadMethodDeclaration(context.Asset)$
$HeaderGetNameMethodDeclaration(context.Asset)$
};
}
>>
LoadMemberReference_Array(context, structure, member, reference) ::= <<
$first(reference.ArrayEntries):{entry | $LoadMemberReference(context, structure, member, entry)$}$
$rest(reference.ArrayEntries):{entry |
$LoadMemberReference(context, structure, member, entry)$}$
>>
LoadMemberReference(context, structure, member, reference) ::= <%
$if(reference.IsDynamicArray)$
$LoadDynamicArray(context, structure, member, reference)$
$elseif(reference.IsSinglePointer)$
$LoadSinglePointer(context, structure, member, reference)$
$elseif(reference.IsArrayPointer)$
$LoadArrayPointer(context, structure, member, reference)$
$elseif(reference.IsPointerArray)$
$LoadPointerArray(context, structure, member, reference)$
$elseif(reference.IsArray && !reference.NextReference)$
$LoadEmbeddedArray(context, structure, member, reference)$
$elseif(!reference.Reference)$
$LoadEmbedded(context, structure, member, reference)$
$elseif(reference.IsArray)$
$LoadMemberReference_Array(context, structure, member, reference)$
$else$
// LoadMemberReference failed @ $member.Member.Name$
$endif$
%>
LoadMemberCondition_Struct(context, structure, member) ::= <<
$if(member.Condition)$
if($PrintEvaluation(member.Condition)$)
{
$LoadMemberReference(context, structure, member, member.Computations.References)$
}$\\$
$else$
$LoadMemberReference(context, structure, member, member.Computations.References)$$\\$
$endif$
>>
LoadMemberCondition_Union(context, structure, member) ::= <<
$if(member.Computations.IsFirstMember)$$\\$
$if(member.Condition)$
if($PrintEvaluation(member.Condition)$)
{
$LoadMemberReference(context, structure, member, member.Computations.References)$
}$\\$
$else$
$LoadMemberReference(context, structure, member, member.Computations.References)$$\\$
$endif$$\\$
$elseif(member.Computations.IsLastMember)$$\\$
$if(member.Condition)$
else if($PrintEvaluation(member.Condition)$)
{
$LoadMemberReference(context, structure, member, member.Computations.References)$
}$\\$
$else$
else
{
$LoadMemberReference(context, structure, member, member.Computations.References)$
}$\\$
$endif$$\\$
$else$$\\$
$if(member.Condition)$
else if($PrintEvaluation(member.Condition)$)
{
$LoadMemberReference(context, structure, member, member.Computations.References)$
}$\\$
$else$$\\$
#error Middle member of union must have condition ($member.Member.Name$)
$endif$$\\$
$endif$
>>
LoadMemberCondition(context, structure, member) ::= <%
$if(structure.IsUnion)$
$LoadMemberCondition_Union(context, structure, member)$
$else$
$LoadMemberCondition_Struct(context, structure, member)$
$endif$
%>
LoadMemberIfNeedsTreatment(context, structure, member) ::= <%
$if(!member.Computations.ShouldIgnore)$
$if(member.IsString || member.IsScriptString)$
$LoadMemberCondition(context, structure, member)$
$elseif(member.Computations.ContainsNonEmbeddedReference)$
$LoadMemberCondition(context, structure, member)$
$elseif(member.StructureType && !member.StructureType.IsLeaf)$
$LoadMemberCondition(context, structure, member)$
$elseif(member.Computations.IsAfterPartialLoad)$
$LoadMemberCondition(context, structure, member)$
$endif$
$endif$
%>
LoadTempPtrMethod(context, structure) ::= <<
void $LoaderClassName(context.Asset)$::LoadPtr_$structure.Type.Name$(const bool atStreamStart)
{
assert($TypePtrVarName(structure.Type)$ != nullptr);
if(atStreamStart)
m_stream->Load<$structure.Type.FullName$*>($TypePtrVarName(structure.Type)$);
m_stream->PushBlock($context.DefaultTempBlock.Name$);
if(*$TypePtrVarName(structure.Type)$ != nullptr)
{
if(*$TypePtrVarName(structure.Type)$ == PTR_FOLLOWING || *$TypePtrVarName(structure.Type)$ == PTR_INSERT)
{
$structure.Type.FullName$* ptr = *$TypePtrVarName(structure.Type)$;
*$TypePtrVarName(structure.Type)$ = m_stream->Alloc<$structure.Type.FullName$>(alignof($structure.Type.FullName$));
$structure.Type.FullName$** toInsert = nullptr;
if(ptr == PTR_INSERT)
toInsert = m_stream->InsertPointer<$structure.Type.FullName$>();
$if(!structure.IsLeaf)$
$TypeVarName(structure.Type)$ = *$TypePtrVarName(structure.Type)$;
Load_$structure.Type.Name$(true);
$endif$
$if(structure.PostLoadAction)$
$CustomAction(structure.PostLoadAction)$
$endif$
$if(structure.IsAsset)$
LoadAsset_$structure.Type.Name$($TypePtrVarName(structure.Type)$);
$endif$
if(toInsert != nullptr)
*toInsert = *$TypePtrVarName(structure.Type)$;
}
else
{
*$TypePtrVarName(structure.Type)$ = m_stream->ConvertOffsetToAlias(*$TypePtrVarName(structure.Type)$);
}
}
m_stream->PopBlock();
}
>>
LoadArrayMethod(context, type, structure) ::= <<
void $LoaderClassName(context.Asset)$::LoadArray_$type.Name$(const bool atStreamStart, const size_t count)
{
assert($TypeVarName(type)$ != nullptr);
if(atStreamStart)
m_stream->Load<$type.FullName$>($TypeVarName(type)$, count);
$type.FullName$* var = $TypeVarName(type)$;
for(size_t index = 0; index < count; index++)
{
$if(!type.Members)$
$TypeVarName(structure.Type)$ = var;
$else$
$TypeVarName(type)$ = var;
$endif$
Load_$structure.Type.Name$(false);
var++;
}
}
>>
LoadMethod(context, structure) ::= <<
void $LoaderClassName(context.Asset)$::Load_$structure.Type.Name$(const bool atStreamStart)
{
assert($TypeVarName(structure.Type)$ != nullptr);$\\$
$if(!(structure.IsUnion && structure.Computations.DynamicMember))$
if(atStreamStart)
$if(!structure.Computations.DynamicMember)$
m_stream->Load<$structure.Type.FullName$>($TypeVarName(structure.Type)$); // Size: $structure.Type.Size$$\\$
$else$
m_stream->LoadPartial<$structure.Type.FullName$>($TypeVarName(structure.Type)$, offsetof($structure.Type.FullName$, $structure.Computations.DynamicMember.Member.Name$));$\\$
$endif$
$else$
assert(atStreamStart);$\\$
$endif$
$if(structure.Block)$
m_stream->PushBlock($structure.Block.Name$);$\\$
$elseif(structure.IsAsset)$
m_stream->PushBlock($context.DefaultNormalBlock.Name$);$\\$
$endif$
$structure.OrderedMembers:{member | $LoadMemberIfNeedsTreatment(context, structure, member)$}$
$if(structure.Block || structure.IsAsset)$
m_stream->PopBlock();
$endif$
}
>>
VariableInitialization(type) ::= <<
var$type.Name$ = nullptr;
>>
PointerVariableInitialization(type) ::= <<
var$type.Name$Ptr = nullptr;
>>
ConstructorMethod(context) ::= <<
$LoaderClassName(context.Asset)$::$LoaderClassName(context.Asset)$(Zone* zone, IZoneInputStream* stream)
: AssetLoader($context.Asset.AssetEnumEntry.Name$, zone, stream)$\\$
$if(context.HasActions)$, m_actions(zone)$endif$
{
m_asset_info = nullptr;
$VariableInitialization(context.Asset.Type)$
$PointerVariableInitialization(context.Asset.Type)$
$context.UsedTypes:{type | $if(type.Information && !type.Information.Type.IsAnonymous && !type.Information.IsLeaf && !type.Information.IsAsset)$$VariableInitialization(type.Type)$
$endif$}$
$context.UsedTypes:{type | $if(type.Information && type.PointerArrayReferenceExists && !type.IsContextAsset)$$PointerVariableInitialization(type.Type)$
$endif$}$$\\$
}
>>
LoadAssetMethod(context, structure) ::= <<
void $LoaderClassName(context.Asset)$::LoadAsset_$structure.Type.Name$($structure.Type.FullName$** pAsset)
{
assert(pAsset != nullptr);
m_asset_info = reinterpret_cast<XAssetInfo<$structure.Type.FullName$>*>(LinkAsset(GetAssetName(*pAsset), *pAsset));
*pAsset = m_asset_info->Asset();
}
>>
MainLoadMethod(context) ::= <<
XAssetInfo<$context.Asset.Type.FullName$>* $LoaderClassName(context.Asset)$::Load($context.Asset.Type.FullName$** pAsset)
{
assert(pAsset != nullptr);
m_asset_info = nullptr;
$TypePtrVarName(context.Asset.Type)$ = pAsset;
LoadPtr_$context.Asset.Type.Name$(false);
if(m_asset_info == nullptr && *pAsset != nullptr)
m_asset_info = reinterpret_cast<XAssetInfo<$context.Asset.Type.FullName$>*>(GetAssetInfo(GetAssetName(*pAsset)));
return m_asset_info;
}
>>
GetNameMethod(context) ::= <<
std::string $LoaderClassName(context.Asset)$::GetAssetName($context.Asset.Type.FullName$* pAsset)
{
$if(context.Asset.NameChain)$
return pAsset->$first(context.Asset.NameChain):{member | $member.Member.Name$}$$rest(context.Asset.NameChain):{member | .$member.Member.Name$}$;
$else$
return "$context.Asset.Type.Name$";
$endif$
}
>>
IncludeHeaderOfOtherAsset(asset) ::= <<
#include "../$Lower(asset.Type.Name)$/$Lower(asset.Type.Name)$_load_db.h"
>>
// =======================
// Source file entry point
// =======================
source(context) ::= <<
// ====================================================================
// This file has been generated by ZoneCodeGenerator.
// Do not modify.
// Any changes will be discarded when regenerating.
// ====================================================================
#include "$Lower(context.Asset.Type.Name)$_load_db.h"
#include <cassert>
// Referenced Assets:
$context.ReferencedAssets:IncludeHeaderOfOtherAsset()$
using namespace $context.Game$;
$ConstructorMethod(context)$
$context.UsedTypes:{usedType | $if(usedType.PointerArrayReferenceExists)$$LoadPointerArrayMethod(context, usedType.Type, usedType.Information, usedType.PointerArrayReferenceIsReusable)$$\n$$\n$$endif$}$
$context.UsedTypes:{usedType | $if(usedType.ArrayReferenceExists && usedType.Information && !usedType.Information.IsLeaf && usedType.NonRuntimeReferenceExists)$$LoadArrayMethod(context, usedType.Type, usedType.Information)$$\n$$\n$$endif$}$
$context.UsedStructures:{usedStructure | $if(usedStructure.NonRuntimeReferenceExists && !usedStructure.Information.IsLeaf && !usedStructure.Information.IsAsset)$$LoadMethod(context, usedStructure.Information)$$\n$$\n$$endif$}$
$LoadMethod(context, context.Asset)$
$LoadTempPtrMethod(context, context.Asset)$
$LoadAssetMethod(context, context.Asset)$
$MainLoadMethod(context)$
$GetNameMethod(context)$
>>

View File

@ -1,38 +0,0 @@
delimiters "$", "$"
import "Common.stg"
WriterClassName(asset) ::= "$asset.Type.Name; format=\"cap\"$ZoneWriter"
// =======================
// Header file entry point
// =======================
header(context) ::= <<
#pragma once
namespace ZoneLoader
{
class $WriterClassName(context.Asset)$
{
public:
// TODO
}
}
>>
IncludeHeaderOfOtherAsset(asset) ::= <<
#include "../$asset.Type.Name$/$asset.Type.Name; format="lower"$_write_db.h"
>>
// =======================
// Source file entry point
// =======================
source(context) ::= <<
#include "$context.Asset.Type.Name; format="lower"$_write_db.h"
// Referenced Assets:
$context.ReferencedAssets:IncludeHeaderOfOtherAsset()$
// TODO
>>

View File

@ -1,113 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace ZoneCodeGenerator.Interface.Arguments
{
class ArgumentParser
{
private readonly CommandLineOption[] options;
private readonly List<string> noOptionArgs;
private readonly Dictionary<CommandLineOption, List<string>> optionArgs;
public IReadOnlyList<string> Arguments => noOptionArgs.AsReadOnly();
public ArgumentParser(CommandLineOption[] options)
{
this.options = options;
noOptionArgs = new List<string>();
optionArgs = new Dictionary<CommandLineOption, List<string>>();
}
public bool ParseArguments(string[] args)
{
noOptionArgs.Clear();
optionArgs.Clear();
for (var i = 0; i < args.Length; i++)
{
var arg = args[i];
if (arg.StartsWith("-"))
{
CommandLineOption matchedOption;
if (arg.StartsWith("--"))
{
var longNameToFind = arg.Substring(2);
matchedOption = options.FirstOrDefault(option => longNameToFind.Equals(option.LongName));
}
else
{
var shortNameToFind = arg.Substring(1);
matchedOption = options.FirstOrDefault(option => shortNameToFind.Equals(option.ShortName));
}
if (matchedOption == null)
{
Console.WriteLine($"Unknown option '{arg}'.");
return false;
}
List<string> parameters;
if (optionArgs.ContainsKey(matchedOption))
{
if (!matchedOption.MultiUse)
{
Console.WriteLine($"Option '{arg}' already specified.");
return false;
}
parameters = optionArgs[matchedOption];
}
else
{
parameters = new List<string>();
optionArgs.Add(matchedOption, parameters);
}
if (i + matchedOption.ParameterCount >= args.Length)
{
Console.WriteLine($"Not enough parameters for option '{arg}'.");
return false;
}
for (var parameter = 0; parameter < matchedOption.ParameterCount; parameter++)
{
if (args[i + parameter + 1].StartsWith("-"))
{
Console.WriteLine($"Not enough parameters for option '{arg}'.");
return false;
}
parameters.Add(args[i + parameter + 1]);
}
i += matchedOption.ParameterCount;
}
else
{
noOptionArgs.Add(arg);
}
}
return true;
}
public bool IsOptionSpecified(CommandLineOption option)
{
return optionArgs.ContainsKey(option);
}
public string GetValueForOption(CommandLineOption option)
{
return IsOptionSpecified(option) ? string.Join(" ", optionArgs[option]) : null;
}
public IReadOnlyList<string> GetParametersForOption(CommandLineOption option)
{
return IsOptionSpecified(option) ? optionArgs[option].AsReadOnly() : null;
}
}
}

View File

@ -1,83 +0,0 @@
using System.Collections.Generic;
namespace ZoneCodeGenerator.Interface.Arguments
{
class CommandLineOption
{
public string ShortName { get; private set; }
public string LongName { get; private set; }
public string Description { get; private set; }
public string Category { get; private set; }
public bool MultiUse { get; private set; }
private readonly List<string> parameters;
public IReadOnlyList<string> Parameters => parameters.AsReadOnly();
public int ParameterCount => parameters.Count;
private CommandLineOption()
{
ShortName = null;
LongName = null;
Description = "";
Category = "";
MultiUse = false;
parameters = new List<string>();
}
public class CommandLineOptionBuilder
{
private readonly CommandLineOption option;
private CommandLineOptionBuilder()
{
option = new CommandLineOption();
}
public static CommandLineOptionBuilder Create()
{
return new CommandLineOptionBuilder();
}
public CommandLineOptionBuilder WithShortName(string shortName)
{
option.ShortName = shortName;
return this;
}
public CommandLineOptionBuilder WithLongName(string longName)
{
option.LongName = longName;
return this;
}
public CommandLineOptionBuilder WithDescription(string description)
{
option.Description = description;
return this;
}
public CommandLineOptionBuilder WithCategory(string category)
{
option.Category = category;
return this;
}
public CommandLineOptionBuilder WithParameter(string argumentName)
{
option.parameters.Add(argumentName);
return this;
}
public CommandLineOptionBuilder Reusable()
{
option.MultiUse = true;
return this;
}
public CommandLineOption Build()
{
return option;
}
}
}
}

View File

@ -1,108 +0,0 @@
using System;
using System.Linq;
using System.Text;
namespace ZoneCodeGenerator.Interface.Arguments
{
static class UsageInformation
{
public static string FromCommandlineOptions(CommandLineOption[] options)
{
var usageInformation = new StringBuilder();
usageInformation.AppendLine("Usage:");
usageInformation.AppendLine();
var longestShortName = 0;
var longestLongName = 0;
var longestArgumentLength = 0;
foreach (var option in CommandLineOptions.ALL_OPTIONS)
{
if (option.ShortName != null && longestShortName < option.ShortName.Length)
longestShortName = option.ShortName.Length;
if (option.LongName != null && longestLongName < option.LongName.Length)
longestLongName = option.LongName.Length;
var argumentLength = GetOptionArgumentLength(option);
if (longestArgumentLength < argumentLength)
longestArgumentLength = argumentLength;
}
var categories = CommandLineOptions.ALL_OPTIONS
.Select(option => option.Category)
.Distinct();
var firstCategory = true;
foreach (var category in categories)
{
var optionsOfCategory = CommandLineOptions.ALL_OPTIONS
.Where(option => category.Equals(option.Category));
if(!firstCategory)
usageInformation.AppendLine();
if (!string.IsNullOrEmpty(category))
{
usageInformation.AppendLine($"== {category} ==");
}
foreach (var option in optionsOfCategory)
{
if (option.ShortName != null)
{
usageInformation.Append($"-{option.ShortName}");
usageInformation.Append(' ', longestShortName - option.ShortName.Length);
if (option.LongName != null)
usageInformation.Append(", ");
else
usageInformation.Append(' ', 2);
}
else
{
usageInformation.Append(' ', longestShortName + 1 + 2);
}
if (option.LongName != null)
{
usageInformation.Append($"--{option.LongName}");
usageInformation.Append(' ', longestLongName - option.LongName.Length);
}
else
{
usageInformation.Append(' ', longestLongName + 2);
}
usageInformation.Append(' ');
var argumentLength = GetOptionArgumentLength(option);
for(var i = 0; i < option.ParameterCount; i++)
{
if (i != 0)
usageInformation.Append(' ');
usageInformation.Append($"<{option.Parameters[i]}>");
}
usageInformation.Append(' ', longestArgumentLength - argumentLength + 1);
usageInformation.Append(option.Description);
usageInformation.AppendLine();
}
firstCategory = false;
}
return usageInformation.ToString();
}
private static int GetOptionArgumentLength(CommandLineOption option)
{
return option.ParameterCount * 2 // < and >
+ option.Parameters.Select(s => s.Length).Sum() // Length of the argument name
+ Math.Max(0, option.ParameterCount - 1); // One space between each argument
}
}
}

View File

@ -1,112 +0,0 @@
using System;
using System.Linq;
using ZoneCodeGenerator.Generating;
using ZoneCodeGenerator.Interface.Arguments;
using ZoneCodeGenerator.Parsing.C_Header;
using ZoneCodeGenerator.Parsing.CommandFile;
namespace ZoneCodeGenerator.Interface
{
class CUI
{
public bool Start(string[] args)
{
var argumentParser = new ArgumentParser(CommandLineOptions.ALL_OPTIONS);
if (args.Length == 0 || !argumentParser.ParseArguments(args))
{
PrintUsage();
return false;
}
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_HELP))
{
PrintUsage();
return true;
}
var session = new CUISession
{
Verbose = argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_VERBOSE)
};
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_OUTPUT_FOLDER))
{
session.GeneratorOutputPath = argumentParser.GetValueForOption(CommandLineOptions.OPTION_OUTPUT_FOLDER);
}
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_CREATE))
{
session.SourceFilePath = argumentParser.GetValueForOption(CommandLineOptions.OPTION_CREATE);
session.Repository = HeaderReader.ReadFile(session.SourceFilePath, session.Verbose);
if (session.Repository == null)
{
Console.WriteLine($"Creating a database from header file '{argumentParser.GetValueForOption(CommandLineOptions.OPTION_CREATE)}' failed.");
return false;
}
}
else
{
Console.WriteLine("Parsing a c header is needed to perform any other action.");
return false;
}
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_EDITING_COMMANDS))
{
if (!CommandFileReader.ReadFile(argumentParser.GetValueForOption(CommandLineOptions.OPTION_EDITING_COMMANDS), session, session.Verbose))
{
return false;
}
}
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_PRINT))
{
var printer = new PrettyPrinter(session.Repository);
printer.PrintAll();
}
if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_GENERATE))
{
var generationArgs = argumentParser.GetParametersForOption(CommandLineOptions.OPTION_GENERATE);
for (var i = 0; i < generationArgs.Count; i += CommandLineOptions.OPTION_GENERATE.ParameterCount)
{
var assetName = generationArgs[i];
var preset = generationArgs[i + 1];
var assets = session.Repository.GetAllStructureInformation()
.Where(inf => inf.IsAsset);
if (!assetName.Equals("*"))
assets = assets.Where(inf =>
inf.Type.FullName.Equals(assetName, StringComparison.CurrentCultureIgnoreCase));
if (!assets.Any())
{
Console.WriteLine($"Could not find asset '{assetName}'.");
continue;
}
foreach (var asset in assets)
{
if (CodeGenerator.GenerateCodeForPreset(preset, asset, session))
{
Console.WriteLine($"Successfully generated code for asset '{asset.Type.FullName}' with preset '{preset}'");
}
else
{
Console.WriteLine($"Could not generate code for asset '{asset.Type.FullName}' with preset '{preset}'");
}
}
}
}
return true;
}
private static void PrintUsage()
{
Console.WriteLine(UsageInformation.FromCommandlineOptions(CommandLineOptions.ALL_OPTIONS));
}
}
}

View File

@ -1,20 +0,0 @@
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Interface
{
class CUISession
{
public string Game { get; set; }
public IDataRepository Repository { get; set; }
public string GeneratorOutputPath { get; set; }
public string SourceFilePath { get; set; }
public bool Verbose { get; set; }
public CUISession()
{
Repository = null;
GeneratorOutputPath = ".";
Verbose = false;
}
}
}

View File

@ -1,98 +0,0 @@
using ZoneCodeGenerator.Generating;
using ZoneCodeGenerator.Interface.Arguments;
namespace ZoneCodeGenerator.Interface
{
static class CommandLineOptions
{
// ------
// GENERAL
// ------
public static readonly CommandLineOption OPTION_HELP = CommandLineOption.CommandLineOptionBuilder.Create()
.WithShortName("?")
.WithLongName("help")
.WithDescription("Show usage.")
.Build();
public static readonly CommandLineOption OPTION_VERBOSE = CommandLineOption.CommandLineOptionBuilder.Create()
.WithShortName("v")
.WithLongName("verbose")
.WithDescription("Gives a lot and detailed output.")
.Build();
// ------
// INPUT
// ------
private const string CategoryInput = "Input";
public static readonly CommandLineOption OPTION_CREATE = CommandLineOption.CommandLineOptionBuilder.Create()
.WithShortName("h")
.WithLongName("header")
.WithDescription("Create a new database from the specified header file.")
.WithCategory(CategoryInput)
.WithParameter("headerFile")
.Build();
// ------
// EDITING
// ------
private const string CategoryEditing = "Editing";
public static readonly CommandLineOption OPTION_EDITING_COMMANDS = CommandLineOption.CommandLineOptionBuilder.Create()
.WithShortName("e")
.WithLongName("editing-commands")
.WithDescription("Specifies the editing command file. Defaults to stdin.")
.WithCategory(CategoryEditing)
.WithParameter("commandFile")
.Build();
// ------
// OUTPUT
// ------
private const string CategoryOutput = "Output";
public static readonly CommandLineOption OPTION_OUTPUT_FOLDER = CommandLineOption.CommandLineOptionBuilder.Create()
.WithShortName("o")
.WithLongName("output")
.WithDescription("Specify the folder to save the generate code files to. Defaults to the current directory.")
.WithCategory(CategoryOutput)
.WithParameter("outputPath")
.Build();
public static readonly CommandLineOption OPTION_PRINT = CommandLineOption.CommandLineOptionBuilder.Create()
.WithShortName("p")
.WithLongName("print")
.WithDescription("Print the loaded data.")
.WithCategory(CategoryOutput)
.Build();
public static readonly CommandLineOption OPTION_GENERATE = CommandLineOption.CommandLineOptionBuilder.Create()
.WithShortName("g")
.WithLongName("generate")
.WithDescription($"Generates a specified asset/preset combination. Can be used multiple times. Available presets: {string.Join(", ", CodeGenerator.Presets)}")
.WithCategory(CategoryOutput)
.WithParameter("assetName")
.WithParameter("preset")
.Reusable()
.Build();
public static readonly CommandLineOption[] ALL_OPTIONS =
{
// GENERAL
OPTION_HELP,
OPTION_VERBOSE,
// INPUT
OPTION_CREATE,
// EDITING
OPTION_EDITING_COMMANDS,
// OUTPUT
OPTION_OUTPUT_FOLDER,
OPTION_PRINT,
OPTION_GENERATE,
};
}
}

View File

@ -1,315 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Interface
{
class PrettyPrinter
{
private readonly IDataRepository dataRepository;
public PrettyPrinter(IDataRepository dataRepository)
{
this.dataRepository = dataRepository;
}
public void PrintEnums()
{
var allEnums = dataRepository.GetAllEnums();
var dataTypeEnums = allEnums.ToList();
Console.WriteLine($"{dataTypeEnums.Count} enums:");
foreach(var _enum in dataTypeEnums)
{
Console.WriteLine($" Name: {_enum.FullName}");
Console.WriteLine($" Alignment: {_enum.Alignment}");
Console.WriteLine($" Size: {_enum.Size}");
foreach(var member in _enum.Members)
{
Console.WriteLine($" {member.Name} = {member.Value}");
}
Console.WriteLine();
}
}
private static void PrintVariablePointerToArray(Variable variable)
{
var arraySize = new List<int>();
var pointerDepth = 0;
var referenceOffset = 0;
for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
{
if (!(variable.VariableType.References[referenceOffset] is ReferenceTypePointer))
break;
pointerDepth++;
}
for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
{
if (!(variable.VariableType.References[referenceOffset] is ReferenceTypeArray array))
throw new Exception("Expected the rest of the references to be array references");
arraySize.Add(array.ArraySize);
}
var memberBuilder = new StringBuilder();
memberBuilder.Append(" ");
memberBuilder.Append(variable.VariableType.Type.FullName);
memberBuilder.Append('(');
memberBuilder.Append('*', pointerDepth);
memberBuilder.Append(variable.Name);
memberBuilder.Append(')');
foreach (var array in arraySize)
{
memberBuilder.Append('[');
memberBuilder.Append(array);
memberBuilder.Append(']');
}
Console.WriteLine(memberBuilder.ToString());
}
private static void PrintVariableArrayOfPointers(Variable variable)
{
var arraySize = new List<int>();
var pointerDepth = 0;
var referenceOffset = 0;
for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
{
if (!(variable.VariableType.References[referenceOffset] is ReferenceTypeArray array))
break;
arraySize.Add(array.ArraySize);
}
for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
{
if (!(variable.VariableType.References[referenceOffset] is ReferenceTypePointer))
throw new Exception("Expected the rest of the references to be pointer references");
pointerDepth++;
}
var memberBuilder = new StringBuilder();
memberBuilder.Append(" ");
memberBuilder.Append(variable.VariableType.Type.FullName);
memberBuilder.Append('*', pointerDepth);
memberBuilder.Append(" ");
memberBuilder.Append(variable.Name);
foreach (var array in arraySize)
{
memberBuilder.Append('[');
memberBuilder.Append(array);
memberBuilder.Append(']');
}
Console.WriteLine(memberBuilder.ToString());
}
private static void PrintVariable(Variable variable)
{
if (variable.VariableType.References.Count == 0)
{
Console.WriteLine($" {variable.VariableType.Type.FullName} {variable.Name}");
}
else
{
if (variable.VariableType.References[0] is ReferenceTypePointer &&
variable.VariableType.References.OfType<ReferenceTypeArray>().Any())
{
PrintVariablePointerToArray(variable);
}
else
{
PrintVariableArrayOfPointers(variable);
}
}
}
public void PrintStructs()
{
var allStructs = dataRepository.GetAllStructs();
var dataTypeStructs = allStructs.ToList();
Console.WriteLine($"{dataTypeStructs.Count} structs:");
foreach(var _struct in dataTypeStructs)
{
Console.WriteLine($" Name: {_struct.FullName}");
Console.WriteLine($" Alignment: {_struct.Alignment}");
Console.WriteLine($" Size: {_struct.Size}");
foreach(var member in _struct.Members)
PrintVariable(member);
Console.WriteLine();
}
}
public void PrintUnions()
{
var allUnions = dataRepository.GetAllUnions();
var dataTypeUnions = allUnions.ToList();
Console.WriteLine($"{dataTypeUnions.Count} unions:");
foreach(var union in dataTypeUnions)
{
Console.WriteLine($" Name: {union.FullName}");
Console.WriteLine($" Alignment: {union.Alignment}");
Console.WriteLine($" Size: {union.Size}");
foreach(var member in union.Members)
PrintVariable(member);
Console.WriteLine();
}
}
private static void PrintTypedefPointerToArray(DataTypeTypedef typedef)
{
var arraySize = new List<int>();
var pointerDepth = 0;
var referenceOffset = 0;
for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
{
if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypePointer))
break;
pointerDepth++;
}
for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
{
if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypeArray array))
throw new Exception("Expected the rest of the references to be array references");
arraySize.Add(array.ArraySize);
}
var memberBuilder = new StringBuilder();
memberBuilder.Append(" ");
memberBuilder.Append(typedef.TypeDefinition.Type.FullName);
memberBuilder.Append('(');
memberBuilder.Append('*', pointerDepth);
memberBuilder.Append(')');
foreach (var array in arraySize)
{
memberBuilder.Append('[');
memberBuilder.Append(array);
memberBuilder.Append(']');
}
Console.WriteLine(memberBuilder.ToString());
}
private static void PrintTypedefArrayOfPointers(DataTypeTypedef typedef)
{
var arraySize = new List<int>();
var pointerDepth = 0;
var referenceOffset = 0;
for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
{
if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypeArray array))
break;
arraySize.Add(array.ArraySize);
}
for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
{
if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypePointer))
throw new Exception("Expected the rest of the references to be pointer references");
pointerDepth++;
}
var memberBuilder = new StringBuilder();
memberBuilder.Append(" ");
memberBuilder.Append(typedef.TypeDefinition.Type.FullName);
memberBuilder.Append('*', pointerDepth);
foreach (var array in arraySize)
{
memberBuilder.Append('[');
memberBuilder.Append(array);
memberBuilder.Append(']');
}
Console.WriteLine(memberBuilder.ToString());
}
public void PrintTypedefs()
{
var allTypedefs = dataRepository.GetAllTypedefs();
var dataTypeTypedefs = allTypedefs.ToList();
Console.WriteLine($"{dataTypeTypedefs.Count} typedefs:");
foreach (var typeDef in dataTypeTypedefs)
{
Console.WriteLine($" Name: {typeDef.FullName}");
Console.WriteLine($" Alignment: {typeDef.Alignment}");
Console.WriteLine($" Size: {typeDef.Size}");
if (typeDef.TypeDefinition.References.Count == 0)
{
Console.WriteLine($" {typeDef.TypeDefinition.Type.FullName}");
}
else
{
if (typeDef.TypeDefinition.References[0] is ReferenceTypePointer &&
typeDef.TypeDefinition.References.OfType<ReferenceTypeArray>().Any())
{
PrintTypedefPointerToArray(typeDef);
}
else
{
PrintTypedefArrayOfPointers(typeDef);
}
}
Console.WriteLine();
}
}
public void PrintAll()
{
PrintEnums();
Console.WriteLine();
Console.WriteLine("==========================================================================================================");
Console.WriteLine();
PrintStructs();
Console.WriteLine();
Console.WriteLine("==========================================================================================================");
Console.WriteLine();
PrintUnions();
Console.WriteLine();
Console.WriteLine("==========================================================================================================");
Console.WriteLine();
PrintTypedefs();
}
}
}

View File

@ -1,11 +0,0 @@
using System;
namespace ZoneCodeGenerator
{
class LoadingException : Exception
{
public LoadingException(string message) : base(message)
{
}
}
}

View File

@ -1,11 +0,0 @@
namespace ZoneCodeGenerator.Parsing.C_Header
{
enum BlockType
{
None,
Enum,
Namespace,
Struct,
Union
}
}

View File

@ -1,25 +0,0 @@
using System.Collections.Generic;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
abstract class Block
{
protected readonly IHeaderParserState State;
public BlockType Type { get; }
protected Block(IHeaderParserState headerParserState, BlockType type)
{
State = headerParserState;
Type = type;
}
public abstract IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests();
public abstract void OnOpen();
public abstract void OnClose();
public abstract void OnChildBlockClose(Block childBlock);
}
}

View File

@ -1,114 +0,0 @@
using System;
using System.Collections.Generic;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.C_Header.Tests;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
class BlockEnum : Block, INameAssignable, IVariableBlock
{
private readonly ITokenTest<IHeaderParserState>[] tests =
{
new TestEnumMember(),
new TestCloseBlock(true)
};
public string Name { get; }
public string AssignedName { get; private set; }
public string Namespace { get; private set; }
public DataTypeBaseType ParentType { get; }
public bool IsTypedef { get; }
public List<EnumMember> Members { get; }
private DataTypeEnum _enum;
public BlockEnum(IHeaderParserState headerParserState, string name, DataTypeBaseType parentType, bool isTypedef) : base(headerParserState, BlockType.Enum)
{
Name = name;
ParentType = parentType;
IsTypedef = isTypedef;
Members = new List<EnumMember>();
}
public override IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests()
{
return tests;
}
public override void OnOpen()
{
Namespace = State.CurrentNamespace.ToString();
State.CurrentNamespace.Push(Name);
}
public override void OnClose()
{
var poppedNamespaceName = State.CurrentNamespace.Pop();
if (!Name.Equals(poppedNamespaceName))
throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of union block '{Name}'");
_enum = new DataTypeEnum(Namespace, Name, ParentType);
_enum.Members.AddRange(Members);
State.AddDataType(_enum);
if (IsTypedef)
{
var typeDeclaration = new TypeDeclaration(_enum, new List<ReferenceType>());
var typedef = new DataTypeTypedef(Namespace, AssignedName, typeDeclaration);
State.AddDataType(typedef);
}
}
public override void OnChildBlockClose(Block childBlock)
{
}
public void AssignName(string nameAssignment)
{
AssignedName = nameAssignment;
}
public virtual void AddMember(EnumMember enumMember)
{
Members.Add(enumMember);
}
public virtual EnumMember FindMember(string enumMemberName)
{
return Members.Find(member => member.Name.Equals(enumMemberName));
}
public virtual long GetNextEnumValue()
{
var nextValue = 0L;
if (Members.Count > 0)
{
nextValue = Members[Members.Count - 1].Value + 1;
}
return nextValue;
}
public bool DefinesVariable()
{
return !IsTypedef && !string.IsNullOrEmpty(AssignedName) && _enum != null;
}
public Variable GetDefinedVariable()
{
if (!DefinesVariable())
return null;
var typeDeclaration = new TypeDeclaration(_enum, new List<ReferenceType>());
return new Variable(AssignedName, typeDeclaration);
}
}
}

View File

@ -1,51 +0,0 @@
using System;
using System.Collections.Generic;
using ZoneCodeGenerator.Parsing.C_Header.Tests;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
class BlockNamespace : Block
{
private readonly ITokenTest<IHeaderParserState>[] tests =
{
new TestNamespace(),
new TestEnum(),
new TestStruct(),
new TestUnion(),
new TestTypedef(),
new TestForwardDecl(),
new TestCloseBlock()
};
public string Name { get; }
public BlockNamespace(IHeaderParserState headerParserState, string namespaceName) : base(headerParserState, BlockType.Namespace)
{
Name = namespaceName;
}
public override IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests()
{
return tests;
}
public override void OnOpen()
{
State.CurrentNamespace.Push(Name);
}
public override void OnClose()
{
var poppedNamespaceName = State.CurrentNamespace.Pop();
if (!Name.Equals(poppedNamespaceName))
throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of namespace block '{Name}'");
}
public override void OnChildBlockClose(Block childBlock)
{
// Do nothing
}
}
}

View File

@ -1,44 +0,0 @@
using System.Collections.Generic;
using ZoneCodeGenerator.Parsing.C_Header.Tests;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
class BlockNone : Block
{
private readonly ITokenTest<IHeaderParserState>[] tests =
{
new TestNamespace(),
new TestEnum(),
new TestStruct(),
new TestUnion(),
new TestTypedef(),
new TestForwardDecl()
};
public BlockNone(IHeaderParserState headerParserState) : base(headerParserState, BlockType.None)
{
}
public override IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests()
{
return tests;
}
public override void OnOpen()
{
// Do nothing
}
public override void OnClose()
{
// Do nothing
}
public override void OnChildBlockClose(Block childBlock)
{
// Do nothing
}
}
}

View File

@ -1,134 +0,0 @@
using System;
using System.Collections.Generic;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.C_Header.Tests;
using ZoneCodeGenerator.Parsing.Testing;
using ZoneCodeGenerator.Utils;
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
class BlockStruct : Block, INameAssignable, IVariableHolder, IVariableBlock
{
private readonly ITokenTest<IHeaderParserState>[] tests =
{
new TestStruct(),
new TestEnum(),
new TestUnion(),
new TestVariable(),
new TestCloseBlock(true)
};
public string Name { get; }
public bool IsAnonymous { get; }
public string AssignedName { get; private set; }
public string Namespace { get; private set; }
public bool IsTypedef { get; }
public int? CustomAlignment { get; set; }
public int Pack { get; private set; }
public List<Variable> Variables { get; }
private DataTypeStruct _struct;
private DataTypeTypedef typedef;
public BlockStruct(IHeaderParserState headerParserState, string name, bool isTypedef) : base(headerParserState, BlockType.Struct)
{
if (!string.IsNullOrEmpty(name))
{
Name = name;
IsAnonymous = false;
}
else
{
Name = RandomName.GenerateName();
IsAnonymous = true;
}
IsTypedef = isTypedef;
Variables = new List<Variable>();
AssignedName = "";
_struct = null;
typedef = null;
}
public override IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests()
{
return tests;
}
public override void OnOpen()
{
Pack = State.CurrentPack;
Namespace = State.CurrentNamespace.ToString();
State.CurrentNamespace.Push(Name);
State.AddForwardDeclaration(new ForwardDeclaration(Namespace, Name, DataTypeType.Struct));
}
public override void OnClose()
{
var poppedNamespaceName = State.CurrentNamespace.Pop();
if (!Name.Equals(poppedNamespaceName))
throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of struct block '{Name}'");
_struct = new DataTypeStruct(Namespace, Name, Pack)
{
AlignmentOverride = CustomAlignment,
IsAnonymous = IsAnonymous
};
_struct.Members.AddRange(Variables);
State.AddDataType(_struct);
if (IsTypedef)
{
var typeDeclaration = new TypeDeclaration(_struct, new List<ReferenceType>());
typedef = new DataTypeTypedef(Namespace, AssignedName, typeDeclaration);
State.AddDataType(typedef);
}
}
public override void OnChildBlockClose(Block childBlock)
{
if (childBlock is IVariableBlock variableBlock)
{
AddVariable(variableBlock.GetDefinedVariable());
}
}
public void AssignName(string nameAssignment)
{
AssignedName = nameAssignment;
}
public void AddVariable(Variable variable)
{
Variables.Add(variable);
}
public Variable GetDefinedVariable()
{
var name = "";
DataType dataType = _struct;
if (!IsTypedef)
name = AssignedName;
else
dataType = typedef;
var typeDeclaration = new TypeDeclaration(dataType, new List<ReferenceType>());
return new Variable(name, typeDeclaration);
}
public void Inherit(DataTypeStruct parent)
{
foreach(var variable in parent.Members)
AddVariable(variable);
}
}
}

View File

@ -1,134 +0,0 @@
using System;
using System.Collections.Generic;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.C_Header.Tests;
using ZoneCodeGenerator.Parsing.Testing;
using ZoneCodeGenerator.Utils;
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
class BlockUnion : Block, INameAssignable, IVariableHolder, IVariableBlock
{
private readonly ITokenTest<IHeaderParserState>[] tests =
{
new TestStruct(),
new TestEnum(),
new TestUnion(),
new TestVariable(),
new TestCloseBlock(true)
};
public string Name { get; }
public bool IsAnonymous { get; }
public string AssignedName { get; private set; }
public string Namespace { get; private set; }
public bool IsTypedef { get; }
public int? CustomAlignment { get; set; }
public int Pack { get; private set; }
public List<Variable> Variables { get; }
private DataTypeUnion union;
private DataTypeTypedef typedef;
public BlockUnion(IHeaderParserState headerParserState, string name, bool isTypedef) : base(headerParserState, BlockType.Union)
{
if (!string.IsNullOrEmpty(name))
{
Name = name;
IsAnonymous = false;
}
else
{
Name = RandomName.GenerateName();
IsAnonymous = true;
}
IsTypedef = isTypedef;
Variables = new List<Variable>();
CustomAlignment = null;
AssignedName = "";
union = null;
typedef = null;
}
public override IEnumerable<ITokenTest<IHeaderParserState>> GetAvailableTests()
{
return tests;
}
public override void OnOpen()
{
Namespace = State.CurrentNamespace.ToString();
Pack = State.CurrentPack;
State.CurrentNamespace.Push(Name);
State.AddForwardDeclaration(new ForwardDeclaration(Namespace, Name, DataTypeType.Union));
}
public override void OnClose()
{
var poppedNamespaceName = State.CurrentNamespace.Pop();
if (!Name.Equals(poppedNamespaceName))
throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of union block '{Name}'");
union = new DataTypeUnion(Namespace, Name, Pack)
{
AlignmentOverride = CustomAlignment,
IsAnonymous = IsAnonymous
};
union.Members.AddRange(Variables);
State.AddDataType(union);
if (IsTypedef)
{
var typeDeclaration = new TypeDeclaration(union, new List<ReferenceType>());
typedef = new DataTypeTypedef(Namespace, AssignedName, typeDeclaration);
State.AddDataType(typedef);
}
}
public override void OnChildBlockClose(Block childBlock)
{
if (childBlock is IVariableBlock variableBlock)
{
AddVariable(variableBlock.GetDefinedVariable());
}
}
public void AssignName(string nameAssignment)
{
AssignedName = nameAssignment;
}
public void AddVariable(Variable variable)
{
Variables.Add(variable);
}
public Variable GetDefinedVariable()
{
var name = "";
DataType dataType = union;
if (!IsTypedef)
name = AssignedName;
else
dataType = typedef;
var typeDeclaration = new TypeDeclaration(dataType, new List<ReferenceType>());
return new Variable(name, typeDeclaration);
}
public void Inherit(DataTypeUnion parent)
{
foreach(var variable in parent.Members)
AddVariable(variable);
}
}
}

View File

@ -1,7 +0,0 @@
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
interface INameAssignable
{
void AssignName(string nameAssignment);
}
}

View File

@ -1,9 +0,0 @@
using ZoneCodeGenerator.Domain;
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
interface IVariableBlock
{
Variable GetDefinedVariable();
}
}

View File

@ -1,9 +0,0 @@
using ZoneCodeGenerator.Domain;
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
{
interface IVariableHolder
{
void AddVariable(Variable variable);
}
}

View File

@ -1,80 +0,0 @@
using System;
using System.IO;
using System.Linq;
using ZoneCodeGenerator.Parsing.C_Header.Impl;
using ZoneCodeGenerator.Parsing.Impl;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing.C_Header
{
static class HeaderReader
{
private static readonly IDataPostProcessor[] postProcessors =
{
};
public static IDataRepository ReadFile(string path, bool verbose = false)
{
try
{
using (IIncludingParsingStream streamFileSystem = new IncludingStreamFileSystem(path))
{
var state = new HeaderParserState();
IDataRepository dataRepository;
using (IParsingFileStream preprocessorStream = new Preprocessor(streamFileSystem, state))
{
var lexer = new Lexer(preprocessorStream);
var parser = new Parser<HeaderParserState>(state, lexer);
if (!parser.Parse(verbose))
return null;
dataRepository = new InMemoryDataRepository();
try
{
state.FinishAndSaveTo(dataRepository);
}
catch (LoadingException e)
{
PrintFinishingError(e);
return null;
}
preprocessorStream.Close();
streamFileSystem.Close();
}
if (!PostProcessRepository(dataRepository))
{
Console.WriteLine("Postprocessing data failed.");
return null;
}
return dataRepository;
}
}
catch (IOException e)
{
Console.WriteLine("An exception occured while trying to read header file");
Console.WriteLine(e.Message);
return null;
}
}
private static bool PostProcessRepository(IDataRepository repository)
{
return postProcessors.All(postProcessor => postProcessor.PostProcess(repository));
}
private static void PrintFinishingError(LoadingException e)
{
Console.WriteLine("Parsing failed.");
Console.WriteLine(e.Message);
Console.WriteLine();
}
}
}

View File

@ -1,28 +0,0 @@
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing.C_Header
{
interface IHeaderParserState : IParserState<IHeaderParserState>
{
Namespace CurrentNamespace { get; }
int CurrentPack { get; }
Block CurrentBlock { get; }
Block PreviousBlock { get; }
void PushPack(int pack);
int PopPack();
void PushBlock(Block block);
Block PopBlock();
void AddDataType(DataType dataType);
void AddForwardDeclaration(ForwardDeclaration forwardDeclaration);
DataType FindType(string typename);
EnumMember FindEnumMember(string enumMemberName);
void FinishAndSaveTo(IDataRepository dataRepository);
}
}

View File

@ -1,216 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
using ZoneCodeGenerator.Parsing.Testing;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing.C_Header.Impl
{
class HeaderParserState : IHeaderParserState
{
private const int DefaultPack = 8;
private readonly Block defaultBlock;
private readonly Stack<int> packStack;
private readonly Stack<Block> blockStack;
private readonly Dictionary<string, DataType> dataTypes;
private readonly Dictionary<string, ForwardDeclaration> forwardDeclarations;
public Namespace CurrentNamespace { get; }
public HeaderParserState()
{
defaultBlock = new BlockNone(this);
packStack = new Stack<int>();
blockStack = new Stack<Block>();
dataTypes = new Dictionary<string, DataType>();
forwardDeclarations = new Dictionary<string, ForwardDeclaration>();
CurrentNamespace = new Namespace();
}
public int CurrentPack => packStack.Count == 0 ? DefaultPack : packStack.Peek();
public Block CurrentBlock => blockStack.Count == 0 ? defaultBlock : blockStack.Peek();
public Block PreviousBlock => blockStack.Count < 2 ? defaultBlock : blockStack.ElementAt(1);
public void PushPack(int pack)
{
packStack.Push(pack);
}
public int PopPack()
{
return packStack.Pop();
}
public void PushBlock(Block block)
{
block.OnOpen();
blockStack.Push(block);
}
public Block PopBlock()
{
var block = blockStack.Pop();
block.OnClose();
CurrentBlock.OnChildBlockClose(block);
return block;
}
public void AddDataType(DataType dataType)
{
if (dataTypes.ContainsKey(dataType.FullName))
throw new ParserException($"Type '{dataType.FullName}' is already defined.");
dataTypes.Add(dataType.FullName, dataType);
}
public void AddForwardDeclaration(ForwardDeclaration forwardDeclaration)
{
if (forwardDeclarations.ContainsKey(forwardDeclaration.FullName))
{
var existingForwardDeclaration = forwardDeclarations[forwardDeclaration.FullName];
if (existingForwardDeclaration.Type != forwardDeclaration.Type)
throw new ParserException(
$"Forward declaration of type '{forwardDeclaration.FullName}' already done with different type.");
}
else
{
forwardDeclarations.Add(forwardDeclaration.FullName, forwardDeclaration);
}
}
public DataType FindType(string typename)
{
var currentNamespaceTypename = Namespace.Combine(CurrentNamespace, typename);
var baseType =
DataTypeBaseType.BASE_TYPES.FirstOrDefault(databaseBaseType => databaseBaseType.Name.Equals(typename));
if (baseType != null)
return baseType;
if (dataTypes.ContainsKey(typename))
{
return dataTypes[typename];
}
if (dataTypes.ContainsKey(currentNamespaceTypename))
{
return dataTypes[currentNamespaceTypename];
}
if (forwardDeclarations.ContainsKey(typename))
{
return forwardDeclarations[typename];
}
if (forwardDeclarations.ContainsKey(currentNamespaceTypename))
{
return forwardDeclarations[currentNamespaceTypename];
}
return null;
}
public EnumMember FindEnumMember(string enumMemberName)
{
foreach (var block in blockStack)
{
if (!(block is BlockEnum blockEnum)) continue;
var foundMember = blockEnum.FindMember(enumMemberName);
if (foundMember != null)
return foundMember;
}
foreach (var dataType in dataTypes)
{
if (!(dataType.Value is DataTypeEnum _enum))
continue;
var foundMember = _enum.Members.Find(member => member.Name.Equals(enumMemberName));
if (foundMember != null)
return foundMember;
}
return null;
}
private void ResolveForwardDeclarations()
{
foreach (var forwardDeclaration in forwardDeclarations.Values)
{
var foundType = FindType(forwardDeclaration.FullName);
if (foundType == null || foundType is ForwardDeclaration)
throw new ParserException($"Type {forwardDeclaration.FullName} was declared but not defined.");
forwardDeclaration.ForwardedType = foundType;
}
foreach (var dataType in dataTypes.Values)
{
if (dataType is DataTypeWithMembers dataTypeWithMembers)
{
foreach (var variable in dataTypeWithMembers.Members)
{
if (variable.VariableType.Type is ForwardDeclaration forwardDeclaration)
variable.VariableType.Type = forwardDeclaration.ForwardedType;
}
}
else if (dataType is DataTypeTypedef typeDef)
{
if (typeDef.TypeDefinition.Type is ForwardDeclaration forwardDeclaration)
typeDef.TypeDefinition.Type = forwardDeclaration.ForwardedType;
}
}
}
public void FinishAndSaveTo(IDataRepository dataRepository)
{
if (blockStack.Count > 0)
throw new ParserException($"Parsing finished but {blockStack.Count} blocks were not closed.");
ResolveForwardDeclarations();
foreach (var dataType in dataTypes.Values)
{
switch (dataType)
{
case DataTypeEnum _enum:
dataRepository.Add(_enum);
break;
case DataTypeStruct _struct:
_struct.FinalizeDataType();
dataRepository.Add(_struct);
break;
case DataTypeTypedef typedef:
dataRepository.Add(typedef);
break;
case DataTypeUnion union:
union.FinalizeDataType();
dataRepository.Add(union);
break;
default:
throw new ArgumentOutOfRangeException(nameof(dataType));
}
}
}
public IEnumerable<ITokenTest<IHeaderParserState>> GetTests()
{
return CurrentBlock.GetAvailableTests();
}
}
}

View File

@ -1,182 +0,0 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using ZoneCodeGenerator.Parsing.Impl;
using ZoneCodeGenerator.Utils;
namespace ZoneCodeGenerator.Parsing.C_Header.Impl
{
class Preprocessor : IParsingFileStream
{
private static readonly Regex packPushRegex = new Regex(@"^\s*#pragma\s+pack\s*\(\s*push\s*,\s*(\d+)\s*\)\s*$");
private static readonly Regex packPopRegex = new Regex(@"^\s*#pragma\s+pack\s*\(\s*pop\s*\)\s*$");
private static readonly Regex defineRegex = new Regex(@"^\s*#define\s+(\w+)(?:\s+(.*))?$");
private static readonly Regex undefRegex = new Regex(@"^\s*#undef\s+(\w+)\s*$");
private static readonly Regex includeRegex = new Regex(@"^\s*#include\s+(?:\""(.*)\""|\<(.*)\>)\s*$");
private static readonly Regex ifdefRegex = new Regex(@"^\s*#ifdef\s+(\w+)\s*$");
private static readonly Regex ifndefRegex = new Regex(@"^\s*#ifndef\s+(\w+)\s*$");
private static readonly Regex elseRegex = new Regex(@"^\s*#else\s*$");
private static readonly Regex endifRegex = new Regex(@"^\s*#endif\s*$");
private readonly IIncludingParsingStream streamFileSystem;
private readonly IHeaderParserState state;
private readonly ICommentProcessor commentProcessor;
private readonly Dictionary<string, string> defines;
private readonly Stack<bool> conditions;
public bool EndOfStream => streamFileSystem.EndOfStream;
public string Filename => streamFileSystem.Filename;
public int Line => streamFileSystem.Line;
public Preprocessor(IIncludingParsingStream includingParsingStream, IHeaderParserState state)
{
streamFileSystem = includingParsingStream;
this.state = state;
commentProcessor = new CommentProcessor();
defines = new Dictionary<string, string>
{
{"__zonecodegenerator", "1"}
};
conditions = new Stack<bool>();
}
private void ParseCompilerExpression(string line)
{
var packPush = packPushRegex.Match(line.ToLower());
if(packPush.Success)
{
state.PushPack(int.Parse(packPush.Groups[1].Value));
return;
}
var packPop = packPopRegex.Match(line.ToLower());
if(packPop.Success)
{
state.PopPack();
return;
}
var define = defineRegex.Match(line);
if (define.Success)
{
var key = define.Groups[1].Value;
var value = define.Groups[2].Value.Trim();
if (defines.ContainsKey(key))
defines[key] = value;
else
defines.Add(key, value);
return;
}
var undef = undefRegex.Match(line);
if (undef.Success)
{
var key = undef.Groups[1].Value;
if(defines.ContainsKey(key))
defines.Remove(key);
return;
}
var include = includeRegex.Match(line);
if (include.Success)
{
var filename = include.Groups[1].Success ? include.Groups[1].Value : include.Groups[2].Value;
streamFileSystem.IncludeFile(filename);
return;
}
var ifdef = ifdefRegex.Match(line);
if (ifdef.Success)
{
var key = ifdef.Groups[1].Value;
conditions.Push(defines.ContainsKey(key));
return;
}
var ifndef = ifndefRegex.Match(line);
if (ifndef.Success)
{
var key = ifndef.Groups[1].Value;
conditions.Push(!defines.ContainsKey(key));
return;
}
var _else = elseRegex.Match(line);
if (_else.Success)
{
if (conditions.Count > 0)
{
conditions.Push(!conditions.Pop());
}
return;
}
var endif = endifRegex.Match(line);
if (endif.Success)
{
if (conditions.Count > 0)
{
conditions.Pop();
}
return;
}
}
private string Preprocess(string line)
{
bool defineMatched;
line = commentProcessor.RemoveComments(line);
if (line.StartsWith("#"))
{
ParseCompilerExpression(line);
return "";
}
if (conditions.Count > 0 && !conditions.Peek())
{
return "";
}
do
{
defineMatched = false;
foreach (var (defineKey, defineValue) in defines)
{
var match = Regex.Match(line, $@"^(.*\W)?{defineKey}(\W.*)?$");
if (!match.Success) continue;
line = match.Groups[1].Value + defineValue + match.Groups[2].Value;
defineMatched = true;
break;
}
} while (defineMatched);
return line;
}
public string ReadLine()
{
return Preprocess(streamFileSystem.ReadLine());
}
public void Dispose()
{
Close();
}
public void Close()
{
streamFileSystem.Close();
}
}
}

View File

@ -1,48 +0,0 @@
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{
class TestCloseBlock : AbstractTokenTest<IHeaderParserState>
{
private const string NameToken = "close_with_name";
private const string SemicolonToken = "close_with_semi_colon";
private readonly bool semicolonRequired;
private static readonly TokenMatcher[] matchers = {
new MatcherLiteral("}"),
new MatcherGroupOptional( new MatcherGroupAnd(
new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
new MatcherLiteral(";").WithName(SemicolonToken)
))
};
public TestCloseBlock(bool semicolonRequired = false) : base(matchers)
{
this.semicolonRequired = semicolonRequired;
}
protected override void ProcessMatch(IHeaderParserState state)
{
if (HasMatcherTokens(NameToken))
{
if (state.CurrentBlock is INameAssignable nameAssignableBlock)
{
nameAssignableBlock.AssignName(NextMatch(NameToken));
}
else
{
throw new TestFailedException($"Cannot give block '{state.CurrentBlock.Type}' a name when closing");
}
}
if (!HasMatcherTokens(SemicolonToken) && semicolonRequired)
throw new TestFailedException($"Block '{state.CurrentBlock.Type}' needs to be closed with a '{'}'};'");
state.PopBlock();
}
}
}

View File

@ -1,57 +0,0 @@
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
using ZoneCodeGenerator.Utils;
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{
class TestEnum : AbstractTokenTest<IHeaderParserState>
{
private const string TypedefToken = "typedef";
private const string NameToken = "name";
private const string TypenameToken = "typename";
private static readonly TokenMatcher[] matchers = {
new MatcherGroupOptional(new MatcherLiteral("typedef").WithName(TypedefToken)),
new MatcherLiteral("enum"),
new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
new MatcherGroupOptional(new MatcherGroupAnd(new MatcherLiteral(":"), new MatcherTypename().WithName(TypenameToken))),
new MatcherLiteral("{")
};
public TestEnum() : base(matchers)
{
}
protected override void ProcessMatch(IHeaderParserState state)
{
var isTypedef = HasMatcherTokens(TypedefToken);
var name = NextMatch(NameToken) ?? RandomName.GenerateName();
var parentType = DataTypeBaseType.INT;
if (HasMatcherTokens(TypenameToken))
{
var typeName = NextMatch(TypenameToken);
var type = state.FindType(typeName);
if (type == null)
throw new TestFailedException($"Parent type '{typeName}' of enum '{name}' not found.");
while (type is DataTypeTypedef typedef)
{
if (typedef.TypeDefinition.References.Count > 0)
throw new TestFailedException($"Parent type of enum '{name}' cannot be a typedef that is an array or a pointer.");
type = typedef.TypeDefinition.Type;
}
parentType = type as DataTypeBaseType ?? throw new TestFailedException($"Parent type of enum '{name}' must be a base type.");
}
state.PushBlock(new BlockEnum(state, name, parentType, isTypedef));
}
}
}

View File

@ -1,66 +0,0 @@
using System;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{
class TestEnumMember : AbstractTokenTest<IHeaderParserState>
{
private const string NameToken = "name";
private const string NumberValueToken = "value_number";
private const string EnumMemberValueToken = "value_string";
private static readonly TokenMatcher[] matchers = {
new MatcherName().WithName(NameToken),
new MatcherGroupOptional(new MatcherGroupAnd(
new MatcherLiteral("="),
new MatcherGroupOr(
new MatcherNumber().WithName(NumberValueToken),
new MatcherName().WithName(EnumMemberValueToken)
))),
new MatcherGroupOr(
new MatcherLiteral(","),
new MatcherLiteral("}").NonConsuming()
)
};
public TestEnumMember() : base(matchers)
{
}
protected override void ProcessMatch(IHeaderParserState state)
{
var name = NextMatch(NameToken);
long value;
if (!(state.CurrentBlock is BlockEnum _enum))
throw new Exception("Excepted enum to be top block when parsing an enum member.");
if (HasMatcherTokens(NumberValueToken))
{
value = long.Parse(NextMatch(NumberValueToken));
}
else if(HasMatcherTokens(EnumMemberValueToken))
{
var stringValue = NextMatch(EnumMemberValueToken);
var memberWithFittingName = state.FindEnumMember(stringValue);
if(memberWithFittingName == null)
throw new TestFailedException($"Could not find value for '{stringValue}'.");
value = memberWithFittingName.Value;
}
else
{
value = _enum.GetNextEnumValue();
}
var enumMember = new EnumMember(name, value);
_enum.AddMember(enumMember);
}
}
}

View File

@ -1,52 +0,0 @@
using System;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{
class TestForwardDecl : AbstractTokenTest<IHeaderParserState>
{
private const string EnumToken = "enum";
private const string StructToken = "struct";
private const string UnionToken = "union";
private const string NameToken = "name";
private static readonly TokenMatcher[] matchers = {
new MatcherGroupOr(
new MatcherLiteral("enum").WithName(EnumToken),
new MatcherLiteral("struct").WithName(StructToken),
new MatcherLiteral("union").WithName(UnionToken)
),
new MatcherName().WithName(NameToken),
new MatcherLiteral(";")
};
public TestForwardDecl() : base(matchers)
{
}
protected override void ProcessMatch(IHeaderParserState state)
{
var name = NextMatch(NameToken);
var _namespace = state.CurrentNamespace.ToString();
if (HasMatcherTokens(EnumToken))
{
state.AddForwardDeclaration(new ForwardDeclaration(_namespace, name, DataTypeType.Enum));
}
else if (HasMatcherTokens(StructToken))
{
state.AddForwardDeclaration(new ForwardDeclaration(_namespace, name, DataTypeType.Struct));
}
else if (HasMatcherTokens(UnionToken))
{
state.AddForwardDeclaration(new ForwardDeclaration(_namespace, name, DataTypeType.Union));
}
else
throw new Exception("Unknown type for forward declaration.");
}
}
}

View File

@ -1,29 +0,0 @@
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{
class TestNamespace : AbstractTokenTest<IHeaderParserState>
{
private const string NamespaceNameToken = "namespace_name";
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("namespace"),
new MatcherName().WithName(NamespaceNameToken),
new MatcherLiteral("{")
};
public TestNamespace() : base(matchers)
{
}
protected override void ProcessMatch(IHeaderParserState state)
{
state.PushBlock(new BlockNamespace(state, NextMatch(NamespaceNameToken)));
}
}
}

View File

@ -1,69 +0,0 @@
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
using ZoneCodeGenerator.Utils;
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{
class TestStruct : AbstractTokenTest<IHeaderParserState>
{
private const string TypedefToken = "typedef";
private const string NameToken = "name";
private const string AlignToken = "align";
private const string ParentToken = "parent";
private static readonly TokenMatcher[] matchers = {
new MatcherGroupOptional(new MatcherLiteral("typedef").WithName(TypedefToken)),
new MatcherGroupOptional(new MatcherLiteral("const")),
new MatcherLiteral("struct"),
new MatcherGroupOptional(new MatcherGroupAnd(
new MatcherLiteral("__declspec"),
new MatcherLiteral("("),
new MatcherLiteral("align"),
new MatcherLiteral("("),
new MatcherNumber().WithName(AlignToken),
new MatcherLiteral(")"),
new MatcherLiteral(")")
)),
new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
new MatcherGroupOptional(new MatcherGroupAnd(
new MatcherLiteral(":"),
new MatcherTypename().WithName(ParentToken)
)),
new MatcherLiteral("{")
};
public TestStruct() : base(matchers)
{
}
protected override void ProcessMatch(IHeaderParserState state)
{
var isTypedef = HasMatcherTokens(TypedefToken);
var name = NextMatch(NameToken) ?? "";
var block = new BlockStruct(state, name, isTypedef);
if (HasMatcherTokens(AlignToken))
block.CustomAlignment = int.Parse(NextMatch(AlignToken));
if (HasMatcherTokens(ParentToken))
{
var parentDataTypeName = NextMatch(ParentToken);
var parentDataType = state.FindType(parentDataTypeName);
if(parentDataType == null)
throw new TestFailedException($"Could not find parent data type '{parentDataTypeName}' for struct '{name}'");
if(!(parentDataType is DataTypeStruct parentStruct))
throw new TestFailedException($"Parent data type '{parentDataTypeName}' for struct '{name}' must be a struct as well.");
block.Inherit(parentStruct);
}
state.PushBlock(block);
}
}
}

View File

@ -1,133 +0,0 @@
using System.Collections.Generic;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{
class TestTypedef : AbstractTokenTest<IHeaderParserState>
{
private const string TypeNameTokens = "typename";
private const string PointerTokens = "pointer";
private const string NameToken = "name";
private const string ArrayTokens = "array";
private const string AlignValueToken = "alignValue";
private const string TokenConst = "constToken";
private const string TagAlign = "alignTag";
private const string TagArrayOfPointers = "arrayOfPointersTag";
private const string TagPointerToArray = "pointerToArrayTag";
private static readonly TokenMatcher align = new MatcherGroupAnd(
new MatcherLiteral("__declspec", "("),
new MatcherLiteral("align", "("),
new MatcherNumber().WithName(AlignValueToken),
new MatcherLiteral(")"),
new MatcherLiteral(")")
).WithTag(TagAlign);
private static readonly TokenMatcher arrayOfPointers = new MatcherGroupAnd(
new MatcherGroupOptional(new MatcherLiteral("const").WithName(TokenConst)),
new MatcherTypename().WithName(TypeNameTokens),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple,
new MatcherLiteral("*").WithName(PointerTokens)),
new MatcherName().WithName(NameToken),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray().WithName(ArrayTokens)),
new MatcherLiteral(";")
).WithTag(TagArrayOfPointers);
private static readonly TokenMatcher pointerToArray = new MatcherGroupAnd(
new MatcherGroupOptional(new MatcherLiteral("const").WithName(TokenConst)),
new MatcherTypename().WithName(TypeNameTokens),
new MatcherLiteral("("),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple,
new MatcherLiteral("*").WithName(PointerTokens)),
new MatcherName().WithName(NameToken),
new MatcherLiteral(")"),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherArray().WithName(ArrayTokens)),
new MatcherLiteral(";")
).WithTag(TagPointerToArray);
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("typedef"),
new MatcherGroupOptional(new MatcherWithTag(TagAlign)),
new MatcherGroupOr(
new MatcherWithTag(TagArrayOfPointers),
new MatcherWithTag(TagPointerToArray)
)
};
public TestTypedef() : base(matchers)
{
AddTaggedMatcher(align);
AddTaggedMatcher(arrayOfPointers);
AddTaggedMatcher(pointerToArray);
}
protected override void ProcessMatch(IHeaderParserState state)
{
// Check if a custom alignment has been defined
int? alignmentOverride = null;
if (PeekTag().Equals(TagAlign))
{
NextTag();
alignmentOverride = int.Parse(NextMatch(AlignValueToken));
}
// See which variant has been used
var isArrayOfPointersVariant = NextTag().Equals(TagArrayOfPointers);
// Get name of typedef and the amount of pointer depth it has
var name = NextMatch(NameToken);
var pointerDepth = GetMatcherTokenCount(PointerTokens);
// Find referenced type
var typeName = NextMatch(TypeNameTokens);
var type = state.FindType(typeName);
if (type == null)
throw new TestFailedException($"Could not find type '{typeName}' of typedef '{name}'.");
// Collect all array sizes that have been specified
var arraySize = new int[GetMatcherTokenCount(ArrayTokens)];
string arrayToken;
var index = 0;
while ((arrayToken = NextMatch(ArrayTokens)) != null)
{
if (!int.TryParse(arrayToken, out arraySize[index++]))
throw new TestFailedException($"Array size '{arrayToken}' is not numeric.");
}
var references = new List<ReferenceType>();
if (isArrayOfPointersVariant)
{
foreach (var array in arraySize)
references.Add(new ReferenceTypeArray(array));
for (var i = 0; i < pointerDepth; i++)
references.Add(new ReferenceTypePointer());
}
else
{
for (var i = 0; i < pointerDepth; i++)
references.Add(new ReferenceTypePointer());
foreach (var array in arraySize)
references.Add(new ReferenceTypeArray(array));
}
var typeDeclaration = new TypeDeclaration(type, references)
{
IsConst = HasMatcherTokens(TokenConst)
};
var typedef = new DataTypeTypedef(state.CurrentNamespace.ToString(), name, typeDeclaration)
{
AlignmentOverride = alignmentOverride
};
state.AddDataType(typedef);
}
}
}

View File

@ -1,69 +0,0 @@
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
using ZoneCodeGenerator.Utils;
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{
class TestUnion : AbstractTokenTest<IHeaderParserState>
{
private const string TypedefToken = "typedef";
private const string NameToken = "name";
private const string AlignToken = "align";
private const string ParentToken = "parent";
private static readonly TokenMatcher[] matchers = {
new MatcherGroupOptional(new MatcherLiteral("typedef").WithName(TypedefToken)),
new MatcherGroupOptional(new MatcherLiteral("const")),
new MatcherLiteral("union"),
new MatcherGroupOptional(new MatcherGroupAnd(
new MatcherLiteral("__declspec"),
new MatcherLiteral("("),
new MatcherLiteral("align"),
new MatcherLiteral("("),
new MatcherNumber().WithName(AlignToken),
new MatcherLiteral(")"),
new MatcherLiteral(")")
)),
new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
new MatcherGroupOptional(new MatcherGroupAnd(
new MatcherLiteral(":"),
new MatcherTypename().WithName(ParentToken)
)),
new MatcherLiteral("{")
};
public TestUnion() : base(matchers)
{
}
protected override void ProcessMatch(IHeaderParserState state)
{
var isTypedef = HasMatcherTokens(TypedefToken);
var name = NextMatch(NameToken) ?? "";
var block = new BlockUnion(state, name, isTypedef);
if (HasMatcherTokens(AlignToken))
block.CustomAlignment = int.Parse(NextMatch(AlignToken));
if (HasMatcherTokens(ParentToken))
{
var parentDataTypeName = NextMatch(ParentToken);
var parentDataType = state.FindType(parentDataTypeName);
if(parentDataType == null)
throw new TestFailedException($"Could not find parent data type '{parentDataTypeName}' for union '{name}'");
if(!(parentDataType is DataTypeUnion parentUnion))
throw new TestFailedException($"Parent data type '{parentDataTypeName}' for union '{name}' must be a union as well.");
block.Inherit(parentUnion);
}
state.PushBlock(block);
}
}
}

View File

@ -1,119 +0,0 @@
using System;
using System.Collections.Generic;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.C_Header.Blocks;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{
class TestVariable : AbstractTokenTest<IHeaderParserState>
{
private const string PointerToArrayVariant = "pointertoarray";
private const string ArrayOfPointersVariant = "arrayofpointers";
private const string TypeNameToken = "typename";
private const string PointerTokens = "pointer";
private const string NameToken = "name";
private const string ArrayTokens = "array";
private const string BitSizeToken = "bitsize";
private const string TokenConst = "constToken";
private static readonly TokenMatcher[] arrayOfPointersMatchers = {
new MatcherGroupOptional(new MatcherLiteral("const").WithName(TokenConst)),
new MatcherTypename().WithName(TypeNameToken),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
new MatcherName().WithName(NameToken),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray().WithName(ArrayTokens)),
new MatcherGroupOptional(new MatcherGroupAnd(
new MatcherLiteral(":"),
new MatcherNumber().WithName(BitSizeToken)
)),
new MatcherLiteral(";").WithName(ArrayOfPointersVariant)
};
private static readonly TokenMatcher[] pointerToArrayMatchers = {
new MatcherGroupOptional(new MatcherLiteral("const").WithName(TokenConst)),
new MatcherTypename().WithName(TypeNameToken),
new MatcherLiteral("("),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
new MatcherName().WithName(NameToken),
new MatcherLiteral(")"),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherArray().WithName(ArrayTokens)),
new MatcherLiteral(";").WithName(PointerToArrayVariant)
};
private static readonly TokenMatcher[] matchers =
{
new MatcherGroupOr(
new MatcherGroupAnd(arrayOfPointersMatchers),
new MatcherGroupAnd(pointerToArrayMatchers)
)
};
public TestVariable() : base(matchers)
{
}
protected override void ProcessMatch(IHeaderParserState state)
{
var name = NextMatch(NameToken);
var typeName = NextMatch(TypeNameToken);
var type = state.FindType(typeName);
if (type == null)
throw new TestFailedException($"Type '{typeName}' not found.");
var pointerDepth = GetMatcherTokenCount(PointerTokens);
int? bitSize = null;
if (HasMatcherTokens(BitSizeToken))
bitSize = int.Parse(NextMatch(BitSizeToken));
string arrayToken;
var index = 0;
var arraySize = new int[GetMatcherTokenCount(ArrayTokens)];
while ((arrayToken = NextMatch(ArrayTokens)) != null)
{
if (!int.TryParse(arrayToken, out arraySize[index++]))
throw new TestFailedException($"Array size '{arrayToken}' is not numeric.");
}
if (state.CurrentBlock is IVariableHolder variableHolder)
{
var references = new List<ReferenceType>();
if (HasMatcherTokens(PointerToArrayVariant))
{
for (var i = 0; i < pointerDepth; i++)
references.Add(new ReferenceTypePointer());
foreach(var array in arraySize)
references.Add(new ReferenceTypeArray(array));
}
else
{
foreach(var array in arraySize)
references.Add(new ReferenceTypeArray(array));
for (var i = 0; i < pointerDepth; i++)
references.Add(new ReferenceTypePointer());
}
var typeDeclaration = new TypeDeclaration(type, references)
{
CustomBitSize = bitSize,
IsConst = HasMatcherTokens(TokenConst)
};
var variable = new Variable(name, typeDeclaration);
variableHolder.AddVariable(variable);
}
else
{
throw new Exception("Expected current block to be a variable holder when parsing variables.");
}
}
}
}

View File

@ -1,70 +0,0 @@
using System;
using System.IO;
using System.Linq;
using ZoneCodeGenerator.Interface;
using ZoneCodeGenerator.Parsing.CommandFile.Impl;
using ZoneCodeGenerator.Parsing.CommandFile.PostProcessor;
using ZoneCodeGenerator.Parsing.Impl;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing.CommandFile
{
static class CommandFileReader
{
private static readonly IDataPostProcessor[] postProcessors =
{
new PostProcessorUsages(),
new PostProcessorLeafs(),
new PostProcessorMemberLeafs(),
new PostProcessorUnions(),
};
public static bool ReadFile(string path, CUISession session, bool verbose = false)
{
try
{
using (IIncludingParsingStream streamFileSystem = new IncludingStreamFileSystem(path))
{
var state = new CommandParserState(session.Repository);
using (IParsingFileStream preprocessorStream = new CommandFilePreprocessor(streamFileSystem))
{
var lexer = new Lexer(preprocessorStream);
var parser = new Parser<ICommandParserState>(state, lexer);
if (!parser.Parse(verbose))
return false;
preprocessorStream.Close();
streamFileSystem.Close();
if (!state.Apply(session))
{
Console.WriteLine("Finalizing from command file failed");
return false;
}
if (!PostProcessRepository(session.Repository))
{
Console.WriteLine("Postprocessing commands failed.");
return false;
}
}
return true;
}
}
catch (IOException)
{
}
return false;
}
private static bool PostProcessRepository(IDataRepository repository)
{
return postProcessors.All(postProcessor => postProcessor.PostProcess(repository));
}
}
}

View File

@ -1,20 +0,0 @@
using System.Collections.Generic;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.FastFileStructure;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing.CommandFile
{
interface ICommandParserState : IParserState<ICommandParserState>
{
string Game { get; set; }
IReadOnlyDataRepository Repository { get; }
List<FastFileBlock> FastFileBlocks { get; }
StructureInformation DataTypeInUse { get; set; }
bool GetMembersFromParts(string[] parts, StructureInformation baseType, out List<MemberInformation> members);
bool GetTypenameAndMembersFromParts(string[] parts, out StructureInformation typeInformation,
out List<MemberInformation> members);
}
}

View File

@ -1,56 +0,0 @@
using System.Text.RegularExpressions;
using ZoneCodeGenerator.Parsing.Impl;
namespace ZoneCodeGenerator.Parsing.CommandFile.Impl
{
class CommandFilePreprocessor : IParsingFileStream
{
private static readonly Regex includeRegex = new Regex(@"^\s*include\s*(?:\""(.*)\""|\<(.*)\>)\s*$");
private readonly IIncludingParsingStream parsingStream;
private readonly ICommentProcessor commentProcessor;
public CommandFilePreprocessor(IIncludingParsingStream parsingStream)
{
this.parsingStream = parsingStream;
commentProcessor = new CommentProcessor();
}
public void Dispose()
{
parsingStream.Close();
}
public bool EndOfStream => parsingStream.EndOfStream;
public string Filename => parsingStream.Filename;
public int Line => parsingStream.Line;
public string ReadLine()
{
return Preprocess(parsingStream.ReadLine());
}
public void Close()
{
parsingStream.Close();
}
private string Preprocess(string line)
{
line = commentProcessor.RemoveComments(line);
var includeMatch = includeRegex.Match(line);
if (includeMatch.Success)
{
var filename = includeMatch.Groups[1].Success ? includeMatch.Groups[1].Value : includeMatch.Groups[2].Value;
parsingStream.IncludeFile(filename);
return "";
}
return line;
}
}
}

View File

@ -1,138 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.FastFileStructure;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Interface;
using ZoneCodeGenerator.Parsing.CommandFile.Tests;
using ZoneCodeGenerator.Parsing.Testing;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing.CommandFile.Impl
{
class CommandParserState : ICommandParserState
{
private static readonly ITokenTest<ICommandParserState>[] tests =
{
new TestAction(),
new TestArrayCount(),
new TestArraySize(),
new TestAsset(),
new TestBlock(),
new TestCondition(),
new TestCount(),
new TestGame(),
new TestName(),
new TestReorder(),
new TestReusable(),
new TestScriptString(),
new TestSetBlock(),
new TestString(),
new TestUse()
};
public string Game { get; set; }
public IReadOnlyDataRepository Repository { get; }
public List<FastFileBlock> FastFileBlocks { get; }
public StructureInformation DataTypeInUse { get; set; }
public CommandParserState(IReadOnlyDataRepository repository)
{
Repository = repository;
FastFileBlocks = new List<FastFileBlock>();
DataTypeInUse = null;
}
public IEnumerable<ITokenTest<ICommandParserState>> GetTests()
{
return tests;
}
public bool Apply(CUISession session)
{
session.Game = Game;
foreach (var block in FastFileBlocks)
{
session.Repository.Add(block);
}
return true;
}
private bool FindTypenameParts(string[] parts, out DataTypeWithMembers dataTypeWithMembers,
out int typeNamePartCount)
{
typeNamePartCount = 1;
while (typeNamePartCount <= parts.Length)
{
var currentTypeName = string.Join("::", parts, 0, typeNamePartCount);
var foundDataType = Repository.GetDataTypeByName(currentTypeName);
if (foundDataType != null)
{
if (!(foundDataType is DataTypeWithMembers foundDataTypeWithMembers))
{
throw new TestFailedException(
$"Referenced type '{currentTypeName}' needs to be a data type with members to be used in an evaluation.");
}
dataTypeWithMembers = foundDataTypeWithMembers;
return true;
}
typeNamePartCount++;
}
dataTypeWithMembers = null;
return false;
}
public bool GetMembersFromParts(string[] parts, StructureInformation baseType,
out List<MemberInformation> members)
{
members = new List<MemberInformation>();
var currentStructure = baseType;
foreach (var part in parts)
{
var member = currentStructure.OrderedMembers.FirstOrDefault(information =>
information.Member.Name.Equals(part));
if (member == null)
{
members = null;
return false;
}
members.Add(member);
currentStructure = member.StructureType;
}
return true;
}
public bool GetTypenameAndMembersFromParts(string[] parts, out StructureInformation typeInformation,
out List<MemberInformation> members)
{
if (!FindTypenameParts(parts, out var type, out var typeNamePartCount))
{
typeInformation = null;
members = null;
return false;
}
typeInformation = Repository.GetInformationFor(type);
if (typeInformation == null)
{
members = null;
return false;
}
var memberParts = new string[parts.Length - typeNamePartCount];
Array.Copy(parts, typeNamePartCount, memberParts, 0, memberParts.Length);
return GetMembersFromParts(memberParts, typeInformation, out members);
}
}
}

View File

@ -1,62 +0,0 @@
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
{
class PostProcessorLeafs : IDataPostProcessor
{
public static bool IsLeaf(StructureInformation structureInformation)
{
foreach (var member in structureInformation.OrderedMembers)
{
// If there is a condition to this member and it always evaluates to false: Skip this member
if (member.Condition != null && member.Condition.IsStatic && member.Condition.EvaluateNumeric() == 0)
continue;
// Any ScriptStrings or Strings need to be processed.
if (member.IsScriptString
|| member.IsString)
return false;
// If there are any Pointer members that are not always count 0 it needs to be processed.
var hasNoPointerMembers = member.Member.VariableType.References.OfType<ReferenceTypePointer>().All(pointer =>
{
if (!pointer.Count.IsStatic)
return false;
return pointer.Count.EvaluateNumeric() == 0;
});
if (!hasNoPointerMembers)
return false;
// If the member has an embedded type with dynamic size
if (member.Computations.HasDynamicArraySize)
return false;
if (member.StructureType != null
&& member.StructureType != structureInformation
&& !IsLeaf(member.StructureType))
return false;
}
return true;
}
public bool PostProcess(IDataRepository repository)
{
foreach (var dataTypeWithMembers in repository.GetAllStructs()
.AsEnumerable<DataTypeWithMembers>()
.Concat(repository.GetAllUnions()))
{
var information = repository.GetInformationFor(dataTypeWithMembers);
information.IsLeaf = IsLeaf(information);
}
return true;
}
}
}

View File

@ -1,59 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
{
class PostProcessorMemberLeafs : IDataPostProcessor
{
private static bool MemberIsLeaf(MemberInformation member)
{
if (member.IsString || member.IsScriptString)
return false;
if (member.StructureType != null && !member.StructureType.IsLeaf)
return false;
// If there are any Pointer members that are not always count 0 it needs to be processed.
var hasNoPointerMembers = member.Member.VariableType.References.OfType<ReferenceTypePointer>().All(pointer =>
{
if (!pointer.Count.IsStatic)
return false;
return pointer.Count.EvaluateNumeric() == 0;
});
if (!hasNoPointerMembers)
return false;
if (member.Computations.HasDynamicArraySize)
return false;
return true;
}
private static void ProcessStructureInformation(StructureInformation structure)
{
foreach (var member in structure.OrderedMembers)
{
member.IsLeaf = MemberIsLeaf(member);
}
}
public bool PostProcess(IDataRepository repository)
{
foreach (var structure in repository.GetAllStructs()
.Cast<DataTypeWithMembers>()
.Concat(repository.GetAllUnions())
.Select(repository.GetInformationFor))
{
ProcessStructureInformation(structure);
}
return true;
}
}
}

View File

@ -1,41 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
{
class PostProcessorUnions : IDataPostProcessor
{
private static bool ProcessUnion(StructureInformation unionInformation)
{
var entriesWithoutConditionCount =
unionInformation.OrderedMembers.Count(member => member.Condition == null && !member.IsLeaf);
if (entriesWithoutConditionCount > 1 && unionInformation.Usages.Any() && !unionInformation.IsLeaf)
{
Console.WriteLine($"Union '{unionInformation.Type.FullName}' has more than one entry without a condition!");
return false;
}
else if (entriesWithoutConditionCount == 1)
{
// If there is only one entry without condition make it the last of the ordered members
var entryWithoutCondition = unionInformation.OrderedMembers.First(information => information.Condition == null);
unionInformation.OrderedMembers.Remove(entryWithoutCondition);
unionInformation.OrderedMembers.Insert(unionInformation.OrderedMembers.Count, entryWithoutCondition);
}
return true;
}
public bool PostProcess(IDataRepository repository)
{
return repository.GetAllUnions()
.Select(repository.GetInformationFor)
.All(ProcessUnion);
}
}
}

View File

@ -1,63 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Persistence;
namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
{
class PostProcessorUsages : IDataPostProcessor
{
private static bool ProcessAsset(StructureInformation assetStructure)
{
var processedAssets = new HashSet<StructureInformation>();
var processingQueue = new Queue<StructureInformation>();
processingQueue.Enqueue(assetStructure);
while (processingQueue.Count != 0)
{
var currentStructure = processingQueue.Dequeue();
if (!processedAssets.Add(currentStructure))
{
continue;
}
foreach (var member in currentStructure.OrderedMembers
.Where(member => member.StructureType != null)
.Where(member => !member.Computations.ShouldIgnore))
{
if (member.Computations.ContainsNonEmbeddedReference)
member.StructureType.NonEmbeddedReferenceExists = true;
if (member.Computations.ContainsSinglePointerReference)
member.StructureType.SinglePointerReferenceExists = true;
if (member.Computations.ContainsArrayPointerReference)
member.StructureType.ArrayPointerReferenceExists = true;
if (member.Computations.ContainsArrayReference)
member.StructureType.ArrayReferenceExists = true;
if (member.Computations.IsNotDefaultNormalBlock)
member.StructureType.ReferenceFromNonDefaultNormalBlockExists = true;
member.StructureType.Usages.Add(currentStructure);
processingQueue.Enqueue(member.StructureType);
}
}
return true;
}
public bool PostProcess(IDataRepository repository)
{
return repository.GetAllStructs()
.AsEnumerable<DataTypeWithMembers>()
.Concat(repository.GetAllUnions())
.Select(repository.GetInformationFor)
.Where(information => information.IsAsset)
.All(ProcessAsset);
}
}
}

View File

@ -1,114 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestAction : AbstractTokenTest<ICommandParserState>
{
private const string TokenTypename = "typeName";
private const string TagTypename = "typeName";
private const string TokenActionName = "actionName";
private const string TokenActionArgument = "actionArgument";
private const string TagActionArguments = "actionArguments";
private static readonly TokenMatcher actionArguments = new MatcherGroupAnd(
new MatcherLiteral("("),
new MatcherGroupOptional(new MatcherGroupAnd(
new MatcherTypename().WithName(TokenActionArgument),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherGroupAnd(
new MatcherLiteral(","),
new MatcherTypename().WithName(TokenActionArgument)
))
)),
new MatcherLiteral(")")
).WithTag(TagActionArguments);
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("set"),
new MatcherLiteral("action"),
new MatcherGroupOr(
new MatcherGroupAnd(
new MatcherName().WithName(TokenActionName),
new MatcherWithTag(TagActionArguments)
),
new MatcherGroupAnd(
new MatcherTypename().WithName(TokenTypename).WithTag(TagTypename),
new MatcherName().WithName(TokenActionName),
new MatcherWithTag(TagActionArguments)
)
),
new MatcherLiteral(";")
};
public TestAction() : base(matchers)
{
AddTaggedMatcher(actionArguments);
}
protected override void ProcessMatch(ICommandParserState state)
{
StructureInformation selectedStructure;
if (PeekTag().Equals(TagTypename))
{
NextTag();
var typeName = NextMatch(TokenTypename);
var typeNameParts = typeName.Split(new[] {"::"}, StringSplitOptions.None);
if (state.DataTypeInUse != null &&
state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var selectedMembers))
{
selectedStructure = state.DataTypeInUse;
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out selectedStructure, out selectedMembers))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type '{typeName}'.");
}
if (selectedMembers.Any())
{
selectedStructure = selectedMembers.Last().StructureType ??
throw new TestFailedException("Member is not a data type with members.");
}
}
else
{
selectedStructure = state.DataTypeInUse ?? throw new TestFailedException("No type found for action.");
}
var actionName = NextMatch(TokenActionName);
if (string.IsNullOrEmpty(actionName))
{
throw new TestFailedException("Action needs a valid name!");
}
var parameterTypes = new List<DataType>();
string parameter;
while ((parameter = NextMatch(TokenActionArgument)) != null)
{
var parameterDataType = state.Repository.GetDataTypeByName(parameter);
if (parameterDataType == null)
{
throw new TestFailedException($"Could not find type '{parameter}'.");
}
parameterTypes.Add(parameterDataType);
}
selectedStructure.PostLoadAction = new CustomAction(actionName, parameterTypes);
}
}
}

View File

@ -1,82 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestArrayCount : TestWithEvaluation
{
private StructureInformation referencedType;
private const string TypeNameToken = "typeName";
// set count <typename> <calculationStatement>;
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("set"),
new MatcherLiteral("arraycount"),
new MatcherTypename().WithName(TypeNameToken),
new MatcherWithTag(TagEvaluation),
new MatcherLiteral(";")
};
public TestArrayCount() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(TypeNameToken);
var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None);
if (state.DataTypeInUse != null
&& state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var typeMembers))
{
referencedType = state.DataTypeInUse;
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out referencedType, out typeMembers))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type/members '{typeName}'");
}
if (typeMembers == null
|| !typeMembers.Any())
{
throw new TestFailedException("Can only set array size for members and not for types.");
}
if (!NextTag().Equals(TagEvaluation))
throw new Exception("Expected first array size tag to be a calculation statement");
var evaluation = ProcessEvaluation(state);
var referencedMember = typeMembers.Last();
var reference = referencedMember.Member.VariableType.References.OfType<ReferenceTypeArray>()
.FirstOrDefault();
if (reference != null)
reference.DynamicCount = evaluation;
else
throw new TestFailedException(
$"Member '{referencedMember.Member.Name}' of type '{referencedMember.Member.VariableType.Type.FullName}' cannot have its array count set due to it not having an array reference");
}
protected override IEnumerable<StructureInformation> GetUsedTypes(ICommandParserState state)
{
if (state.DataTypeInUse != null
&& state.DataTypeInUse != referencedType)
{
return new[] { state.DataTypeInUse, referencedType };
}
return new[] { referencedType };
}
}
}

View File

@ -1,89 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestArraySize : TestWithEvaluation
{
private StructureInformation referencedType;
private const string TypeNameToken = "typeName";
// set count <typename> <calculationStatement>;
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("set"),
new MatcherLiteral("arraysize"),
new MatcherTypename().WithName(TypeNameToken),
new MatcherWithTag(TagEvaluation),
new MatcherLiteral(";")
};
public TestArraySize() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(TypeNameToken);
var typeNameParts = typeName.Split(new[] {"::"}, StringSplitOptions.None);
if (state.DataTypeInUse != null
&& state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var typeMembers))
{
referencedType = state.DataTypeInUse;
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out referencedType, out typeMembers))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type/members '{typeName}'");
}
if (typeMembers == null
|| !typeMembers.Any())
{
throw new TestFailedException("Can only set array size for members and not for types.");
}
if (!NextTag().Equals(TagEvaluation))
throw new Exception("Expected first array size tag to be a calculation statement");
var evaluation = ProcessEvaluation(state);
var referencedMember = typeMembers.Last();
var reference = referencedMember.Member.VariableType.References.OfType<ReferenceTypeArray>()
.FirstOrDefault();
if (!referencedMember.Parent.IsUnion &&
referencedMember.Parent.Type.Members.Last() != referencedMember.Member)
{
throw new TestFailedException(
"Cannot change the array size of a member that is not the last member of its structure.");
}
if (reference != null)
reference.DynamicSize = evaluation;
else
throw new TestFailedException(
$"Member '{referencedMember.Member.Name}' of type '{referencedMember.Member.VariableType.Type.FullName}' cannot have its array size set due to it not having an array reference");
}
protected override IEnumerable<StructureInformation> GetUsedTypes(ICommandParserState state)
{
if (state.DataTypeInUse != null
&& state.DataTypeInUse != referencedType)
{
return new[] {state.DataTypeInUse, referencedType};
}
return new[] {referencedType};
}
}
}

View File

@ -1,59 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestAsset : AbstractTokenTest<ICommandParserState>
{
private const string AssetTypeNameToken = "name";
private const string AssetEnumEntryToken = "enumEntry";
private static readonly TokenMatcher[] matchers = {
new MatcherLiteral("asset"),
new MatcherTypename().WithName(AssetTypeNameToken),
new MatcherName().WithName(AssetEnumEntryToken),
new MatcherLiteral(";")
};
public TestAsset() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var assetTypeName = NextMatch(AssetTypeNameToken);
var assetType = state.Repository.GetDataTypeByName(assetTypeName);
if (assetType == null)
{
throw new TestFailedException($"Could not find type '{assetTypeName}' to mark it as an asset.");
}
if (!(assetType is DataTypeWithMembers assetTypeWithMembers))
{
throw new TestFailedException($"Type of asset '{assetTypeName}' needs to be struct or union.");
}
var assetInfo = state.Repository.GetInformationFor(assetTypeWithMembers);
if (assetInfo == null)
{
throw new TestFailedException($"Could not find information for type '{assetTypeName}' to mark it as an asset.");
}
var enumEntryName = NextMatch(AssetEnumEntryToken);
var enumEntry = state.Repository.GetAllEnums()
.SelectMany(_enum => _enum.Members)
.FirstOrDefault(member => member.Name.Equals(enumEntryName, StringComparison.CurrentCultureIgnoreCase));
assetInfo.AssetEnumEntry = enumEntry ?? throw new TestFailedException(
$"Could not find enum entry '{enumEntryName}' as an asset type index for asset type '{assetTypeName}'.");
}
}
}

View File

@ -1,56 +0,0 @@
using System;
using System.Linq;
using ZoneCodeGenerator.Domain.FastFileStructure;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestBlock : AbstractTokenTest<ICommandParserState>
{
private const string BlockTypeToken = "type";
private const string BlockEnumMemberToken = "enumEntry";
private const string DefaultToken = "default";
private static readonly TokenMatcher[] matchers = {
new MatcherLiteral("block"),
new MatcherName().WithName(BlockTypeToken),
new MatcherName().WithName(BlockEnumMemberToken),
new MatcherGroupOptional(
new MatcherLiteral("default").WithName(DefaultToken)
),
new MatcherLiteral(";")
};
public TestBlock() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var blockEnumEntryName = NextMatch(BlockEnumMemberToken);
var blockEnumEntry = state.Repository.GetAllEnums()
.SelectMany(_enum => _enum.Members)
.FirstOrDefault(member => member.Name.Equals(blockEnumEntryName));
if (blockEnumEntry == null)
{
throw new TestFailedException($"Could not find enum entry '{blockEnumEntryName}' for block.");
}
var blockTypeInput = NextMatch(BlockTypeToken);
if (!Enum.TryParse(blockTypeInput, true, out FastFileBlock.Type blockType))
{
var blockTypeValues = Enum.GetValues(typeof(FastFileBlock.Type)).OfType<FastFileBlock.Type>()
.Select(type => type.ToString());
throw new TestFailedException($"Unknown fastfile block type '{blockTypeInput}'. Must be one of the following: {string.Join(", ", blockTypeValues)}");
}
var block = new FastFileBlock(blockEnumEntry.Name, blockEnumEntry.Value, blockType, HasMatcherTokens(DefaultToken));
state.FastFileBlocks.Add(block);
}
}
}

View File

@ -1,98 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Evaluation;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestCondition : TestWithEvaluation
{
private StructureInformation referencedType;
private const string TagAlways = "always";
private const string TagNever = "never";
private const string TypeNameToken = "typeName";
// set condition <typename> (always | never | <CalculationStatementTag>);
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("set"),
new MatcherLiteral("condition"),
new MatcherTypename().WithName(TypeNameToken),
new MatcherGroupOr(
new MatcherLiteral("always").WithTag(TagAlways),
new MatcherLiteral("never").WithTag(TagNever),
new MatcherWithTag(TagEvaluation)
),
new MatcherLiteral(";")
};
public TestCondition() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(TypeNameToken);
var typeNameParts = typeName.Split(new[] {"::"}, StringSplitOptions.None);
if (state.DataTypeInUse != null
&& state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var typeMembers))
{
referencedType = state.DataTypeInUse;
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out referencedType, out typeMembers))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type/members '{typeName}'");
}
if (typeMembers == null
|| !typeMembers.Any())
{
throw new TestFailedException("Can only set conditions for members and not for types.");
}
IEvaluation evaluation;
switch (NextTag())
{
case TagAlways:
evaluation = new OperandStatic(1);
break;
case TagNever:
evaluation = new OperandStatic(0);
break;
case TagEvaluation:
evaluation = ProcessEvaluation(state);
break;
default:
throw new Exception("Unexpected Tag in TestCondition");
}
var referencedMember = typeMembers.Last();
referencedMember.Condition = evaluation;
}
protected override IEnumerable<StructureInformation> GetUsedTypes(ICommandParserState state)
{
if (state.DataTypeInUse != null
&& state.DataTypeInUse != referencedType)
{
return new[] {state.DataTypeInUse, referencedType};
}
return new[] {referencedType};
}
}
}

View File

@ -1,137 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Evaluation;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestCount : TestWithEvaluation
{
private StructureInformation referencedType;
private const string TokenTypeName = "typeName";
private const string TokenPointerResolve = "pointerResolve";
private const string TokenArrayIndex = "arrayIndex";
// set count <typename> <calculationStatement>;
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("set"),
new MatcherLiteral("count"),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple,
new MatcherLiteral("*").WithName(TokenPointerResolve)),
new MatcherTypename().WithName(TokenTypeName),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple,
new MatcherArray().WithName(TokenArrayIndex)),
new MatcherWithTag(TagEvaluation),
new MatcherLiteral(";")
};
public TestCount() : base(matchers)
{
}
private void SetCountByArrayIndex(MemberInformation referencedMember, ReferenceTypePointer pointer,
IEvaluation evaluation)
{
if (pointer.CountByArrayIndex == null)
{
pointer.CountByArrayIndex = new IEvaluation[referencedMember.Member.VariableType.References
.OfType<ReferenceTypeArray>().Select(array => array.ArraySize).Aggregate((i1, i2) => i1 * i2)];
}
var arraySizes = referencedMember.Member.VariableType.References
.OfType<ReferenceTypeArray>()
.Select(array => array.ArraySize)
.ToList();
var index = 0;
var indexDepth = 0;
string s;
while ((s = NextMatch(TokenArrayIndex)) != null)
{
var specifiedIndex = int.Parse(s);
if (specifiedIndex >= arraySizes[indexDepth])
{
throw new TestFailedException($"Specified index '{specifiedIndex}' is out of bounds at type '{referencedMember.Parent.Type.FullName}::{referencedMember.Member.Name}'");
}
var sizePerIndexInCurrentDepth = arraySizes.Count <= indexDepth + 1 ?
1 : arraySizes.Skip(indexDepth + 1).Aggregate((i1, i2) => i1 * i2);
index += specifiedIndex * sizePerIndexInCurrentDepth;
indexDepth++;
}
pointer.CountByArrayIndex[index] = evaluation;
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(TokenTypeName);
var typeNameParts = typeName.Split(new[] {"::"}, StringSplitOptions.None);
if (state.DataTypeInUse != null
&& state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var typeMembers))
{
referencedType = state.DataTypeInUse;
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out referencedType, out typeMembers))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type/members '{typeName}'");
}
if (typeMembers == null
|| !typeMembers.Any())
{
throw new TestFailedException("Can only set count for members and not for types.");
}
if (!NextTag().Equals(TagEvaluation))
throw new Exception("Expected first count tag to be a calculation statement");
var evaluation = ProcessEvaluation(state);
var referencedMember = typeMembers.Last();
var reference = referencedMember.Member.VariableType.References
.OfType<ReferenceTypePointer>()
.Skip(GetMatcherTokenCount(TokenPointerResolve))
.FirstOrDefault();
if (reference != null)
{
if (HasMatcherTokens(TokenArrayIndex))
{
SetCountByArrayIndex(referencedMember, reference, evaluation);
}
else
{
reference.Count = evaluation;
}
}
else
{
throw new TestFailedException(
$"Member '{referencedMember.Member.Name}' of type '{referencedMember.Member.VariableType.Type.FullName}' cannot have its count set due to it not having a pointer reference");
}
}
protected override IEnumerable<StructureInformation> GetUsedTypes(ICommandParserState state)
{
if (state.DataTypeInUse != null
&& state.DataTypeInUse != referencedType)
{
return new[] {state.DataTypeInUse, referencedType};
}
return new[] {referencedType};
}
}
}

View File

@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZoneCodeGenerator.Domain.FastFileStructure;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestGame : AbstractTokenTest<ICommandParserState>
{
private const string GameNameToken = "name";
private static readonly TokenMatcher[] matchers = {
new MatcherLiteral("game"),
new MatcherName().WithName(GameNameToken),
new MatcherLiteral(";")
};
public TestGame() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
if (!string.IsNullOrEmpty(state.Game))
{
throw new TestFailedException($"Game has already been set with value '{state.Game}'");
}
state.Game = NextMatch(GameNameToken);
}
}
}

View File

@ -1,67 +0,0 @@
using System;
using System.Linq;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestName : AbstractTokenTest<ICommandParserState>
{
private const string MemberTypeNameToken = "name";
private static readonly TokenMatcher[] matchers = {
new MatcherLiteral("set"),
new MatcherLiteral("name"),
new MatcherTypename().WithName(MemberTypeNameToken),
new MatcherLiteral(";")
};
public TestName() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(MemberTypeNameToken);
var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None);
StructureInformation structure;
if (state.DataTypeInUse != null &&
state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var memberList))
{
structure = state.DataTypeInUse;
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out structure, out memberList))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type '{typeName}'.");
}
if (memberList == null || !memberList.Any())
{
throw new TestFailedException("Need to specify a member when trying to set to a structure name.");
}
for (var i = 0; i < memberList.Count - 1; i++)
{
if (memberList[i].Computations.ContainsNonEmbeddedReference)
{
throw new TestFailedException("Can only add embedded members to name chain.");
}
}
if (!memberList[memberList.Count - 1].IsString)
{
throw new TestFailedException("Final name member must be a string.");
}
structure.NameChain = memberList;
}
}
}

View File

@ -1,127 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestReorder : AbstractTokenTest<ICommandParserState>
{
private const string TypeNameToken = "typeName";
private const string ReorderMemberNameToken = "member";
private const string TokenFindFirst = "findFirst";
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("reorder"),
new MatcherGroupOptional(new MatcherTypename().WithName(TypeNameToken)),
new MatcherLiteral(":"),
new MatcherGroupOptional(new MatcherLiteral(".", ".", ".").WithName(TokenFindFirst)),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple,
new MatcherName().WithName(ReorderMemberNameToken)),
new MatcherLiteral(";")
};
public TestReorder() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
StructureInformation typeToReorder;
if (HasMatcherTokens(TypeNameToken))
{
// If there was a type specified then use it to reorder.
var typeName = NextMatch(TypeNameToken);
var typeNameParts = typeName.Split(new[] {"::"}, StringSplitOptions.None);
if (!state.GetTypenameAndMembersFromParts(typeNameParts, out typeToReorder, out var memberList))
{
throw new TestFailedException($"Could not parse type with name '{typeName}'.");
}
// If there were members specified, use the type of the member.
if (memberList.Any())
{
var lastMember = memberList.Last();
typeToReorder = lastMember.StructureType
?? throw new TestFailedException(
$"Cannot reorder type of '{lastMember.Member.Name}'. Type is not a data type with members.");
}
}
else if (state.DataTypeInUse != null)
{
// If there was no type specified try to use the one currently in use.
typeToReorder = state.DataTypeInUse;
}
else
{
// No type specified and no type in use. We don't know what to reorder.
throw new TestFailedException("A type to reorder needs to be specified.");
}
// Create a pool of all members that have not been sorted yet.
var memberPool = new List<MemberInformation>(typeToReorder.OrderedMembers);
// Create a list that will be the sorted list at the end.
var sortedMembers = new List<MemberInformation>(memberPool.Count);
if (HasMatcherTokens(TokenFindFirst))
{
var firstMemberName = NextMatch(ReorderMemberNameToken);
var firstMember =
memberPool.FirstOrDefault(information => information.Member.Name.Equals(firstMemberName));
if (firstMember == null)
{
throw new TestFailedException(
$"Cannot find member with name '{firstMemberName}' in type '{typeToReorder.Type.FullName}'.");
}
var firstMemberIndex = memberPool.IndexOf(firstMember);
sortedMembers.AddRange(memberPool.GetRange(0, firstMemberIndex + 1));
memberPool.RemoveRange(0, firstMemberIndex + 1);
}
string nextMemberName;
while ((nextMemberName = NextMatch(ReorderMemberNameToken)) != null)
{
var nextMember =
memberPool.FirstOrDefault(information => information.Member.Name.Equals(nextMemberName));
if (nextMember != null)
{
sortedMembers.Add(nextMember);
memberPool.Remove(nextMember);
}
else
{
nextMember =
sortedMembers.FirstOrDefault(information => information.Member.Name.Equals(nextMemberName));
if (nextMember == null)
{
throw new TestFailedException(
$"Cannot find member with name '{nextMemberName}' in type '{typeToReorder.Type.FullName}'.");
}
sortedMembers.Remove(nextMember);
sortedMembers.Add(nextMember);
}
}
// Insert members that have not been mentioned at the end.
sortedMembers.AddRange(memberPool);
// Apply new members to the StructureInformation
typeToReorder.OrderedMembers = sortedMembers;
}
}
}

View File

@ -1,63 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestReusable : AbstractTokenTest<ICommandParserState>
{
private const string MemberTypeNameToken = "name";
private static readonly TokenMatcher[] matchers = {
new MatcherLiteral("set"),
new MatcherLiteral("reusable"),
new MatcherTypename().WithName(MemberTypeNameToken),
new MatcherLiteral(";")
};
public TestReusable() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(MemberTypeNameToken);
var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None);
if (state.DataTypeInUse != null &&
state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var memberList))
{
// Do nothing
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out _, out memberList))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type '{typeName}'.");
}
if (memberList == null || !memberList.Any())
{
throw new TestFailedException("Need to specify a member when trying to set to a string.");
}
var lastMember = memberList.Last();
if (!lastMember.Computations.ContainsNonEmbeddedReference)
{
throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is not a pointer reference and therefore cannot be reusable.");
}
lastMember.IsReusable = true;
}
}
}

View File

@ -1,61 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestScriptString : AbstractTokenTest<ICommandParserState>
{
private const string MemberTypeNameToken = "name";
private static readonly TokenMatcher[] matchers = {
new MatcherLiteral("set"),
new MatcherLiteral("scriptstring"),
new MatcherTypename().WithName(MemberTypeNameToken),
new MatcherLiteral(";")
};
public TestScriptString() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(MemberTypeNameToken);
var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None);
if (state.DataTypeInUse != null &&
state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var memberList))
{
// Do nothing
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out _, out memberList))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type '{typeName}'.");
}
if (memberList == null || !memberList.Any())
{
throw new TestFailedException("Need to specify a member when trying to set to a script string.");
}
var lastMember = memberList.Last();
if (!(lastMember.Member.VariableType.Type is DataTypeBaseType))
{
throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is not a base type and therefore cannot be a script string.");
}
lastMember.IsScriptString = true;
}
}
}

View File

@ -1,83 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ZoneCodeGenerator.Domain.Information;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestSetBlock : AbstractTokenTest<ICommandParserState>
{
private const string TokenTypeName = "name";
private const string TokenBlockEnumEntry = "block";
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("set"),
new MatcherLiteral("block"),
new MatcherGroupOr(new MatcherGroupAnd(
new MatcherTypename().WithName(TokenTypeName),
new MatcherName().WithName(TokenBlockEnumEntry)
),
new MatcherName().WithName(TokenBlockEnumEntry)),
new MatcherLiteral(";")
};
public TestSetBlock() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(TokenTypeName);
StructureInformation typeInfo;
List<MemberInformation> memberList;
if (typeName != null)
{
var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None);
if (state.DataTypeInUse != null &&
state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out memberList))
{
typeInfo = state.DataTypeInUse;
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out typeInfo, out memberList))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type '{typeName}'.");
}
}
else
{
typeInfo = state.DataTypeInUse;
memberList = new List<MemberInformation>();
if(typeInfo == null)
throw new TestFailedException("Must specify a type or member.");
}
var blockName = NextMatch(TokenBlockEnumEntry);
var block = state.FastFileBlocks
.FirstOrDefault(fastFileBlock => fastFileBlock.Name.Equals(blockName));
if (block == null)
throw new TestFailedException($"Could not find fastfile block with name '{blockName}'");
if (memberList.Any())
{
var member = memberList.Last();
member.Block = block;
}
else
{
typeInfo.Block = block;
}
}
}
}

View File

@ -1,67 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestString : AbstractTokenTest<ICommandParserState>
{
private const string MemberTypeNameToken = "name";
private static readonly TokenMatcher[] matchers = {
new MatcherLiteral("set"),
new MatcherLiteral("string"),
new MatcherTypename().WithName(MemberTypeNameToken),
new MatcherLiteral(";")
};
public TestString() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(MemberTypeNameToken);
var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None);
if (state.DataTypeInUse != null &&
state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var memberList))
{
// Do nothing
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out _, out memberList))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type '{typeName}'.");
}
if (memberList == null || !memberList.Any())
{
throw new TestFailedException("Need to specify a member when trying to set to a string.");
}
var lastMember = memberList.Last();
if (lastMember.Member.VariableType.Type != DataTypeBaseType.CHAR)
{
throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is not char type and therefore cannot be a string.");
}
if (!lastMember.Computations.ContainsSinglePointerReference)
{
throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is a single pointer reference and therefore cannot be a string.");
}
lastMember.IsString = true;
}
}
}

View File

@ -1,49 +0,0 @@
using System;
using ZoneCodeGenerator.Domain;
using ZoneCodeGenerator.Parsing.Matching;
using ZoneCodeGenerator.Parsing.Matching.Matchers;
using ZoneCodeGenerator.Parsing.Testing;
namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
{
class TestUse : AbstractTokenTest<ICommandParserState>
{
private const string TypeNameToken = "typeName";
private static readonly TokenMatcher[] matchers = {
new MatcherLiteral("use"),
new MatcherTypename().WithName(TypeNameToken),
new MatcherLiteral(";")
};
public TestUse() : base(matchers)
{
}
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(TypeNameToken);
var dataTypeToUse = state.Repository.GetDataTypeByName(typeName);
if (dataTypeToUse == null)
{
throw new TestFailedException($"Could not find data type '{typeName}'");
}
if (!(dataTypeToUse is DataTypeWithMembers dataTypeWithMembersToUse))
{
throw new TestFailedException($"To use data type '{typeName}' it must either be a struct or a union.");
}
var dataTypeToUseInformation = state.Repository.GetInformationFor(dataTypeWithMembersToUse);
if (dataTypeToUseInformation == null)
{
throw new Exception($"Could not find information for type '{dataTypeWithMembersToUse.FullName}'");
}
state.DataTypeInUse = dataTypeToUseInformation;
}
}
}

Some files were not shown because too many files have changed in this diff Show More