Skip to content

Commit

Permalink
implement bitfield parsing (#476)
Browse files Browse the repository at this point in the history
fixes #464
  • Loading branch information
WebFreak001 committed Nov 9, 2022
1 parent 7348c5f commit 94cc2ef
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 21 deletions.
15 changes: 14 additions & 1 deletion src/dparse/ast.d
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ abstract class ASTVisitor
/** */ void visit(const BreakStatement breakStatement) { breakStatement.accept(this); }
/** */ void visit(const BaseClass baseClass) { baseClass.accept(this); }
/** */ void visit(const BaseClassList baseClassList) { baseClassList.accept(this); }
/** */ void visit(const BitfieldWidth bitfieldWidth) { bitfieldWidth.accept(this); }
/** */ void visit(const CaseRangeStatement caseRangeStatement) { caseRangeStatement.accept(this); }
/** */ void visit(const CaseStatement caseStatement) { caseStatement.accept(this); }
/** */ void visit(const CastExpression castExpression) { castExpression.accept(this); }
Expand Down Expand Up @@ -1393,16 +1394,28 @@ final class Declarator : BaseNode
{
override void accept(ASTVisitor visitor) const
{
mixin (visitIfNotNull!(templateParameters, initializer));
mixin (visitIfNotNull!(templateParameters, bitfieldWidth, initializer));
}
/** */ Token name;
/** */ TemplateParameters templateParameters;
/** */ BitfieldWidth bitfieldWidth;
/** */ Initializer initializer;
/** */ TypeSuffix[] cstyle;
/** */ string comment;
mixin OpEquals;
}

///
final class BitfieldWidth : BaseNode
{
override void accept(ASTVisitor visitor) const
{
mixin (visitIfNotNull!(expression));
}
/** */ ExpressionNode expression;
mixin OpEquals;
}

///
final class DeclaratorIdentifierList : BaseNode
{
Expand Down
7 changes: 7 additions & 0 deletions src/dparse/astprinter.d
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ class XMLPrinter : ASTVisitor
output.writeln("<breakStatement label=\"", breakStatement.label.text, "\"/>");
}

override void visit(const BitfieldWidth bitfieldWidth)
{
output.writeln("<bitfieldWidth>");
bitfieldWidth.accept(this);
output.writeln("</bitfieldWidth>");
}

override void visit(const CaseRangeStatement caseRangeStatement)
{
output.writeln("<caseRangeStatement>");
Expand Down
15 changes: 15 additions & 0 deletions src/dparse/formatter.d
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,12 @@ class Formatter(Sink)
foreach(suffix; declarator.cstyle)
format(suffix);

if (declarator.bitfieldWidth)
{
put(declarator.name is Token.init ? ": " : " : ");
format(declarator.bitfieldWidth.expression);
}

if (declarator.templateParameters)
format(declarator.templateParameters);

Expand Down Expand Up @@ -4255,6 +4261,15 @@ do
}`
);
testFormatNode!(Declaration)(q{int i = throw new Ex();});
testFormatNode!(Declaration)(q{int i : 4 = 1;});
testFormatNode!(Declaration)(q{int i : (4 * 2) = 1;});
testFormatNode!(Declaration)(q{int i : (4 * 2);});
testFormatNode!(Declaration)(q{int i : coolTemplate!(4);});
testFormatNode!(Declaration)(q{int i : justAFunction(4);});
testFormatNode!(Declaration)(q{int i : 8;});
testFormatNode!(Declaration)(q{int x : 3, y : 2;});
testFormatNode!(Declaration)(q{int : 3, y : 2;});
testFormatNode!(Declaration)(q{int : 3, : 2;});
testFormatNode!(FunctionDeclaration)(q{void someFunction()
{
foo(a, throw b, c);
Expand Down
75 changes: 55 additions & 20 deletions src/dparse/parser.d
Original file line number Diff line number Diff line change
Expand Up @@ -2399,7 +2399,7 @@ class Parser
foreach (B; BasicTypes) { case B: }
type:
Type t = parseType();
if (t is null || !currentIs(tok!"identifier"))
if (t is null || !currentIsOneOf(tok!"identifier", tok!":"))
{
if (t)
error("no identifier for declarator");
Expand Down Expand Up @@ -2554,6 +2554,9 @@ class Parser
* $(GRAMMAR $(RULEDEF declarator):
* $(LITERAL Identifier)
* | $(LITERAL Identifier) $(LITERAL '=') $(RULE initializer)
* | $(LITERAL ':') $(RULE bitfieldWidth)
* | $(LITERAL Identifier) $(LITERAL ':') $(RULE bitfieldWidth)
* | $(LITERAL Identifier) $(LITERAL ':') $(RULE bitfieldWidth) $(LITERAL '=') $(RULE initializer)
* | $(LITERAL Identifier) $(RULE templateParameters) $(LITERAL '=') $(RULE initializer)
* ;)
*/
Expand All @@ -2562,28 +2565,44 @@ class Parser
mixin(traceEnterAndExit!(__FUNCTION__));
auto startIndex = index;
Declarator node = allocator.make!Declarator;
const id = expect(tok!"identifier");
mixin (nullCheck!`id`);
node.name = *id;
if (currentIs(tok!"[")) // dmd doesn't accept pointer after identifier
{
warn("C-style array declaration.");
StackBuffer typeSuffixes;
while (moreTokens() && currentIs(tok!"["))
if (!typeSuffixes.put(parseTypeSuffix()))
return null;
ownArray(node.cstyle, typeSuffixes);
}
if (currentIs(tok!"("))
if (currentIs(tok!":"))
{
mixin (nullCheck!`(node.templateParameters = parseTemplateParameters())`);
mixin(tokenCheck!"=");
mixin (nullCheck!`(node.initializer = parseInitializer())`);
advance();
mixin(parseNodeQ!(`node.bitfieldWidth`, `BitfieldWidth`));
}
else if (currentIs(tok!"="))
else
{
advance();
mixin(parseNodeQ!(`node.initializer`, `Initializer`));
const id = expect(tok!"identifier");
mixin (nullCheck!`id`);
node.name = *id;
if (currentIs(tok!"[")) // dmd doesn't accept pointer after identifier
{
warn("C-style array declaration.");
StackBuffer typeSuffixes;
while (moreTokens() && currentIs(tok!"["))
if (!typeSuffixes.put(parseTypeSuffix()))
return null;
ownArray(node.cstyle, typeSuffixes);
}
if (currentIs(tok!"("))
{
mixin (nullCheck!`(node.templateParameters = parseTemplateParameters())`);
mixin(tokenCheck!"=");
mixin (nullCheck!`(node.initializer = parseInitializer())`);
}
else
{
if (currentIs(tok!":"))
{
advance();
mixin(parseNodeQ!(`node.bitfieldWidth`, `BitfieldWidth`));
}
if (currentIs(tok!"="))
{
advance();
mixin(parseNodeQ!(`node.initializer`, `Initializer`));
}
}
}
node.tokens = tokens[startIndex .. index];
return node;
Expand Down Expand Up @@ -2619,6 +2638,22 @@ class Parser
return node;
}

/**
* Parses a BitfieldWidth
*
* $(GRAMMAR $(RULEDEF bitfieldWidth):
* $(RULE ternaryExpression)
* ;)
*/
BitfieldWidth parseBitfieldWidth()
{
auto node = allocator.make!BitfieldWidth;
auto startIndex = index;
mixin(parseNodeQ!(`node.expression`, `TernaryExpression`));
node.tokens = tokens[startIndex .. index];
return node;
}

/**
* Parses a DefaultStatement
*
Expand Down
4 changes: 4 additions & 0 deletions test/pass_files/bitfields.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
struct B
{
int x:3, y:2;
}

0 comments on commit 94cc2ef

Please sign in to comment.