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