Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

ShParser.cpp

00001 // Sh: A GPU metaprogramming language. 00002 // 00003 // Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory 00004 // Project administrator: Michael D. McCool 00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa, 00006 // Michael D. McCool 00007 // 00008 // This software is provided 'as-is', without any express or implied 00009 // warranty. In no event will the authors be held liable for any damages 00010 // arising from the use of this software. 00011 // 00012 // Permission is granted to anyone to use this software for any purpose, 00013 // including commercial applications, and to alter it and redistribute it 00014 // freely, subject to the following restrictions: 00015 // 00016 // 1. The origin of this software must not be misrepresented; you must 00017 // not claim that you wrote the original software. If you use this 00018 // software in a product, an acknowledgment in the product documentation 00019 // would be appreciated but is not required. 00020 // 00021 // 2. Altered source versions must be plainly marked as such, and must 00022 // not be misrepresented as being the original software. 00023 // 00024 // 3. This notice may not be removed or altered from any source 00025 // distribution. 00027 #include "ShParser.hpp" 00028 #include <string> 00029 #include "ShToken.hpp" 00030 #include "ShBasicBlock.hpp" 00031 #include "ShTokenizer.hpp" 00032 #include "ShException.hpp" 00033 #include "ShError.hpp" 00034 00035 namespace SH { 00036 00037 void checkCond(bool cond, const std::string& message = "Internal Error") 00038 { 00039 if (!cond) shError( ShParseException(message) ); 00040 } 00041 00042 00043 void ShParser::parse(ShCtrlGraphNodePtr& head, 00044 ShCtrlGraphNodePtr& tail, 00045 ShBlockListPtr blocks) 00046 { 00047 parseStmts(head, tail, blocks); 00048 checkCond(blocks->empty(), "Unexpected token"); // TODO: improve 00049 } 00050 00051 00052 void ShParser::parseStmts(ShCtrlGraphNodePtr& head, 00053 ShCtrlGraphNodePtr& tail, 00054 ShBlockListPtr blocks) 00055 { 00056 ShBlockPtr next = blocks->getFront(); 00057 head = tail = 0; 00058 00059 if (!next) { 00060 return; 00061 } 00062 00063 ShBasicBlockPtr basic = shref_dynamic_cast<ShBasicBlock>(next); 00064 ShTokenPtr token = shref_dynamic_cast<ShToken>(next); 00065 00066 if (basic) { 00067 // This is a basic block. Just make a node for it. 00068 head = tail = new ShCtrlGraphNode(); 00069 tail->block = basic; 00070 blocks->removeFront(); 00071 } else if (token) { 00072 // This is a token. Check what type it has. 00073 switch(token->type()) { 00074 case SH_TOKEN_IF: 00075 parseIf(head, tail, blocks); 00076 break; 00077 case SH_TOKEN_FOR: 00078 parseFor(head, tail, blocks); 00079 break; 00080 case SH_TOKEN_WHILE: 00081 parseWhile(head, tail, blocks); 00082 break; 00083 case SH_TOKEN_DO: 00084 parseDo(head, tail, blocks); 00085 break; 00086 case SH_TOKEN_BREAK: 00087 case SH_TOKEN_CONTINUE: 00088 return; // TODO: break, continue semantics 00089 case SH_TOKEN_ELSE: 00090 case SH_TOKEN_ENDIF: 00091 case SH_TOKEN_ENDWHILE: 00092 case SH_TOKEN_UNTIL: 00093 case SH_TOKEN_ENDFOR: 00094 return; 00095 } 00096 } else { // not a basic block, not a token 00097 return; 00098 } 00099 if (tail) { 00100 ShCtrlGraphNodePtr nh, nt; 00101 parseStmts(nh, nt, blocks); 00102 if (nh) { 00103 tail->append(nh); 00104 tail = nt; 00105 } 00106 } 00107 } 00108 00109 void ShParser::parseIf(ShCtrlGraphNodePtr& head, 00110 ShCtrlGraphNodePtr& tail, ShBlockListPtr blocks) 00111 { 00112 head = tail = 0; 00113 00114 ShTokenPtr ifToken = shref_dynamic_cast<ShToken>(blocks->getFront()); 00115 blocks->removeFront(); 00116 00117 checkCond(ifToken); 00118 checkCond(ifToken->type() == SH_TOKEN_IF); 00119 checkCond(ifToken->arguments.size() == 1); 00120 00121 ShTokenArgument condArg = ifToken->arguments.front(); 00122 00123 parseStmts(head, tail, condArg.blockList); 00124 if (!tail) { 00125 head = tail = new ShCtrlGraphNode(); 00126 } 00127 00128 ShCtrlGraphNodePtr headIf = 0, tailIf = 0, headElse = 0, tailElse = 0; 00129 parseStmts(headIf, tailIf, blocks); 00130 00131 ShTokenPtr nt = shref_dynamic_cast<ShToken>(blocks->getFront()); 00132 checkCond(nt); 00133 00134 if (nt->type() == SH_TOKEN_ELSE) { 00135 blocks->removeFront(); 00136 parseStmts(headElse, tailElse, blocks); 00137 00138 nt = shref_dynamic_cast<ShToken>(blocks->getFront()); 00139 checkCond(nt); 00140 } 00141 checkCond(nt->type() == SH_TOKEN_ENDIF); 00142 blocks->removeFront(); 00143 00144 if (!headIf) headIf = tailIf = new ShCtrlGraphNode(); 00145 if (!headElse) headElse = tailElse = new ShCtrlGraphNode(); 00146 00147 tail->append(headIf, condArg.result); 00148 tail->append(headElse); 00149 00150 ShCtrlGraphNodePtr merge = new ShCtrlGraphNode(); 00151 tailIf->append(merge); 00152 tailElse->append(merge); 00153 00154 tail = merge; 00155 } 00156 00157 void ShParser::parseFor(ShCtrlGraphNodePtr& head, 00158 ShCtrlGraphNodePtr& tail, ShBlockListPtr blocks) 00159 { 00160 head = tail = 0; 00161 00162 ShTokenPtr forToken = shref_dynamic_cast<ShToken>(blocks->getFront()); 00163 checkCond(forToken); 00164 checkCond(forToken->type() == SH_TOKEN_FOR); 00165 checkCond(forToken->arguments.size() == 3); 00166 blocks->removeFront(); 00167 00168 ShTokenArgument initArg = forToken->arguments[0]; 00169 ShTokenArgument condArg = forToken->arguments[1]; 00170 ShTokenArgument updateArg = forToken->arguments[2]; 00171 00172 parseStmts(head, tail, initArg.blockList); 00173 if (!tail) { 00174 head = tail = new ShCtrlGraphNode(); 00175 } 00176 00177 ShCtrlGraphNodePtr headCond = 0, tailCond = 0; 00178 parseStmts(headCond, tailCond, condArg.blockList); 00179 if (!tailCond) { 00180 headCond = tailCond = new ShCtrlGraphNode(); 00181 } 00182 00183 ShCtrlGraphNodePtr headUpdate = 0, tailUpdate = 0; 00184 parseStmts(headUpdate, tailUpdate, updateArg.blockList); 00185 if (!tailUpdate) { 00186 headUpdate = tailUpdate = new ShCtrlGraphNode(); 00187 } 00188 00189 ShCtrlGraphNodePtr headBody = 0, tailBody = 0; 00190 parseStmts(headBody, tailBody, blocks); 00191 if (!tailBody) { 00192 headBody = tailBody = new ShCtrlGraphNode(); 00193 } 00194 00195 ShTokenPtr nt = shref_dynamic_cast<ShToken>(blocks->getFront()); 00196 checkCond(nt); 00197 checkCond(nt->type() == SH_TOKEN_ENDFOR); 00198 blocks->removeFront(); 00199 00200 tail->append(headCond); 00201 tailCond->append(headBody, condArg.result); 00202 tailBody->append(headUpdate); 00203 tailUpdate->append(headCond); 00204 tail = tailCond; 00205 } 00206 00207 void ShParser::parseWhile(ShCtrlGraphNodePtr& head, 00208 ShCtrlGraphNodePtr& tail, ShBlockListPtr blocks) 00209 { 00210 head = tail = 0; 00211 00212 ShTokenPtr whileToken = shref_dynamic_cast<ShToken>(blocks->getFront()); 00213 checkCond(whileToken); 00214 checkCond(whileToken->type() == SH_TOKEN_WHILE); 00215 checkCond(whileToken->arguments.size() == 1); 00216 blocks->removeFront(); 00217 00218 ShTokenArgument condArg = whileToken->arguments[0]; 00219 00220 parseStmts(head, tail, condArg.blockList); 00221 if (!tail) { 00222 head = tail = new ShCtrlGraphNode(); 00223 } 00224 00225 ShCtrlGraphNodePtr headBody = 0, tailBody = 0; 00226 parseStmts(headBody, tailBody, blocks); 00227 if (!tailBody) { 00228 headBody = tailBody = new ShCtrlGraphNode(); 00229 } 00230 00231 ShTokenPtr nt = shref_dynamic_cast<ShToken>(blocks->getFront()); 00232 checkCond(nt); 00233 checkCond(nt->type() == SH_TOKEN_ENDWHILE); 00234 blocks->removeFront(); 00235 00236 tail->append(headBody, condArg.result); 00237 tailBody->append(head); 00238 } 00239 00240 void ShParser::parseDo(ShCtrlGraphNodePtr& head, 00241 ShCtrlGraphNodePtr& tail, ShBlockListPtr blocks) 00242 { 00243 head = tail = 0; 00244 00245 ShTokenPtr doToken = shref_dynamic_cast<ShToken>(blocks->getFront()); 00246 checkCond(doToken); 00247 checkCond(doToken->type() == SH_TOKEN_DO); 00248 blocks->removeFront(); 00249 00250 parseStmts(head, tail, blocks); 00251 if (!tail) { 00252 head = tail = new ShCtrlGraphNode(); 00253 } 00254 00255 ShTokenPtr nt = shref_dynamic_cast<ShToken>(blocks->getFront()); 00256 checkCond(nt); 00257 checkCond(nt->type() == SH_TOKEN_UNTIL); 00258 checkCond(nt->arguments.size() == 1); 00259 blocks->removeFront(); 00260 00261 ShTokenArgument condArg = nt->arguments[0]; 00262 00263 ShCtrlGraphNodePtr headCond = 0, tailCond = 0; 00264 parseStmts(headCond, tailCond, condArg.blockList); 00265 if (!tailCond) { 00266 headCond = tailCond = new ShCtrlGraphNode(); 00267 } 00268 00269 tail->append(headCond); 00270 00271 // Add empty fallthrough node. 00272 ShCtrlGraphNodePtr fallthrough = new ShCtrlGraphNode(); 00273 00274 // If the result of the UNTIL test is true, break out of the loop 00275 tailCond->append(fallthrough, condArg.result); 00276 00277 // Otherwise, continue looping. 00278 tailCond->append(head); 00279 tail = fallthrough; 00280 } 00281 00282 }

Generated on Mon Oct 18 14:17:39 2004 for Sh by doxygen 1.3.7