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 class DataTypeBaseType : DataType
{ {
@ -6,7 +11,6 @@
public static readonly DataTypeBaseType DOUBLE = new DataTypeBaseType("double", 8); public static readonly DataTypeBaseType DOUBLE = new DataTypeBaseType("double", 8);
public static readonly DataTypeBaseType BOOL = new DataTypeBaseType("bool", 1); public static readonly DataTypeBaseType BOOL = new DataTypeBaseType("bool", 1);
public static readonly DataTypeBaseType CHAR = new DataTypeBaseType("char", 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 UNSIGNED_CHAR = new DataTypeBaseType("unsigned char", 1);
public static readonly DataTypeBaseType SHORT = new DataTypeBaseType("short", 2); public static readonly DataTypeBaseType SHORT = new DataTypeBaseType("short", 2);
public static readonly DataTypeBaseType UNSIGNED_SHORT = new DataTypeBaseType("unsigned 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 UNSIGNED_LONG_LONG = new DataTypeBaseType("unsigned long long", 8);
public static readonly DataTypeBaseType VOID = new DataTypeBaseType("void", 0); public static readonly DataTypeBaseType VOID = new DataTypeBaseType("void", 0);
public static readonly DataTypeBaseType[] BASE_TYPES = { public static readonly IEnumerable<DataTypeBaseType> BASE_TYPES = typeof(DataTypeBaseType)
FLOAT, .GetFields(BindingFlags.Public | BindingFlags.Static)
DOUBLE, .Where(info => info.FieldType == typeof(DataTypeBaseType))
BOOL, .Select(info => info.GetValue(null))
CHAR, .Cast<DataTypeBaseType>()
CONST_CHAR, .ToList();
UNSIGNED_CHAR,
SHORT,
UNSIGNED_SHORT,
INT,
UNSIGNED_INT,
LONG,
UNSIGNED_LONG,
LONG_LONG,
UNSIGNED_LONG_LONG,
VOID
};
public override int Size { get; } public override int Size { get; }
public override int Alignment => Size; public override int Alignment => Size;

View File

@ -9,7 +9,8 @@
TypeDefinition = typeDefinitionDeclaration; 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; public override int Size => TypeDefinition.Size;
} }
} }

View File

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

View File

@ -8,87 +8,124 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests
{ {
class TestTypedef : AbstractTokenTest<IHeaderParserState> class TestTypedef : AbstractTokenTest<IHeaderParserState>
{ {
private const string PointerToArrayVariant = "pointertoarray";
private const string ArrayOfPointersVariant = "arrayofpointers";
private const string TypeNameTokens = "typename"; private const string TypeNameTokens = "typename";
private const string PointerTokens = "pointer"; private const string PointerTokens = "pointer";
private const string NameToken = "name"; private const string NameToken = "name";
private const string ArrayTokens = "array"; private const string ArrayTokens = "array";
private const string AlignValueToken = "alignValue";
private const string TokenConst = "constToken";
private static readonly TokenMatcher[] arrayOfPointersMatchers = { private const string TagAlign = "alignTag";
new MatcherLiteral("typedef"), 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 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 MatcherName().WithName(NameToken),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray().WithName(ArrayTokens)), new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray().WithName(ArrayTokens)),
new MatcherLiteral(";").WithName(ArrayOfPointersVariant) new MatcherLiteral(";")
}; ).WithTag(TagArrayOfPointers);
private static readonly TokenMatcher[] pointerToArrayMatchers = { private static readonly TokenMatcher pointerToArray = new MatcherGroupAnd(
new MatcherLiteral("typedef"), new MatcherGroupOptional(new MatcherLiteral("const").WithName(TokenConst)),
new MatcherTypename().WithName(TypeNameTokens), new MatcherTypename().WithName(TypeNameTokens),
new MatcherLiteral("("), 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 MatcherName().WithName(NameToken),
new MatcherLiteral(")"), new MatcherLiteral(")"),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherArray().WithName(ArrayTokens)), new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherArray().WithName(ArrayTokens)),
new MatcherLiteral(";").WithName(PointerToArrayVariant) new MatcherLiteral(";")
}; ).WithTag(TagPointerToArray);
private static readonly TokenMatcher[] matchers = private static readonly TokenMatcher[] matchers =
{ {
new MatcherLiteral("typedef"),
new MatcherGroupOptional(new MatcherWithTag(TagAlign)),
new MatcherGroupOr( new MatcherGroupOr(
new MatcherGroupAnd(arrayOfPointersMatchers), new MatcherWithTag(TagArrayOfPointers),
new MatcherGroupAnd(pointerToArrayMatchers) new MatcherWithTag(TagPointerToArray)
) )
}; };
public TestTypedef() : base(matchers) public TestTypedef() : base(matchers)
{ {
AddTaggedMatcher(align);
AddTaggedMatcher(arrayOfPointers);
AddTaggedMatcher(pointerToArray);
} }
protected override void ProcessMatch(IHeaderParserState state) 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 name = NextMatch(NameToken);
var pointerDepth = GetMatcherTokenCount(PointerTokens); var pointerDepth = GetMatcherTokenCount(PointerTokens);
// Find referenced type
var typeName = NextMatch(TypeNameTokens); var typeName = NextMatch(TypeNameTokens);
var type = state.FindType(typeName); var type = state.FindType(typeName);
if (type == null) if (type == null)
throw new TestFailedException($"Could not find type '{typeName}' of typedef '{name}'."); 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)]; var arraySize = new int[GetMatcherTokenCount(ArrayTokens)];
string arrayToken; string arrayToken;
var index = 0; var index = 0;
while((arrayToken = NextMatch(ArrayTokens)) != null) while ((arrayToken = NextMatch(ArrayTokens)) != null)
{ {
if (!int.TryParse(arrayToken, out arraySize[index++])) if (!int.TryParse(arrayToken, out arraySize[index++]))
throw new TestFailedException($"Array size '{arrayToken}' is not numeric."); throw new TestFailedException($"Array size '{arrayToken}' is not numeric.");
} }
var references = new List<ReferenceType>(); var references = new List<ReferenceType>();
if (isArrayOfPointersVariant)
if (HasMatcherTokens(PointerToArrayVariant))
{ {
foreach (var array in arraySize)
references.Add(new ReferenceTypeArray(array));
for (var i = 0; i < pointerDepth; i++) for (var i = 0; i < pointerDepth; i++)
references.Add(new ReferenceTypePointer()); references.Add(new ReferenceTypePointer());
foreach(var array in arraySize)
references.Add(new ReferenceTypeArray(array));
} }
else else
{ {
foreach(var array in arraySize)
references.Add(new ReferenceTypeArray(array));
for (var i = 0; i < pointerDepth; i++) for (var i = 0; i < pointerDepth; i++)
references.Add(new ReferenceTypePointer()); references.Add(new ReferenceTypePointer());
foreach (var array in arraySize)
references.Add(new ReferenceTypeArray(array));
} }
var typeDeclaration = new TypeDeclaration(type, references); var typeDeclaration = new TypeDeclaration(type, references)
var typedef = new DataTypeTypedef(state.CurrentNamespace.ToString(), name, typeDeclaration); {
IsConst = HasMatcherTokens(TokenConst)
};
var typedef = new DataTypeTypedef(state.CurrentNamespace.ToString(), name, typeDeclaration)
{
AlignmentOverride = alignmentOverride
};
state.AddDataType(typedef); state.AddDataType(typedef);
} }

View File

@ -17,8 +17,10 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests
private const string NameToken = "name"; private const string NameToken = "name";
private const string ArrayTokens = "array"; private const string ArrayTokens = "array";
private const string BitSizeToken = "bitsize"; private const string BitSizeToken = "bitsize";
private const string TokenConst = "constToken";
private static readonly TokenMatcher[] arrayOfPointersMatchers = { private static readonly TokenMatcher[] arrayOfPointersMatchers = {
new MatcherGroupOptional(new MatcherLiteral("const").WithTag(TokenConst)),
new MatcherTypename().WithName(TypeNameToken), new MatcherTypename().WithName(TypeNameToken),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherLiteral("*").WithName(PointerTokens)), new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
new MatcherName().WithName(NameToken), new MatcherName().WithName(NameToken),
@ -31,6 +33,7 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests
}; };
private static readonly TokenMatcher[] pointerToArrayMatchers = { private static readonly TokenMatcher[] pointerToArrayMatchers = {
new MatcherGroupOptional(new MatcherLiteral("const").WithTag(TokenConst)),
new MatcherTypename().WithName(TypeNameToken), new MatcherTypename().WithName(TypeNameToken),
new MatcherLiteral("("), new MatcherLiteral("("),
new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherLiteral("*").WithName(PointerTokens)), new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
@ -97,7 +100,11 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests
references.Add(new ReferenceTypePointer()); 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); 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 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) private int MatchTypenameExtension(MatchingContext context, int tokenOffset)
{ {
if (!":".Equals(context.Lexer.PeekToken(tokenOffset++))) if (!":".Equals(context.Lexer.PeekToken(tokenOffset++)))
@ -31,20 +25,18 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers
var startTokenOffset = tokenOffset; var startTokenOffset = tokenOffset;
var currentPart = lexer.PeekToken(tokenOffset++); var currentPart = lexer.PeekToken(tokenOffset++);
if ("unsigned".Equals(currentPart)
|| "signed".Equals(currentPart))
{
typename.Append(currentPart);
typename.Append(' ');
currentPart = lexer.PeekToken(tokenOffset++);
}
if (!nameRegex.IsMatch(currentPart)) if (!nameRegex.IsMatch(currentPart))
return new MatchingResult(false, 0); return new MatchingResult(false, 0);
typename.Append(currentPart); typename.Append(currentPart);
while (typenamePrefixes.Contains(currentPart))
{
currentPart = lexer.PeekToken(tokenOffset++);
if (!nameRegex.IsMatch(currentPart))
return new MatchingResult(false, 0);
typename.Append(' ');
typename.Append(currentPart);
}
if ("long".Equals(currentPart)) if ("long".Equals(currentPart))
{ {
currentPart = lexer.PeekToken(tokenOffset); currentPart = lexer.PeekToken(tokenOffset);
@ -55,17 +47,19 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers
typename.Append(currentPart); typename.Append(currentPart);
} }
} }
else
var extensionLength = MatchTypenameExtension(context, tokenOffset);
while (extensionLength > 0)
{ {
for (var i = 0; i < extensionLength; i++) var extensionLength = MatchTypenameExtension(context, tokenOffset);
while (extensionLength > 0)
{ {
typename.Append(lexer.PeekToken(tokenOffset + i)); for (var i = 0; i < extensionLength; i++)
} {
typename.Append(lexer.PeekToken(tokenOffset + i));
}
tokenOffset += extensionLength; tokenOffset += extensionLength;
extensionLength = MatchTypenameExtension(context, tokenOffset); extensionLength = MatchTypenameExtension(context, tokenOffset);
}
} }
SetMatcherOutput(typename.ToString()); SetMatcherOutput(typename.ToString());

View File

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