This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
00001 //===-- parser/ParseStmt.cpp ---------------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2008-2010, Stephen Wilson 00006 // 00007 //===----------------------------------------------------------------------===// 00008 00009 #include "comma/basic/Pragmas.h" 00010 #include "comma/parser/Parser.h" 00011 00012 #include <cassert> 00013 #include <cstring> 00014 00015 using namespace comma; 00016 00017 Node Parser::parseStatement() 00018 { 00019 Node node = getInvalidNode(); 00020 00021 switch (currentTokenCode()) { 00022 00023 default: 00024 if (assignmentFollows()) 00025 node = parseAssignmentStmt(); 00026 else if (blockStmtFollows()) 00027 node = parseBlockStmt(); 00028 else 00029 node = parseProcedureCallStatement(); 00030 break; 00031 00032 case Lexer::TKN_IF: 00033 node = parseIfStmt(); 00034 break; 00035 00036 case Lexer::TKN_WHILE: 00037 node = parseWhileStmt(); 00038 break; 00039 00040 case Lexer::TKN_FOR: 00041 node = parseForStmt(); 00042 break; 00043 00044 case Lexer::TKN_LOOP: 00045 node = parseLoopStmt(); 00046 break; 00047 00048 case Lexer::TKN_RETURN: 00049 node = parseReturnStmt(); 00050 break; 00051 00052 case Lexer::TKN_RAISE: 00053 node = parseRaiseStmt(); 00054 break; 00055 00056 case Lexer::TKN_PRAGMA: 00057 node = parsePragmaStmt(); 00058 break; 00059 00060 case Lexer::TKN_NULL: 00061 node = client.acceptNullStmt(ignoreToken()); 00062 break; 00063 } 00064 00065 if (!requireToken(Lexer::TKN_SEMI)) 00066 seekAndConsumeToken(Lexer::TKN_SEMI); 00067 return node; 00068 } 00069 00070 Node Parser::parseProcedureCallStatement() 00071 { 00072 Node name = parseName(Statement_Name); 00073 if (name.isValid()) 00074 return client.acceptProcedureCall(name); 00075 return getInvalidNode(); 00076 } 00077 00078 Node Parser::parseReturnStmt() 00079 { 00080 assert(currentTokenIs(Lexer::TKN_RETURN)); 00081 00082 Location loc = ignoreToken(); 00083 00084 if (currentTokenIs(Lexer::TKN_SEMI)) 00085 return client.acceptEmptyReturnStmt(loc); 00086 00087 Node expr = parseExpr(); 00088 00089 if (expr.isValid()) 00090 return client.acceptReturnStmt(loc, expr); 00091 00092 seekSemi(); 00093 return getInvalidNode(); 00094 } 00095 00096 Node Parser::parseAssignmentStmt() 00097 { 00098 assert(assignmentFollows()); 00099 00100 Node target = parseName(); 00101 00102 if (target.isInvalid()) { 00103 seekSemi(); 00104 return getInvalidNode(); 00105 } 00106 00107 ignoreToken(); // Ignore the `:='. 00108 00109 Node value = parseExpr(); 00110 00111 if (value.isValid()) 00112 return client.acceptAssignmentStmt(target, value); 00113 else { 00114 seekSemi(); 00115 return getInvalidNode(); 00116 } 00117 } 00118 00119 Node Parser::parseIfStmt() 00120 { 00121 assert(currentTokenIs(Lexer::TKN_IF)); 00122 00123 Location loc = ignoreToken(); 00124 Node condition = parseExpr(); 00125 NodeVector stmts; 00126 00127 if (condition.isInvalid() || !requireToken(Lexer::TKN_THEN)) { 00128 seekEndIf(); 00129 return getInvalidNode(); 00130 } 00131 00132 do { 00133 Node stmt = parseStatement(); 00134 if (stmt.isValid()) 00135 stmts.push_back(stmt); 00136 } while (!currentTokenIs(Lexer::TKN_END) && 00137 !currentTokenIs(Lexer::TKN_ELSE) && 00138 !currentTokenIs(Lexer::TKN_ELSIF) && 00139 !currentTokenIs(Lexer::TKN_EOT)); 00140 00141 Node result = client.acceptIfStmt(loc, condition, stmts); 00142 if (result.isInvalid()) { 00143 seekEndIf(); 00144 return getInvalidNode(); 00145 } 00146 00147 while (currentTokenIs(Lexer::TKN_ELSIF)) { 00148 loc = ignoreToken(); 00149 condition = parseExpr(); 00150 if (condition.isInvalid() || !requireToken(Lexer::TKN_THEN)) { 00151 seekEndIf(); 00152 return getInvalidNode(); 00153 } 00154 00155 stmts.clear(); 00156 do { 00157 Node stmt = parseStatement(); 00158 if (stmt.isValid()) 00159 stmts.push_back(stmt); 00160 } while (!currentTokenIs(Lexer::TKN_END) && 00161 !currentTokenIs(Lexer::TKN_ELSE) && 00162 !currentTokenIs(Lexer::TKN_ELSIF) && 00163 !currentTokenIs(Lexer::TKN_EOT)); 00164 00165 result = client.acceptElsifStmt(loc, result, condition, stmts); 00166 00167 if (result.isInvalid()) { 00168 seekEndIf(); 00169 return getInvalidNode(); 00170 } 00171 } 00172 00173 if (currentTokenIs(Lexer::TKN_ELSE)) { 00174 loc = ignoreToken(); 00175 stmts.clear(); 00176 do { 00177 Node stmt = parseStatement(); 00178 if (stmt.isValid()) 00179 stmts.push_back(stmt); 00180 } while (!currentTokenIs(Lexer::TKN_END) && 00181 !currentTokenIs(Lexer::TKN_EOT)); 00182 00183 result = client.acceptElseStmt(loc, result, stmts); 00184 } 00185 00186 if (!requireToken(Lexer::TKN_END) || !requireToken(Lexer::TKN_IF)) 00187 return getInvalidNode(); 00188 00189 return Node(result); 00190 } 00191 00192 Node Parser::parseBlockStmt() 00193 { 00194 Location loc = currentLocation(); 00195 IdentifierInfo *label = 0; 00196 00197 assert(blockStmtFollows()); 00198 00199 // Parse this blocks label, if available. 00200 if (currentTokenIs(Lexer::TKN_IDENTIFIER)) { 00201 label = parseIdentifier(); 00202 ignoreToken(); // Ignore the ":". 00203 } 00204 00205 Node block = client.beginBlockStmt(loc, label); 00206 00207 if (reduceToken(Lexer::TKN_DECLARE)) { 00208 while (!currentTokenIs(Lexer::TKN_BEGIN) && 00209 !currentTokenIs(Lexer::TKN_EOT)) { 00210 parseDeclaration(); 00211 requireToken(Lexer::TKN_SEMI); 00212 } 00213 } 00214 00215 if (!requireToken(Lexer::TKN_BEGIN)) { 00216 client.endBlockStmt(block); 00217 seekAndConsumeEndTag(label); 00218 return getInvalidNode(); 00219 } 00220 00221 // Consume each statement in the block. 00222 while (!currentTokenIs(Lexer::TKN_END) && 00223 !currentTokenIs(Lexer::TKN_EXCEPTION) && 00224 !currentTokenIs(Lexer::TKN_EOT)) { 00225 Node stmt = parseStatement(); 00226 if (stmt.isValid()) 00227 client.acceptStmt(block, stmt); 00228 } 00229 00230 // Inform the client all statements have been consumed. 00231 client.endBlockStmt(block); 00232 00233 // Process any exception handlers. 00234 if (currentTokenIs(Lexer::TKN_EXCEPTION)) 00235 parseExceptionStmt(block); 00236 00237 // Finish up. 00238 if (!parseEndTag(label)) 00239 seekAndConsumeEndTag(label); 00240 return block; 00241 } 00242 00243 Node Parser::parseWhileStmt() 00244 { 00245 assert(currentTokenIs(Lexer::TKN_WHILE)); 00246 00247 Location loc = ignoreToken(); 00248 Node condition = parseExpr(); 00249 NodeVector stmts; 00250 00251 if (condition.isInvalid() || !requireToken(Lexer::TKN_LOOP)) { 00252 seekEndLoop(); 00253 return getInvalidNode(); 00254 } 00255 00256 do { 00257 Node stmt = parseStatement(); 00258 if (stmt.isValid()) 00259 stmts.push_back(stmt); 00260 } while (!currentTokenIs(Lexer::TKN_END) && 00261 !currentTokenIs(Lexer::TKN_EOT)); 00262 00263 if (!requireToken(Lexer::TKN_END) || !requireToken(Lexer::TKN_LOOP)) 00264 return getInvalidNode(); 00265 00266 return client.acceptWhileStmt(loc, condition, stmts); 00267 } 00268 00269 Node Parser::parseLoopStmt() 00270 { 00271 assert(currentTokenIs(Lexer::TKN_LOOP)); 00272 00273 Location loc = ignoreToken(); 00274 NodeVector stmts; 00275 00276 do { 00277 Node stmt = parseStatement(); 00278 if (stmt.isValid()) 00279 stmts.push_back(stmt); 00280 } while (!currentTokenIs(Lexer::TKN_END) && 00281 !currentTokenIs(Lexer::TKN_EOT)); 00282 00283 if (!requireToken(Lexer::TKN_END) || !requireToken(Lexer::TKN_LOOP)) 00284 return getInvalidNode(); 00285 00286 return client.acceptLoopStmt(loc, stmts); 00287 } 00288 00289 Node Parser::parseForStmt() 00290 { 00291 assert(currentTokenIs(Lexer::TKN_FOR)); 00292 Location forLoc = ignoreToken(); 00293 00294 Location iterLoc = currentLocation(); 00295 IdentifierInfo *iterName = parseIdentifier(); 00296 00297 if (!iterName || !requireToken(Lexer::TKN_IN)) { 00298 seekEndLoop(); 00299 return getInvalidNode(); 00300 } 00301 00302 bool isReversed = reduceToken(Lexer::TKN_REVERSE); 00303 Node DST = parseDSTDefinition(false); 00304 if (DST.isInvalid() || !requireToken(Lexer::TKN_LOOP)) { 00305 seekEndLoop(); 00306 return getInvalidNode(); 00307 } 00308 00309 Node forNode = client.beginForStmt( 00310 forLoc, iterName, iterLoc, DST, isReversed); 00311 00312 NodeVector stmts; 00313 do { 00314 Node stmt = parseStatement(); 00315 if (stmt.isValid()) 00316 stmts.push_back(stmt); 00317 } while (!currentTokenIs(Lexer::TKN_END) && 00318 !currentTokenIs(Lexer::TKN_EOT)); 00319 00320 // Provide the client with the complete set of statements immediately since 00321 // we must match the call to beginForStmt with the following call to 00322 // endForStmt; 00323 forNode = client.endForStmt(forNode, stmts); 00324 00325 if (!requireToken(Lexer::TKN_END) || !requireToken(Lexer::TKN_LOOP)) 00326 return getInvalidNode(); 00327 00328 return forNode; 00329 } 00330 00331 Node Parser::parsePragmaStmt() 00332 { 00333 assert(currentTokenIs(Lexer::TKN_PRAGMA)); 00334 ignoreToken(); 00335 00336 Location loc = currentLocation(); 00337 IdentifierInfo *name = parseIdentifier(); 00338 00339 if (!name) { 00340 seekSemi(); 00341 return getInvalidNode(); 00342 } 00343 00344 llvm::StringRef ref(name->getString()); 00345 pragma::PragmaID ID = pragma::getPragmaID(ref); 00346 00347 if (ID == pragma::UNKNOWN_PRAGMA) { 00348 report(loc, diag::UNKNOWN_PRAGMA) << name; 00349 seekSemi(); 00350 return getInvalidNode(); 00351 } 00352 00353 // Currently, the only pragma accepted in a statement context is Assert. 00354 // When the set of valid pragmas expands, special parsers will be written to 00355 // parse the arguments. 00356 switch (ID) { 00357 default: 00358 seekSemi(); 00359 report(loc, diag::INVALID_PRAGMA_CONTEXT) << name; 00360 return getInvalidNode(); 00361 00362 case pragma::Assert: 00363 return parsePragmaAssert(name, loc); 00364 } 00365 } 00366 00367 Node Parser::parsePragmaAssert(IdentifierInfo *name, Location loc) 00368 { 00369 if (requireToken(Lexer::TKN_LPAREN)) { 00370 NodeVector args; 00371 00372 Node condition = parseExpr(); 00373 if (condition.isInvalid()) { 00374 seekToken(Lexer::TKN_RPAREN); 00375 return getInvalidNode(); 00376 } 00377 args.push_back(condition); 00378 00379 if (reduceToken(Lexer::TKN_COMMA)) { 00380 Node message = parseExpr(); 00381 if (message.isInvalid()) { 00382 seekToken(Lexer::TKN_RPAREN); 00383 return getInvalidNode(); 00384 } 00385 args.push_back(message); 00386 } 00387 00388 if (!requireToken(Lexer::TKN_RPAREN)) { 00389 seekToken(Lexer::TKN_RPAREN); 00390 return getInvalidNode(); 00391 } 00392 else 00393 return client.acceptPragmaStmt(name, loc, args); 00394 } 00395 seekSemi(); 00396 return getInvalidNode(); 00397 } 00398 00399 Node Parser::parseRaiseStmt() 00400 { 00401 assert(currentTokenIs(Lexer::TKN_RAISE)); 00402 Location raiseLoc = ignoreToken(); 00403 00404 Node exception = parseName(); 00405 if (exception.isInvalid()) { 00406 seekSemi(); 00407 return getInvalidNode(); 00408 } 00409 00410 Node message = getNullNode(); 00411 if (reduceToken(Lexer::TKN_WITH)) { 00412 message = parseExpr(); 00413 if (message.isInvalid()) { 00414 seekSemi(); 00415 return getInvalidNode(); 00416 } 00417 } 00418 return client.acceptRaiseStmt(raiseLoc, exception, message); 00419 } 00420 00421 void Parser::parseExceptionStmt(Node context) 00422 { 00423 assert(currentTokenIs(Lexer::TKN_EXCEPTION)); 00424 ignoreToken(); 00425 00426 // FIXME: Recovery from parse errors needs to be improved considerably. 00427 bool seenOthers = false; 00428 Location othersLoc = 0; 00429 do { 00430 Location loc = currentLocation(); 00431 if (!requireToken(Lexer::TKN_WHEN)) { 00432 seekToken(Lexer::TKN_END); 00433 return; 00434 } 00435 00436 if (seenOthers) { 00437 report(othersLoc, diag::OTHERS_HANDLER_NOT_FINAL); 00438 seekToken(Lexer::TKN_END); 00439 return; 00440 } 00441 00442 // FIXME: Exception occurrence declarations are not yet supported, just 00443 // choices. 00444 NodeVector choices; 00445 do { 00446 Location choiceLoc = currentLocation(); 00447 if (reduceToken(Lexer::TKN_OTHERS)) { 00448 if (!choices.empty()) { 00449 report(choiceLoc, diag::OTHERS_HANDLER_NOT_UNIQUE); 00450 seekToken(Lexer::TKN_END); 00451 return; 00452 } 00453 seenOthers = true; 00454 othersLoc = choiceLoc; 00455 break; 00456 } 00457 00458 Node exception = parseName(); 00459 if (exception.isValid()) 00460 choices.push_back(exception); 00461 else { 00462 seekToken(Lexer::TKN_END); 00463 return; 00464 } 00465 } while (reduceToken(Lexer::TKN_BAR)); 00466 00467 if (!requireToken(Lexer::TKN_RDARROW)) { 00468 seekToken(Lexer::TKN_END); 00469 return; 00470 } 00471 00472 Node handler = client.beginHandlerStmt(loc, choices); 00473 if (handler.isInvalid()) { 00474 seekToken(Lexer::TKN_END); 00475 return; 00476 } 00477 00478 do { 00479 Node stmt = parseStatement(); 00480 if (stmt.isValid()) 00481 client.acceptStmt(handler, stmt); 00482 } while (!currentTokenIs(Lexer::TKN_WHEN) && 00483 !currentTokenIs(Lexer::TKN_END) && 00484 !currentTokenIs(Lexer::TKN_EOT)); 00485 00486 client.endHandlerStmt(context, handler); 00487 } while (currentTokenIs(Lexer::TKN_WHEN)); 00488 }