001/*
002 * Units of Measurement Systems
003 * Copyright (c) 2005-2021, Jean-Marie Dautelle, Werner Keil and others.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification,
008 * are permitted provided that the following conditions are met:
009 *
010 * 1. Redistributions of source code must retain the above copyright notice,
011 *    this list of conditions and the following disclaimer.
012 *
013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
014 *    and the following disclaimer in the documentation and/or other materials provided with the distribution.
015 *
016 * 3. Neither the name of JSR-385, Units of Measurement nor the names of their contributors may be used to
017 *    endorse or promote products derived from this software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package systems.uom.ucum.internal.format;
031
032import static systems.uom.ucum.internal.format.UnitTokenConstants.*;
033import static tech.units.indriya.AbstractUnit.ONE;
034
035import javax.measure.Unit;
036import javax.measure.Prefix;
037
038import tech.units.indriya.format.SymbolMap;
039import tech.units.indriya.function.LogConverter;
040import tech.units.indriya.function.MultiplyConverter;
041
042
043@SuppressWarnings({"rawtypes", "unchecked"})
044public final class UnitFormatParser {
045
046    private static class Exponent {
047
048        public final int pow;
049
050        public final int root;
051
052        public Exponent(int pow, int root) {
053            this.pow = pow;
054            this.root = root;
055        }
056    }
057    private SymbolMap symbols;
058
059    public UnitFormatParser(SymbolMap symbols, java.io.Reader in) {
060        this(in);
061        this.symbols = symbols;
062    }
063
064
065    final public Unit parseUnit() throws TokenException {
066        Unit result = CompoundExpr();
067        consumeToken(0);
068        {
069            return result;
070        }
071    }
072
073    final public Unit CompoundExpr() throws TokenException {
074        throw new UnsupportedOperationException("Compound units not supported");
075    }
076
077    final public Unit AddExpr() throws TokenException {
078        Unit result = ONE;
079        Number n1 = null;
080        Token sign1 = null;
081        Number n2 = null;
082        Token sign2 = null;
083        if (jj_2_1(2147483647)) {
084            n1 = NumberExpr();
085            sign1 = Sign();
086        } else {
087        }
088        result = MulExpr();
089        switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
090            case PLUS:
091            case MINUS:
092                sign2 = Sign();
093                n2 = NumberExpr();
094                break;
095            default:
096                laA[1] = genInt;
097        }
098        if (n1 != null) {
099            if (sign1.image.equals("-")) {
100                result = result.multiply(-1);
101            }
102            result = result.shift(n1.doubleValue());
103        }
104        if (n2 != null) {
105            double offset = n2.doubleValue();
106            if (sign2.image.equals("-")) {
107                offset = -offset;
108            }
109            result = result.shift(offset);
110        }
111        {
112            return result;
113        }
114    }
115
116    final public Unit MulExpr() throws TokenException {
117        Unit result = ONE;
118        Unit temp = ONE;
119        result = ExponentExpr();
120        label_2:
121        while (true) {
122            switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
123                case ASTERISK:
124                case MIDDLE_DOT:
125                case SOLIDUS:
126                    break;
127                default:
128                    laA[2] = genInt;
129                    break label_2;
130            }
131            switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
132                case ASTERISK:
133                case MIDDLE_DOT:
134                    switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
135                        case ASTERISK:
136                            consumeToken(ASTERISK);
137                            break;
138                        case MIDDLE_DOT:
139                            consumeToken(MIDDLE_DOT);
140                            break;
141                        default:
142                            laA[3] = genInt;
143                            consumeToken(-1);
144                            throw new TokenException();
145                    }
146                    temp = ExponentExpr();
147                    result = result.multiply(temp);
148                    break;
149                case SOLIDUS:
150                    consumeToken(SOLIDUS);
151                    temp = ExponentExpr();
152                    result = result.divide(temp);
153                    break;
154                default:
155                    laA[4] = genInt;
156                    consumeToken(-1);
157                    throw new TokenException();
158            }
159        }
160        {
161            return result;
162        }
163    }
164
165    final public Unit ExponentExpr() throws TokenException {
166        Unit result = ONE;
167        Exponent exponent = null;
168        Token token = null;
169        if (jj_2_2(2147483647)) {
170            switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
171                case INTEGER:
172                    token = consumeToken(INTEGER);
173                    break;
174                case E:
175                    token = consumeToken(E);
176                    break;
177                default:
178                    laA[5] = genInt;
179                    consumeToken(-1);
180                    throw new TokenException();
181            }
182            consumeToken(CARET);
183            result = AtomicExpr();
184            double base;
185            if (token.kind == INTEGER) {
186                base = Integer.parseInt(token.image);
187            } else {
188                base = StrictMath.E;
189            }
190            {
191                return result.transform(new LogConverter(base).inverse());
192            }
193        } else {
194            switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
195                case OPEN_PAREN:
196                case INTEGER:
197                case FLOATING_POINT:
198                case UNIT_IDENTIFIER:
199                    result = AtomicExpr();
200                    switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
201                        case CARET:
202                        case SUPERSCRIPT_INTEGER:
203                            exponent = Exp();
204                            break;
205                        default:
206                            laA[6] = genInt;
207                    }
208                    if (exponent != null) {
209                        if (exponent.pow != 1) {
210                            result = result.pow(exponent.pow);
211                        }
212                        if (exponent.root != 1) {
213                            result = result.root(exponent.root);
214                        }
215                    } {
216                    return result;
217                }
218                case LOG:
219                case NAT_LOG:
220                    switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
221                        case LOG:
222                            consumeToken(LOG);
223                            switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
224                                case INTEGER:
225                                    token = consumeToken(INTEGER);
226                                    break;
227                                default:
228                                    laA[7] = genInt;
229                            }
230                            break;
231                        case NAT_LOG:
232                            token = consumeToken(NAT_LOG);
233                            break;
234                        default:
235                            laA[8] = genInt;
236                            consumeToken(-1);
237                            throw new TokenException();
238                    }
239                    consumeToken(OPEN_PAREN);
240                    result = AddExpr();
241                    consumeToken(CLOSE_PAREN);
242                    double base = 10;
243                    if (token != null) {
244                        if (token.kind == INTEGER) {
245                            base = Integer.parseInt(token.image);
246                        } else if (token.kind == NAT_LOG) {
247                            base = StrictMath.E;
248                        }
249                    } {
250                    return result.transform(new LogConverter(base));
251                }
252                default:
253                    laA[9] = genInt;
254                    consumeToken(-1);
255                    throw new TokenException();
256            }
257        }
258    }
259
260    final public Unit AtomicExpr() throws TokenException {
261        Unit result = ONE;
262        Number n = null;
263        Token token = null;
264        switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
265            case INTEGER:
266            case FLOATING_POINT:
267                n = NumberExpr();
268                if (n instanceof Integer) {
269                    {
270                        return result.multiply(n.intValue());
271                    }
272                } else {
273                    {
274                        return result.multiply(n.doubleValue());
275                    }
276                }
277            case UNIT_IDENTIFIER:
278                token = consumeToken(UNIT_IDENTIFIER);
279                Unit unit = symbols.getUnit(token.image);
280                if (unit == null) {
281                    Prefix prefix = symbols.getPrefix(token.image);
282                    if (prefix != null) {
283                        String prefixSymbol = symbols.getSymbol(prefix);
284                        unit = symbols.getUnit(token.image.substring(prefixSymbol.length()));
285                        if (unit != null) {
286                            {
287                                return unit.transform(MultiplyConverter.ofPrefix(prefix));
288                            }
289                        }
290                    }
291                    {
292                        throw new TokenException();
293                    }
294                } else {
295                    {
296                        return unit;
297                    }
298                }
299            case OPEN_PAREN:
300                consumeToken(OPEN_PAREN);
301                result = AddExpr();
302                consumeToken(CLOSE_PAREN); {
303                return result;
304            }
305            default:
306                laA[10] = genInt;
307                consumeToken(-1);
308                throw new TokenException();
309        }
310    }
311
312    final public Token Sign() throws TokenException {
313        Token result = null;
314        switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
315            case PLUS:
316                result = consumeToken(PLUS);
317                break;
318            case MINUS:
319                result = consumeToken(MINUS);
320                break;
321            default:
322                laA[11] = genInt;
323                consumeToken(-1);
324                throw new TokenException();
325        }
326        {
327            return result;
328        }
329    }
330
331    final public Number NumberExpr() throws TokenException {
332        Token token = null;
333        switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
334            case INTEGER:
335                token = consumeToken(INTEGER); {
336                return Long.valueOf(token.image);
337            }
338            case FLOATING_POINT:
339                token = consumeToken(FLOATING_POINT); {
340                return Double.valueOf(token.image);
341            }
342            default:
343                laA[12] = genInt;
344                consumeToken(-1);
345                throw new TokenException();
346        }
347    }
348
349    final public Exponent Exp() throws TokenException {
350        Token powSign = null;
351        Token powToken = null;
352        Token rootSign = null;
353        Token rootToken = null;
354        switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
355            case CARET:
356                consumeToken(CARET);
357                switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
358                    case PLUS:
359                    case MINUS:
360                    case INTEGER:
361                        switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
362                            case PLUS:
363                            case MINUS:
364                                powSign = Sign();
365                                break;
366                            default:
367                                laA[13] = genInt;
368                        }
369                        powToken = consumeToken(INTEGER);
370                        int pow = Integer.parseInt(powToken.image);
371                        if ((powSign != null) && powSign.image.equals("-")) {
372                            pow = -pow;
373                        } {
374                        return new Exponent(pow, 1);
375                    }
376                    case OPEN_PAREN:
377                        consumeToken(OPEN_PAREN);
378                        switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
379                            case PLUS:
380                            case MINUS:
381                                powSign = Sign();
382                                break;
383                            default:
384                                laA[14] = genInt;
385                        }
386                        powToken = consumeToken(INTEGER);
387                        switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
388                            case SOLIDUS:
389                                consumeToken(SOLIDUS);
390                                switch ((nextTokenIndex == -1) ? jj_ntk() : nextTokenIndex) {
391                                    case PLUS:
392                                    case MINUS:
393                                        rootSign = Sign();
394                                        break;
395                                    default:
396                                        laA[15] = genInt;
397                                }
398                                rootToken = consumeToken(INTEGER);
399                                break;
400                            default:
401                                laA[16] = genInt;
402                        }
403                        consumeToken(CLOSE_PAREN);
404                        pow = Integer.parseInt(powToken.image);
405                        if ((powSign != null) && powSign.image.equals("-")) {
406                            pow = -pow;
407                        }
408                        int root = 1;
409                        if (rootToken != null) {
410                            root = Integer.parseInt(rootToken.image);
411                            if ((rootSign != null) && rootSign.image.equals("-")) {
412                                root = -root;
413                            }
414                        } {
415                        return new Exponent(pow, root);
416                    }
417                    default:
418                        laA[17] = genInt;
419                        consumeToken(-1);
420                        throw new TokenException();
421                }
422            case SUPERSCRIPT_INTEGER:
423                powToken = consumeToken(SUPERSCRIPT_INTEGER);
424                int pow = 0;
425                for (int i = 0; i < powToken.image.length(); i += 1) {
426                    pow *= 10;
427                    switch (powToken.image.charAt(i)) {
428                        case '\u00b9':
429                            pow += 1;
430                            break;
431                        case '\u00b2':
432                            pow += 2;
433                            break;
434                        case '\u00b3':
435                            pow += 3;
436                            break;
437                        case '\u2074':
438                            pow += 4;
439                            break;
440                        case '\u2075':
441                            pow += 5;
442                            break;
443                        case '\u2076':
444                            pow += 6;
445                            break;
446                        case '\u2077':
447                            pow += 7;
448                            break;
449                        case '\u2078':
450                            pow += 8;
451                            break;
452                        case '\u2079':
453                            pow += 9;
454                            break;
455                    }
456                } {
457                return new Exponent(pow, 1);
458            }
459            default:
460                laA[18] = genInt;
461                consumeToken(-1);
462                throw new TokenException();
463        }
464    }
465
466    private boolean jj_2_1(int xla) {
467        laInt = xla;
468        lastpos = scanpos = token;
469        try {
470            return !jj_3_1();
471        } catch (LookaheadSuccess ls) {
472            return true;
473        } finally {
474            jj_save(0, xla);
475        }
476    }
477
478    private boolean jj_2_2(int xla) {
479        laInt = xla;
480        lastpos = scanpos = token;
481        try {
482            return !jj_3_2();
483        } catch (LookaheadSuccess ls) {
484            return true;
485        } finally {
486            jj_save(1, xla);
487        }
488    }
489
490    private boolean jj_3R_3() {
491        Token xsp;
492        xsp = scanpos;
493        if (jj_3R_5()) {
494            scanpos = xsp;
495            if (jj_3R_6())
496                return true;
497        }
498        return false;
499    }
500
501    private boolean jj_3R_6() {
502        return scanToken(FLOATING_POINT);
503    }
504
505    private boolean jj_3_2() {
506        Token xsp;
507        xsp = scanpos;
508        if (scanToken(14)) {
509            scanpos = xsp;
510            if (scanToken(19))
511                return true;
512        }
513        return scanToken(CARET);
514    }
515
516    private boolean jj_3_1() {
517        return jj_3R_3() || jj_3R_4();
518    }
519
520    private boolean jj_3R_4() {
521        Token xsp;
522        xsp = scanpos;
523        if (scanToken(5)) {
524            scanpos = xsp;
525            if (scanToken(6))
526                return true;
527        }
528        return false;
529    }
530
531    private boolean jj_3R_5() {
532        return scanToken(INTEGER);
533    }
534    /** Generated Token Manager. */
535    public UnitTokenManager tokenSource;
536
537    UCUMCharStream inputStream;
538
539    /** Current token. */
540    public Token token;
541
542    /** Next token. */
543    public Token nextToken;
544
545    private int nextTokenIndex;
546
547    private Token scanpos, lastpos;
548
549    private int laInt;
550
551    private int genInt;
552
553    final private int[] laA = new int[19];
554
555    static private int[] laB;
556
557    static {
558        init();
559    }
560
561    private static void init() {
562        laB = new int[]{0x800, 0x60, 0x380, 0x180, 0x380, 0x84000, 0x8400, 0x4000, 0x60000, 0x175000, 0x115000, 0x60, 0x14000, 0x60, 0x60, 0x60, 0x200, 0x5060, 0x8400,};
563    }
564    final private JJCalls[] rtns = new JJCalls[2];
565
566    private boolean rescan = false;
567
568    private int gcInt = 0;
569
570    /** Constructor with InputStream. */
571    public UnitFormatParser(java.io.InputStream stream) {
572        this(stream, null);
573    }
574
575    /** Constructor with InputStream and supplied encoding */
576    public UnitFormatParser(java.io.InputStream stream, String encoding) {
577        try {
578            inputStream = new UCUMCharStream(stream, encoding, 1, 1);
579        } catch (java.io.UnsupportedEncodingException e) {
580            throw new RuntimeException(e);
581        }
582        tokenSource = new UnitTokenManager(inputStream);
583        token = new Token();
584        nextTokenIndex = -1;
585        genInt = 0;
586        for (int i = 0; i < 19; i++) {
587            laA[i] = -1;
588        }
589        for (int i = 0; i < rtns.length; i++) {
590            rtns[i] = new JJCalls();
591        }
592    }
593
594    /** Reinitialise. */
595    public void ReInit(java.io.InputStream stream) {
596        ReInit(stream, null);
597    }
598
599    /** Reinitialise. */
600    public void ReInit(java.io.InputStream stream, String encoding) {
601        try {
602            inputStream.ReInit(stream, encoding, 1, 1);
603        } catch (java.io.UnsupportedEncodingException e) {
604            throw new RuntimeException(e);
605        }
606        tokenSource.ReInit(inputStream);
607        token = new Token();
608        nextTokenIndex = -1;
609        genInt = 0;
610        for (int i = 0; i < 19; i++) {
611            laA[i] = -1;
612        }
613        for (int i = 0; i < rtns.length; i++) {
614            rtns[i] = new JJCalls();
615        }
616    }
617
618    /** Constructor. */
619    public UnitFormatParser(java.io.Reader stream) {
620        inputStream = new UCUMCharStream(stream, 1, 1);
621        tokenSource = new UnitTokenManager(inputStream);
622        token = new Token();
623        nextTokenIndex = -1;
624        genInt = 0;
625        for (int i = 0; i < 19; i++) {
626            laA[i] = -1;
627        }
628        for (int i = 0; i < rtns.length; i++) {
629            rtns[i] = new JJCalls();
630        }
631    }
632
633    /** Reinitialise. */
634    public void ReInit(java.io.Reader stream) {
635        inputStream.ReInit(stream, 1, 1);
636        tokenSource.ReInit(inputStream);
637        token = new Token();
638        nextTokenIndex = -1;
639        genInt = 0;
640        for (int i = 0; i < 19; i++) {
641            laA[i] = -1;
642        }
643        for (int i = 0; i < rtns.length; i++) {
644            rtns[i] = new JJCalls();
645        }
646    }
647
648    /** Constructor with generated Token Manager. */
649    public UnitFormatParser(UnitTokenManager tm) {
650        tokenSource = tm;
651        token = new Token();
652        nextTokenIndex = -1;
653        genInt = 0;
654        for (int i = 0; i < 19; i++) {
655            laA[i] = -1;
656        }
657        for (int i = 0; i < rtns.length; i++) {
658            rtns[i] = new JJCalls();
659        }
660    }
661
662    /** Reinitialise. */
663    public void ReInit(UnitTokenManager tm) {
664        tokenSource = tm;
665        token = new Token();
666        nextTokenIndex = -1;
667        genInt = 0;
668        for (int i = 0; i < 19; i++) {
669            laA[i] = -1;
670        }
671        for (int i = 0; i < rtns.length; i++) {
672            rtns[i] = new JJCalls();
673        }
674    }
675
676    private Token consumeToken(int kind) throws TokenException {
677        Token oldToken;
678        if ((oldToken = token).next != null)
679            token = token.next;
680        else
681            token = token.next = tokenSource.getNextToken();
682        nextTokenIndex = -1;
683        if (token.kind == kind) {
684            genInt++;
685            if (++gcInt > 100) {
686                gcInt = 0;
687                for (JJCalls jj_2_rtn : rtns) {
688                    JJCalls c = jj_2_rtn;
689                    while (c != null) {
690                        if (c.gen < genInt)
691                            c.first = null;
692                        c = c.next;
693                    }
694                }
695            }
696            return token;
697        }
698        token = oldToken;
699        this.kind = kind;
700        throw raiseTokenException();
701    }
702
703    static private final class LookaheadSuccess extends java.lang.RuntimeException {
704        private static final long serialVersionUID = 2205332054119123041L;
705    }
706
707    private boolean scanToken(int kind) {
708        if (scanpos == lastpos) {
709            laInt--;
710            if (scanpos.next == null) {
711                lastpos = scanpos = scanpos.next = tokenSource.getNextToken();
712            } else {
713                lastpos = scanpos = scanpos.next;
714            }
715        } else {
716            scanpos = scanpos.next;
717        }
718        if (rescan) {
719            int i = 0;
720            Token tok = token;
721            while (tok != null && tok != scanpos) {
722                i++;
723                tok = tok.next;
724            }
725            if (tok != null)
726                jj_add_error_token(kind, i);
727        }
728        if (scanpos.kind != kind)
729            return true;
730        if (laInt == 0 && scanpos == lastpos)
731            throw new LookaheadSuccess();
732        return false;
733    }
734
735    /** Get the next Token. */
736    final public Token getNextToken() {
737        if (token.next != null)
738            token = token.next;
739        else
740            token = token.next = tokenSource.getNextToken();
741        nextTokenIndex = -1;
742        genInt++;
743        return token;
744    }
745
746    /** Get the specific Token. */
747    final public Token getToken(int index) {
748        Token t = token;
749        for (int i = 0; i < index; i++) {
750            if (t.next != null)
751                t = t.next;
752            else
753                t = t.next = tokenSource.getNextToken();
754        }
755        return t;
756    }
757
758    private int jj_ntk() {
759        if ((nextToken = token.next) == null) {
760            return (nextTokenIndex = (token.next = tokenSource.getNextToken()).kind);
761        }
762        else {
763            return (nextTokenIndex = nextToken.kind);
764        }
765    }
766    private java.util.List<int[]> expentries = new java.util.ArrayList<>();
767
768    private int[] expentry;
769
770    private int kind = -1;
771
772    private int[] lastTokens = new int[100];
773
774    private int endpos;
775
776    private void jj_add_error_token(int kind, int pos) {
777        if (pos >= 100)
778            return;
779        if (pos == endpos + 1) {
780            lastTokens[endpos++] = kind;
781        } else if (endpos != 0) {
782            expentry = new int[endpos];
783            System.arraycopy(lastTokens, 0, expentry, 0, endpos);
784            entriesLoop:
785            for (int[] jj_expentry1 : expentries) {
786                if (jj_expentry1.length == expentry.length) {
787                    for (int i = 0; i < expentry.length; i++) {
788                        if (jj_expentry1[i] != expentry[i]) {
789                            continue entriesLoop;
790                        }
791                    }
792                    expentries.add(expentry);
793                    break;
794                }
795            }
796            if (pos != 0)
797                lastTokens[(endpos = pos) - 1] = kind;
798        }
799    }
800
801    /** Generate TokenException. */
802    TokenException raiseTokenException() {
803        expentries.clear();
804        boolean[] la1tokens = new boolean[21];
805        if (kind >= 0) {
806            la1tokens[kind] = true;
807            kind = -1;
808        }
809        for (int i = 0; i < 19; i++) {
810            if (laA[i] == genInt) {
811                for (int j = 0; j < 32; j++) {
812                    if ((laB[i] & (1 << j)) != 0) {
813                        la1tokens[j] = true;
814                    }
815                }
816            }
817        }
818        for (int i = 0; i < 21; i++) {
819            if (la1tokens[i]) {
820                expentry = new int[1];
821                expentry[0] = i;
822                expentries.add(expentry);
823            }
824        }
825        endpos = 0;
826        jj_rescan_token();
827        jj_add_error_token(0, 0);
828        int[][] exptokseq = new int[expentries.size()][];
829        for (int i = 0; i < expentries.size(); i++) {
830            exptokseq[i] = expentries.get(i);
831        }
832        return new TokenException(token, exptokseq, tokenImage);
833    }
834
835    /** Enable tracing. */
836    final public void enable_tracing() {
837    }
838
839    /** Disable tracing. */
840    final public void disable_tracing() {
841    }
842
843    private void jj_rescan_token() {
844        rescan = true;
845        for (int i = 0; i < 2; i++) {
846            try {
847                JJCalls p = rtns[i];
848                do {
849                    if (p.gen > genInt) {
850                        laInt = p.arg;
851                        lastpos = scanpos = p.first;
852                        switch (i) {
853                            case 0:
854                                jj_3_1();
855                                break;
856                            case 1:
857                                jj_3_2();
858                                break;
859                        }
860                    }
861                    p = p.next;
862                } while (p != null);
863            } catch (LookaheadSuccess ls) {
864            }
865        }
866        rescan = false;
867    }
868
869    private void jj_save(int index, int xla) {
870        JJCalls p = rtns[index];
871        while (p.gen > genInt) {
872            if (p.next == null) {
873                p = p.next = new JJCalls();
874                break;
875            }
876            p = p.next;
877        }
878        p.gen = genInt + xla - laInt;
879        p.first = token;
880        p.arg = xla;
881    }
882
883    static final class JJCalls {
884
885        int gen;
886
887        Token first;
888
889        int arg;
890
891        JJCalls next;
892
893    }
894}