001package gudusoft.gsqlparser;
002
003
004import java.io.BufferedReader;
005import java.io.IOException;
006import java.util.ArrayList;
007import java.util.HashMap;
008import java.util.Locale;
009
010/**
011 * Base lexer of all databases.
012 */
013public class TCustomLexer {
014
015    // 在 lexer level 创建 token table, 按照 token code存储所有 token 的一些关键信息,主要用于处理一个关键字token被用作column,table name的情况
016    public static int MAX_TOKEN_SIZE = 2048; // 所有可能的token的数量
017    public static int MAX_TOKEN_COLUMN_SIZE = 10;
018
019    // 定义一个具有 MAX_TOKEN_SIZE 个元素的常量数组,每个元素有 MAX_TOKEN_COLUMN_SIZE 列, 列的类型为整数
020    // column 0: 代表该token出现的次数
021    // column 1: 代表该token第一次出现的 x position
022    // column 2: 代表该token第一次出现的 y position
023    // column 3: 代表该token最后一次出现的 x position
024    // column 4: 代表该token最后一次出现的 y position
025    // column 5: 代表该token第一次出现的 position in the token list
026    // column 6: 代表该token最后一次出现的 position in the token list
027
028    public static int COLUMN0_COUNT = 0;
029    public static int COLUMN1_FIRST_X = 1;
030    public static int COLUMN2_FIRST_Y = 2;
031    public static int COLUMN3_LAST_X = 3;
032    public static int COLUMN4_LAST_Y = 4;
033    public static int COLUMN5_FIRST_POS = 5;
034    public static int COLUMN6_LAST_POS = 6;
035
036    public long[][] TOKEN_TABLE = new long[MAX_TOKEN_SIZE][MAX_TOKEN_COLUMN_SIZE];
037
038    // define a function to reset all values in TOKEN_TABLE to 0
039    public void resetTokenTable() {
040        for (int i = 0; i < MAX_TOKEN_SIZE; i++) {
041            for (int j = 0; j < MAX_TOKEN_COLUMN_SIZE; j++) {
042                TOKEN_TABLE[i][j] = 0L;
043            }
044        }
045    }
046
047    // define a function to set value when token is found, input is token id, a token with TSourceToken type
048    public void setTokenTableValue( TSourceToken token) {
049        if (token == null) return;
050        int tokenId = token.tokencode;
051
052        if (tokenId < 0 || tokenId >= MAX_TOKEN_SIZE) {
053            return;
054        }
055        if (TOKEN_TABLE[tokenId][COLUMN0_COUNT] == 0) {
056            TOKEN_TABLE[tokenId][COLUMN0_COUNT] = 1;
057            TOKEN_TABLE[tokenId][COLUMN1_FIRST_X] = token.lineNo;
058            TOKEN_TABLE[tokenId][COLUMN2_FIRST_Y] = token.columnNo;
059            TOKEN_TABLE[tokenId][COLUMN3_LAST_X] = token.lineNo;
060            TOKEN_TABLE[tokenId][COLUMN4_LAST_Y] = token.columnNo;
061            TOKEN_TABLE[tokenId][COLUMN5_FIRST_POS] = token.posinlist;
062            TOKEN_TABLE[tokenId][COLUMN6_LAST_POS] = token.posinlist;
063        } else {
064            TOKEN_TABLE[tokenId][COLUMN0_COUNT] += 1;
065            TOKEN_TABLE[tokenId][COLUMN3_LAST_X] = token.lineNo;
066            TOKEN_TABLE[tokenId][COLUMN4_LAST_Y] = token.columnNo;
067            TOKEN_TABLE[tokenId][COLUMN6_LAST_POS] = token.posinlist;
068        }
069    }
070
071    public BufferedReader yyinput;
072    long yylineno,yycolno,offset,yylineno_p,yycolno_p,offset_p;
073    int bufptr,yystate,yysstate,yylstate,yytextlen,yyretval, yytextbufsize,
074            yymatches,yysleng;
075    char[] yyline;
076    String yylvalstr;
077    public String  dolqstart = "";//postgresql, start part of Dollar-quoted String Constants
078    char yylastchar,yyactchar,yytablechar;
079    boolean yydone,yyreject;
080    char[] yytextbuf;
081    char[] buf;
082    int bufsize;
083    boolean endOfInput;
084
085    //StringBuffer literalbuf;
086    StringBuilder literalbuf;
087    int literallen,literalalloc,xcdepth,nchars,slashstar,dashdash;
088    boolean isqmarktoident;
089    boolean insqlpluscmd;
090    char dummych1,dummych2,dummych3;
091    boolean utf8NoBreakSpaceReady = false;
092
093    int nestedLessThan = 0;
094
095    boolean isReadyForFunctionBody = false, isInFunctionBody = false;
096    int   functionBodyDelimiterIndex = -1;
097    ArrayList<String> functionBodyDelimiter = new ArrayList<>();
098
099    public static int keyword_type_reserved = 0x0001;
100    public static int keyword_type_keyword = 0x0002;
101    public static int keyword_type_identifier = 0x0004;
102    public static int keyword_type_column = 0x0008;
103
104    public char delimiterchar;
105    public String defaultDelimiterStr;
106    public String tmpDelimiter;
107    
108    final static int intial_bufsize = 16384;
109    final static char lf = (char)10;
110    final static int max_chars = 65536*10*2;
111    final static int max_rules = 256*2*10;
112    int  max_matches = 1024*20*10*2;
113
114
115    // 下面这些常量按照在 l 文件中出现的次序,必须以  +2 的方式递加. 为什么以 +2 的方式递加 原因忘了,尚未搞清楚。
116    final static int init = 2;
117    final static int xc = 4;
118    final static int xd = 6;
119    final static int xq = 8;
120    final static int xqq = 10;  //oracle
121    final static int xdolq = 10;//postgresql
122    final static int xdbracket = 10;
123    final static int xdbrace = 12;
124    final static int xbacktick = 12;
125
126    final static int xbracketrs = 12; //redshift
127    final static int xqtriple = 14;//bigquery
128    final static int xdtriple = 16;//bigquery
129
130
131
132    //https://docs.microsoft.com/en-us/sql/sql-server/maximum-capacity-specifications-for-sql-server
133    final static int namedatalen = 8060;//255;
134    
135    final static int cmtslashstar = 257;
136    final static int cmtdoublehyphen = 258;
137    final static int lexspace = 259;
138    final static int lexnewline = 260;
139    final static int fconst  = 261;
140    final static int sconst = 262;
141    final static int iconst = 263;
142    final static int ident = 264;
143    final static int op = 265;
144    final static int cmpop = 266;
145    final static int bind_v = 267;
146    final static int assign_sign = 268;
147    final static int double_dot = 269;
148    final static int label_begin = 270;
149    final static int label_end = 271;
150    final static int substitution_v  = 272;
151    final static int filepath_sign = TBaseType.filepath_sign;
152    final static int sqlpluscmd = 273;
153    final static int atversion = TBaseType.atversion; //databricks
154    final static int error = 274;
155    final static int variable = 275;
156    final static int mslabel = 276;
157    public final static int bconst = TBaseType.bconst; //postgresql
158    final static int leftjoin_op = 277;
159    final static int odbc_esc_prefix = 277;
160    final static int rightjoin_op = 278;
161    final static int odbc_esc_terminator = 278;
162    final static int db2label = 279;
163    public final static int xconst = TBaseType.xconst; //postgresql
164    final static int ref_arrow = 280;
165    final static int rw_scriptoptions = 281;
166    public final static int UNICODE_ENCODE_ID = 281;
167    final static int mysqllabel = 282;
168    final static int NAMED_PARAMETER_SIGN = 282; //oracle,db2,snowflake CALL update_order (5000, NEW_STATUS => 'Shipped')
169    final static int QUOTED_IDENT = 282;//used in mdx
170    final static int BTEQCMD = 282;
171    final static int concatenationop = 283;
172    final static int rw_not_deferrable = 284;
173    final static int rw_for1 = 285;
174    final static int stmt_delimiter = 286;
175    final static int AMP_QUOTED_ID = 285; //used in mdx
176    final static int AMP_UNQUOTED_ID = 286; //used in mdx
177    final static int m_clause = 287;
178    final static int MySQL_CHARSET_NAME = 287;
179    final static int typecast = TBaseType.typecast;//postgresql
180    final static int k_clause = 288;
181    final static int slash_dot = 288;
182    final static int outer_join = 289;
183
184    final static int not_equal = 290;
185
186    final static int param = TBaseType.param;
187    final static int mysql_null = TBaseType.rrw_mysql_null;
188
189    final static int rw_locktable = 296;
190    final static int rw_foreign2 = 297;
191    final static int rw_constraint2 = 298;
192    final static int rw_primary2 = 299;
193    final static int rw_unique2 = 300;
194    final static int     NEXT_PARAM = TBaseType.NEXT_PARAM;
195    final static int     POSITIONAL_PARAM = TBaseType.POSITIONAL_PARAM;
196    final static int     NAMED_PARAM = TBaseType.NAMED_PARAM;
197
198    final static int castoperator = TBaseType.castoperator;
199    final static int twocolons = TBaseType.twocolons;
200    final static int compoundAssignmentOperator = TBaseType.compoundAssignmentOperator;
201    final static int postgresql_function_delimiter = TBaseType.rrw_postgresql_function_delimiter;
202    final static int greenplum_function_delimiter = TBaseType.rrw_greenplum_function_delimiter;
203
204    final static int redshift_function_delimiter = TBaseType.rrw_redshift_function_delimiter;
205    final static int snowflake_function_delimiter = TBaseType.rrw_snowflake_function_delimiter;
206
207
208
209    int[] yypos;// = new int[max_rules + 1];      // 1 based in delphi, Position 0 was not used here
210    int[] yystack;// = new int[max_matches + 1];  // 1 based in delphi, Position 0 was not used here
211  //  ArrayList yystack;
212
213    //String keywordvaluefile,keywordfile,yyk_file,yym_file,yykl_file;
214    //String yykh_file,yyml_file,yymh_file,yytl_file,yyth_file,yytint_file,yyt_file;
215
216    EDbVendor dbvendor;
217    TSourceToken prevToken = null;
218
219    public void setSqlCharset(String sqlCharset) {
220        this.sqlCharset = sqlCharset;
221    }
222
223    public String getSqlCharset() {
224        return sqlCharset;
225    }
226
227    private String sqlCharset = null;
228
229    public TCustomLexer(){
230       //this.yyinput = pbuf;
231       yytextbufsize = intial_bufsize - 1;
232       yytextbuf = new char[intial_bufsize];
233       checkyytextbuf(yytextbufsize);
234
235       bufsize = intial_bufsize - 1;
236       buf = new char[intial_bufsize];
237       checkbuf(bufsize);
238
239       //literalbuf = new StringBuffer();
240        literalbuf = new StringBuilder();
241        //keywordList = new TreeMap();
242        delimiterchar = ';';
243        tmpDelimiter = "";
244
245        xcdepth = 0;
246        nchars = 0;
247        isqmarktoident = true;
248
249       yylvalstr = "";
250        yysstate = 0;
251        yylstate = 0;
252        yymatches = 0;
253        yysleng = 0;
254       bufptr = 0;
255       yylineno = 0;
256       yycolno = 0;
257       offset = -1;
258       yylineno_p = 1;
259       yycolno_p = 1;
260       offset_p = 0;
261
262       yypos = new int[max_rules + 1];
263       max_matches = TBaseType.LEXER_INIT_MAX_MATCHES;
264       yystack = new int[max_matches + 1];
265
266        prevToken = null;
267    }
268
269    /*
270     * this function is not used. 
271    private void getkeywordvaluefromfile(){
272        int i;
273        keywordValueList.clear();
274        for(i=0; i<keywordlist.length; i++){
275           // System.out.println(keywordlist[i]);
276            String[] ss = keywordlist[i].split("[=]");
277            keywordValueList.put(ss[0].toUpperCase(),ss[1]);
278        }
279    }
280     */
281
282public  int iskeyword(String str){
283    return -1;
284}
285
286public boolean isAtBeginOfLine(){
287    return (yyretval == lexnewline || yyretval == 0);
288}
289
290//public boolean canBeColumnName(int tokencode){
291//    return false;
292//}
293
294
295public String getStringByCode(int tokenCode){
296    return null;
297}
298
299    public  int getkeywordvalue(String keyword){
300        return 0;
301    }
302
303
304    /**
305     * @deprecated , please use keywordChecker.isKeyword() instead.
306     *
307     * because there are so many non-reserved keywords in some databases, it's not suitable to put those
308     * non-reserved keywords in lexer and parser.
309     *
310     * @param keyword
311     * @param keywordValueList
312     * @param keywordTypeList
313     * @return
314     */
315    public static EKeywordType getKeywordType(String keyword, HashMap<String, Integer> keywordValueList,HashMap<Integer, Integer> keywordTypeList){
316        EKeywordType ret = EKeywordType.NOT_A_KEYWORD;
317        Integer s = keywordValueList.get(keyword.toUpperCase(Locale.ENGLISH));
318        if( s == null) return ret;
319
320        Integer i = keywordTypeList.get(s);
321        if (i == 1) return EKeywordType.RESERVED_WORD;
322        else if (i == 2) return EKeywordType.NON_RESERVED_KEYWORD;
323        else return  ret;
324    }
325
326    /**
327     * 如果是ascii 字符,直接返回,如果是unicode 字符,需要进行转换。否则 String.charAt() 返回的unicode字符不是我们想要的字符,
328     * 例如中文的括号,我们实际需要的ascii的括号
329     *
330     * @param pYylvalstr
331     * @param index
332     * @return
333     */
334   char lexer_charAt(String pYylvalstr,int index){
335        char ret = pYylvalstr.charAt(index);
336        if (ret > 255){
337            // this is a unicode code
338            if ((ret == 0xFF08)){
339                // https://www.utf8-chartable.de/unicode-utf8-table.pl?start=65280&number=128
340                // Unicode code point for FULLWIDTH LEFT PARENTHESIS (, 0xFF08
341                //System.out.println(c);
342                ret = '(';
343            }
344            if ( (ret == 0xFF09)){
345                // https://www.utf8-chartable.de/unicode-utf8-table.pl?start=65280&number=128
346                // Unicode code point for FULLWIDTH RIGHT PARENTHESIS ), 0xFF09
347                // System.out.println(c);
348                ret = ')';
349            }
350        }
351        return ret;
352   }
353   void totablechar(){
354       //System.out.println("char:"+yyactchar+" ,hex:"+String.format("%04x", (int) yyactchar));
355       //System.out.println(String.format("0x%08X", (int)yyactchar)+", "+(char)yyactchar);
356
357    if (((int) yyactchar == 0) && !endOfInput) {
358        yytablechar = (char)255;
359        return;
360    }
361
362     if ((int)(yyactchar) < 228){ // 228 is ä in unicode
363       yytablechar = yyactchar;
364         if ((((int)(yyactchar) == 160)&&(utf8NoBreakSpaceReady))||(yyactchar == 0xA0)){
365             yytablechar = (char)32;
366         }
367       utf8NoBreakSpaceReady = false;
368//         if (yyactchar == 0x27){
369//             insideSingleQuoteStr = !insideSingleQuoteStr;
370//          }
371     }else{
372         yytablechar = (char)'a';//(char)255;
373
374         if ((int)(yyactchar) == 914) { // c2 a0, utf-8 NO-BREAK SPACE
375             utf8NoBreakSpaceReady = true;
376             yytablechar = (char) 32;
377         }else if ((yyactchar == 0x2018)||(yyactchar == 0x2019)){
378             if (stringLiteralStartWithUnicodeSingleQuote){
379                 // WHERE Name LIKE ‘Acme%’
380                 // 如上,如果string literal 以unicode quote 开始,则不管当前是否在string literal中,新碰到的unicode quote都看成是string literal的结尾符,
381                 yytablechar = 0x27; // treat  Unicode Character 'LEFT SINGLE QUOTATION MARK' as the ascii char ', but don't change it
382             }else {
383                 if (insideSingleQuoteStr){
384                     // don't change the unicode quote char
385                 }else {
386                     yytablechar = 0x27; // treat  Unicode Character 'LEFT SINGLE QUOTATION MARK' as the ascii char ', but don't change it
387                 }
388             }
389
390         }else if ((yyactchar == 0x200B)||(yyactchar == 0x3000)){
391             // Unicode code point 0x200B: treat  Unicode Character ZERO WIDTH SPACE as the ascii char space, but don't change it
392             // Unicode code point 0x3000: treat  Unicode Character IDEOGRAPHIC SPACE (UTF-8: e3 80 80) as the ascii char space, but don't change it
393             yytablechar = 0x20;
394         }else if (yyactchar == 0xFF08){
395             yytablechar = '('; // treat  Unicode code point for FULLWIDTH LEFT PARENTHESIS  as the ascii char (, but don't change it
396         }else if (yyactchar == 0xFF09){
397             yytablechar = ')'; // treat  Unicode code point for FULLWIDTH RIGHT PARENTHESIS  as the ascii char ), but don't change it
398         }else if (yyactchar == 0xFF0C){
399             yytablechar = ','; // treat  Unicode code point for FULLWIDTH COMMA  as the ascii char comma, but don't change it
400         }else {
401             utf8NoBreakSpaceReady = false;
402         }
403     }
404   }
405
406    String getyytext(){
407      return new String(yytextbuf,0,yytextlen);
408    }
409
410    void checkyytextbuf(int size){
411       while ( size >= yytextbufsize){
412          yytextbufsize = yytextbufsize * 2 > intial_bufsize ? yytextbufsize * 2: intial_bufsize;
413          char[] tmp = new char[yytextbufsize];
414           System.arraycopy(yytextbuf,0,tmp,0, yytextbuf.length);
415           yytextbuf = tmp;
416       }
417    }
418    
419    void checkbuf(int size){
420       // System.out.println("while begin2"+" size:"+size+" bufsize:"+bufsize);
421       while ( size >= bufsize){
422          bufsize = bufsize * 2 > intial_bufsize ? bufsize * 2: intial_bufsize;
423          char[] tmp = new char[bufsize];
424           System.arraycopy(buf,0,tmp,0, buf.length);
425           buf = tmp;
426       }
427       // System.out.println("while end2");
428    }
429
430    boolean eof(BufferedReader pbuf){
431        try{
432        return !pbuf.ready();
433        }catch(IOException e){
434          return true;
435        }
436    }
437
438    void yynew(){
439        if (yylastchar != (char)0){
440          if(yylastchar == lf){
441            yylstate = 1;
442          }else{
443              yylstate = 0;
444          }
445        }
446
447        yystate = yysstate + yylstate;
448        checkyytextbuf(0);
449        yytextlen = 0;
450        yymatches = 0;
451        yydone = false;
452    }
453
454    void yyscan(){
455        yyactchar = get_char();
456        checkyytextbuf(yytextlen + 1);
457        yytextlen++;
458        yytextbuf[yytextlen - 1] = yyactchar;
459    }
460
461    void yymark(int n){
462        if (n > max_rules ){
463           System.out.println("n > max_rules ");
464        }
465        yypos[n] = yytextlen;
466    }
467
468    void yymatch(int n){
469        yymatches++;
470        if(yymatches > max_matches){
471
472            int new_yystack[] = new int[max_matches*2+1];
473            System.arraycopy(yystack, 0, new_yystack, 0, max_matches);
474            yystack = new_yystack;
475            max_matches = max_matches * 2;
476
477           // this is valid in JDK 1.6, proguard will report warning and stop
478           // yystack = Arrays.copyOf(yystack,max_matches+1);
479
480        }
481        yystack [yymatches] = n;
482    }
483
484    int yyfind(){
485        //return -1 mean not found
486        int ret = -1;
487
488        yyreject = false;
489        
490        while (( yymatches > 0 ) && ( yypos[yystack[yymatches]] == 0 )) {
491           yymatches-- ;
492        }
493        
494
495        if (yymatches > 0){
496          yysleng = yytextlen;
497          ret = yystack[yymatches];
498          yyless( yypos[ret] );
499          yypos[ret] = 0;
500          if (yytextlen >0){
501            yylastchar = yytextbuf [yytextlen-1];
502          }else{
503            yylastchar = (char)0;
504          }
505        }else{
506          yyless( 0 );
507          yylastchar = (char)0;
508        }
509
510       return ret;
511    }
512
513    boolean yydefault(){
514        boolean ret;
515
516        yyreject = false;
517        yyactchar = get_char();
518        if (yyactchar != (char)0){
519          //put_char( yyactchar );
520          ret = true;
521        }else{
522          yylstate = 1;
523          ret = false;
524        }
525        yylastchar = yyactchar;
526        return ret;
527    }
528    void yyless(int n){
529        for(int i= yytextlen; i> n; i--){
530            unget_char(yytextbuf[i - 1]);
531        }
532        checkyytextbuf(n);
533        yytextlen = n;
534    }
535    void returni(int n){
536        yyretval = n;
537        yydone = true;
538    }
539    void returnc(char c){
540        yyretval = (int)c;
541        yydone = true;
542    }
543    void yyclear(){
544        bufptr = 0;
545        yysstate = 0;
546        yylstate = 1;
547        yylastchar = (char)0;
548        yytextlen = 0;
549        yylineno = 0;
550        yycolno = 0;
551        offset = -1;
552       // yystext := '';
553
554        yylineno_p = 1;
555        yycolno_p = 1;
556        offset_p = 0;
557
558    }
559
560    
561    boolean yywrap(){
562        return true;
563    }
564    int getyysstate(){
565        return yysstate;
566    }
567    void start(int pstate){
568        yysstate = pstate;
569        if (pstate == xq){
570            insideSingleQuoteStr = true;
571            if ((yylvalstr.charAt(0) == 0x2018)||(yylvalstr.charAt(0) == 0x2019)){
572                stringLiteralStartWithUnicodeSingleQuote = true;
573            }else{
574                stringLiteralStartWithUnicodeSingleQuote = false;
575            }
576        }else{
577            insideSingleQuoteStr = false;
578        }
579    }
580
581
582    void unget_char(char pchar){
583        if(bufptr == max_chars)
584        {
585            System.out.println("input buffer overflow");
586        }
587      //  if (bufptr > 0) {
588        bufptr++;
589        yycolno--;
590        offset--;
591        checkbuf(bufptr+1);
592        buf[bufptr] = pchar;
593      //  }
594
595    }
596
597    public void reset(){
598        insideSingleQuoteStr = false;
599        nestedLessThan = 0;
600    }
601
602    public boolean insideSingleQuoteStr = false;
603    public boolean stringLiteralStartWithUnicodeSingleQuote = false;
604
605
606    // Previous implementation of readln, 2025-05-04
607    // char[] readln()  throws IOException {
608    //     int c;
609    //     char[] buffer = new char[80];
610    //     int bufferSize = 0;
611
612    //     while ((c = yyinput.read()) != -1) {
613    //         if (bufferSize >= buffer.length) {
614    //             char[] newBuffer = new char[buffer.length * 2];
615    //             System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
616    //             buffer = newBuffer;
617    //         }
618
619    //         buffer[bufferSize++] = (char)c;
620
621    //         if (c == '\n' || c == '\r') {
622    //             break;
623    //         }
624    //     }
625
626    //     if (bufferSize > 0 && buffer[bufferSize - 1] == '\r') {
627    //         yyinput.mark(1);
628    //         c = yyinput.read();
629    //         if (c == '\n') {
630    //             if (bufferSize >= buffer.length) {
631    //                 char[] newBuffer = new char[buffer.length + 1];
632    //                 System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
633    //                 buffer = newBuffer;
634    //             }
635    //             buffer[bufferSize++] = '\n';
636    //         } else {
637    //             yyinput.reset();
638    //         }
639    //     }
640
641    //     if (bufferSize == 0) {
642    //         return null;
643    //     }else{
644    //         char[] result = new char[bufferSize];
645    //         System.arraycopy(buffer, 0, result, 0, bufferSize);
646    //         return result;
647    //     }
648    // }
649
650/**
651 * High-performance line reader with optimal buffer management
652 * @return char array containing the line including line ending, or null if end of stream
653 */
654char[] readln() throws IOException {
655    if (yyinput == null) return null;
656    
657    // Use larger initial buffer size to reduce reallocations
658    char[] buffer = new char[4096];
659    int position = 0;
660    int c;
661    
662    // Read characters until line ending or EOF
663    while ((c = yyinput.read()) != -1) {
664        // Expand buffer if needed
665        if (position >= buffer.length) {
666            char[] newBuffer = new char[buffer.length * 2];
667            System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
668            buffer = newBuffer;
669        }
670        
671        // Store character
672        buffer[position++] = (char)c;
673        
674        // Check for line endings
675        if (c == '\n') {
676            break; // LF - end of line
677        } else if (c == '\r') {
678            // Need to check for CR+LF sequence
679            yyinput.mark(1);
680            c = yyinput.read();
681            
682            if (c == '\n') {
683                // CR+LF sequence - include LF in result
684                if (position >= buffer.length) {
685                    char[] newBuffer = new char[buffer.length + 1];
686                    System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
687                    buffer = newBuffer;
688                }
689                buffer[position++] = '\n';
690            } else {
691                // CR only - reset stream to keep the character after CR
692                yyinput.reset();
693            }
694            break;
695        }
696    }
697    
698    // Return null if no characters were read (end of stream)
699    if (position == 0) {
700        return null;
701    }
702    
703    // Create right-sized result array
704    char[] result = new char[position];
705    System.arraycopy(buffer, 0, result, 0, position);
706    return result;
707}
708
709    char get_char(){
710
711        char ret ;
712         boolean readlineok = true;
713
714        if ((bufptr == 0) && !eof(yyinput) )
715        {
716            try{
717               endOfInput = false;
718               yyline = readln();//yyinput.readLine();
719              // System.out.println("readln: "+yyline);
720                if (yyline == null){
721                  readlineok = false;
722                }  else{
723                    yylineno++;
724                    yycolno = 0;
725                    //bufptr = yyline.length();
726                    bufptr = yyline.length;
727                    checkbuf(bufptr+1);
728                    for(int k=1;k<=bufptr;k++){
729                        buf[k] = yyline[bufptr - k];
730                    //    buf[k] = yyline.charAt(bufptr - k);
731                    }
732                   //  System.out.println("line read:\r\n "+yyline);
733                }
734            }catch(IOException e){
735              readlineok = false;
736            }
737        }
738
739        if (! readlineok){
740          endOfInput = true;
741          return (char)0;
742        }
743
744       if (bufptr > 0){
745         bufptr--;
746         yycolno++;
747         offset++;
748
749         return buf[bufptr+1];
750         //return yyline.charAt(yyline.length()  - (bufptr + 1));
751       }else{
752       // bufptr--;
753           endOfInput = true;
754        return  (char)0;
755       }
756
757    }
758
759    void startlit(){
760        literalbuf.setLength(0);
761        literallen = 0;
762        literalalloc = 0;
763    }
764
765    void addlit(String ytext, int yleng){
766        literallen = literallen + yleng;
767        literalbuf.append(ytext,0,yleng);
768    }
769
770    void addlitchar(char ychar){
771        literallen++;
772        literalbuf.append(ychar);
773    }
774
775    String litbufdup(){
776        return literalbuf.toString();//.intern();
777    }
778
779    boolean isopchar(char ch){
780        String opstr = new String("~!@#^&|`?$%");
781        return opstr.indexOf((int)ch) != -1;
782    }
783
784    boolean isselfchar(char ch){
785        String opstr = new String(",()[].;$:+-*/%^<>=!");
786        return opstr.indexOf((int)ch) != -1;
787    }
788
789    boolean charinarray(char c, char[] a){
790       // return new String(a).indexOf((int)c) != -1;
791        int len = a.length;
792        for (int i = 0; i < len; i++) {
793            if (a[i] == c)
794                return true;
795        }
796        return false;
797    }
798
799    void setlengthofliteralbuf(int plen){
800      literalbuf.setLength(plen);
801    }
802
803    void yyaction(int yyruleno){
804    }
805
806    int yylex(){
807        return 0;
808    }
809
810
811    int yylexwrap(TSourceToken psourcetoken) {
812        // Get token code and handle EOF
813        if ((psourcetoken.tokencode = yylex()) == 0) return 0;
814    
815        // Assign token text
816        psourcetoken.astext = yylvalstr;
817    
818        // Record token position information
819        psourcetoken.lineNo = yylineno_p;
820        psourcetoken.columnNo = yycolno_p;
821        psourcetoken.offset = offset_p;
822        yylineno_p = yylineno;
823        yycolno_p = yycolno + 1;
824        offset_p = offset + 1;
825        
826        // Track token in token table for analysis
827        setTokenTableValue(psourcetoken);
828    
829        // Handle token types based on token code
830        switch (psourcetoken.tokencode) {
831            case cmtdoublehyphen:
832                psourcetoken.tokentype = ETokenType.ttsimplecomment;
833                if (dbvendor == EDbVendor.dbvmdx && psourcetoken.toString().startsWith("/")) {
834                    psourcetoken.tokentype = ETokenType.ttCPPComment;
835                }
836                break;
837                
838            case cmtslashstar:
839                psourcetoken.tokentype = ETokenType.ttbracketedcomment;
840                break;
841                
842            case lexspace:
843                psourcetoken.tokentype = ETokenType.ttwhitespace;
844                break;
845                
846            case lexnewline:
847                psourcetoken.tokentype = ETokenType.ttreturn;
848                break;
849                
850            case bind_v:
851                psourcetoken.tokentype = ETokenType.ttbindvar;
852                if (dbvendor == EDbVendor.dbvoracle) {
853                    psourcetoken.astext = psourcetoken.astext.replace(TBaseType.newline, "");
854                }
855                break;
856                
857            case stmt_delimiter:
858                psourcetoken.tokentype = ETokenType.ttstmt_delimiter;
859                psourcetoken.tokencode = cmtslashstar;
860                break;
861                
862            case concatenationop:
863                psourcetoken.tokentype = ETokenType.ttconcatenationop;
864                break;
865                
866            case variable:
867                psourcetoken.tokentype = ETokenType.ttsqlvar;
868                break;
869                
870            case fconst:
871            case iconst:
872                psourcetoken.tokentype = ETokenType.ttnumber;
873                break;
874                
875            case sconst:
876                psourcetoken.tokentype = ETokenType.ttsqstring;
877                psourcetoken.dolqstart = dolqstart;
878                dolqstart = "";
879                break;
880                
881            case ident:
882            case QUOTED_IDENT:
883                handleIdentifierToken(psourcetoken);
884                break;
885                
886            case cmpop:
887                handleComparisonOperator(psourcetoken);
888                break;
889                
890            case op:
891                handleOperatorToken(psourcetoken);
892                break;
893                
894            default:
895                handleDefaultToken(psourcetoken);
896                break;
897        }
898    
899        prevToken = psourcetoken;
900        return psourcetoken.tokencode;
901    }
902    
903    // Helper methods to better organize the complex token handling logic
904    private void handleIdentifierToken(TSourceToken psourcetoken) {
905        psourcetoken.tokentype = ETokenType.ttidentifier;
906        String tokenText = psourcetoken.astext.trim();
907        
908        if (tokenText.startsWith("\"")) {
909            psourcetoken.tokentype = ETokenType.ttdqstring;
910        } else if (tokenText.startsWith("[")) {
911            if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) {
912                psourcetoken.tokentype = ETokenType.ttdbstring;
913            }
914        } else if (tokenText.startsWith("{")) {
915            if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) {
916                psourcetoken.tokentype = ETokenType.ttbrstring;
917                if (tokenText.toLowerCase().startsWith("{escape")) {
918                    psourcetoken.tokencode = TBaseType.rrw_sqlserver_odbc_escape;
919                }
920            }
921        } else if (tokenText.startsWith("&")) {
922            if (dbvendor == EDbVendor.dbvmdx) {
923                if (psourcetoken.tokencode == QUOTED_IDENT) {
924                    psourcetoken.tokencode = AMP_QUOTED_ID;
925                } else if (psourcetoken.tokencode == ident) {
926                    psourcetoken.tokencode = AMP_UNQUOTED_ID;
927                }
928            }
929        } else if (tokenText.startsWith(".")) {
930            if (dbvendor == EDbVendor.dbvteradata) {
931                psourcetoken.tokentype = ETokenType.ttBTEQCmd;
932            }
933        }
934    }
935    
936    private void handleComparisonOperator(TSourceToken psourcetoken) {
937        psourcetoken.tokentype = ETokenType.ttmulticharoperator;
938        String token = yylvalstr;
939        
940        if ((token.startsWith("!") && token.endsWith("=")) ||
941            (token.startsWith("^") && token.endsWith("=")) ||
942            (token.startsWith("<") && token.endsWith(">"))) {
943            
944            psourcetoken.tokencode = TBaseType.not_equal;
945            
946            // Handle MySQL NULL-safe equal
947            if (token.indexOf("=", 1) > 0 && 
948                token.startsWith("<") && token.endsWith(">")) {
949                psourcetoken.tokencode = (int)'=';
950            }
951        } else if (token.startsWith(">") && token.endsWith("=")) {
952            psourcetoken.tokencode = TBaseType.great_equal;
953        } else if (token.startsWith("<") && token.endsWith("=")) {
954            psourcetoken.tokencode = TBaseType.less_equal;
955        } else if ((token.startsWith("!") && token.endsWith("<")) ||
956                   (token.startsWith("^") && token.endsWith("<"))) {
957            psourcetoken.tokencode = TBaseType.not_less;
958        } else if ((token.startsWith("!") && token.endsWith(">")) ||
959                   (token.startsWith("^") && token.endsWith(">"))) {
960            psourcetoken.tokencode = TBaseType.not_great;
961        } else if (token.length() == 2 && token.charAt(0) == ':' && token.charAt(1) == '=') {
962            psourcetoken.tokencode = assign_sign;
963        }
964    }
965    
966    private void handleOperatorToken(TSourceToken psourcetoken) {
967        psourcetoken.tokentype = ETokenType.ttmulticharoperator;
968        String token = yylvalstr;
969        int tokenLength = token.length();
970        char firstChar = tokenLength > 0 ? token.charAt(0) : '\0';
971        char secondChar = tokenLength > 1 ? token.charAt(1) : '\0';
972        
973        // Handle question mark specially
974        if (token.equals("?") && isqmarktoident) {
975            handleQuestionMark(psourcetoken);
976            return;
977        }
978        
979        // Handle special two-character operators
980        if (tokenLength == 2) {
981            if (handleTwoCharOperator(psourcetoken, firstChar, secondChar)) {
982                return;
983            }
984        }
985        
986        // Handle special three-character operators
987        if (tokenLength == 3) {
988            if (handleThreeCharOperator(psourcetoken, firstChar, secondChar, token.charAt(2))) {
989                return;
990            }
991        }
992        
993        // Handle comparison operators
994        if (handleComparisonOp(psourcetoken, token)) {
995            return;
996        }
997        
998        // Handle single character operators
999        if (tokenLength == 1) {
1000            handleSingleCharOperator(psourcetoken, firstChar);
1001        }
1002    }
1003    
1004    private boolean handleTwoCharOperator(TSourceToken psourcetoken, char firstChar, char secondChar) {
1005        switch (firstChar) {
1006            case '<':
1007                if (secondChar == '<') {
1008                    return handleLeftShiftOperator(psourcetoken);
1009                } else if (secondChar == '@') {
1010                    psourcetoken.tokencode = TBaseType.JSON_RIGHT_CONTAIN;
1011                    return true;
1012                }
1013                break;
1014                
1015            case '>':
1016                if (secondChar == '>') {
1017                    return handleRightShiftOperator(psourcetoken);
1018                }
1019                break;
1020                
1021            case '=':
1022                if (secondChar == '>') {
1023                    if (dbvendor == EDbVendor.dbvodbc) {
1024                        psourcetoken.tokencode = TBaseType.great_equal;
1025                    } else if (dbvendor == EDbVendor.dbvpostgresql || dbvendor == EDbVendor.dbvgaussdb) {
1026                        psourcetoken.tokencode = TBaseType.assign_sign;
1027                    } else {
1028                        psourcetoken.tokencode = NAMED_PARAMETER_SIGN;
1029                    }
1030                    return true;
1031                } else if (secondChar == '*') {
1032                    if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) {
1033                        psourcetoken.tokencode = rightjoin_op;
1034                    }
1035                    return true;
1036                } else if (secondChar == '<') {
1037                    if (dbvendor == EDbVendor.dbvodbc) {
1038                        psourcetoken.tokencode = TBaseType.less_equal;
1039                    }
1040                    return true;
1041                } else if (secondChar == '=') {
1042                    if (dbvendor == EDbVendor.dbvsparksql) {
1043                        psourcetoken.tokencode = '=';
1044                    }
1045                    return true;
1046                }
1047                break;
1048                
1049            case '-':
1050                if (secondChar == '>') {
1051                    if (dbvendor == EDbVendor.dbvpostgresql || dbvendor == EDbVendor.dbvgaussdb 
1052                        || dbvendor == EDbVendor.dbvgreenplum || dbvendor == EDbVendor.dbvmysql) {
1053                        psourcetoken.tokencode = TBaseType.JSON_GET_OBJECT;
1054                    } else {
1055                        psourcetoken.tokencode = ref_arrow;
1056                    }
1057                    return true;
1058                } else if (secondChar == '=') {
1059                    if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) {
1060                        psourcetoken.tokencode = compoundAssignmentOperator;
1061                    }
1062                    return true;
1063                }
1064                break;
1065                
1066            case '.':
1067                if (secondChar == '.') {
1068                    if (dbvendor == EDbVendor.dbvdb2 || dbvendor == EDbVendor.dbvoracle 
1069                        || dbvendor == EDbVendor.dbvmysql || dbvendor == EDbVendor.dbvhana) {
1070                        psourcetoken.tokencode = double_dot;
1071                    }
1072                    return true;
1073                }
1074                break;
1075                
1076            case '*':
1077                if (secondChar == '=') {
1078                    if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) {
1079                        psourcetoken.tokencode = leftjoin_op;
1080                    }
1081                    return true;
1082                } else if (secondChar == '*') {
1083                    if (dbvendor == EDbVendor.dbvteradata || dbvendor == EDbVendor.dbvnetezza) {
1084                        psourcetoken.tokencode = TBaseType.exponentiate;
1085                    }
1086                    return true;
1087                }
1088                break;
1089                
1090            case '|':
1091                if (secondChar == '|') {
1092                    if (dbvendor == EDbVendor.dbvmysql) {
1093                        psourcetoken.tokencode = TBaseType.logical_or;
1094                    } else if (isStringConcatVendor(dbvendor)) {
1095                        psourcetoken.tokencode = TBaseType.concatenationop;
1096                    }
1097                    return true;
1098                } else if (secondChar == '/') {
1099                    if (dbvendor == EDbVendor.dbvredshift) {
1100                        psourcetoken.tokencode = TBaseType.square_root;
1101                    }
1102                    return true;
1103                }
1104                break;
1105                
1106            case '&':
1107                if (secondChar == '&') {
1108                    if (dbvendor == EDbVendor.dbvmysql) {
1109                        psourcetoken.tokencode = TBaseType.logical_and;
1110                    }
1111                    return true;
1112                }
1113                break;
1114                
1115            case '?':
1116                if (secondChar == '|') {
1117                    psourcetoken.tokencode = TBaseType.JSON_ANY_EXIST;
1118                    return true;
1119                } else if (secondChar == '&') {
1120                    psourcetoken.tokencode = TBaseType.JSON_ALL_EXIST;
1121                    return true;
1122                }
1123                break;
1124                
1125            case '@':
1126                if (secondChar == '>') {
1127                    psourcetoken.tokencode = TBaseType.JSON_LEFT_CONTAIN;
1128                    return true;
1129                }
1130                break;
1131                
1132            case '#':
1133                if (secondChar == '>') {
1134                    psourcetoken.tokencode = TBaseType.JSON_GET_OBJECT_AT_PATH;
1135                    return true;
1136                }
1137                break;
1138                
1139            case ':':
1140                if (secondChar == '=') {
1141                    psourcetoken.tokencode = assign_sign;
1142                    return true;
1143                }
1144                break;
1145        }
1146        
1147        // Handle compound assignment operators
1148        if ((firstChar == '+' || firstChar == '-' || firstChar == '*' || 
1149             firstChar == '/' || firstChar == '%' || firstChar == '&' || 
1150             firstChar == '^' || firstChar == '|') && secondChar == '=') {
1151            if (dbvendor == EDbVendor.dbvmssql || dbvendor == EDbVendor.dbvsybase) {
1152                psourcetoken.tokencode = compoundAssignmentOperator;
1153                return true;
1154            } else if (dbvendor == EDbVendor.dbvmysql && firstChar == '^' && secondChar == '=') {
1155                psourcetoken.tokencode = not_equal;
1156                return true;
1157            }
1158        }
1159        
1160        return false;
1161    }
1162    
1163    private boolean handleThreeCharOperator(TSourceToken psourcetoken, char firstChar, char secondChar, char thirdChar) {
1164        if (firstChar == '-' && secondChar == '>' && thirdChar == '>') {
1165            psourcetoken.tokencode = TBaseType.JSON_GET_TEXT;
1166            return true;
1167        } else if (firstChar == '#' && secondChar == '>' && thirdChar == '>') {
1168            psourcetoken.tokencode = TBaseType.JSON_GET_TEXT_AT_PATH;
1169            return true;
1170        } else if (firstChar == '|' && secondChar == '|' && thirdChar == '/') {
1171            if (dbvendor == EDbVendor.dbvredshift) {
1172                psourcetoken.tokencode = TBaseType.cube_root;
1173                return true;
1174            }
1175        }
1176        return false;
1177    }
1178    
1179    private boolean handleComparisonOp(TSourceToken psourcetoken, String token) {
1180        if ((token.startsWith("!") && token.endsWith("=")) ||
1181            (token.startsWith("^") && token.endsWith("=")) ||
1182            (token.startsWith("<") && token.endsWith(">"))) {
1183            psourcetoken.tokencode = TBaseType.not_equal;
1184            return true;
1185        } else if (token.startsWith(">") && token.endsWith("=")) {
1186            psourcetoken.tokencode = TBaseType.great_equal;
1187            return true;
1188        } else if (token.startsWith("<") && token.endsWith("=")) {
1189            psourcetoken.tokencode = TBaseType.less_equal;
1190            return true;
1191        } else if ((token.startsWith("!") && token.endsWith("<")) ||
1192                   (token.startsWith("^") && token.endsWith("<"))) {
1193            psourcetoken.tokencode = TBaseType.not_less;
1194            return true;
1195        } else if ((token.startsWith("!") && token.endsWith(">")) ||
1196                   (token.startsWith("^") && token.endsWith(">"))) {
1197            psourcetoken.tokencode = TBaseType.not_great;
1198            return true;
1199        }
1200        return false;
1201    }
1202    
1203    private void handleSingleCharOperator(TSourceToken psourcetoken, char ch) {
1204        switch (ch) {
1205            case '~':
1206                if (dbvendor == EDbVendor.dbvmysql || dbvendor == EDbVendor.dbvredshift || 
1207                    dbvendor == EDbVendor.dbvsnowflake) {
1208                    psourcetoken.tokencode = (int)'~';
1209                }
1210                break;
1211                
1212            case '#':
1213                if (dbvendor == EDbVendor.dbvmssql) {
1214                    psourcetoken.tokencode = (int)'#';
1215                }
1216                break;
1217                
1218            case '&':
1219                if (dbvendor == EDbVendor.dbvmysql || dbvendor == EDbVendor.dbvvertica || 
1220                    dbvendor == EDbVendor.dbvsparksql) {
1221                    psourcetoken.tokencode = (int)'&';
1222                }
1223                break;
1224                
1225            case '|':
1226                if (dbvendor == EDbVendor.dbvmysql || dbvendor == EDbVendor.dbvvertica) {
1227                    psourcetoken.tokencode = (int)'|';
1228                }
1229                break;
1230        }
1231    }
1232    
1233    private void handleQuestionMark(TSourceToken psourcetoken) {
1234        if (dbvendor == EDbVendor.dbvpostgresql || dbvendor == EDbVendor.dbvgaussdb || 
1235            dbvendor == EDbVendor.dbvgreenplum) {
1236            psourcetoken.tokencode = TBaseType.JSON_EXIST;
1237        } else if (dbvendor == EDbVendor.dbvodbc) {
1238            psourcetoken.tokencode = '?';
1239        } else if (dbvendor == EDbVendor.dbvsnowflake) {
1240            psourcetoken.tokencode = bind_v;
1241            psourcetoken.tokentype = ETokenType.ttquestionmark;
1242        } else {
1243            psourcetoken.tokencode = ident;
1244        }
1245    }
1246    
1247    private boolean handleLeftShiftOperator(TSourceToken psourcetoken) {
1248        if (dbvendor == EDbVendor.dbvoracle || dbvendor == EDbVendor.dbvmssql || 
1249            dbvendor == EDbVendor.dbvsybase || dbvendor == EDbVendor.dbvpostgresql || 
1250            dbvendor == EDbVendor.dbvgaussdb || dbvendor == EDbVendor.dbvaccess || 
1251            dbvendor == EDbVendor.dbvgreenplum) {
1252            psourcetoken.tokencode = label_begin;
1253        } else if (dbvendor == EDbVendor.dbvmysql) {
1254            psourcetoken.tokencode = TBaseType.rrw_left_shift;
1255        } else if (dbvendor == EDbVendor.dbvredshift) {
1256            psourcetoken.tokencode = TBaseType.bitwise_shift_left;
1257        } else if (dbvendor == EDbVendor.dbvnetezza) {
1258            psourcetoken.tokencode = TBaseType.rrw_netezza_op_less_less;
1259        }
1260        return true;
1261    }
1262    
1263    private boolean handleRightShiftOperator(TSourceToken psourcetoken) {
1264        if (dbvendor == EDbVendor.dbvoracle || dbvendor == EDbVendor.dbvmssql || 
1265            dbvendor == EDbVendor.dbvsybase || dbvendor == EDbVendor.dbvpostgresql || 
1266            dbvendor == EDbVendor.dbvgaussdb || dbvendor == EDbVendor.dbvgreenplum || 
1267            dbvendor == EDbVendor.dbvaccess) {
1268            psourcetoken.tokencode = label_end;
1269        } else if (dbvendor == EDbVendor.dbvmysql) {
1270            psourcetoken.tokencode = TBaseType.rrw_right_shift;
1271        } else if (dbvendor == EDbVendor.dbvredshift) {
1272            psourcetoken.tokencode = TBaseType.bitwise_shift_right;
1273        } else if (dbvendor == EDbVendor.dbvnetezza) {
1274            psourcetoken.tokencode = TBaseType.rrw_netezza_op_great_great;
1275        }
1276        return true;
1277    }
1278    
1279    private boolean isStringConcatVendor(EDbVendor vendor) {
1280        return vendor == EDbVendor.dbvdb2 || vendor == EDbVendor.dbvnetezza || 
1281               vendor == EDbVendor.dbvpostgresql || vendor == EDbVendor.dbvgaussdb || 
1282               vendor == EDbVendor.dbvredshift || vendor == EDbVendor.dbvgreenplum || 
1283               vendor == EDbVendor.dbvbigquery || vendor == EDbVendor.dbvsnowflake || 
1284               vendor == EDbVendor.dbvsparksql || vendor == EDbVendor.dbvvertica;
1285    }
1286    
1287    private void handleDefaultToken(TSourceToken psourcetoken) {
1288        psourcetoken.tokentype = ETokenType.ttkeyword;
1289        
1290        if (psourcetoken.tokencode < 255) {
1291            // Single character operators (ASCII characters)
1292            psourcetoken.astext = Character.toString(yylvalstr.charAt(0));
1293            psourcetoken.tokentype = ETokenType.ttsinglecharoperator;
1294            
1295            switch (psourcetoken.tokencode) {
1296                case ',':
1297                    psourcetoken.tokentype = ETokenType.ttcomma;
1298                    break;
1299                case '(':
1300                    psourcetoken.tokentype = ETokenType.ttleftparenthesis;
1301                    break;
1302                case ')':
1303                    psourcetoken.tokentype = ETokenType.ttrightparenthesis;
1304                    break;
1305                case '[':
1306                    psourcetoken.tokentype = ETokenType.ttleftbracket;
1307                    break;
1308                case ']':
1309                    psourcetoken.tokentype = ETokenType.ttrightbracket;
1310                    break;
1311                case '.':
1312                    psourcetoken.tokentype = ETokenType.ttperiod;
1313                    break;
1314                case ';':
1315                    psourcetoken.tokentype = ETokenType.ttsemicolon;
1316                    break;
1317                case '$':
1318                    psourcetoken.tokentype = ETokenType.ttdolorsign;
1319                    break;
1320                case ':':
1321                    psourcetoken.tokentype = ETokenType.ttcolon;
1322                    break;
1323                case '+':
1324                    psourcetoken.tokentype = ETokenType.ttplussign;
1325                    break;
1326                case '-':
1327                    psourcetoken.tokentype = ETokenType.ttminussign;
1328                    break;
1329                case '*':
1330                    psourcetoken.tokentype = ETokenType.ttasterisk;
1331                    break;
1332                case '/':
1333                    psourcetoken.tokentype = ETokenType.ttslash;
1334                    break;
1335                case '^':
1336                    psourcetoken.tokentype = ETokenType.ttcaret;
1337                    break;
1338                case '<':
1339                    psourcetoken.tokentype = ETokenType.ttlessthan;
1340                    break;
1341                case '>':
1342                    psourcetoken.tokentype = ETokenType.ttgreaterthan;
1343                    break;
1344                case '=':
1345                    psourcetoken.tokentype = ETokenType.ttequals;
1346                    break;
1347                case '@':
1348                    if (delimiterchar == '@') {
1349                        psourcetoken.tokencode = (int)';';
1350                        psourcetoken.tokentype = ETokenType.ttsemicolon;
1351                    } else {
1352                        psourcetoken.tokentype = ETokenType.ttatsign;
1353                    }
1354                    break;
1355                case '~':
1356                    psourcetoken.tokentype = ETokenType.tttilde;
1357                    break;
1358                case '&':
1359                    psourcetoken.tokentype = ETokenType.ttampersand;
1360                    break;
1361                case '|':
1362                    psourcetoken.tokentype = ETokenType.ttverticalbar;
1363                    break;
1364                case '?':
1365                    if (isqmarktoident && dbvendor != EDbVendor.dbvodbc && 
1366                        dbvendor != EDbVendor.dbvpostgresql && dbvendor != EDbVendor.dbvgaussdb) {
1367                        psourcetoken.tokencode = ident;
1368                    }
1369                    break;
1370            }
1371        } else if (dbvendor == EDbVendor.dbvhive && psourcetoken.tokencode == TBaseType.hive_equal) {
1372            psourcetoken.tokentype = ETokenType.ttequals;
1373        }
1374    }
1375
1376}
1377