ZoneCodeGenerator: Add tests for reordering, scriptstring, string

This commit is contained in:
Jan 2019-11-10 22:14:01 +01:00
parent 6ca7f18f9f
commit 73424c9bc1
6 changed files with 156 additions and 37 deletions

View File

@ -1,4 +1,5 @@
using ZoneCodeGenerator.Domain.Evaluation;
using System.Linq;
using ZoneCodeGenerator.Domain.Evaluation;
namespace ZoneCodeGenerator.Domain.Information
{
@ -6,15 +7,32 @@ namespace ZoneCodeGenerator.Domain.Information
{
public StructureInformation StructureType { get; }
public Variable Member { get; set; }
public bool IsString { get; set; }
public bool IsScriptString { get; set; }
public IEvaluation Condition { get; set; }
public bool IsNonEmbeddedReference => Member.VariableType.References.Any();
public bool IsSinglePointerReference => Member.VariableType.References.Any()
&& Member.VariableType.References.Last() is ReferenceTypePointer
pointerReference
&& !pointerReference.IsArray;
public bool IsArrayPointerReference => Member.VariableType.References.Any()
&& Member.VariableType.References.Last() is ReferenceTypePointer
pointerReference
&& pointerReference.IsArray;
public bool IsArrayReference => Member.VariableType.References.Any()
&& Member.VariableType.References.Last() is ReferenceTypeArray;
public MemberInformation(Variable member, StructureInformation structureType)
{
Member = member;
StructureType = structureType;
IsString = false;
IsScriptString = false;
Condition = null;
}
}
}
}

View File

@ -24,7 +24,7 @@ namespace ZoneCodeGenerator.Domain.Information
}
public List<StructureInformation> Usages { get; }
public List<MemberInformation> OrderedMembers { get; }
public List<MemberInformation> OrderedMembers { get; set; }
public bool NonEmbeddedReferenceExists { get; set; }
public bool SinglePointerReferenceExists { get; set; }
public bool ArrayPointerReferenceExists { get; set; }

View File

@ -20,46 +20,21 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
memberInformation.StructureType.Usages.Add(information);
if (IsNonEmbeddedReference(memberInformation.Member))
if (memberInformation.IsNonEmbeddedReference)
memberInformation.StructureType.NonEmbeddedReferenceExists = true;
if (IsSinglePointerReference(memberInformation.Member))
if (memberInformation.IsSinglePointerReference)
memberInformation.StructureType.SinglePointerReferenceExists = true;
if (IsArrayPointerReference(memberInformation.Member))
if (memberInformation.IsArrayPointerReference)
memberInformation.StructureType.ArrayPointerReferenceExists = true;
if (IsArrayReference(memberInformation.Member))
if (memberInformation.IsArrayReference)
memberInformation.StructureType.ArrayReferenceExists = true;
}
}
return true;
}
private static bool IsNonEmbeddedReference(Variable var)
{
return var.VariableType.References.Any();
}
private static bool IsSinglePointerReference(Variable var)
{
return var.VariableType.References.Any()
&& var.VariableType.References.Last() is ReferenceTypePointer pointerReference
&& !pointerReference.IsArray;
}
private static bool IsArrayPointerReference(Variable var)
{
return var.VariableType.References.Any()
&& var.VariableType.References.Last() is ReferenceTypePointer pointerReference
&& pointerReference.IsArray;
}
private static bool IsArrayReference(Variable var)
{
return var.VariableType.References.Any()
&& var.VariableType.References.Last() is ReferenceTypeArray;
}
}
}

View File

@ -1,6 +1,9 @@
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;
@ -12,22 +15,83 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
private const string TypeNameToken = "typeName";
private const string ReorderMemberNameToken = "member";
private static readonly TokenMatcher[] matchers = {
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("reorder"),
new MatcherGroupOptional(new MatcherTypename().WithName(TypeNameToken)),
new MatcherGroupOptional(new MatcherTypename().WithName(TypeNameToken)),
new MatcherLiteral(":"),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherName().WithName(ReorderMemberNameToken)),
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);
string nextMemberName;
while ((nextMemberName = NextMatch(ReorderMemberNameToken)) != null)
{
var nextMember =
memberPool.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.Add(nextMember);
memberPool.Remove(nextMember);
}
// Insert members that have not been mentioned at the end.
sortedMembers.AddRange(memberPool);
// Apply new members to the StructureInformation
typeToReorder.OrderedMembers = sortedMembers;
}
}
}
}

View File

@ -27,7 +27,35 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
protected override void ProcessMatch(ICommandParserState state)
{
var typeName = NextMatch(MemberTypeNameToken);
var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None);
if (state.DataTypeInUse != null &&
state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var memberList))
{
// Do nothing
}
else if (state.GetTypenameAndMembersFromParts(typeNameParts, out _, out memberList))
{
// Do nothing
}
else
{
throw new TestFailedException($"Could not find type '{typeName}'.");
}
if (memberList == null || !memberList.Any())
{
throw new TestFailedException("Need to specify a member when trying to set to a script string.");
}
var lastMember = memberList.Last();
if (!(lastMember.Member.VariableType.Type is DataTypeBaseType))
{
throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is not a base type and therefore cannot be a script string.");
}
lastMember.IsScriptString = true;
}
}
}

View File

@ -3,6 +3,7 @@ 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;
@ -27,7 +28,40 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
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.IsSinglePointerReference)
{
throw new TestFailedException($"Specified member '{lastMember.Member.Name}' is a single pointer reference and therefore cannot be a string.");
}
lastMember.IsString = true;
}
}
}