001package gudusoft.gsqlparser; 002 003import java.util.ArrayList; 004import java.util.Iterator; 005 006/** 007 * List of source token. 008 */ 009public class TSourceTokenList implements Iterator<TSourceToken> { 010 public void set(int index, TSourceToken st) { 011 // st.setGsqlparser(this.gsqlparser); 012 items.set(index, st); 013 } 014 015 int iteratorpos = -1; 016 017 public TGSqlParser getGsqlparser() { 018 return gsqlparser; 019 } 020 021 public void setGsqlparser(TGSqlParser gsqlparser) { 022 023 this.gsqlparser = gsqlparser; 024 } 025 026 private TGSqlParser gsqlparser = null; 027 028 public void resetiterator(){ 029 iteratorpos = -1; 030 } 031 032 public boolean hasNext(){ 033 boolean ret = (iteratorpos < (items.size() - 1)); 034 if (ret) iteratorpos++; 035 return ret; 036 } 037 038 public TSourceToken next(){ 039 return (TSourceToken)items.get(iteratorpos) ; 040 } 041 042 /** 043 * Not supportted yet. 044 */ 045 public void remove(){ 046 throw new UnsupportedOperationException(); 047 } 048 049 public TSourceTokenList(){ 050 items = new ArrayList(); 051 curpos = -1; 052 resetiterator(); 053 } 054 ArrayList items; 055 056 /** 057 * Used by parser internally. 058 * this curpos is start from -1, when a new token is created, curpos must be increased by 1 and then assign this 059 * value to the {@link TSourceToken.posinlist} . 060 */ 061 int curpos; 062 063 public TSourceToken get(int index){ 064 return (TSourceToken)items.get(index); 065 } 066 067 public void add(TSourceToken st){ 068 // st.setGsqlparser(this.gsqlparser); 069 items.add(st); 070 } 071 072 public void add(int index,TSourceToken st){ 073 //st.setGsqlparser(this.gsqlparser); 074 items.add(index,st); 075 } 076 077 public void remove(int index){ 078 items.remove(index); 079 } 080 081 public void remove(TSourceToken st){ 082 items.remove(st); 083 } 084 085 public int size(){ 086 return items.size(); 087 } 088 089 public void clear(){ 090 items.clear(); 091 } 092 093 094 boolean isnonsolidtoken(TSourceToken st,boolean pcmtissolidtoken){ 095 boolean ret = false; 096 switch(st.tokentype){ 097 case ttwhitespace: 098 case ttreturn: 099 ret = true; 100 break; 101 case ttsimplecomment: 102 case ttbracketedcomment: 103 if (!pcmtissolidtoken) ret = true; 104 break; 105 } 106 return ret; 107 } 108 109 /** 110 * Find solid token start from ptoken, distance is pstep. 111 * @param ptoken Search start from this token. 112 * @param pstep If pstep > 0 then find solid token after ptoken, if pstep < 0 then find solid token before ptoken. 113 * @param pcmtissolidtoken If it's true then treat comment as solid token. 114 * @return 115 */ 116 public TSourceToken nextsolidtoken(TSourceToken ptoken,int pstep,boolean pcmtissolidtoken){ 117 TSourceToken ret = null; 118 if (ptoken == null) {return null;} 119 if (ptoken.posinlist == -1) {return null;}; 120 return nextsolidtoken(ptoken.posinlist,pstep,pcmtissolidtoken); 121 } 122 123 /** 124 * Find solid token start from ptoken, distance is pstep. 125 * @param ptokenpos Search start from this position, not include this token 126 * @param pstep If pstep > 0 then find solid token after ptoken, if pstep < 0 then find solid token before ptoken. 127 * @param pcmtissolidtoken If it's true then treat comment as solid token. 128 * @return 129 */ 130 public TSourceToken nextsolidtoken(int ptokenpos,int pstep,boolean pcmtissolidtoken){ 131 TSourceToken ret = null; 132 if (items == null) {return ret;} 133 134 if (ptokenpos < 0 ) {return ret;} 135 if (ptokenpos > size() - 1) {return ret;} 136 if ((pstep > 0) && (ptokenpos == size() - 1)) {return ret;} 137 138 //lcnonsolidtokenset := [ttwhitespace,ttreturn]; 139 if (!pcmtissolidtoken) 140 { 141 //lcnonsolidtokenset = lcnonsolidtokenset + [ttsimplecomment,ttbracketedcomment]; 142 } 143 144 int step = 0; 145 if (pstep > 0 ) 146 for (int i= ptokenpos + 1; i < size();i++) 147 { 148 TSourceToken lctoken = this.get(i); 149 if (isnonsolidtoken(lctoken,pcmtissolidtoken)) 150 { 151 continue; 152 } 153 step++; 154 if (step == pstep) 155 { 156 ret = this.get(i); 157 break; 158 } 159 } 160 161 if (pstep < 0 ) 162 { 163 164 for (int i= ptokenpos - 1; i >= 0;i--) 165 { 166 TSourceToken lctoken = this.get(i); 167 if (isnonsolidtoken(lctoken,pcmtissolidtoken)) 168 { 169 continue; 170 } 171 step++; 172 if (step == Math.abs(pstep)) 173 { 174 ret = this.get(i); 175 break; 176 } 177 } 178 } 179 return ret; 180 } 181 182 /** 183 * Search token of the next/previous object 184 * 185 * @param ptokenpos, search from this token, not included. 186 * @param pstep pstep > 0 means search forward, <0 means search backward 187 * @param pcmtissolidtoken, treat comment as solid token if it's true. 188 * @return -1 means not found. If search next, then return position of the last token of qualified object name, 189 * if search previous, then return position of the first token of qualified object name. 190 */ 191 public int nextObjectNameToken(int ptokenpos,int pstep,boolean pcmtissolidtoken){ 192 int ret = -1; 193 boolean waitForNextSolidToken = false; 194 if (items == null) {return ret;} 195 196 if (ptokenpos < 0 ) {return ret;} 197 if (ptokenpos > size() - 1) {return ret;} 198 if ((pstep > 0) && (ptokenpos == size() - 1)) {return ret;} 199 200 int step = 0; 201 if (pstep > 0 ) 202 for (int i= ptokenpos + 1; i < size();i++) 203 { 204 TSourceToken lctoken = this.get(i); 205 if (isnonsolidtoken(lctoken,pcmtissolidtoken)) 206 { 207 continue; 208 } 209 if (lctoken.tokencode == '.') { 210 waitForNextSolidToken = true; 211 continue; 212 } 213 214 if (ret == -1){ 215 ret = i; 216 continue; 217 }else{ 218 if (waitForNextSolidToken){ 219 waitForNextSolidToken = false; 220 ret = i; 221 continue; 222 } 223 } 224 225 step++; 226 if (step == pstep) break; 227 } 228 229 if (pstep < 0 ) 230 { 231 232 for (int i= ptokenpos - 1; i >= 0;i--) 233 { 234 TSourceToken lctoken = this.get(i); 235 if (isnonsolidtoken(lctoken,pcmtissolidtoken)) 236 { 237 continue; 238 } 239 240 if (lctoken.tokencode == '.') { 241 waitForNextSolidToken = true; 242 continue; 243 } 244 245 if (ret == -1){ 246 ret = i; 247 continue; 248 }else{ 249 if (waitForNextSolidToken){ 250 waitForNextSolidToken = false; 251 ret = i; 252 continue; 253 } 254 } 255 256 step++; 257 if (step == Math.abs(pstep)) break; 258 } 259 } 260 return ret; 261 } 262 263 int solidtokenafterpos(int piindex,String psstr,int scope,String ignoretoken){ 264 int ret = 0; 265 if ( items == null ) return ret; 266 267 if ( piindex < 0 ) return ret; 268 if ( piindex > size() - 2 ) return ret; 269 int step = 0; 270 for (int i = piindex + 1; i< size() ;i++) 271 { 272 if (this.get(i).isnonsolidtoken()) continue; 273 274 if ( (ignoretoken.length() > 0) && ( TBaseType.mycomparetext(this.get(i).astext,ignoretoken) == 0) ) continue; 275 276 if ( TBaseType.mycomparetext(psstr,this.get(i).astext) == 0 ) ret = i; 277 step++; 278 if ( (ret > 0) || (step >= scope) ) 279 break; 280 }; 281 return ret; 282 } 283 284 /** 285 * Search token by token code, start from pStart within range pSteps, and ignore pIngoreThisString if any during searching. 286 * Ingore non-solid token while searching. 287 * 288 * @param pStart Start from this position. 289 * @param pTokenCode TokenCode that search for. 290 * @param pSteps Must > 0. 291 * @param pIgnoreThisString String to be ignored. 292 * @return 0 if no token found, otherwise, return position in sourcetoken list. 293 */ 294 public int solidtokenafterpos(int pStart,int pTokenCode,int pSteps,String pIgnoreThisString){ 295 int ret = 0; 296 if ( items == null ) return ret; 297 298 if ( pStart < 0 ) return ret; 299 if ( pStart > size() - 2 ) return ret; 300 int step = 0; 301 for (int i = pStart + 1; i< size() ;i++) 302 { 303 if (this.get(i).isnonsolidtoken()) continue; 304 if ( (pIgnoreThisString.length() > 0) && ( TBaseType.mycomparetext(this.get(i).astext,pIgnoreThisString) == 0) ) continue; 305 306 307 if ( pTokenCode == this.get(i).tokencode ) ret = i; 308 step++; 309 if ( (ret > 0) || (step >= pSteps) ) 310 break; 311 }; 312 return ret; 313 } 314 315 /** 316 * Search solid token before pStart. 317 * @param pStart 318 * @return return null if no token found. 319 */ 320 public TSourceToken solidtokenbefore(int pStart){ 321 return nextsolidtoken(pStart,-1,false); 322 } 323 324public boolean sqlplusaftercurtoken(){ 325 return (sqlplusaftertoken(curpos) > 0); 326} 327 328 /** 329 * Search Oracle sqlplus token after pStart. Ignore non-solid token while searching. 330 * @param pStart 331 * @return 332 */ 333int sqlplusaftertoken(int pStart){ 334 int ret = 0; 335 if (items == null) return ret; 336 337 if ((pStart < 0 ) || (pStart+1 > size() - 1 )) return ret; 338 for (int i = pStart+1;i <size();i++) 339 { 340 if (this.get(i).isnonsolidtoken()) continue; 341 if (get(i).tokencode == TBaseType.sqlpluscmd) ret = i; 342 break; 343 } 344 345 return ret; 346} 347 348 public int searchLastTokenAtTheSameLine(int pStart){ 349 int ret = -1; 350 if (items == null) return ret; 351 352 if ((pStart < 0 ) || (pStart+1 > size() - 1 ) ) return ret; 353 for (int i = pStart+1; i<size();i++) 354 { 355 ret = i; 356 if (get(i).tokentype == ETokenType.ttreturn) break; 357 } 358 359 return ret-1; 360 } 361 362 /** 363 * Is there linebreak after current token. 364 * @param ignorecmt If it's true, ignore comment while searching linebreak. 365 * @return 366 */ 367public boolean returnaftercurtoken(boolean ignorecmt){ 368 return searchReturnTokenDirectlyAfter(curpos,ignorecmt) > 0; 369} 370 371 /** 372 * Found whether a linebreak is followed directly after the start token, 373 * If linebreak is followed directly, return the position of this linebreak, otherwise, return 0 374 * 375 * @param pStart Start from this position in sourcetoken list. 376 * @param ignorecomment If it's true, ignore comment while searching linebreak. 377 * @return 0 means no linebreak was found, otherwise, return the distance between start token and linebreak 378 */ 379 int searchReturnTokenDirectlyAfter(int pStart, boolean ignorecomment){ 380 int ret = 0,j = 0; 381 382 if (items == null) return ret; 383 384 if ((pStart < 0 ) || (pStart+1 > size() - 1 ) ) return ret; 385 for (int i = pStart+1; i<size();i++) 386 { 387 j = i; 388 if (get(i).tokentype == ETokenType.ttwhitespace) continue; 389 if ( ( 390 (get(i).tokentype == ETokenType.ttsimplecomment) 391 ||(get(i).tokentype == ETokenType.ttbracketedcomment) 392 ) && ignorecomment ) continue; 393 394 break; 395 } 396 if (get(j).tokentype == ETokenType.ttreturn) {ret = j - pStart;} 397 398 return ret; 399} 400 401public boolean returnbeforecurtoken(boolean ignorecomment){ 402 return returnbeforecurtoken(ignorecomment,true); 403} 404 /** 405 * Is there a linebreak before current token, comment is not ignored if ignorecomment is true, 406 * space is ignored. 407 * @return 408 */ 409 410public boolean returnbeforecurtoken(boolean ignorecomment, boolean ignoreWhiteSpace){ 411 boolean ret = false; 412 413 if (items == null) return ret; 414 415 if (curpos <= 0) return ret; 416 if (curpos > size() - 1) return ret; 417 int i = curpos-1; 418 419 for (int j = i; j>=0;j--) 420 { 421 if ((ignoreWhiteSpace) && (get(j).tokentype == ETokenType.ttwhitespace)) continue; 422 if ((ignorecomment)&&((get(j).tokentype == ETokenType.ttsimplecomment)||(get(j).tokentype == ETokenType.ttbracketedcomment))) continue; 423 if (get(j).tokentype == ETokenType.ttreturn) ret = true; 424 break; 425 } 426 427 return ret; 428} 429 430 public TSourceToken searchToken(int targetTokenCode, String targetTokenText, TSourceToken startToken, int range){ 431 return searchToken(targetTokenCode,targetTokenText,startToken,range,0,false); 432 } 433 /** 434 * 435 * @param targetTokenCode, > 0, search target token by token code; = 0, search target token by token text 436 * @param targetTokenText 437 * @param startToken 438 * @param range, > 0, search token after startToken 439 * = 0, just compare with this startToken, 440 * < 0, search token before startToken 441 * @return 442 */ 443public TSourceToken searchToken(int targetTokenCode, String targetTokenText, TSourceToken startToken, int range, int stopTokenCode, boolean stopAtSemiColon){ 444 TSourceToken ret = null; 445 446 if (items == null) {return ret;} 447 448 int ptokenpos = startToken.posinlist; 449 450 if ((ptokenpos < 0) || ( (ptokenpos > size() - 1)&&(range > 0)) ) {return ret;} 451 452 if ((range > 0) && (ptokenpos == size() - 1)) {return ret;} 453 if ((range < 0) && (ptokenpos == 0)) {return ret;} 454 if (range == 0){ 455 if (targetTokenCode > 0){ 456 if (startToken.tokencode == targetTokenCode ){ 457 ret = startToken; 458 } 459 }else{ 460 if (startToken.toString().equalsIgnoreCase(targetTokenText)){ 461 ret = startToken; 462 } 463 } 464 return ret; 465 } 466 467 TSourceToken lctoken = null; 468 469 if (range > 0 ){ 470 for (int i= ptokenpos + 1; i < size();i++) 471 { 472 lctoken = this.get(i); 473 474 if (isnonsolidtoken(lctoken,false)) { continue; } 475 476 if ( --range >= 0) 477 { 478 if (targetTokenCode > 0){ 479 if (lctoken.tokencode == targetTokenCode ){ 480 ret = lctoken; 481 break; 482 } 483 }else{ 484 if (lctoken.toString().equalsIgnoreCase(targetTokenText)){ 485 ret = lctoken; 486 break; 487 } 488 } 489 }else{ 490 break; 491 } 492 493 if (stopTokenCode != 0){ 494 if (lctoken.tokencode == stopTokenCode) break; 495 } 496 497 if ((lctoken.tokencode == ';')&& (stopAtSemiColon)) break; 498 } 499 500 range = 0; 501 } 502 503 if (range < 0 ) 504 { 505 for (int i= ptokenpos - 1; i >= 0;i--) 506 { 507 lctoken = this.get(i); 508 if (isnonsolidtoken(lctoken,false)){continue;} 509 if (++range <= 0) 510 { 511 if (targetTokenCode > 0){ 512 if (lctoken.tokencode == targetTokenCode ){ 513 ret = lctoken; 514 break; 515 } 516 }else{ 517 if (lctoken.toString().equalsIgnoreCase(targetTokenText)){ 518 ret = lctoken; 519 break; 520 } 521 } 522 }else{ 523 break; 524 } 525 526 527 if (stopTokenCode != 0){ 528 if (lctoken.tokencode == stopTokenCode) break; 529 } 530 if ((lctoken.tokencode == ';')&& (stopAtSemiColon)) break; 531 } 532 } 533 534 return ret; 535} 536 537 538public void setTokenStatus(ETokenStatus ps,int pstart,int pend){ 539 if (pstart < 0 ) return ; 540 if (pend > this.size() - 1 ) return; 541 542 for(int i=pstart;i<=pend;i++){ 543 this.get(i).tokenstatus = ps; 544 } 545 546} 547 548public int indexOf(TSourceToken pst){ 549 return items.indexOf(pst); 550} 551 552}