ZoneCodeGenerator: Remove the const keyword from typename but instead save whether a reference is cosnt in the typedeclaration

This commit is contained in:
Jan 2019-11-01 01:46:40 +01:00
parent 3d30915308
commit f71ae1bcf5
7 changed files with 117 additions and 104 deletions

View File

@ -1,4 +1,9 @@
namespace ZoneCodeGenerator.Domain
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace ZoneCodeGenerator.Domain
{
class DataTypeBaseType : DataType
{
@ -6,7 +11,6 @@
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 CONST_CHAR = new DataTypeBaseType("const 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);
@ -18,23 +22,12 @@
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 DataTypeBaseType[] BASE_TYPES = {
FLOAT,
DOUBLE,
BOOL,
CHAR,
CONST_CHAR,
UNSIGNED_CHAR,
SHORT,
UNSIGNED_SHORT,
INT,
UNSIGNED_INT,
LONG,
UNSIGNED_LONG,
LONG_LONG,
UNSIGNED_LONG_LONG,
VOID
};
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 int Size { get; }
public override int Alignment => Size;

View File

@ -9,7 +9,8 @@
TypeDefinition = typeDefinitionDeclaration;
}
public override int Alignment => TypeDefinition.Alignment;
public int? AlignmentOverride { get; set; }
public override int Alignment => AlignmentOverride ?? TypeDefinition.Alignment;
public override int Size => TypeDefinition.Size;
}
}

View File

@ -23,7 +23,9 @@ namespace ZoneCodeGenerator.Domain
set => type = value;
}
public int? CustomBitSize { get; }
public int? CustomBitSize { get; set; }
public bool IsConst { get; set; }
public bool HasCustomBitSize => CustomBitSize != null;
@ -61,10 +63,5 @@ namespace ZoneCodeGenerator.Domain
this.references = references ?? new List<ReferenceType>();
CustomBitSize = null;
}
public TypeDeclaration(DataType type, int customBitSize, List<ReferenceType> references) : this(type, references)
{
CustomBitSize = customBitSize;
}
}
}

View File

@ -8,57 +8,88 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{
class TestTypedef : AbstractTokenTest<IHeaderParserState>
{
private const string PointerToArrayVariant = "pointertoarray";
private const string ArrayOfPointersVariant = "arrayofpointers";
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 static readonly TokenMatcher[] arrayOfPointersMatchers = {
new MatcherLiteral("typedef"),
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 MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple,
new MatcherLiteral("*").WithName(PointerTokens)),
new MatcherName().WithName(NameToken),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray().WithName(ArrayTokens)),
new MatcherLiteral(";").WithName(ArrayOfPointersVariant)
};
new MatcherLiteral(";")
).WithTag(TagArrayOfPointers);
private static readonly TokenMatcher[] pointerToArrayMatchers = {
new MatcherLiteral("typedef"),
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 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)
};
new MatcherLiteral(";")
).WithTag(TagPointerToArray);
private static readonly TokenMatcher[] matchers =
{
new MatcherLiteral("typedef"),
new MatcherGroupOptional(new MatcherWithTag(TagAlign)),
new MatcherGroupOr(
new MatcherGroupAnd(arrayOfPointersMatchers),
new MatcherGroupAnd(pointerToArrayMatchers)
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;
@ -69,26 +100,32 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests
}
var references = new List<ReferenceType>();
if (HasMatcherTokens(PointerToArrayVariant))
if (isArrayOfPointersVariant)
{
for (var i = 0; i < pointerDepth; i++)
references.Add(new ReferenceTypePointer());
foreach (var array in arraySize)
references.Add(new ReferenceTypeArray(array));
for (var i = 0; i < pointerDepth; i++)
references.Add(new ReferenceTypePointer());
}
else
{
foreach(var array in arraySize)
references.Add(new ReferenceTypeArray(array));
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);
var typedef = new DataTypeTypedef(state.CurrentNamespace.ToString(), name, typeDeclaration);
var typeDeclaration = new TypeDeclaration(type, references)
{
IsConst = HasMatcherTokens(TokenConst)
};
var typedef = new DataTypeTypedef(state.CurrentNamespace.ToString(), name, typeDeclaration)
{
AlignmentOverride = alignmentOverride
};
state.AddDataType(typedef);
}

View File

@ -17,8 +17,10 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests
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").WithTag(TokenConst)),
new MatcherTypename().WithName(TypeNameToken),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
new MatcherName().WithName(NameToken),
@ -31,6 +33,7 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests
};
private static readonly TokenMatcher[] pointerToArrayMatchers = {
new MatcherGroupOptional(new MatcherLiteral("const").WithTag(TokenConst)),
new MatcherTypename().WithName(TypeNameToken),
new MatcherLiteral("("),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
@ -97,7 +100,11 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests
references.Add(new ReferenceTypePointer());
}
var typeDeclaration = bitSize == null ? new TypeDeclaration(type, references) : new TypeDeclaration(type, bitSize.Value, references);
var typeDeclaration = new TypeDeclaration(type, references)
{
CustomBitSize = bitSize,
IsConst = HasMatcherTokens(TokenConst)
};
var variable = new Variable(name, typeDeclaration);

View File

@ -8,12 +8,6 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers
{
private static readonly Regex nameRegex = new Regex(@"^[a-zA-Z_$][a-zA-Z0-9_$]*$");
private static readonly string[] typenamePrefixes = {
"const",
"signed",
"unsigned"
};
private int MatchTypenameExtension(MatchingContext context, int tokenOffset)
{
if (!":".Equals(context.Lexer.PeekToken(tokenOffset++)))
@ -31,19 +25,17 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers
var startTokenOffset = tokenOffset;
var currentPart = lexer.PeekToken(tokenOffset++);
if (!nameRegex.IsMatch(currentPart))
return new MatchingResult(false, 0);
typename.Append(currentPart);
while (typenamePrefixes.Contains(currentPart))
if ("unsigned".Equals(currentPart)
|| "signed".Equals(currentPart))
{
typename.Append(currentPart);
typename.Append(' ');
currentPart = lexer.PeekToken(tokenOffset++);
}
if (!nameRegex.IsMatch(currentPart))
return new MatchingResult(false, 0);
typename.Append(' ');
typename.Append(currentPart);
}
if ("long".Equals(currentPart))
{
@ -55,7 +47,8 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers
typename.Append(currentPart);
}
}
else
{
var extensionLength = MatchTypenameExtension(context, tokenOffset);
while (extensionLength > 0)
{
@ -67,6 +60,7 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers
tokenOffset += extensionLength;
extensionLength = MatchTypenameExtension(context, tokenOffset);
}
}
SetMatcherOutput(typename.ToString());
return new MatchingResult(true, tokenOffset - startTokenOffset);

View File

@ -99,22 +99,6 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers
Assert.AreEqual("signed int", result.NamedMatches["type_token"].ElementAtOrDefault(0));
}
[TestMethod]
public void EnsureConstTypeNamesAreRecognized()
{
tokens.AddRange(new List<string>
{
"const", "int"
});
var matcher = new MatcherTypename().WithName("type_token");
var result = matcher.Test(matchingContext, 0);
Assert.IsTrue(result.Successful);
Assert.AreEqual(2, result.ConsumedTokenCount);
Assert.AreEqual("const int", result.NamedMatches["type_token"].ElementAtOrDefault(0));
}
[TestMethod]
public void EnsureDoubleLongIsRecognized()
{
@ -136,15 +120,15 @@ namespace ZoneCodeGeneratorTests.Parsing.Matching.Matchers
{
tokens.AddRange(new List<string>
{
"const", "unsigned", "long", "long"
"unsigned", "long", "long"
});
var matcher = new MatcherTypename().WithName("type_token");
var result = matcher.Test(matchingContext, 0);
Assert.IsTrue(result.Successful);
Assert.AreEqual(4, result.ConsumedTokenCount);
Assert.AreEqual("const unsigned long long", result.NamedMatches["type_token"].ElementAtOrDefault(0));
Assert.AreEqual(3, result.ConsumedTokenCount);
Assert.AreEqual("unsigned long long", result.NamedMatches["type_token"].ElementAtOrDefault(0));
}
[TestMethod]