@@ -118,6 +118,16 @@ Module parseModule(F)(const(Token)[] tokens, string fileName, RollbackAllocator*
118118 */
119119class 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