001 002package gudusoft.gsqlparser.pp.utils; 003 004import gudusoft.gsqlparser.ETokenStatus; 005import gudusoft.gsqlparser.ETokenType; 006import gudusoft.gsqlparser.TSourceToken; 007import gudusoft.gsqlparser.TSourceTokenList; 008 009public class SourceTokenSearcher 010{ 011 012 /** 013 * search the source token in the source token list from the top 014 * 015 * @param list 016 * @param startPos 017 * @param endPos 018 * @param text 019 * @return position 020 */ 021 public static int indexOf( TSourceTokenList list, int startPos, int endPos, 022 String text ) 023 { 024 if ( text == null ) 025 { 026 return -1; 027 } 028 029 for ( int i = startPos; i < endPos; i++ ) 030 { 031 if ( i >= 0 && i < list.size( ) ) 032 { 033 if (list.get(i).tokenstatus == ETokenStatus.tsdeleted) { 034 continue; 035 } 036 037 if ( list.get(i).getAstext() != null 038 && list.get(i).getAstext().trim( ).equalsIgnoreCase( text ) ) 039 { 040 return i; 041 } 042 } 043 else 044 { 045 return -1; 046 } 047 } 048 049 return -1; 050 } 051 052 /** 053 * search the source token in the source token list from the top 054 * 055 * @param list 056 * @param startPos 057 * @param endPos 058 * @param type 059 * @return 060 */ 061 public static int indexOf( TSourceTokenList list, int startPos, int endPos, 062 ETokenType type ) 063 { 064 for ( int i = startPos; i < endPos; i++ ) 065 { 066 if ( i >= 0 && i < list.size( ) ) 067 { 068 if(list.get(i).tokenstatus == ETokenStatus.tsdeleted) { 069 continue; 070 } 071 072 if ( type == list.get( i ).tokentype ) 073 { 074 return i; 075 } 076 } 077 else 078 { 079 return -1; 080 } 081 } 082 083 return -1; 084 } 085 086 /** 087 * search the source token in the source token list from the top 088 * 089 * @param list 090 * @param startPos 091 * @param text 092 * @return 093 */ 094 public static int indexOf( TSourceTokenList list, int startPos, String text ) 095 { 096 return indexOf( list, startPos, list.size( ) - 1, text ); 097 } 098 099 /** 100 * backward search the source token 101 * 102 * @param backsearchSize 103 * @param text 104 * @return 105 */ 106 public static TSourceToken backforwardSearch( TSourceToken token, 107 int backsearchSize, String text ) 108 { 109 int pos = SourceTokenSearcher.lastIndexOf( token.container, 110 token.posinlist - backsearchSize, 111 token.posinlist, 112 text ); 113 if ( pos == -1 ) 114 { 115 return null; 116 } 117 return token.container.get( pos ); 118 } 119 120 /** 121 * forward search the source token 122 * 123 * @param token 124 * @param forwardSearchSize 125 * @param text 126 * @return 127 */ 128 public static TSourceToken forwardSearch( TSourceToken token, 129 int forwardSearchSize, String text ) 130 { 131 int pos = SourceTokenSearcher.indexOf( token.container, 132 token.posinlist, 133 token.posinlist + forwardSearchSize, 134 text ); 135 if ( pos == -1 ) 136 { 137 return null; 138 } 139 return token.container.get( pos ); 140 } 141 142 /** 143 * search the source token in the source token list from the end 144 * 145 * @param list 146 * @param startPos 147 * @param endPos 148 * @param text 149 * @return position 150 */ 151 public static int lastIndexOf( TSourceTokenList list, int startPos, 152 int endPos, String text ) 153 { 154 if ( text == null ) 155 { 156 return -1; 157 } 158 if ( startPos < 0 ) 159 { 160 startPos = 0; 161 } 162 if ( endPos - 1 > list.size( ) ) 163 { 164 endPos = list.size( ); 165 } 166 167 for ( int i = endPos - 1; i >= startPos; i-- ) 168 { 169 if ( i >= 0 && i < list.size( ) ) 170 { 171 if ( list.get(i).getAstext() != null 172 && list.get(i).getAstext().trim( ).equalsIgnoreCase( text ) ) 173 { 174 return i; 175 } 176 } 177 else 178 { 179 return -1; 180 } 181 } 182 183 return -1; 184 } 185 186 /** 187 * search the source token in the source token list from the end 188 * 189 * @param list 190 * @param endPos 191 * @param text 192 * @return 193 */ 194 public static int lastIndexOf( TSourceTokenList list, int endPos, 195 String text ) 196 { 197 return lastIndexOf( list, 0, endPos, text ); 198 } 199 200 /** 201 * get last token which is not whitespace and return token 202 * 203 * @param list 204 * @param startPos 205 * @param endPos 206 * @return 207 */ 208 public static TSourceToken lastNotWhitespaceAndReturnToken( 209 TSourceTokenList list, int startPos, int endPos ) 210 { 211 212 for ( int i = endPos - 1; i >= startPos; i-- ) 213 { 214 if ( i >= 0 && i < list.size( ) ) 215 { 216 if(list.get(i).tokenstatus == ETokenStatus.tsdeleted) { 217 continue; 218 } 219 220 if ( list.get( i ).tokentype == ETokenType.ttwhitespace 221 || list.get( i ).tokentype == ETokenType.ttreturn 222 || list.get( i ).tokentype == ETokenType.ttsimplecomment 223 || list.get( i ).tokentype == ETokenType.ttbracketedcomment ) 224 { 225 continue; 226 } 227 else 228 { 229 return list.get( i ); 230 } 231 } 232 else 233 { 234 return null; 235 } 236 } 237 238 return null; 239 } 240 241 /** 242 * get last token which is not whitespace and return token 243 * 244 * @param list 245 * @param endPos 246 * @return 247 */ 248 public static TSourceToken lastNotWhitespaceAndReturnToken( 249 TSourceTokenList list, int endPos ) 250 { 251 return lastNotWhitespaceAndReturnToken( list, 0, endPos ); 252 } 253 254 /** 255 * backward search the token which is the first not whitespace or return 256 * token, and its value is a fixed text 257 * 258 * @param list 259 * @param endPos 260 * the fixed value 261 * @return 262 */ 263 public static TSourceToken lastSelectedNotWhitespaceAndReturnToken( 264 TSourceTokenList list, int endPos, String text ) 265 { 266 TSourceToken token = lastNotWhitespaceAndReturnToken( list, endPos ); 267 if ( token != null 268 && token.getAstext() != null 269 && token.getAstext().trim( ).equalsIgnoreCase( text ) ) 270 { 271 return token; 272 } 273 return null; 274 } 275 276 /** 277 * get first token which is not whitespace and return token 278 * 279 * @param list 280 * @param startPos 281 * @param endPos 282 * @return 283 */ 284 public static TSourceToken firstNotWhitespaceAndReturnToken( 285 TSourceTokenList list, int startPos, int endPos ) 286 { 287 288 for ( int i = startPos; i < endPos; i++ ) 289 { 290 if ( i >= 0 && i < list.size( ) ) 291 { 292 if(list.get(i).tokenstatus == ETokenStatus.tsdeleted) { 293 continue; 294 } 295 296 if ( list.get( i ).tokentype == ETokenType.ttwhitespace 297 || list.get( i ).tokentype == ETokenType.ttreturn 298 || list.get( i ).tokentype == ETokenType.ttsimplecomment 299 || list.get( i ).tokentype == ETokenType.ttbracketedcomment ) 300 { 301 continue; 302 } 303 else 304 { 305 return list.get( i ); 306 } 307 } 308 else 309 { 310 return null; 311 } 312 } 313 314 return null; 315 } 316 317 /** 318 * forward search the token which is the first not whitespace or return 319 * token, and its value is a fixed text 320 * 321 * @param list 322 * @param startPos 323 * @param text 324 * @return 325 */ 326 public static TSourceToken firstSelectNotWhitespaceAndReturnToken( 327 TSourceTokenList list, int startPos, String text ) 328 { 329 for ( int i = startPos; i < list.size( ); i++ ) 330 { 331 if ( i >= 0 && i < list.size( ) ) 332 { 333 if(list.get(i).tokenstatus == ETokenStatus.tsdeleted) { 334 continue; 335 } 336 337 TSourceToken token = list.get( i ); 338 if ( token.tokentype == ETokenType.ttwhitespace 339 || token.tokentype == ETokenType.ttreturn 340 || list.get( i ).tokentype == ETokenType.ttsimplecomment 341 || list.get( i ).tokentype == ETokenType.ttbracketedcomment ) 342 { 343 continue; 344 } 345 else 346 { 347 if ( token.getAstext() != null 348 && token.getAstext().trim( ).equalsIgnoreCase( text ) ) 349 { 350 return token; 351 } 352 else 353 { 354 return null; 355 } 356 } 357 } 358 } 359 360 return null; 361 } 362 363 /** 364 * backward search the token which is the first not whitespace or return 365 * token, and its value is a fixed text 366 * 367 * @param token 368 * @param text 369 * @return 370 */ 371 public static TSourceToken lastSelectedNotWhitespaceAndReturnToken( 372 TSourceToken token, String text ) 373 { 374 if ( token == null ) 375 { 376 return null; 377 } 378 return lastSelectedNotWhitespaceAndReturnToken( token.container, 379 token.posinlist, 380 text ); 381 } 382 383 public static boolean isNewLineToken( TSourceToken token ) 384 { 385 if ( token == null || token.tokentype != ETokenType.ttreturn ) 386 { 387 return false; 388 } 389 else 390 { 391 return true; 392 } 393 } 394 395 public static boolean isSimpleComment( TSourceToken token ) 396 { 397 if ( token == null || token.tokentype != ETokenType.ttsimplecomment ) 398 { 399 return false; 400 } 401 else 402 { 403 return true; 404 } 405 } 406 407 /** 408 * Search backward from {@code token} for the token whose text is 409 * {@code text}, counting only solid tokens: whitespace, line breaks and 410 * comments do not consume a step. {@link #backforwardSearch} counts every 411 * token, so a comment sitting between the searched keyword and its 412 * anchor pushed the keyword out of the window and the caller received 413 * {@code null} (NullPointerException in CTEProcessor and 414 * AppendLineAfterInsertTableNameProcessor on real-world scripts). 415 */ 416 public static TSourceToken backforwardSearchSolid( TSourceToken token, 417 int solidSteps, String text ) 418 { 419 if ( token == null || token.container == null || text == null ) 420 { 421 return null; 422 } 423 TSourceTokenList list = token.container; 424 int steps = 0; 425 for ( int i = token.posinlist - 1; i >= 0 && steps < solidSteps; i-- ) 426 { 427 TSourceToken t = list.get( i ); 428 if ( t.tokenstatus == ETokenStatus.tsdeleted || isTrivia( t ) ) 429 { 430 continue; 431 } 432 if ( t.getAstext( ) != null && t.getAstext( ).trim( ).equalsIgnoreCase( text ) ) 433 { 434 return t; 435 } 436 steps++; 437 } 438 return null; 439 } 440 441 /** Forward twin of {@link #backforwardSearchSolid}. */ 442 public static TSourceToken forwardSearchSolid( TSourceToken token, 443 int solidSteps, String text ) 444 { 445 if ( token == null || token.container == null || text == null ) 446 { 447 return null; 448 } 449 TSourceTokenList list = token.container; 450 int steps = 0; 451 for ( int i = token.posinlist; i < list.size( ) && steps < solidSteps; i++ ) 452 { 453 TSourceToken t = list.get( i ); 454 if ( t.tokenstatus == ETokenStatus.tsdeleted || isTrivia( t ) ) 455 { 456 continue; 457 } 458 if ( t.getAstext( ) != null && t.getAstext( ).trim( ).equalsIgnoreCase( text ) ) 459 { 460 return t; 461 } 462 steps++; 463 } 464 return null; 465 } 466 467 private static boolean isTrivia( TSourceToken t ) 468 { 469 return t.tokentype == ETokenType.ttwhitespace 470 || t.tokentype == ETokenType.ttreturn 471 || t.tokentype == ETokenType.ttsimplecomment 472 || t.tokentype == ETokenType.ttbracketedcomment 473 || t.tokentype == ETokenType.ttCPPComment; 474 } 475 476 public static TSourceToken backforwardSearchNotWhitespaceAndReturnToken( 477 TSourceToken endToken, int backforwardSearchSize, String text ) 478 { 479 TSourceToken currentToken = endToken; 480 while ( backforwardSearchSize > 0 ) 481 { 482 currentToken = lastNotWhitespaceAndReturnToken( currentToken.container, 483 currentToken.posinlist ); 484 if ( currentToken != null 485 && currentToken.getAstext() != null 486 && currentToken.getAstext().trim( ).equalsIgnoreCase( text ) ) 487 { 488 return currentToken; 489 } 490 491 backforwardSearchSize--; 492 } 493 return null; 494 } 495 496 public static TSourceToken lastSelectedToken( TSourceTokenList list, 497 int startPos, int endPos, String text ) 498 { 499 for ( int i = endPos; i >= startPos; i-- ) 500 { 501 if ( i >= 0 && i < list.size( ) ) 502 { 503 if(list.get(i).tokenstatus == ETokenStatus.tsdeleted) { 504 continue; 505 } 506 507 TSourceToken token = list.get( i ); 508 if ( token.toString( ).equalsIgnoreCase( text ) ) 509 { 510 return token; 511 } 512 } 513 else 514 { 515 return null; 516 } 517 } 518 return null; 519 } 520 521 public static TSourceToken firstSelectedToken( TSourceTokenList list, 522 int startPos, int endPos, String text ) 523 { 524 for ( int i = startPos; i <= endPos; i++ ) 525 { 526 if ( i >= 0 && i < list.size( ) ) 527 { 528 if(list.get(i).tokenstatus == ETokenStatus.tsdeleted) { 529 continue; 530 } 531 532 TSourceToken token = list.get( i ); 533 if ( token.toString( ).equalsIgnoreCase( text ) ) 534 { 535 return token; 536 } 537 } 538 else 539 { 540 return null; 541 } 542 } 543 return null; 544 } 545 546 // public static boolean isStartWithReturnToken(TSourceToken token) { 547 // if (token == null) { 548 // return false; 549 // } 550 // if (token.astext.startsWith("\n") || token.astext.startsWith("\r\n")) { 551 // return true; 552 // } else { 553 // return false; 554 // } 555 // } 556 557}