Skip to content

Commit 94cc2ef

Browse files
authored
implement bitfield parsing (#476)
fixes #464
1 parent 7348c5f commit 94cc2ef

File tree

5 files changed

+95
-21
lines changed

5 files changed

+95
-21
lines changed

src/dparse/ast.d

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ abstract class ASTVisitor
195195
/** */ void visit(const BreakStatement breakStatement) { breakStatement.accept(this); }
196196
/** */ void visit(const BaseClass baseClass) { baseClass.accept(this); }
197197
/** */ void visit(const BaseClassList baseClassList) { baseClassList.accept(this); }
198+
/** */ void visit(const BitfieldWidth bitfieldWidth) { bitfieldWidth.accept(this); }
198199
/** */ void visit(const CaseRangeStatement caseRangeStatement) { caseRangeStatement.accept(this); }
199200
/** */ void visit(const CaseStatement caseStatement) { caseStatement.accept(this); }
200201
/** */ void visit(const CastExpression castExpression) { castExpression.accept(this); }
@@ -1393,16 +1394,28 @@ final class Declarator : BaseNode
13931394
{
13941395
override void accept(ASTVisitor visitor) const
13951396
{
1396-
mixin (visitIfNotNull!(templateParameters, initializer));
1397+
mixin (visitIfNotNull!(templateParameters, bitfieldWidth, initializer));
13971398
}
13981399
/** */ Token name;
13991400
/** */ TemplateParameters templateParameters;
1401+
/** */ BitfieldWidth bitfieldWidth;
14001402
/** */ Initializer initializer;
14011403
/** */ TypeSuffix[] cstyle;
14021404
/** */ string comment;
14031405
mixin OpEquals;
14041406
}
14051407

1408+
///
1409+
final class BitfieldWidth : BaseNode
1410+
{
1411+
override void accept(ASTVisitor visitor) const
1412+
{
1413+
mixin (visitIfNotNull!(expression));
1414+
}
1415+
/** */ ExpressionNode expression;
1416+
mixin OpEquals;
1417+
}
1418+
14061419
///
14071420
final class DeclaratorIdentifierList : BaseNode
14081421
{

src/dparse/astprinter.d

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,13 @@ class XMLPrinter : ASTVisitor
178178
output.writeln("<breakStatement label=\"", breakStatement.label.text, "\"/>");
179179
}
180180

181+
override void visit(const BitfieldWidth bitfieldWidth)
182+
{
183+
output.writeln("<bitfieldWidth>");
184+
bitfieldWidth.accept(this);
185+
output.writeln("</bitfieldWidth>");
186+
}
187+
181188
override void visit(const CaseRangeStatement caseRangeStatement)
182189
{
183190
output.writeln("<caseRangeStatement>");

src/dparse/formatter.d

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,12 @@ class Formatter(Sink)
10431043
foreach(suffix; declarator.cstyle)
10441044
format(suffix);
10451045

1046+
if (declarator.bitfieldWidth)
1047+
{
1048+
put(declarator.name is Token.init ? ": " : " : ");
1049+
format(declarator.bitfieldWidth.expression);
1050+
}
1051+
10461052
if (declarator.templateParameters)
10471053
format(declarator.templateParameters);
10481054

@@ -4255,6 +4261,15 @@ do
42554261
}`
42564262
);
42574263
testFormatNode!(Declaration)(q{int i = throw new Ex();});
4264+
testFormatNode!(Declaration)(q{int i : 4 = 1;});
4265+
testFormatNode!(Declaration)(q{int i : (4 * 2) = 1;});
4266+
testFormatNode!(Declaration)(q{int i : (4 * 2);});
4267+
testFormatNode!(Declaration)(q{int i : coolTemplate!(4);});
4268+
testFormatNode!(Declaration)(q{int i : justAFunction(4);});
4269+
testFormatNode!(Declaration)(q{int i : 8;});
4270+
testFormatNode!(Declaration)(q{int x : 3, y : 2;});
4271+
testFormatNode!(Declaration)(q{int : 3, y : 2;});
4272+
testFormatNode!(Declaration)(q{int : 3, : 2;});
42584273
testFormatNode!(FunctionDeclaration)(q{void someFunction()
42594274
{
42604275
foo(a, throw b, c);

src/dparse/parser.d

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2399,7 +2399,7 @@ class Parser
23992399
foreach (B; BasicTypes) { case B: }
24002400
type:
24012401
Type t = parseType();
2402-
if (t is null || !currentIs(tok!"identifier"))
2402+
if (t is null || !currentIsOneOf(tok!"identifier", tok!":"))
24032403
{
24042404
if (t)
24052405
error("no identifier for declarator");
@@ -2554,6 +2554,9 @@ class Parser
25542554
* $(GRAMMAR $(RULEDEF declarator):
25552555
* $(LITERAL Identifier)
25562556
* | $(LITERAL Identifier) $(LITERAL '=') $(RULE initializer)
2557+
* | $(LITERAL ':') $(RULE bitfieldWidth)
2558+
* | $(LITERAL Identifier) $(LITERAL ':') $(RULE bitfieldWidth)
2559+
* | $(LITERAL Identifier) $(LITERAL ':') $(RULE bitfieldWidth) $(LITERAL '=') $(RULE initializer)
25572560
* | $(LITERAL Identifier) $(RULE templateParameters) $(LITERAL '=') $(RULE initializer)
25582561
* ;)
25592562
*/
@@ -2562,28 +2565,44 @@ class Parser
25622565
mixin(traceEnterAndExit!(__FUNCTION__));
25632566
auto startIndex = index;
25642567
Declarator node = allocator.make!Declarator;
2565-
const id = expect(tok!"identifier");
2566-
mixin (nullCheck!`id`);
2567-
node.name = *id;
2568-
if (currentIs(tok!"[")) // dmd doesn't accept pointer after identifier
2569-
{
2570-
warn("C-style array declaration.");
2571-
StackBuffer typeSuffixes;
2572-
while (moreTokens() && currentIs(tok!"["))
2573-
if (!typeSuffixes.put(parseTypeSuffix()))
2574-
return null;
2575-
ownArray(node.cstyle, typeSuffixes);
2576-
}
2577-
if (currentIs(tok!"("))
2568+
if (currentIs(tok!":"))
25782569
{
2579-
mixin (nullCheck!`(node.templateParameters = parseTemplateParameters())`);
2580-
mixin(tokenCheck!"=");
2581-
mixin (nullCheck!`(node.initializer = parseInitializer())`);
2570+
advance();
2571+
mixin(parseNodeQ!(`node.bitfieldWidth`, `BitfieldWidth`));
25822572
}
2583-
else if (currentIs(tok!"="))
2573+
else
25842574
{
2585-
advance();
2586-
mixin(parseNodeQ!(`node.initializer`, `Initializer`));
2575+
const id = expect(tok!"identifier");
2576+
mixin (nullCheck!`id`);
2577+
node.name = *id;
2578+
if (currentIs(tok!"[")) // dmd doesn't accept pointer after identifier
2579+
{
2580+
warn("C-style array declaration.");
2581+
StackBuffer typeSuffixes;
2582+
while (moreTokens() && currentIs(tok!"["))
2583+
if (!typeSuffixes.put(parseTypeSuffix()))
2584+
return null;
2585+
ownArray(node.cstyle, typeSuffixes);
2586+
}
2587+
if (currentIs(tok!"("))
2588+
{
2589+
mixin (nullCheck!`(node.templateParameters = parseTemplateParameters())`);
2590+
mixin(tokenCheck!"=");
2591+
mixin (nullCheck!`(node.initializer = parseInitializer())`);
2592+
}
2593+
else
2594+
{
2595+
if (currentIs(tok!":"))
2596+
{
2597+
advance();
2598+
mixin(parseNodeQ!(`node.bitfieldWidth`, `BitfieldWidth`));
2599+
}
2600+
if (currentIs(tok!"="))
2601+
{
2602+
advance();
2603+
mixin(parseNodeQ!(`node.initializer`, `Initializer`));
2604+
}
2605+
}
25872606
}
25882607
node.tokens = tokens[startIndex .. index];
25892608
return node;
@@ -2619,6 +2638,22 @@ class Parser
26192638
return node;
26202639
}
26212640

2641+
/**
2642+
* Parses a BitfieldWidth
2643+
*
2644+
* $(GRAMMAR $(RULEDEF bitfieldWidth):
2645+
* $(RULE ternaryExpression)
2646+
* ;)
2647+
*/
2648+
BitfieldWidth parseBitfieldWidth()
2649+
{
2650+
auto node = allocator.make!BitfieldWidth;
2651+
auto startIndex = index;
2652+
mixin(parseNodeQ!(`node.expression`, `TernaryExpression`));
2653+
node.tokens = tokens[startIndex .. index];
2654+
return node;
2655+
}
2656+
26222657
/**
26232658
* Parses a DefaultStatement
26242659
*

test/pass_files/bitfields.d

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
struct B
2+
{
3+
int x:3, y:2;
4+
}

0 commit comments

Comments
 (0)