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