00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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");
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
00068 head = tail =
new ShCtrlGraphNode();
00069 tail->block = basic;
00070 blocks->removeFront();
00071 }
else if (token) {
00072
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;
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 {
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
00272 ShCtrlGraphNodePtr fallthrough =
new ShCtrlGraphNode();
00273
00274
00275 tailCond->append(fallthrough, condArg.result);
00276
00277
00278 tailCond->append(head);
00279 tail = fallthrough;
00280 }
00281
00282 }