mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 00:02:55 +00:00
Remove old ZoneCodeGenerator implementation in c#
This commit is contained in:
parent
5290d3a768
commit
f85c82f487
@ -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 ""
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
class DataException : LoadingException
|
||||
{
|
||||
public DataException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
enum DataTypeType
|
||||
{
|
||||
Struct,
|
||||
Union,
|
||||
Enum,
|
||||
Typedef,
|
||||
BaseType
|
||||
}
|
||||
}
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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}]"))}";
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
@ -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}";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace ZoneCodeGenerator.Domain
|
||||
{
|
||||
abstract class ReferenceType
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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$}$
|
||||
};
|
||||
}
|
||||
>>
|
@ -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$
|
||||
%>
|
@ -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++;
|
||||
}
|
||||
}
|
||||
>>
|
@ -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)$}$);
|
||||
>>
|
@ -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)$
|
||||
%>
|
@ -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)$
|
||||
>>
|
@ -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)$
|
||||
%>
|
@ -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)$
|
||||
%>
|
@ -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)$
|
||||
>>
|
@ -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
|
||||
>>
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace ZoneCodeGenerator
|
||||
{
|
||||
class LoadingException : Exception
|
||||
{
|
||||
public LoadingException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header
|
||||
{
|
||||
enum BlockType
|
||||
{
|
||||
None,
|
||||
Enum,
|
||||
Namespace,
|
||||
Struct,
|
||||
Union
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
interface INameAssignable
|
||||
{
|
||||
void AssignName(string nameAssignment);
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using ZoneCodeGenerator.Domain;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
interface IVariableBlock
|
||||
{
|
||||
Variable GetDefinedVariable();
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using ZoneCodeGenerator.Domain;
|
||||
|
||||
namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
|
||||
{
|
||||
interface IVariableHolder
|
||||
{
|
||||
void AddVariable(Variable variable);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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 };
|
||||
}
|
||||
}
|
||||
}
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
@ -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}'.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
@ -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};
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
Loading…
x
Reference in New Issue
Block a user