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