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