From f71ae1bcf57f162ae079f023763492927661c5bc Mon Sep 17 00:00:00 2001 From: Jan Date: Fri, 1 Nov 2019 01:46:40 +0100 Subject: [PATCH] ZoneCodeGenerator: Remove the const keyword from typename but instead save whether a reference is cosnt in the typedeclaration --- .../Domain/DataTypeBaseType.cs | 31 ++---- .../Domain/DataTypeTypedef.cs | 3 +- .../Domain/TypeDeclaration.cs | 9 +- .../Parsing/C_Header/Tests/TestTypedef.cs | 105 ++++++++++++------ .../Parsing/C_Header/Tests/TestVariable.cs | 9 +- .../Matching/Matchers/MatcherTypename.cs | 42 +++---- .../Matching/Matchers/MatcherTypenameTest.cs | 22 +--- 7 files changed, 117 insertions(+), 104 deletions(-) diff --git a/src/ZoneCodeGenerator/Domain/DataTypeBaseType.cs b/src/ZoneCodeGenerator/Domain/DataTypeBaseType.cs index c20efdab..04deaabe 100644 --- a/src/ZoneCodeGenerator/Domain/DataTypeBaseType.cs +++ b/src/ZoneCodeGenerator/Domain/DataTypeBaseType.cs @@ -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 BASE_TYPES = typeof(DataTypeBaseType) + .GetFields(BindingFlags.Public | BindingFlags.Static) + .Where(info => info.FieldType == typeof(DataTypeBaseType)) + .Select(info => info.GetValue(null)) + .Cast() + .ToList(); public override int Size { get; } public override int Alignment => Size; diff --git a/src/ZoneCodeGenerator/Domain/DataTypeTypedef.cs b/src/ZoneCodeGenerator/Domain/DataTypeTypedef.cs index 1c4c4454..5f1936a0 100644 --- a/src/ZoneCodeGenerator/Domain/DataTypeTypedef.cs +++ b/src/ZoneCodeGenerator/Domain/DataTypeTypedef.cs @@ -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; } } \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Domain/TypeDeclaration.cs b/src/ZoneCodeGenerator/Domain/TypeDeclaration.cs index 0241a25f..dad77550 100644 --- a/src/ZoneCodeGenerator/Domain/TypeDeclaration.cs +++ b/src/ZoneCodeGenerator/Domain/TypeDeclaration.cs @@ -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(); CustomBitSize = null; } - - public TypeDeclaration(DataType type, int customBitSize, List references) : this(type, references) - { - CustomBitSize = customBitSize; - } } } diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs index 5429b55a..b7861398 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs @@ -8,89 +8,126 @@ namespace ZoneCodeGenerator.Parsing.C_Header.Tests { class TestTypedef : AbstractTokenTest { - 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 MatcherLiteral("("), + new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, + new MatcherLiteral("*").WithName(PointerTokens)), new MatcherName().WithName(NameToken), - new MatcherLiteral(")"), + 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; - while((arrayToken = NextMatch(ArrayTokens)) != null) + 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(); - - if (HasMatcherTokens(PointerToArrayVariant)) + if (isArrayOfPointersVariant) { + 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)); } 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); } } -} +} \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs index b2ff23ba..bbc0e5f8 100644 --- a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs +++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs @@ -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); diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherTypename.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherTypename.cs index ef7d1b28..524eae16 100644 --- a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherTypename.cs +++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherTypename.cs @@ -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,20 +25,18 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers var startTokenOffset = 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)) return new MatchingResult(false, 0); 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)) { currentPart = lexer.PeekToken(tokenOffset); @@ -55,17 +47,19 @@ namespace ZoneCodeGenerator.Parsing.Matching.Matchers typename.Append(currentPart); } } - - var extensionLength = MatchTypenameExtension(context, tokenOffset); - while (extensionLength > 0) + else { - 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; - extensionLength = MatchTypenameExtension(context, tokenOffset); + tokenOffset += extensionLength; + extensionLength = MatchTypenameExtension(context, tokenOffset); + } } SetMatcherOutput(typename.ToString()); diff --git a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherTypenameTest.cs b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherTypenameTest.cs index 123bd186..8b59899c 100644 --- a/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherTypenameTest.cs +++ b/test/ZoneCodeGeneratorTests/Parsing/Matching/Matchers/MatcherTypenameTest.cs @@ -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 - { - "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 { - "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]