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