Skip to content

Commit

Permalink
(#72) Parser: typedef name usage & hacky hacks
Browse files Browse the repository at this point in the history
  • Loading branch information
ForNeVeR committed Feb 16, 2022
1 parent 189e107 commit 80c331e
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ obj/
*.dll
*.exe
*.runtimeconfig.json
*.received.txt
*.user
9 changes: 8 additions & 1 deletion Cesium.Ast/Declarations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public record StructOrUnionSpecifier(
string? Identifier,
ImmutableArray<StructDeclaration> StructDeclarations) : ITypeSpecifier;

public record NamedTypeSpecifier(string TypeDefName) : ITypeSpecifier;

// 6.7.2.1 Structure and union specifiers
public enum ComplexTypeKind
{
Expand Down Expand Up @@ -61,8 +63,13 @@ public interface IDirectDeclarator
{
IDirectDeclarator? Base { get; }
}
public record IdentifierDirectDeclarator(string Identifier) : IDirectDeclarator
public record IdentifierDirectDeclarator(string? Identifier) : IDirectDeclarator
{
// HACK: This property is only mutable from CParser.TypeDefNameIdentifierHack.
// This requirement is caused by an issue https://github.com/LanguageDev/Yoakke/issues/138
// TODO: Eventually, we should get rid of that.
public string? Identifier { get; set; } = Identifier;

public IDirectDeclarator? Base => null;
}
public record ArrayDirectDeclarator(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
System.Int32 <Module>::main()
Locals:
System.Int32 V_0
IL_0000: ldc.i4 0
IL_0005: ret
2 changes: 2 additions & 0 deletions Cesium.CodeGen.Tests/CodeGenMethodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ public void VarArgMainDoesNotCompile2() => DoesNotCompile(

[Fact] public Task MultiDeclaration() => DoTest("int main() { int x = 0, y = 2 + 2; }");

[Fact] public Task UninitializedVariable() => DoTest("int main() { int x; return 0; }");

[Fact]
public Task Arithmetic() => DoTest(@"int main(void)
{
Expand Down
4 changes: 4 additions & 0 deletions Cesium.CodeGen.Tests/CodeGenTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ void foo(void)

[Fact]
public Task SingleFieldStructDefinition() => DoTest("typedef struct { int x; } foo;");

[Fact]
public Task TypeDefStructUsage() => DoTest(@"typedef struct { int x; } foo;
int main(void) { foo x; return 0; }");
}
4 changes: 4 additions & 0 deletions Cesium.Parser.Tests/ParserTests/FullParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,8 @@ public Task PrefixIncrementTest() => DoTest(@"int main()

[Fact]
public Task DoubleTypeDef() => DoTest(@"typedef struct { int x; } foo, bar;");

[Fact]
public Task TypeDefStructUsage() => DoTest(@"typedef struct { int x; } foo;
int main(void) { foo x; return 0; }");
}
74 changes: 66 additions & 8 deletions Cesium.Parser/CParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,19 @@ private static Expression MakeAssignmentExpression(
private static Declaration MakeDeclaration(
DeclarationSpecifiers specifiers,
InitDeclaratorList? initDeclarators,
IToken _) => new(specifiers, initDeclarators);
IToken _)
{
var firstInitDeclarator = initDeclarators?.FirstOrDefault();
if (firstInitDeclarator != null)
{
var firstDeclarator = firstInitDeclarator.Declarator;
(specifiers, firstDeclarator) = TypeDefNameIdentifierHack(specifiers, firstDeclarator);
firstInitDeclarator = firstInitDeclarator with { Declarator = firstDeclarator };
initDeclarators = initDeclarators!.Value.RemoveAt(0).Insert(0, firstInitDeclarator);
}

return new(specifiers, initDeclarators);
}

[Rule("declaration_specifiers: storage_class_specifier declaration_specifiers?")]
[Rule("declaration_specifiers: type_specifier declaration_specifiers?")]
Expand Down Expand Up @@ -238,7 +250,10 @@ private static ITypeSpecifier MakeComplexTypeSpecifier(StructOrUnionSpecifier st
structOrUnionSpecifier;

// TODO: [Rule("type_specifier: enum_specifier")]
// TODO: [Rule("type_specifier: typedef_name")]

[Rule("type_specifier: typedef_name")]
private static ITypeSpecifier MakeNamedTypeSpecifier(IToken typeDefName) =>
new NamedTypeSpecifier(typeDefName.Text);

// 6.7.2.1 Structure and union specifiers

Expand Down Expand Up @@ -315,9 +330,9 @@ private static StructDeclaratorList MakeStructDeclaratorList(
private static Declarator MakeDeclarator(Pointer? pointer, IDirectDeclarator directDeclarator) =>
new(pointer, directDeclarator);

[Rule("direct_declarator: Identifier")]
private static IDirectDeclarator MakeDirectDeclarator(ICToken identifier) =>
new IdentifierDirectDeclarator(identifier.Text);
[Rule("direct_declarator: Identifier?")]
private static IDirectDeclarator MakeDirectDeclarator(ICToken? identifier) =>
new IdentifierDirectDeclarator(identifier?.Text);

// TODO: direct_declarator: ( declarator )

Expand Down Expand Up @@ -378,7 +393,11 @@ private static ParameterList MakeParameterList(ParameterList prev, ICToken _, Pa
[Rule("parameter_declaration: declaration_specifiers declarator")]
private static ParameterDeclaration MakeParameterTypeList(
DeclarationSpecifiers specifiers,
Declarator declarator) => new(specifiers, declarator);
Declarator declarator)
{
(specifiers, declarator) = TypeDefNameIdentifierHack(specifiers, declarator);
return new(specifiers, declarator);
}

[Rule("parameter_declaration: declaration_specifiers abstract_declarator?")]
private static ParameterDeclaration MakeParameterTypeList(
Expand Down Expand Up @@ -442,7 +461,9 @@ private static IDirectAbstractDeclarator MakeDirectAbstractDeclarator(
// direct-abstract-declarator? [ * ]
// direct-abstract-declarator? ( parameter-type-list? )

// TODO: 6.7.8 Type definitions
// 6.7.8 Type definitions
[Rule("typedef_name: Identifier")]
private static IToken MakeTypeDefName(IToken identifier) => identifier;

// 6.7.9 Initialization

Expand Down Expand Up @@ -533,7 +554,11 @@ private static FunctionDefinition MakeFunctionDefinition(
DeclarationSpecifiers specifiers,
Declarator declarator,
ImmutableArray<Declaration>? declarationList,
CompoundStatement statement) => new(specifiers, declarator, declarationList, statement);
CompoundStatement statement)
{
(specifiers, declarator) = TypeDefNameIdentifierHack(specifiers, declarator);
return new(specifiers, declarator, declarationList, statement);
}

[Rule("declaration_list: declaration")]
private static ImmutableArray<Declaration> MakeDeclarationList(Declaration declaration) =>
Expand Down Expand Up @@ -608,4 +633,37 @@ private static ImmutableArray<Declaration> MakeDeclarationList(
// TODO: 6.10.7 Null directive
// TODO: 6.10.8 Predefined macro names
// TODO: 6.10.9 Pragma operator

// HACK: The existence of this method is caused caused by an issue https://github.com/LanguageDev/Yoakke/issues/138
// As no simple workaround exist, we have to do ugly manipulations in parser and AST to support this.
// TODO: Eventually, I hope we'll get rid of that.
private static (DeclarationSpecifiers, Declarator) TypeDefNameIdentifierHack(
DeclarationSpecifiers specifiers,
Declarator declarator)
{
var directDeclarator = declarator.DirectDeclarator;
IdentifierDirectDeclarator? identifierDeclarator = null;
while (directDeclarator != null && identifierDeclarator == null)
{
identifierDeclarator = directDeclarator as IdentifierDirectDeclarator;
directDeclarator = directDeclarator.Base;
}

if (identifierDeclarator is { Identifier: null })
{
var lastSpecifier = specifiers.LastOrDefault();
if (lastSpecifier is NamedTypeSpecifier { TypeDefName: var tn })
{
specifiers = specifiers.RemoveAt(specifiers.Length - 1);
identifierDeclarator.Identifier = tn;
}
}

if (identifierDeclarator is { Identifier: null })
throw new NotSupportedException(
"THIS IS A BUG! It is caused by a hack in parsing for the sake of `typedef_name`." +
$" Please report to the Cesium maintainers: [{string.Join(",", specifiers)}] {declarator}.");

return (specifiers, declarator);
}
}

0 comments on commit 80c331e

Please sign in to comment.