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