Skip to content

Commit 594ac83

Browse files
Allow keywords as identifiers in extern(C) blocks for ImportC compatibility
1 parent 6b0a901 commit 594ac83

1 file changed

Lines changed: 56 additions & 19 deletions

File tree

src/dparse/parser.d

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ Module parseModule(F)(const(Token)[] tokens, string fileName, RollbackAllocator*
118118
*/
119119
class Parser
120120
{
121+
/// Is it a interface file for a C source code
122+
bool importC;
123+
/// Depth of extern(C) blocks we're currently inside
124+
int externCDepth;
125+
126+
bool isInExternC() const pure nothrow @safe @nogc
127+
{
128+
return importC || externCDepth > 0;
129+
}
130+
121131
/**
122132
* Parses an AddExpression.
123133
*
@@ -2293,27 +2303,44 @@ class Parser
22932303
warn("Empty declaration");
22942304
advance();
22952305
break;
2296-
case tok!"{":
2297-
if (node.attributes.empty)
2306+
case tok!"{":
2307+
if (node.attributes.empty)
2308+
{
2309+
error("declaration expected instead of `{`");
2310+
return null;
2311+
}
2312+
// Check if we're in an extern(C) block
2313+
bool isExternC = false;
2314+
foreach (attr; node.attributes)
2315+
{
2316+
if (attr.linkageAttribute !is null &&
2317+
attr.linkageAttribute.identifier.text == "C")
22982318
{
2299-
error("declaration expected instead of `{`");
2300-
return null;
2319+
isExternC = true;
2320+
break;
23012321
}
2302-
advance();
2303-
alias declarations = attributes;
2304-
declarations.clear();
2305-
while (moreTokens() && !currentIs(tok!"}"))
2322+
}
2323+
if (isExternC)
2324+
externCDepth++;
2325+
advance();
2326+
alias declarations = attributes;
2327+
declarations.clear();
2328+
while (moreTokens() && !currentIs(tok!"}"))
2329+
{
2330+
auto c = allocator.setCheckpoint();
2331+
if (!declarations.put(parseDeclaration(strict, false, inTemplateDeclaration)))
23062332
{
2307-
auto c = allocator.setCheckpoint();
2308-
if (!declarations.put(parseDeclaration(strict, false, inTemplateDeclaration)))
2309-
{
2310-
allocator.rollback(c);
2311-
return null;
2312-
}
2333+
allocator.rollback(c);
2334+
if (isExternC)
2335+
externCDepth--;
2336+
return null;
23132337
}
2314-
ownArray(node.declarations, declarations);
2315-
mixin(tokenCheck!"}");
2316-
break;
2338+
}
2339+
if (isExternC)
2340+
externCDepth--;
2341+
ownArray(node.declarations, declarations);
2342+
mixin(tokenCheck!"}");
2343+
break;
23172344
case tok!"alias":
23182345
if (startsWith(tok!"alias", tok!"identifier", tok!"this"))
23192346
mixin(parseNodeQ!(`node.aliasThisDeclaration`, `AliasThisDeclaration`));
@@ -2481,7 +2508,7 @@ class Parser
24812508
foreach (B; BasicTypes) { case B: }
24822509
type:
24832510
Type t = parseType();
2484-
if (t is null || !currentIsOneOf(tok!"identifier", tok!":"))
2511+
if (t is null || !(currentIs(tok!"identifier") || (isInExternC() && isKeyword(current.type)) || currentIs(tok!":")))
24852512
{
24862513
if (t)
24872514
error("no identifier for declarator");
@@ -2654,7 +2681,17 @@ class Parser
26542681
}
26552682
else
26562683
{
2657-
const id = expect(tok!"identifier");
2684+
const(Token)* id;
2685+
if (currentIs(tok!"identifier") || (isInExternC() && isKeyword(current.type)))
2686+
id = &tokens[index++];
2687+
else
2688+
{
2689+
error("Expected identifier instead of " ~ (index < tokens.length
2690+
? (tokens[index].text is null ? "`" ~ str(tokens[index].type) ~ "`"
2691+
: str(tokens[index].type) ~ " `" ~ tokens[index].text ~ "`")
2692+
: "EOF"));
2693+
return null;
2694+
}
26582695
mixin (nullCheck!`id`);
26592696
node.name = *id;
26602697
if (currentIs(tok!"[")) // dmd doesn't accept pointer after identifier

0 commit comments

Comments
 (0)