1 /// Author: Aziz Köksal 2 /// License: GPL3 3 /// $(Maturity high) 4 module dil.parser.ImportParser; 5 6 import dil.parser.Parser; 7 import dil.lexer.Tables; 8 import dil.ast.Node, 9 dil.ast.Declarations, 10 dil.ast.Statements; 11 import dil.SourceText, 12 dil.Enums; 13 import common; 14 15 /// A light-weight parser which looks only for import statements 16 /// in the source text. 17 class ImportParser : Parser 18 { 19 this(SourceText srcText, LexerTables tables) 20 { 21 super(srcText, tables); 22 } 23 24 override CompoundDecl start() 25 { 26 auto decls = new CompoundDecl; 27 super.init(); 28 if (token.kind == T!"module") 29 decls ~= parseModuleDecl(); 30 while (token.kind != T!"EOF") 31 parseDeclarationDefinition(Protection.None); 32 return decls; 33 } 34 35 void parseDeclarationDefinitionsBlock(Protection prot) 36 { 37 skip(T!"{"); 38 while (token.kind != T!"}" && token.kind != T!"EOF") 39 parseDeclarationDefinition(prot); 40 skip(T!"}"); 41 } 42 43 void parseDeclarationsBlock(Protection prot) 44 { 45 switch (token.kind) 46 { 47 case T!"{": 48 parseDeclarationDefinitionsBlock(prot); 49 break; 50 case T!":": 51 nT(); 52 while (token.kind != T!"}" && token.kind != T!"EOF") 53 parseDeclarationDefinition(prot); 54 break; 55 default: 56 parseDeclarationDefinition(prot); 57 } 58 } 59 60 bool skipToClosing(TOK opening, TOK closing) 61 { 62 alias next = token; 63 uint level = 1; 64 while (1) 65 { 66 lexer.peek(next); 67 if (next.kind == opening) 68 ++level; 69 else if (next.kind == closing && --level == 0) 70 return true; 71 else if (next.kind == T!"EOF") 72 break; 73 } 74 return false; 75 } 76 77 void skipToTokenAfterClosingParen() 78 { 79 skipToClosing(T!"(", T!")"); 80 nT(); 81 } 82 83 void skipToTokenAfterClosingBrace() 84 { 85 skipToClosing(T!"{", T!"}"); 86 nT(); 87 } 88 89 void skip(TOK tok) 90 { 91 token.kind == tok && nT(); 92 } 93 94 void parseProtectionAttribute() 95 { 96 Protection prot; 97 switch (token.kind) 98 { 99 case T!"private": 100 prot = Protection.Private; break; 101 case T!"package": 102 prot = Protection.Package; break; 103 case T!"protected": 104 prot = Protection.Protected; break; 105 case T!"public": 106 prot = Protection.Public; break; 107 case T!"export": 108 prot = Protection.Export; break; 109 default: 110 assert(0); 111 } 112 nT(); 113 parseDeclarationsBlock(prot); 114 } 115 116 void parseDeclarationDefinition(Protection prot) 117 { 118 switch (token.kind) 119 { 120 case T!"align": 121 nT(); 122 if (token.kind == T!"(") 123 nT(), nT(), nT(); // ( Integer ) 124 parseDeclarationsBlock(prot); 125 break; 126 case T!"pragma": 127 nT(); 128 skipToTokenAfterClosingParen(); 129 parseDeclarationsBlock(prot); 130 break; 131 case T!"export", 132 T!"private", 133 T!"package", 134 T!"protected", 135 T!"public": 136 parseProtectionAttribute(); 137 break; 138 // Storage classes 139 case T!"extern": 140 nT(); 141 token.kind == T!"(" && skipToTokenAfterClosingParen(); 142 parseDeclarationsBlock(prot); 143 break; 144 case T!"const": 145 version(D2) 146 { 147 if (peekNext() == T!"(") 148 goto case_Declaration; 149 } 150 goto case; 151 case T!"override", 152 T!"deprecated", 153 T!"abstract", 154 T!"synchronized", 155 // T!"static", 156 T!"final", 157 T!"auto", 158 T!"scope": 159 case_StaticAttribute: 160 case_InvariantAttribute: 161 nT(); 162 parseDeclarationsBlock(prot); 163 break; 164 // End of storage classes. 165 case T!"alias", T!"typedef": 166 nT(); 167 goto case_Declaration; 168 case T!"static": 169 switch (peekNext()) 170 { 171 case T!"import": 172 goto case_Import; 173 case T!"this": 174 nT(), nT(); // static this 175 skipToTokenAfterClosingParen(); 176 skipFunctionBody(); 177 break; 178 case T!"~": 179 nT(), nT(), nT(), nT(), nT(); // static ~ this ( ) 180 skipFunctionBody(); 181 break; 182 case T!"if": 183 nT(), nT(); 184 skipToTokenAfterClosingParen(); 185 parseDeclarationsBlock(prot); 186 if (token.kind == T!"else") 187 nT(), parseDeclarationsBlock(prot); 188 break; 189 case T!"assert": 190 nT(), nT(); // static assert 191 skipToTokenAfterClosingParen(); 192 skip(T!";"); 193 break; 194 default: 195 goto case_StaticAttribute; 196 } 197 break; 198 case T!"import": 199 case_Import: 200 auto decl = parseImportDecl(); 201 decl.setProtection(prot); // Set the protection attribute. 202 imports ~= decl.to!(ImportDecl); 203 break; 204 case T!"enum": 205 nT(); 206 token.kind == T!"Identifier" && nT(); 207 if (token.kind == T!":") 208 { 209 nT(); 210 while (token.kind != T!"{" && token.kind != T!"EOF") 211 nT(); 212 } 213 if (token.kind == T!";") 214 nT(); 215 else 216 skipToTokenAfterClosingBrace(); 217 break; 218 case T!"class", T!"interface": 219 nT(), skip(T!"Identifier"); // class Identifier 220 token.kind == T!"(" && skipToTokenAfterClosingParen(); // Skip template params. 221 if (token.kind == T!":") 222 { // BaseClasses 223 nT(); 224 while (token.kind != T!"{" && token.kind != T!"EOF") 225 if (token.kind == T!"(") // Skip ( tokens... ) 226 skipToTokenAfterClosingParen(); 227 else 228 nT(); 229 } 230 if (token.kind == T!";") 231 nT(); 232 else 233 parseDeclarationDefinitionsBlock(Protection.None); 234 break; 235 case T!"struct", T!"union": 236 nT(); skip(T!"Identifier"); 237 token.kind == T!"(" && skipToTokenAfterClosingParen(); 238 if (token.kind == T!";") 239 nT(); 240 else 241 parseDeclarationDefinitionsBlock(Protection.None); 242 break; 243 case T!"~": 244 nT(); 245 goto case; 246 case T!"this": 247 nT(); nT(); nT(); // this ( ) 248 skipFunctionBody(); 249 break; 250 case T!"invariant": 251 version(D2) 252 { 253 auto next = peekAfter(token); 254 if (next.kind == T!"(") 255 { 256 if (peekAfter(next).kind != T!")") 257 goto case_Declaration; 258 } 259 else 260 goto case_InvariantAttribute; 261 } 262 nT(); 263 token.kind == T!"(" && skipToTokenAfterClosingParen(); 264 skipFunctionBody(); 265 break; 266 case T!"unittest": 267 nT(); 268 skipFunctionBody(); 269 break; 270 case T!"debug": 271 nT(); 272 if (token.kind == T!"=") 273 { 274 nT(), nT(), nT(); // = Condition ; 275 break; 276 } 277 if (token.kind == T!"(") 278 nT(), nT(), nT(); // ( Condition ) 279 parseDeclarationsBlock(prot); 280 if (token.kind == T!"else") 281 nT(), parseDeclarationsBlock(prot); 282 break; 283 case T!"version": 284 nT(); 285 if (token.kind == T!"=") 286 { 287 nT(), nT(), nT(); // = Condition ; 288 break; 289 } 290 nT(), nT(), nT(); // ( Condition ) 291 parseDeclarationsBlock(prot); 292 if (token.kind == T!"else") 293 nT(), parseDeclarationsBlock(prot); 294 break; 295 case T!"template": 296 nT(); 297 skip(T!"Identifier"); 298 skipToTokenAfterClosingParen(); 299 parseDeclarationDefinitionsBlock(Protection.None); 300 break; 301 case T!"new": 302 nT(); 303 skipToTokenAfterClosingParen(); 304 skipFunctionBody(); 305 break; 306 case T!"delete": 307 nT(); 308 skipToTokenAfterClosingParen(); 309 skipFunctionBody(); 310 break; 311 case T!"mixin": 312 while (token.kind != T!";" && token.kind != T!"EOF") 313 if (token.kind == T!"(") 314 skipToTokenAfterClosingParen(); 315 else 316 nT(); 317 skip(T!";"); 318 break; 319 case T!";": 320 nT(); 321 break; 322 // Declaration 323 case T!"Identifier", T!".", T!"typeof": 324 case_Declaration: 325 while (token.kind != T!";" && token.kind != T!"EOF") 326 if (token.kind == T!"(") 327 skipToTokenAfterClosingParen(); 328 else if (token.kind == T!"{") 329 skipToTokenAfterClosingBrace(); 330 else 331 nT(); 332 skip(T!";"); 333 break; 334 default: 335 if (token.isIntegralType) 336 goto case_Declaration; 337 nT(); 338 } 339 } 340 341 void skipFunctionBody() 342 { 343 while (1) 344 { 345 switch (token.kind) 346 { 347 case T!"{": 348 skipToTokenAfterClosingBrace(); 349 break; 350 case T!";": 351 nT(); 352 break; 353 case T!"in": 354 nT(); 355 skipToTokenAfterClosingBrace(); 356 continue; 357 case T!"out": 358 nT(); 359 if (token.kind == T!"(") 360 nT(), nT(), nT(); // ( Identifier ) 361 skipToTokenAfterClosingBrace(); 362 continue; 363 case T!"body": 364 nT(); 365 goto case T!"{"; 366 default: 367 } 368 break; // Exit loop. 369 } 370 } 371 }