home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2005 July / PCpro_2005_07.ISO / files / wintools / FullSync / FullSyncInstaller.exe / org / apache / regexp / RECompiler.class (.txt) < prev    next >
Encoding:
Java Class File  |  2005-03-08  |  9.1 KB  |  842 lines

  1. package org.apache.regexp;
  2.  
  3. import java.util.Hashtable;
  4.  
  5. public class RECompiler {
  6.    char[] instruction = new char[128];
  7.    int lenInstruction = 0;
  8.    String pattern;
  9.    int len;
  10.    int idx;
  11.    int parens;
  12.    static final int NODE_NORMAL = 0;
  13.    static final int NODE_NULLABLE = 1;
  14.    static final int NODE_TOPLEVEL = 2;
  15.    static final char ESC_MASK = '\ufff0';
  16.    static final char ESC_BACKREF = '\uffff';
  17.    static final char ESC_COMPLEX = '\ufffe';
  18.    static final char ESC_CLASS = '∩┐╜';
  19.    int maxBrackets = 10;
  20.    static final int bracketUnbounded = -1;
  21.    int brackets = 0;
  22.    int[] bracketStart = null;
  23.    int[] bracketEnd = null;
  24.    int[] bracketMin = null;
  25.    int[] bracketOpt = null;
  26.    static Hashtable hashPOSIX = new Hashtable();
  27.  
  28.    void ensure(int var1) {
  29.       int var2 = this.instruction.length;
  30.       if (this.lenInstruction + var1 >= var2) {
  31.          while(this.lenInstruction + var1 >= var2) {
  32.             var2 *= 2;
  33.          }
  34.  
  35.          char[] var3 = new char[var2];
  36.          System.arraycopy(this.instruction, 0, var3, 0, this.lenInstruction);
  37.          this.instruction = var3;
  38.       }
  39.  
  40.    }
  41.  
  42.    void emit(char var1) {
  43.       this.ensure(1);
  44.       this.instruction[this.lenInstruction++] = var1;
  45.    }
  46.  
  47.    void nodeInsert(char var1, int var2, int var3) {
  48.       this.ensure(3);
  49.       System.arraycopy(this.instruction, var3, this.instruction, var3 + 3, this.lenInstruction - var3);
  50.       this.instruction[var3 + 0] = var1;
  51.       this.instruction[var3 + 1] = (char)var2;
  52.       this.instruction[var3 + 2] = 0;
  53.       this.lenInstruction += 3;
  54.    }
  55.  
  56.    void setNextOfEnd(int var1, int var2) {
  57.       for(char var3 = this.instruction[var1 + 2]; var3 != 0 && var1 < this.lenInstruction; var3 = this.instruction[var1 + 2]) {
  58.          if (var1 == var2) {
  59.             var2 = this.lenInstruction;
  60.          }
  61.  
  62.          var1 += var3;
  63.       }
  64.  
  65.       if (var1 < this.lenInstruction) {
  66.          this.instruction[var1 + 2] = (char)((short)(var2 - var1));
  67.       }
  68.  
  69.    }
  70.  
  71.    int node(char var1, int var2) {
  72.       this.ensure(3);
  73.       this.instruction[this.lenInstruction + 0] = var1;
  74.       this.instruction[this.lenInstruction + 1] = (char)var2;
  75.       this.instruction[this.lenInstruction + 2] = 0;
  76.       this.lenInstruction += 3;
  77.       return this.lenInstruction - 3;
  78.    }
  79.  
  80.    void internalError() throws Error {
  81.       throw new Error("Internal error!");
  82.    }
  83.  
  84.    void syntaxError(String var1) throws RESyntaxException {
  85.       throw new RESyntaxException(var1);
  86.    }
  87.  
  88.    void allocBrackets() {
  89.       if (this.bracketStart == null) {
  90.          this.bracketStart = new int[this.maxBrackets];
  91.          this.bracketEnd = new int[this.maxBrackets];
  92.          this.bracketMin = new int[this.maxBrackets];
  93.          this.bracketOpt = new int[this.maxBrackets];
  94.  
  95.          for(int var1 = 0; var1 < this.maxBrackets; ++var1) {
  96.             this.bracketStart[var1] = this.bracketEnd[var1] = this.bracketMin[var1] = this.bracketOpt[var1] = -1;
  97.          }
  98.       }
  99.  
  100.    }
  101.  
  102.    synchronized void reallocBrackets() {
  103.       if (this.bracketStart == null) {
  104.          this.allocBrackets();
  105.       }
  106.  
  107.       int var1 = this.maxBrackets * 2;
  108.       int[] var2 = new int[var1];
  109.       int[] var3 = new int[var1];
  110.       int[] var4 = new int[var1];
  111.       int[] var5 = new int[var1];
  112.  
  113.       for(int var6 = this.brackets; var6 < var1; ++var6) {
  114.          var2[var6] = var3[var6] = var4[var6] = var5[var6] = -1;
  115.       }
  116.  
  117.       System.arraycopy(this.bracketStart, 0, var2, 0, this.brackets);
  118.       System.arraycopy(this.bracketEnd, 0, var3, 0, this.brackets);
  119.       System.arraycopy(this.bracketMin, 0, var4, 0, this.brackets);
  120.       System.arraycopy(this.bracketOpt, 0, var5, 0, this.brackets);
  121.       this.bracketStart = var2;
  122.       this.bracketEnd = var3;
  123.       this.bracketMin = var4;
  124.       this.bracketOpt = var5;
  125.       this.maxBrackets = var1;
  126.    }
  127.  
  128.    void bracket() throws RESyntaxException {
  129.       if (this.idx >= this.len || this.pattern.charAt(this.idx++) != '{') {
  130.          this.internalError();
  131.       }
  132.  
  133.       if (this.idx >= this.len || !Character.isDigit(this.pattern.charAt(this.idx))) {
  134.          this.syntaxError("Expected digit");
  135.       }
  136.  
  137.       StringBuffer var1 = new StringBuffer();
  138.  
  139.       while(this.idx < this.len && Character.isDigit(this.pattern.charAt(this.idx))) {
  140.          var1.append(this.pattern.charAt(this.idx++));
  141.       }
  142.  
  143.       try {
  144.          this.bracketMin[this.brackets] = Integer.parseInt(var1.toString());
  145.       } catch (NumberFormatException var4) {
  146.          this.syntaxError("Expected valid number");
  147.       }
  148.  
  149.       if (this.idx >= this.len) {
  150.          this.syntaxError("Expected comma or right bracket");
  151.       }
  152.  
  153.       if (this.pattern.charAt(this.idx) == '}') {
  154.          ++this.idx;
  155.          this.bracketOpt[this.brackets] = 0;
  156.       } else {
  157.          if (this.idx >= this.len || this.pattern.charAt(this.idx++) != ',') {
  158.             this.syntaxError("Expected comma");
  159.          }
  160.  
  161.          if (this.idx >= this.len) {
  162.             this.syntaxError("Expected comma or right bracket");
  163.          }
  164.  
  165.          if (this.pattern.charAt(this.idx) == '}') {
  166.             ++this.idx;
  167.             this.bracketOpt[this.brackets] = -1;
  168.          } else {
  169.             if (this.idx >= this.len || !Character.isDigit(this.pattern.charAt(this.idx))) {
  170.                this.syntaxError("Expected digit");
  171.             }
  172.  
  173.             var1.setLength(0);
  174.  
  175.             while(this.idx < this.len && Character.isDigit(this.pattern.charAt(this.idx))) {
  176.                var1.append(this.pattern.charAt(this.idx++));
  177.             }
  178.  
  179.             try {
  180.                this.bracketOpt[this.brackets] = Integer.parseInt(var1.toString()) - this.bracketMin[this.brackets];
  181.             } catch (NumberFormatException var3) {
  182.                this.syntaxError("Expected valid number");
  183.             }
  184.  
  185.             if (this.bracketOpt[this.brackets] < 0) {
  186.                this.syntaxError("Bad range");
  187.             }
  188.  
  189.             if (this.idx >= this.len || this.pattern.charAt(this.idx++) != '}') {
  190.                this.syntaxError("Missing close brace");
  191.             }
  192.  
  193.          }
  194.       }
  195.    }
  196.  
  197.    char escape() throws RESyntaxException {
  198.       if (this.pattern.charAt(this.idx) != '\\') {
  199.          this.internalError();
  200.       }
  201.  
  202.       if (this.idx + 1 == this.len) {
  203.          this.syntaxError("Escape terminates string");
  204.       }
  205.  
  206.       this.idx += 2;
  207.       char var1 = this.pattern.charAt(this.idx - 1);
  208.       switch (var1) {
  209.          case '0':
  210.          case '1':
  211.          case '2':
  212.          case '3':
  213.          case '4':
  214.          case '5':
  215.          case '6':
  216.          case '7':
  217.          case '8':
  218.          case '9':
  219.             if ((this.idx >= this.len || !Character.isDigit(this.pattern.charAt(this.idx))) && var1 != '0') {
  220.                return '\uffff';
  221.             } else {
  222.                int var5 = var1 - 48;
  223.                if (this.idx < this.len && Character.isDigit(this.pattern.charAt(this.idx))) {
  224.                   var5 = (var5 << 3) + (this.pattern.charAt(this.idx++) - 48);
  225.                   if (this.idx < this.len && Character.isDigit(this.pattern.charAt(this.idx))) {
  226.                      var5 = (var5 << 3) + (this.pattern.charAt(this.idx++) - 48);
  227.                   }
  228.                }
  229.  
  230.                return (char)var5;
  231.             }
  232.          case ':':
  233.          case ';':
  234.          case '<':
  235.          case '=':
  236.          case '>':
  237.          case '?':
  238.          case '@':
  239.          case 'A':
  240.          case 'C':
  241.          case 'E':
  242.          case 'F':
  243.          case 'G':
  244.          case 'H':
  245.          case 'I':
  246.          case 'J':
  247.          case 'K':
  248.          case 'L':
  249.          case 'M':
  250.          case 'N':
  251.          case 'O':
  252.          case 'P':
  253.          case 'Q':
  254.          case 'R':
  255.          case 'T':
  256.          case 'U':
  257.          case 'V':
  258.          case 'X':
  259.          case 'Y':
  260.          case 'Z':
  261.          case '[':
  262.          case '\\':
  263.          case ']':
  264.          case '^':
  265.          case '_':
  266.          case '`':
  267.          case 'a':
  268.          case 'c':
  269.          case 'e':
  270.          case 'g':
  271.          case 'h':
  272.          case 'i':
  273.          case 'j':
  274.          case 'k':
  275.          case 'l':
  276.          case 'm':
  277.          case 'o':
  278.          case 'p':
  279.          case 'q':
  280.          case 'v':
  281.          default:
  282.             return var1;
  283.          case 'B':
  284.          case 'b':
  285.             return '\ufffe';
  286.          case 'D':
  287.          case 'S':
  288.          case 'W':
  289.          case 'd':
  290.          case 's':
  291.          case 'w':
  292.             return '∩┐╜';
  293.          case 'f':
  294.             return '\f';
  295.          case 'n':
  296.             return '\n';
  297.          case 'r':
  298.             return '\r';
  299.          case 't':
  300.             return '\t';
  301.          case 'u':
  302.          case 'x':
  303.             int var2 = var1 == 'u' ? 4 : 2;
  304.  
  305.             int var3;
  306.             for(var3 = 0; this.idx < this.len && var2-- > 0; ++this.idx) {
  307.                char var4 = this.pattern.charAt(this.idx);
  308.                if (var4 >= '0' && var4 <= '9') {
  309.                   var3 = (var3 << 4) + var4 - 48;
  310.                } else {
  311.                   var4 = Character.toLowerCase(var4);
  312.                   if (var4 >= 'a' && var4 <= 'f') {
  313.                      var3 = (var3 << 4) + (var4 - 97) + 10;
  314.                   } else {
  315.                      this.syntaxError("Expected " + var2 + " hexadecimal digits after \\" + var1);
  316.                   }
  317.                }
  318.             }
  319.  
  320.             return (char)var3;
  321.       }
  322.    }
  323.  
  324.    int characterClass() throws RESyntaxException {
  325.       if (this.pattern.charAt(this.idx) != '[') {
  326.          this.internalError();
  327.       }
  328.  
  329.       if (this.idx + 1 >= this.len || this.pattern.charAt(++this.idx) == ']') {
  330.          this.syntaxError("Empty or unterminated class");
  331.       }
  332.  
  333.       if (this.idx < this.len && this.pattern.charAt(this.idx) == ':') {
  334.          ++this.idx;
  335.  
  336.          int var1;
  337.          for(var1 = this.idx; this.idx < this.len && this.pattern.charAt(this.idx) >= 'a' && this.pattern.charAt(this.idx) <= 'z'; ++this.idx) {
  338.          }
  339.  
  340.          if (this.idx + 1 < this.len && this.pattern.charAt(this.idx) == ':' && this.pattern.charAt(this.idx + 1) == ']') {
  341.             String var2 = this.pattern.substring(var1, this.idx);
  342.             Character var3 = (Character)hashPOSIX.get(var2);
  343.             if (var3 != null) {
  344.                this.idx += 2;
  345.                return this.node('P', var3);
  346.             }
  347.  
  348.             this.syntaxError("Invalid POSIX character class '" + var2 + "'");
  349.          }
  350.  
  351.          this.syntaxError("Invalid POSIX character class syntax");
  352.       }
  353.  
  354.       int var12 = this.node('[', 0);
  355.       char var13 = '\uffff';
  356.       char var14 = var13;
  357.       char var4 = '\u0000';
  358.       boolean var5 = true;
  359.       boolean var6 = false;
  360.       int var7 = this.idx;
  361.       char var8 = 0;
  362.       RERange var10 = new RERange(this);
  363.  
  364.       while(this.idx < this.len && this.pattern.charAt(this.idx) != ']') {
  365.          label105:
  366.          switch (this.pattern.charAt(this.idx)) {
  367.             case '-':
  368.                if (var6) {
  369.                   this.syntaxError("Bad class range");
  370.                }
  371.  
  372.                var6 = true;
  373.                var8 = var14 == var13 ? 0 : var14;
  374.                if (this.idx + 1 >= this.len || this.pattern.charAt(++this.idx) != ']') {
  375.                   continue;
  376.                }
  377.  
  378.                var4 = '\uffff';
  379.                break;
  380.             case '\\':
  381.                char var11;
  382.                switch (var11 = this.escape()) {
  383.                   case '\ufffe':
  384.                   case '\uffff':
  385.                      this.syntaxError("Bad character class");
  386.                   case '∩┐╜':
  387.                      if (var6) {
  388.                         this.syntaxError("Bad character class");
  389.                      }
  390.  
  391.                      switch (this.pattern.charAt(this.idx - 1)) {
  392.                         case 'D':
  393.                         case 'S':
  394.                         case 'W':
  395.                            this.syntaxError("Bad character class");
  396.                         case 's':
  397.                            var10.include('\t', var5);
  398.                            var10.include('\r', var5);
  399.                            var10.include('\f', var5);
  400.                            var10.include('\n', var5);
  401.                            var10.include('\b', var5);
  402.                            var10.include(' ', var5);
  403.                            break;
  404.                         case 'w':
  405.                            var10.include(97, 122, var5);
  406.                            var10.include(65, 90, var5);
  407.                            var10.include('_', var5);
  408.                         case 'd':
  409.                            var10.include(48, 57, var5);
  410.                      }
  411.  
  412.                      var14 = var13;
  413.                      continue;
  414.                   default:
  415.                      var4 = var11;
  416.                      break label105;
  417.                }
  418.             case '^':
  419.                var5 = !var5;
  420.                if (this.idx == var7) {
  421.                   var10.include(0, 65535, true);
  422.                }
  423.  
  424.                ++this.idx;
  425.                continue;
  426.             default:
  427.                var4 = this.pattern.charAt(this.idx++);
  428.          }
  429.  
  430.          if (var6) {
  431.             if (var8 >= var4) {
  432.                this.syntaxError("Bad character class");
  433.             }
  434.  
  435.             var10.include(var8, var4, var5);
  436.             var14 = var13;
  437.             var6 = false;
  438.          } else {
  439.             if (this.idx >= this.len || this.pattern.charAt(this.idx) != '-') {
  440.                var10.include(var4, var5);
  441.             }
  442.  
  443.             var14 = var4;
  444.          }
  445.       }
  446.  
  447.       if (this.idx == this.len) {
  448.          this.syntaxError("Unterminated character class");
  449.       }
  450.  
  451.       ++this.idx;
  452.       this.instruction[var12 + 1] = (char)var10.num;
  453.  
  454.       for(int var16 = 0; var16 < var10.num; ++var16) {
  455.          this.emit((char)var10.minRange[var16]);
  456.          this.emit((char)var10.maxRange[var16]);
  457.       }
  458.  
  459.       return var12;
  460.    }
  461.  
  462.    int atom() throws RESyntaxException {
  463.       int var1 = this.node('A', 0);
  464.       int var2 = 0;
  465.  
  466.       label46:
  467.       while(this.idx < this.len) {
  468.          if (this.idx + 1 < this.len) {
  469.             char var3 = this.pattern.charAt(this.idx + 1);
  470.             if (this.pattern.charAt(this.idx) == '\\') {
  471.                int var4 = this.idx;
  472.                this.escape();
  473.                if (this.idx < this.len) {
  474.                   var3 = this.pattern.charAt(this.idx);
  475.                }
  476.  
  477.                this.idx = var4;
  478.             }
  479.  
  480.             switch (var3) {
  481.                case '*':
  482.                case '+':
  483.                case '?':
  484.                case '{':
  485.                   if (var2 != 0) {
  486.                      break label46;
  487.                   }
  488.             }
  489.          }
  490.  
  491.          switch (this.pattern.charAt(this.idx)) {
  492.             case '$':
  493.             case '(':
  494.             case ')':
  495.             case '.':
  496.             case '[':
  497.             case ']':
  498.             case '^':
  499.             case '|':
  500.                break label46;
  501.             case '*':
  502.             case '+':
  503.             case '?':
  504.             case '{':
  505.                if (var2 == 0) {
  506.                   this.syntaxError("Missing operand to closure");
  507.                }
  508.                break label46;
  509.             case '\\':
  510.                int var5 = this.idx;
  511.                char var6 = this.escape();
  512.                if ((var6 & '\ufff0') == 65520) {
  513.                   this.idx = var5;
  514.                   break label46;
  515.                }
  516.  
  517.                this.emit(var6);
  518.                ++var2;
  519.                break;
  520.             default:
  521.                this.emit(this.pattern.charAt(this.idx++));
  522.                ++var2;
  523.          }
  524.       }
  525.  
  526.       if (var2 == 0) {
  527.          this.internalError();
  528.       }
  529.  
  530.       this.instruction[var1 + 1] = (char)var2;
  531.       return var1;
  532.    }
  533.  
  534.    int terminal(int[] var1) throws RESyntaxException {
  535.       switch (this.pattern.charAt(this.idx)) {
  536.          case '$':
  537.          case '.':
  538.          case '^':
  539.             return this.node(this.pattern.charAt(this.idx++), 0);
  540.          case '(':
  541.             return this.expr(var1);
  542.          case ')':
  543.             this.syntaxError("Unexpected close paren");
  544.          case '|':
  545.             this.internalError();
  546.          case ']':
  547.             this.syntaxError("Mismatched class");
  548.          case '\u0000':
  549.             this.syntaxError("Unexpected end of input");
  550.          case '*':
  551.          case '+':
  552.          case '?':
  553.          case '{':
  554.             this.syntaxError("Missing operand to closure");
  555.          case '\\':
  556.             int var2 = this.idx;
  557.             switch (this.escape()) {
  558.                case '∩┐╜':
  559.                case '\ufffe':
  560.                   var1[0] &= -2;
  561.                   return this.node('\\', this.pattern.charAt(this.idx - 1));
  562.                case '\uffff':
  563.                   char var3 = (char)(this.pattern.charAt(this.idx - 1) - 48);
  564.                   if (this.parens <= var3) {
  565.                      this.syntaxError("Bad backreference");
  566.                   }
  567.  
  568.                   var1[0] |= 1;
  569.                   return this.node('#', var3);
  570.                default:
  571.                   this.idx = var2;
  572.                   var1[0] &= -2;
  573.             }
  574.          default:
  575.             var1[0] &= -2;
  576.             return this.atom();
  577.          case '[':
  578.             return this.characterClass();
  579.       }
  580.    }
  581.  
  582.    int closure(int[] var1) throws RESyntaxException {
  583.       int var2 = this.idx;
  584.       int[] var3 = new int[]{0};
  585.       int var4 = this.terminal(var3);
  586.       var1[0] |= var3[0];
  587.       if (this.idx >= this.len) {
  588.          return var4;
  589.       } else {
  590.          boolean var5 = true;
  591.          char var6 = this.pattern.charAt(this.idx);
  592.          switch (var6) {
  593.             case '*':
  594.             case '?':
  595.                var1[0] |= 1;
  596.             case '+':
  597.                ++this.idx;
  598.             case '{':
  599.                char var7 = this.instruction[var4 + 0];
  600.                if (var7 == '^' || var7 == '$') {
  601.                   this.syntaxError("Bad closure operand");
  602.                }
  603.  
  604.                if ((var3[0] & 1) != 0) {
  605.                   this.syntaxError("Closure operand can't be nullable");
  606.                }
  607.             default:
  608.                if (this.idx < this.len && this.pattern.charAt(this.idx) == '?') {
  609.                   ++this.idx;
  610.                   var5 = false;
  611.                }
  612.  
  613.                if (var5) {
  614.                   switch (var6) {
  615.                      case '+':
  616.                         int var10 = this.node('|', 0);
  617.                         this.setNextOfEnd(var4, var10);
  618.                         this.setNextOfEnd(this.node('G', 0), var4);
  619.                         this.setNextOfEnd(var10, this.node('|', 0));
  620.                         this.setNextOfEnd(var4, this.node('N', 0));
  621.                         break;
  622.                      case '{':
  623.                         boolean var8 = false;
  624.                         this.allocBrackets();
  625.  
  626.                         int var9;
  627.                         for(var9 = 0; var9 < this.brackets; ++var9) {
  628.                            if (this.bracketStart[var9] == this.idx) {
  629.                               var8 = true;
  630.                               break;
  631.                            }
  632.                         }
  633.  
  634.                         if (!var8) {
  635.                            if (this.brackets >= this.maxBrackets) {
  636.                               this.reallocBrackets();
  637.                            }
  638.  
  639.                            this.bracketStart[this.brackets] = this.idx;
  640.                            this.bracket();
  641.                            this.bracketEnd[this.brackets] = this.idx;
  642.                            var9 = this.brackets++;
  643.                         }
  644.  
  645.                         if (this.bracketMin[var9]-- > 0) {
  646.                            if (this.bracketMin[var9] <= 0 && this.bracketOpt[var9] == 0) {
  647.                               this.idx = this.bracketEnd[var9];
  648.                            } else {
  649.                               this.idx = var2;
  650.                            }
  651.                            break;
  652.                         } else if (this.bracketOpt[var9] == -1) {
  653.                            var6 = '*';
  654.                            this.bracketOpt[var9] = 0;
  655.                            this.idx = this.bracketEnd[var9];
  656.                         } else if (this.bracketOpt[var9]-- <= 0) {
  657.                            this.lenInstruction = var4;
  658.                            this.node('N', 0);
  659.                            this.idx = this.bracketEnd[var9];
  660.                            break;
  661.                         } else {
  662.                            if (this.bracketOpt[var9] > 0) {
  663.                               this.idx = var2;
  664.                            } else {
  665.                               this.idx = this.bracketEnd[var9];
  666.                            }
  667.  
  668.                            var6 = '?';
  669.                         }
  670.                      case '*':
  671.                      case '?':
  672.                         if (var5) {
  673.                            if (var6 == '?') {
  674.                               this.nodeInsert('|', 0, var4);
  675.                               this.setNextOfEnd(var4, this.node('|', 0));
  676.                               int var11 = this.node('N', 0);
  677.                               this.setNextOfEnd(var4, var11);
  678.                               this.setNextOfEnd(var4 + 3, var11);
  679.                            }
  680.  
  681.                            if (var6 == '*') {
  682.                               this.nodeInsert('|', 0, var4);
  683.                               this.setNextOfEnd(var4 + 3, this.node('|', 0));
  684.                               this.setNextOfEnd(var4 + 3, this.node('G', 0));
  685.                               this.setNextOfEnd(var4 + 3, var4);
  686.                               this.setNextOfEnd(var4, this.node('|', 0));
  687.                               this.setNextOfEnd(var4, this.node('N', 0));
  688.                            }
  689.                         }
  690.                   }
  691.                } else {
  692.                   this.setNextOfEnd(var4, this.node('E', 0));
  693.                   switch (var6) {
  694.                      case '*':
  695.                         this.nodeInsert('8', 0, var4);
  696.                         break;
  697.                      case '+':
  698.                         this.nodeInsert('=', 0, var4);
  699.                         break;
  700.                      case '?':
  701.                         this.nodeInsert('/', 0, var4);
  702.                   }
  703.  
  704.                   this.setNextOfEnd(var4, this.lenInstruction);
  705.                }
  706.  
  707.                return var4;
  708.          }
  709.       }
  710.    }
  711.  
  712.    int branch(int[] var1) throws RESyntaxException {
  713.       int var3 = this.node('|', 0);
  714.       int var4 = -1;
  715.       int[] var5 = new int[1];
  716.  
  717.       int var2;
  718.       boolean var6;
  719.       for(var6 = true; this.idx < this.len && this.pattern.charAt(this.idx) != '|' && this.pattern.charAt(this.idx) != ')'; var4 = var2) {
  720.          var5[0] = 0;
  721.          var2 = this.closure(var5);
  722.          if (var5[0] == 0) {
  723.             var6 = false;
  724.          }
  725.  
  726.          if (var4 != -1) {
  727.             this.setNextOfEnd(var4, var2);
  728.          }
  729.       }
  730.  
  731.       if (var4 == -1) {
  732.          this.node('N', 0);
  733.       }
  734.  
  735.       if (var6) {
  736.          var1[0] |= 1;
  737.       }
  738.  
  739.       return var3;
  740.    }
  741.  
  742.    int expr(int[] var1) throws RESyntaxException {
  743.       byte var2 = -1;
  744.       int var3 = -1;
  745.       int var4 = this.parens;
  746.       if ((var1[0] & 2) == 0 && this.pattern.charAt(this.idx) == '(') {
  747.          if (this.idx + 2 < this.len && this.pattern.charAt(this.idx + 1) == '?' && this.pattern.charAt(this.idx + 2) == ':') {
  748.             var2 = 2;
  749.             this.idx += 3;
  750.             var3 = this.node('<', 0);
  751.          } else {
  752.             var2 = 1;
  753.             ++this.idx;
  754.             var3 = this.node('(', this.parens++);
  755.          }
  756.       }
  757.  
  758.       var1[0] &= -3;
  759.       int var5 = this.branch(var1);
  760.       if (var3 == -1) {
  761.          var3 = var5;
  762.       } else {
  763.          this.setNextOfEnd(var3, var5);
  764.       }
  765.  
  766.       while(this.idx < this.len && this.pattern.charAt(this.idx) == '|') {
  767.          ++this.idx;
  768.          var5 = this.branch(var1);
  769.          this.setNextOfEnd(var3, var5);
  770.       }
  771.  
  772.       int var6;
  773.       if (var2 > 0) {
  774.          if (this.idx < this.len && this.pattern.charAt(this.idx) == ')') {
  775.             ++this.idx;
  776.          } else {
  777.             this.syntaxError("Missing close paren");
  778.          }
  779.  
  780.          if (var2 == 1) {
  781.             var6 = this.node(')', var4);
  782.          } else {
  783.             var6 = this.node('>', 0);
  784.          }
  785.       } else {
  786.          var6 = this.node('E', 0);
  787.       }
  788.  
  789.       this.setNextOfEnd(var3, var6);
  790.       int var7 = var3;
  791.  
  792.       for(char var8 = this.instruction[var3 + 2]; var8 != 0 && var7 < this.lenInstruction; var7 += var8) {
  793.          if (this.instruction[var7 + 0] == '|') {
  794.             this.setNextOfEnd(var7 + 3, var6);
  795.          }
  796.  
  797.          var8 = this.instruction[var7 + 2];
  798.       }
  799.  
  800.       return var3;
  801.    }
  802.  
  803.    public REProgram compile(String var1) throws RESyntaxException {
  804.       this.pattern = var1;
  805.       this.len = var1.length();
  806.       this.idx = 0;
  807.       this.lenInstruction = 0;
  808.       this.parens = 1;
  809.       this.brackets = 0;
  810.       int[] var2 = new int[]{2};
  811.       this.expr(var2);
  812.       if (this.idx != this.len) {
  813.          if (var1.charAt(this.idx) == ')') {
  814.             this.syntaxError("Unmatched close paren");
  815.          }
  816.  
  817.          this.syntaxError("Unexpected input remains");
  818.       }
  819.  
  820.       char[] var3 = new char[this.lenInstruction];
  821.       System.arraycopy(this.instruction, 0, var3, 0, this.lenInstruction);
  822.       return new REProgram(this.parens, var3);
  823.    }
  824.  
  825.    static {
  826.       hashPOSIX.put("alnum", new Character('w'));
  827.       hashPOSIX.put("alpha", new Character('a'));
  828.       hashPOSIX.put("blank", new Character('b'));
  829.       hashPOSIX.put("cntrl", new Character('c'));
  830.       hashPOSIX.put("digit", new Character('d'));
  831.       hashPOSIX.put("graph", new Character('g'));
  832.       hashPOSIX.put("lower", new Character('l'));
  833.       hashPOSIX.put("print", new Character('p'));
  834.       hashPOSIX.put("punct", new Character('!'));
  835.       hashPOSIX.put("space", new Character('s'));
  836.       hashPOSIX.put("upper", new Character('u'));
  837.       hashPOSIX.put("xdigit", new Character('x'));
  838.       hashPOSIX.put("javastart", new Character('j'));
  839.       hashPOSIX.put("javapart", new Character('k'));
  840.    }
  841. }
  842.