nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java
changeset 17753 4800f03fbfc4
parent 16944 7c9a4d480d39
child 18884 b2032ab50ac4
equal deleted inserted replaced
17752:9d2d0e74a833 17753:4800f03fbfc4
    19  */
    19  */
    20 package jdk.nashorn.internal.runtime.regexp.joni;
    20 package jdk.nashorn.internal.runtime.regexp.joni;
    21 
    21 
    22 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAll;
    22 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAll;
    23 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
    23 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
    24 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsClear;
       
    25 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAt;
    24 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAt;
    26 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAtSimple;
       
    27 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isCaptureGroup;
       
    28 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindCondition;
    25 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindCondition;
    29 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
    26 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
    30 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isMultiline;
    27 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isMultiline;
    31 import static jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode.newAltNode;
    28 import static jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode.newAltNode;
    32 import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepeatInfinite;
    29 import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepeatInfinite;
    34 import java.util.HashSet;
    31 import java.util.HashSet;
    35 
    32 
    36 import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
    33 import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
    37 import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
    34 import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
    38 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
    35 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
    39 import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
       
    40 import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
       
    41 import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
    36 import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
    42 import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
    37 import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
    43 import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
    38 import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
    44 import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
    39 import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
    45 import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode;
    40 import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode;
    47 import jdk.nashorn.internal.runtime.regexp.joni.constants.EncloseType;
    42 import jdk.nashorn.internal.runtime.regexp.joni.constants.EncloseType;
    48 import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType;
    43 import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType;
    49 import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
    44 import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
    50 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
    45 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
    51 import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
    46 import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
    52 import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
       
    53 import jdk.nashorn.internal.runtime.regexp.joni.encoding.ObjPtr;
    47 import jdk.nashorn.internal.runtime.regexp.joni.encoding.ObjPtr;
    54 import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
       
    55 
    48 
    56 final class Analyser extends Parser {
    49 final class Analyser extends Parser {
    57 
    50 
    58     protected Analyser(ScanEnvironment env, char[] chars, int p, int end) {
    51     protected Analyser(ScanEnvironment env, char[] chars, int p, int end) {
    59         super(env, chars, p, end);
    52         super(env, chars, p, end);
    72         regex.numRepeat = 0;
    65         regex.numRepeat = 0;
    73         regex.numNullCheck = 0;
    66         regex.numNullCheck = 0;
    74         //regex.repeatRangeAlloc = 0;
    67         //regex.repeatRangeAlloc = 0;
    75         regex.repeatRangeLo = null;
    68         regex.repeatRangeLo = null;
    76         regex.repeatRangeHi = null;
    69         regex.repeatRangeHi = null;
    77         regex.numCombExpCheck = 0;
       
    78 
       
    79         if (Config.USE_COMBINATION_EXPLOSION_CHECK) regex.numCombExpCheck = 0;
       
    80 
    70 
    81         parse();
    71         parse();
    82 
       
    83         if (Config.USE_NAMED_GROUP) {
       
    84             /* mixed use named group and no-named group */
       
    85             if (env.numNamed > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(regex.options)) {
       
    86                 if (env.numNamed != env.numMem) {
       
    87                     root = disableNoNameGroupCapture(root);
       
    88                 } else {
       
    89                     numberedRefCheck(root);
       
    90                 }
       
    91             }
       
    92         } // USE_NAMED_GROUP
       
    93 
       
    94         if (Config.USE_NAMED_GROUP) {
       
    95             if (env.numCall > 0) {
       
    96                 env.unsetAddrList = new UnsetAddrList(env.numCall);
       
    97                 setupSubExpCall(root);
       
    98                 // r != 0 ???
       
    99                 subexpRecursiveCheckTrav(root);
       
   100                 // r < 0 -< err, FOUND_CALLED_NODE = 1
       
   101                 subexpInfRecursiveCheckTrav(root);
       
   102                 // r != 0  recursion infinite ???
       
   103                 regex.numCall = env.numCall;
       
   104             } else {
       
   105                 regex.numCall = 0;
       
   106             }
       
   107         } // USE_NAMED_GROUP
       
   108 
    72 
   109         if (Config.DEBUG_PARSE_TREE_RAW && Config.DEBUG_PARSE_TREE) {
    73         if (Config.DEBUG_PARSE_TREE_RAW && Config.DEBUG_PARSE_TREE) {
   110             Config.log.println("<RAW TREE>");
    74             Config.log.println("<RAW TREE>");
   111             Config.log.println(root + "\n");
    75             Config.log.println(root + "\n");
   112         }
    76         }
   126             regex.btMemEnd = bsAll();
    90             regex.btMemEnd = bsAll();
   127         } else {
    91         } else {
   128             regex.btMemEnd = env.btMemEnd;
    92             regex.btMemEnd = env.btMemEnd;
   129             regex.btMemEnd |= regex.captureHistory;
    93             regex.btMemEnd |= regex.captureHistory;
   130         }
    94         }
   131 
       
   132         if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
       
   133             if (env.backrefedMem == 0 || (Config.USE_SUBEXP_CALL && env.numCall == 0)) {
       
   134                 setupCombExpCheck(root, 0);
       
   135 
       
   136                 if (Config.USE_SUBEXP_CALL && env.hasRecursion) {
       
   137                     env.numCombExpCheck = 0;
       
   138                 } else { // USE_SUBEXP_CALL
       
   139                     if (env.combExpMaxRegNum > 0) {
       
   140                         for (int i=1; i<env.combExpMaxRegNum; i++) {
       
   141                             if (bsAt(env.backrefedMem, i)) {
       
   142                                 env.numCombExpCheck = 0;
       
   143                                 break;
       
   144                             }
       
   145                         }
       
   146                     }
       
   147                 }
       
   148 
       
   149             } // USE_SUBEXP_CALL
       
   150             regex.numCombExpCheck = env.numCombExpCheck;
       
   151         } // USE_COMBINATION_EXPLOSION_CHECK
       
   152 
    95 
   153         regex.clearOptimizeInfo();
    96         regex.clearOptimizeInfo();
   154 
    97 
   155         if (!Config.DONT_OPTIMIZE) setOptimizedInfoFromTree(root);
    98         if (!Config.DONT_OPTIMIZE) setOptimizedInfoFromTree(root);
   156 
    99 
   165                 regex.stackPopLevel = StackPopLevel.FREE;
   108                 regex.stackPopLevel = StackPopLevel.FREE;
   166             }
   109             }
   167         }
   110         }
   168 
   111 
   169         if (Config.DEBUG_COMPILE) {
   112         if (Config.DEBUG_COMPILE) {
   170             if (Config.USE_NAMED_GROUP) Config.log.print(regex.nameTableToString());
       
   171             Config.log.println("stack used: " + regex.stackNeeded);
   113             Config.log.println("stack used: " + regex.stackNeeded);
   172             if (Config.USE_STRING_TEMPLATES) Config.log.print("templates: " + regex.templateNum + "\n");
   114             if (Config.USE_STRING_TEMPLATES) Config.log.print("templates: " + regex.templateNum + "\n");
   173             Config.log.println(new ByteCodePrinter(regex).byteCodeListToString());
   115             Config.log.println(new ByteCodePrinter(regex).byteCodeListToString());
   174 
   116 
   175         } // DEBUG_COMPILE
   117         } // DEBUG_COMPILE
   176 
   118 
   177         regex.state = RegexState.NORMAL;
   119         regex.state = RegexState.NORMAL;
   178     }
       
   179 
       
   180     private void noNameDisableMapFor_cosAlt(Node node, int[]map, Ptr counter) {
       
   181         ConsAltNode can = (ConsAltNode)node;
       
   182         do {
       
   183             can.setCar(noNameDisableMap(can.car, map, counter));
       
   184         } while ((can = can.cdr) != null);
       
   185     }
       
   186 
       
   187     private void noNameDisableMapFor_quantifier(Node node, int[]map, Ptr counter) {
       
   188         QuantifierNode qn = (QuantifierNode)node;
       
   189         Node target = qn.target;
       
   190         Node old = target;
       
   191         target = noNameDisableMap(target, map, counter);
       
   192 
       
   193         if (target != old) {
       
   194             qn.setTarget(target);
       
   195             if (target.getType() == NodeType.QTFR) qn.reduceNestedQuantifier((QuantifierNode)target);
       
   196         }
       
   197     }
       
   198 
       
   199     private Node noNameDisableMapFor_enclose(Node node, int[]map, Ptr counter) {
       
   200         EncloseNode en = (EncloseNode)node;
       
   201         if (en.type == EncloseType.MEMORY) {
       
   202             if (en.isNamedGroup()) {
       
   203                 counter.p++;
       
   204                 map[en.regNum] = counter.p;
       
   205                 en.regNum = counter.p;
       
   206                 //en.target = noNameDisableMap(en.target, map, counter);
       
   207                 en.setTarget(noNameDisableMap(en.target, map, counter)); // ???
       
   208             } else {
       
   209                 node = en.target;
       
   210                 en.target = null; // remove first enclose: /(a)(?<b>c)/
       
   211                 node = noNameDisableMap(node, map, counter);
       
   212             }
       
   213         } else {
       
   214             //en.target = noNameDisableMap(en.target, map, counter);
       
   215             en.setTarget(noNameDisableMap(en.target, map, counter)); // ???
       
   216         }
       
   217         return node;
       
   218     }
       
   219 
       
   220     private void noNameDisableMapFor_anchor(Node node, int[]map, Ptr counter) {
       
   221         AnchorNode an = (AnchorNode)node;
       
   222         switch (an.type) {
       
   223             case AnchorNode.PREC_READ:
       
   224             case AnchorNode.PREC_READ_NOT:
       
   225             case AnchorNode.LOOK_BEHIND:
       
   226             case AnchorNode.LOOK_BEHIND_NOT:
       
   227                 an.setTarget(noNameDisableMap(an.target, map, counter));
       
   228         }
       
   229     }
       
   230 
       
   231     private Node noNameDisableMap(Node node, int[]map, Ptr counter) {
       
   232         switch (node.getType()) {
       
   233         case NodeType.LIST:
       
   234         case NodeType.ALT:
       
   235             noNameDisableMapFor_cosAlt(node, map, counter);
       
   236             break;
       
   237         case NodeType.QTFR:
       
   238             noNameDisableMapFor_quantifier(node, map, counter);
       
   239             break;
       
   240         case NodeType.ENCLOSE:
       
   241             node = noNameDisableMapFor_enclose(node, map, counter);
       
   242             break;
       
   243         case NodeType.ANCHOR:
       
   244             noNameDisableMapFor_anchor(node, map, counter);
       
   245             break;
       
   246         } // switch
       
   247         return node;
       
   248     }
       
   249 
       
   250     private void renumberByMap(Node node, int[]map) {
       
   251         switch (node.getType()) {
       
   252         case NodeType.LIST:
       
   253         case NodeType.ALT:
       
   254             ConsAltNode can = (ConsAltNode)node;
       
   255             do {
       
   256                 renumberByMap(can.car, map);
       
   257             } while ((can = can.cdr) != null);
       
   258             break;
       
   259 
       
   260         case NodeType.QTFR:
       
   261             renumberByMap(((QuantifierNode)node).target, map);
       
   262             break;
       
   263 
       
   264         case NodeType.ENCLOSE:
       
   265             renumberByMap(((EncloseNode)node).target, map);
       
   266             break;
       
   267 
       
   268         case NodeType.BREF:
       
   269             ((BackRefNode)node).renumber(map);
       
   270             break;
       
   271         } // switch
       
   272     }
       
   273 
       
   274     protected final void numberedRefCheck(Node node) {
       
   275         switch (node.getType()) {
       
   276         case NodeType.LIST:
       
   277         case NodeType.ALT:
       
   278             ConsAltNode can = (ConsAltNode)node;
       
   279             do {
       
   280                 numberedRefCheck(can.car);
       
   281             } while ((can = can.cdr) != null);
       
   282             break;
       
   283 
       
   284         case NodeType.QTFR:
       
   285             numberedRefCheck(((QuantifierNode)node).target);
       
   286             break;
       
   287 
       
   288         case NodeType.ENCLOSE:
       
   289             numberedRefCheck(((EncloseNode)node).target);
       
   290             break;
       
   291 
       
   292         case NodeType.BREF:
       
   293             BackRefNode br = (BackRefNode)node;
       
   294             if (!br.isNameRef()) newValueException(ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED);
       
   295             break;
       
   296         } // switch
       
   297     }
       
   298 
       
   299     protected final Node disableNoNameGroupCapture(Node root) {
       
   300         int[]map = new int[env.numMem + 1];
       
   301 
       
   302         for (int i=1; i<=env.numMem; i++) map[i] = 0;
       
   303 
       
   304         root = noNameDisableMap(root, map, new Ptr(0));
       
   305         renumberByMap(root, map);
       
   306 
       
   307         for (int i=1, pos=1; i<=env.numMem; i++) {
       
   308             if (map[i] > 0) {
       
   309                 env.memNodes[pos] = env.memNodes[i];
       
   310                 pos++;
       
   311             }
       
   312         }
       
   313 
       
   314         int loc = env.captureHistory;
       
   315         env.captureHistory = bsClear();
       
   316 
       
   317         for (int i=1; i<=Config.MAX_CAPTURE_HISTORY_GROUP; i++) {
       
   318             if (bsAt(loc, i)) {
       
   319                 env.captureHistory = bsOnAtSimple(env.captureHistory, map[i]);
       
   320             }
       
   321         }
       
   322 
       
   323         env.numMem = env.numNamed;
       
   324         regex.numMem = env.numNamed;
       
   325 
       
   326         regex.renumberNameTable(map);
       
   327 
       
   328         return root;
       
   329     }
   120     }
   330 
   121 
   331     private void swap(Node a, Node b) {
   122     private void swap(Node a, Node b) {
   332         a.swap(b);
   123         a.swap(b);
   333 
   124 
   350                 int v = quantifiersMemoryInfo(can.car);
   141                 int v = quantifiersMemoryInfo(can.car);
   351                 if (v > info) info = v;
   142                 if (v > info) info = v;
   352             } while ((can = can.cdr) != null);
   143             } while ((can = can.cdr) != null);
   353             break;
   144             break;
   354 
   145 
   355         case NodeType.CALL:
       
   356             if (Config.USE_SUBEXP_CALL) {
       
   357                 CallNode cn = (CallNode)node;
       
   358                 if (cn.isRecursion()) {
       
   359                     return TargetInfo.IS_EMPTY_REC; /* tiny version */
       
   360                 } else {
       
   361                     info = quantifiersMemoryInfo(cn.target);
       
   362                 }
       
   363             } // USE_SUBEXP_CALL
       
   364             break;
       
   365 
       
   366         case NodeType.QTFR:
   146         case NodeType.QTFR:
   367             QuantifierNode qn = (QuantifierNode)node;
   147             QuantifierNode qn = (QuantifierNode)node;
   368             if (qn.upper != 0) {
   148             if (qn.upper != 0) {
   369                 info = quantifiersMemoryInfo(qn.target);
   149                 info = quantifiersMemoryInfo(qn.target);
   370             }
   150             }
   413             for (int i=1; i<br.backNum; i++) {
   193             for (int i=1; i<br.backNum; i++) {
   414                 if (br.back[i] > env.numMem) newValueException(ERR_INVALID_BACKREF);
   194                 if (br.back[i] > env.numMem) newValueException(ERR_INVALID_BACKREF);
   415                 int tmin = getMinMatchLength(env.memNodes[br.back[i]]);
   195                 int tmin = getMinMatchLength(env.memNodes[br.back[i]]);
   416                 if (min > tmin) min = tmin;
   196                 if (min > tmin) min = tmin;
   417             }
   197             }
   418             break;
       
   419 
       
   420         case NodeType.CALL:
       
   421             if (Config.USE_SUBEXP_CALL) {
       
   422                 CallNode cn = (CallNode)node;
       
   423                 if (cn.isRecursion()) {
       
   424                     EncloseNode en = (EncloseNode)cn.target;
       
   425                     if (en.isMinFixed()) min = en.minLength;
       
   426                 } else {
       
   427                     min = getMinMatchLength(cn.target);
       
   428                 }
       
   429             } // USE_SUBEXP_CALL
       
   430             break;
   198             break;
   431 
   199 
   432         case NodeType.LIST:
   200         case NodeType.LIST:
   433             ConsAltNode can = (ConsAltNode)node;
   201             ConsAltNode can = (ConsAltNode)node;
   434             do {
   202             do {
   472 
   240 
   473         case NodeType.ENCLOSE:
   241         case NodeType.ENCLOSE:
   474             EncloseNode en = (EncloseNode)node;
   242             EncloseNode en = (EncloseNode)node;
   475             switch (en.type) {
   243             switch (en.type) {
   476             case EncloseType.MEMORY:
   244             case EncloseType.MEMORY:
   477                 if (Config.USE_SUBEXP_CALL) {
   245                 if (en.isMinFixed()) {
   478                     if (en.isMinFixed()) {
   246                     min = en.minLength;
   479                         min = en.minLength;
   247                 } else {
   480                     } else {
   248                     min = getMinMatchLength(en.target);
   481                         min = getMinMatchLength(en.target);
   249                     en.minLength = min;
   482                         en.minLength = min;
   250                     en.setMinFixed();
   483                         en.setMinFixed();
   251                 }
   484                     }
       
   485                 } // USE_SUBEXP_CALL
       
   486                 break;
   252                 break;
   487 
   253 
   488             case EncloseType.OPTION:
   254             case EncloseType.OPTION:
   489             case EncloseType.STOP_BACKTRACK:
   255             case EncloseType.STOP_BACKTRACK:
   490                 min = getMinMatchLength(en.target);
   256                 min = getMinMatchLength(en.target);
   543             for (int i=0; i<br.backNum; i++) {
   309             for (int i=0; i<br.backNum; i++) {
   544                 if (br.back[i] > env.numMem) newValueException(ERR_INVALID_BACKREF);
   310                 if (br.back[i] > env.numMem) newValueException(ERR_INVALID_BACKREF);
   545                 int tmax = getMaxMatchLength(env.memNodes[br.back[i]]);
   311                 int tmax = getMaxMatchLength(env.memNodes[br.back[i]]);
   546                 if (max < tmax) max = tmax;
   312                 if (max < tmax) max = tmax;
   547             }
   313             }
   548             break;
       
   549 
       
   550         case NodeType.CALL:
       
   551             if (Config.USE_SUBEXP_CALL) {
       
   552                 CallNode cn = (CallNode)node;
       
   553                 if (!cn.isRecursion()) {
       
   554                     max = getMaxMatchLength(cn.target);
       
   555                 } else {
       
   556                     max = MinMaxLen.INFINITE_DISTANCE;
       
   557                 }
       
   558             } // USE_SUBEXP_CALL
       
   559             break;
   314             break;
   560 
   315 
   561         case NodeType.QTFR:
   316         case NodeType.QTFR:
   562             QuantifierNode qn = (QuantifierNode)node;
   317             QuantifierNode qn = (QuantifierNode)node;
   563             if (qn.upper != 0) {
   318             if (qn.upper != 0) {
   574 
   329 
   575         case NodeType.ENCLOSE:
   330         case NodeType.ENCLOSE:
   576             EncloseNode en = (EncloseNode)node;
   331             EncloseNode en = (EncloseNode)node;
   577             switch (en.type) {
   332             switch (en.type) {
   578             case EncloseType.MEMORY:
   333             case EncloseType.MEMORY:
   579                 if (Config.USE_SUBEXP_CALL) {
   334                 if (en.isMaxFixed()) {
   580                     if (en.isMaxFixed()) {
   335                     max = en.maxLength;
   581                         max = en.maxLength;
   336                 } else {
   582                     } else {
   337                     max = getMaxMatchLength(en.target);
   583                         max = getMaxMatchLength(en.target);
   338                     en.maxLength = max;
   584                         en.maxLength = max;
   339                     en.setMaxFixed();
   585                         en.setMaxFixed();
   340                 }
   586                     }
       
   587                 } // USE_SUBEXP_CALL
       
   588                 break;
   341                 break;
   589 
   342 
   590             case EncloseType.OPTION:
   343             case EncloseType.OPTION:
   591             case EncloseType.STOP_BACKTRACK:
   344             case EncloseType.STOP_BACKTRACK:
   592                 max = getMaxMatchLength(en.target);
   345                 max = getMaxMatchLength(en.target);
   661             } else {
   414             } else {
   662                 returnCode = GET_CHAR_LEN_VARLEN;
   415                 returnCode = GET_CHAR_LEN_VARLEN;
   663             }
   416             }
   664             break;
   417             break;
   665 
   418 
   666         case NodeType.CALL:
       
   667             if (Config.USE_SUBEXP_CALL) {
       
   668                 CallNode cn = (CallNode)node;
       
   669                 if (!cn.isRecursion()) {
       
   670                     len = getCharLengthTree(cn.target, level);
       
   671                 } else {
       
   672                     returnCode = GET_CHAR_LEN_VARLEN;
       
   673                 }
       
   674             } // USE_SUBEXP_CALL
       
   675             break;
       
   676 
       
   677         case NodeType.CTYPE:
   419         case NodeType.CTYPE:
   678             len = 1;
   420             len = 1;
   679 
   421 
   680         case NodeType.CCLASS:
   422         case NodeType.CCLASS:
   681         case NodeType.CANY:
   423         case NodeType.CANY:
   684 
   426 
   685         case NodeType.ENCLOSE:
   427         case NodeType.ENCLOSE:
   686             EncloseNode en = (EncloseNode)node;
   428             EncloseNode en = (EncloseNode)node;
   687             switch(en.type) {
   429             switch(en.type) {
   688             case EncloseType.MEMORY:
   430             case EncloseType.MEMORY:
   689                 if (Config.USE_SUBEXP_CALL) {
   431                 if (en.isCLenFixed()) {
   690                     if (en.isCLenFixed()) {
   432                     len = en.charLength;
   691                         len = en.charLength;
   433                 } else {
   692                     } else {
   434                     len = getCharLengthTree(en.target, level);
   693                         len = getCharLengthTree(en.target, level);
   435                     if (returnCode == 0) {
   694                         if (returnCode == 0) {
   436                         en.charLength = len;
   695                             en.charLength = len;
   437                         en.setCLenFixed();
   696                             en.setCLenFixed();
   438                     }
   697                         }
   439                 }
   698                     }
       
   699                 } // USE_SUBEXP_CALL
       
   700                 break;
   440                 break;
   701 
   441 
   702             case EncloseType.OPTION:
   442             case EncloseType.OPTION:
   703             case EncloseType.STOP_BACKTRACK:
   443             case EncloseType.STOP_BACKTRACK:
   704                 len = getCharLengthTree(en.target, level);
   444                 len = getCharLengthTree(en.target, level);
   725         int yType = y.getType();
   465         int yType = y.getType();
   726 
   466 
   727         switch(x.getType()) {
   467         switch(x.getType()) {
   728         case NodeType.CTYPE:
   468         case NodeType.CTYPE:
   729             switch(yType) {
   469             switch(yType) {
   730             case NodeType.CTYPE:
       
   731                 CTypeNode cny = (CTypeNode)y;
       
   732                 CTypeNode cnx = (CTypeNode)x;
       
   733                 return cny.ctype == cnx.ctype && cny.not != cnx.not;
       
   734 
   470 
   735             case NodeType.CCLASS:
   471             case NodeType.CCLASS:
   736                 // !swap:!
   472                 // !swap:!
   737                 tmp = x;
   473                 tmp = x;
   738                 x = y;
   474                 x = y;
   754 
   490 
   755         case NodeType.CCLASS:
   491         case NodeType.CCLASS:
   756             CClassNode xc = (CClassNode)x;
   492             CClassNode xc = (CClassNode)x;
   757 
   493 
   758             switch(yType) {
   494             switch(yType) {
   759             case NodeType.CTYPE:
       
   760                 switch(((CTypeNode)y).ctype) {
       
   761                 case CharacterType.WORD:
       
   762                     if (!((CTypeNode)y).not) {
       
   763                         if (xc.mbuf == null && !xc.isNot()) {
       
   764                             for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
       
   765                                 if (xc.bs.at(i)) {
       
   766                                     if (EncodingHelper.isWord(i)) return false;
       
   767                                 }
       
   768                             }
       
   769                             return true;
       
   770                         }
       
   771                         return false;
       
   772                     } else {
       
   773                         for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
       
   774                             if (!EncodingHelper.isWord(i)) {
       
   775                                 if (!xc.isNot()) {
       
   776                                     if (xc.bs.at(i)) return false;
       
   777                                 } else {
       
   778                                     if (!xc.bs.at(i)) return false;
       
   779                                 }
       
   780                             }
       
   781                         }
       
   782                         return true;
       
   783                     }
       
   784                     // break; not reached
       
   785 
       
   786                 default:
       
   787                     break;
       
   788                 } // inner switch
       
   789                 break;
       
   790 
   495 
   791             case NodeType.CCLASS:
   496             case NodeType.CCLASS:
   792                 CClassNode yc = (CClassNode)y;
   497                 CClassNode yc = (CClassNode)y;
   793 
   498 
   794                 for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
   499                 for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
   818         case NodeType.STR:
   523         case NodeType.STR:
   819             StringNode xs = (StringNode)x;
   524             StringNode xs = (StringNode)x;
   820             if (xs.length() == 0) break;
   525             if (xs.length() == 0) break;
   821 
   526 
   822             switch (yType) {
   527             switch (yType) {
   823             case NodeType.CTYPE:
       
   824                 CTypeNode cy = ((CTypeNode)y);
       
   825                 switch (cy.ctype) {
       
   826                 case CharacterType.WORD:
       
   827                     return !cy.not;
       
   828 
       
   829                 default:
       
   830                     break;
       
   831 
       
   832                 } // inner switch
       
   833                 break;
       
   834 
   528 
   835             case NodeType.CCLASS:
   529             case NodeType.CCLASS:
   836                 CClassNode cc = (CClassNode)y;
   530                 CClassNode cc = (CClassNode)y;
   837                 int code = xs.chars[xs.p];
   531                 int code = xs.chars[xs.p];
   838                 return !cc.isCodeInCC(code);
   532                 return !cc.isCodeInCC(code);
   871         case NodeType.BREF:
   565         case NodeType.BREF:
   872         case NodeType.ALT:
   566         case NodeType.ALT:
   873         case NodeType.CANY:
   567         case NodeType.CANY:
   874             break;
   568             break;
   875 
   569 
   876         case NodeType.CALL:
       
   877             break; // if (Config.USE_SUBEXP_CALL)
       
   878 
       
   879         case NodeType.CTYPE:
   570         case NodeType.CTYPE:
   880         case NodeType.CCLASS:
   571         case NodeType.CCLASS:
   881             if (!exact) n = node;
   572             if (!exact) n = node;
   882             break;
   573             break;
   883 
   574 
   973             break;
   664             break;
   974 
   665 
   975         } // switch
   666         } // switch
   976 
   667 
   977         return invalid;
   668         return invalid;
   978     }
       
   979 
       
   980     private static final int RECURSION_EXIST       = 1;
       
   981     private static final int RECURSION_INFINITE    = 2;
       
   982     private int subexpInfRecursiveCheck(Node node, boolean head) {
       
   983         int r = 0;
       
   984 
       
   985         switch (node.getType()) {
       
   986         case NodeType.LIST:
       
   987             int min;
       
   988             ConsAltNode x = (ConsAltNode)node;
       
   989             do {
       
   990                 int ret = subexpInfRecursiveCheck(x.car, head);
       
   991                 if (ret == RECURSION_INFINITE) return ret;
       
   992                 r |= ret;
       
   993                 if (head) {
       
   994                     min = getMinMatchLength(x.car);
       
   995                     if (min != 0) head = false;
       
   996                 }
       
   997             } while ((x = x.cdr) != null);
       
   998             break;
       
   999 
       
  1000         case NodeType.ALT:
       
  1001             ConsAltNode can = (ConsAltNode)node;
       
  1002             r = RECURSION_EXIST;
       
  1003             do {
       
  1004                 int ret = subexpInfRecursiveCheck(can.car, head);
       
  1005                 if (ret == RECURSION_INFINITE) return ret;
       
  1006                 r &= ret;
       
  1007             } while ((can = can.cdr) != null);
       
  1008             break;
       
  1009 
       
  1010         case NodeType.QTFR:
       
  1011             QuantifierNode qn = (QuantifierNode)node;
       
  1012             r = subexpInfRecursiveCheck(qn.target, head);
       
  1013             if (r == RECURSION_EXIST) {
       
  1014                 if (qn.lower == 0) r = 0;
       
  1015             }
       
  1016             break;
       
  1017 
       
  1018         case NodeType.ANCHOR:
       
  1019             AnchorNode an = (AnchorNode)node;
       
  1020             switch (an.type) {
       
  1021             case AnchorType.PREC_READ:
       
  1022             case AnchorType.PREC_READ_NOT:
       
  1023             case AnchorType.LOOK_BEHIND:
       
  1024             case AnchorType.LOOK_BEHIND_NOT:
       
  1025                 r = subexpInfRecursiveCheck(an.target, head);
       
  1026                 break;
       
  1027             } // inner switch
       
  1028             break;
       
  1029 
       
  1030         case NodeType.CALL:
       
  1031             r = subexpInfRecursiveCheck(((CallNode)node).target, head);
       
  1032             break;
       
  1033 
       
  1034         case NodeType.ENCLOSE:
       
  1035             EncloseNode en = (EncloseNode)node;
       
  1036             if (en.isMark2()) {
       
  1037                 return 0;
       
  1038             } else if (en.isMark1()) {
       
  1039                 return !head ? RECURSION_EXIST : RECURSION_INFINITE;
       
  1040                 // throw exception here ???
       
  1041             } else {
       
  1042                 en.setMark2();
       
  1043                 r = subexpInfRecursiveCheck(en.target, head);
       
  1044                 en.clearMark2();
       
  1045             }
       
  1046             break;
       
  1047 
       
  1048         default:
       
  1049             break;
       
  1050         } // switch
       
  1051         return r;
       
  1052     }
       
  1053 
       
  1054     protected final int subexpInfRecursiveCheckTrav(Node node) {
       
  1055         int r = 0;
       
  1056 
       
  1057         switch (node.getType()) {
       
  1058         case NodeType.LIST:
       
  1059         case NodeType.ALT:
       
  1060             ConsAltNode can = (ConsAltNode)node;
       
  1061             do {
       
  1062                 r = subexpInfRecursiveCheckTrav(can.car);
       
  1063             } while (r == 0 && (can = can.cdr) != null);
       
  1064             break;
       
  1065 
       
  1066         case NodeType.QTFR:
       
  1067             r = subexpInfRecursiveCheckTrav(((QuantifierNode)node).target);
       
  1068             break;
       
  1069 
       
  1070         case NodeType.ANCHOR:
       
  1071             AnchorNode an = (AnchorNode)node;
       
  1072             switch (an.type) {
       
  1073             case AnchorType.PREC_READ:
       
  1074             case AnchorType.PREC_READ_NOT:
       
  1075             case AnchorType.LOOK_BEHIND:
       
  1076             case AnchorType.LOOK_BEHIND_NOT:
       
  1077                 r = subexpInfRecursiveCheckTrav(an.target);
       
  1078                 break;
       
  1079             } // inner switch
       
  1080             break;
       
  1081 
       
  1082         case NodeType.ENCLOSE:
       
  1083             EncloseNode en = (EncloseNode)node;
       
  1084             if (en.isRecursion()) {
       
  1085                 en.setMark1();
       
  1086                 r = subexpInfRecursiveCheck(en.target, true);
       
  1087                 if (r > 0) newValueException(ERR_NEVER_ENDING_RECURSION);
       
  1088                 en.clearMark1();
       
  1089             }
       
  1090             r = subexpInfRecursiveCheckTrav(en.target);
       
  1091             break;
       
  1092 
       
  1093         default:
       
  1094             break;
       
  1095         } // switch
       
  1096 
       
  1097         return r;
       
  1098     }
       
  1099 
       
  1100     private int subexpRecursiveCheck(Node node) {
       
  1101         int r = 0;
       
  1102 
       
  1103         switch (node.getType()) {
       
  1104         case NodeType.LIST:
       
  1105         case NodeType.ALT:
       
  1106             ConsAltNode can = (ConsAltNode)node;
       
  1107             do {
       
  1108                 r |= subexpRecursiveCheck(can.car);
       
  1109             } while ((can = can.cdr) != null);
       
  1110             break;
       
  1111 
       
  1112         case NodeType.QTFR:
       
  1113             r = subexpRecursiveCheck(((QuantifierNode)node).target);
       
  1114             break;
       
  1115 
       
  1116         case NodeType.ANCHOR:
       
  1117             AnchorNode an = (AnchorNode)node;
       
  1118             switch (an.type) {
       
  1119             case AnchorType.PREC_READ:
       
  1120             case AnchorType.PREC_READ_NOT:
       
  1121             case AnchorType.LOOK_BEHIND:
       
  1122             case AnchorType.LOOK_BEHIND_NOT:
       
  1123                 r = subexpRecursiveCheck(an.target);
       
  1124                 break;
       
  1125             } // inner switch
       
  1126             break;
       
  1127 
       
  1128         case NodeType.CALL:
       
  1129             CallNode cn = (CallNode)node;
       
  1130             r = subexpRecursiveCheck(cn.target);
       
  1131             if (r != 0) cn.setRecursion();
       
  1132             break;
       
  1133 
       
  1134         case NodeType.ENCLOSE:
       
  1135             EncloseNode en = (EncloseNode)node;
       
  1136             if (en.isMark2()) {
       
  1137                 return 0;
       
  1138             } else if (en.isMark1()) {
       
  1139                 return 1; /* recursion */
       
  1140             } else {
       
  1141                 en.setMark2();
       
  1142                 r = subexpRecursiveCheck(en.target);
       
  1143                 en.clearMark2();
       
  1144             }
       
  1145             break;
       
  1146 
       
  1147         default:
       
  1148             break;
       
  1149         } // switch
       
  1150 
       
  1151         return r;
       
  1152     }
       
  1153 
       
  1154     private static final int FOUND_CALLED_NODE  = 1;
       
  1155     protected final int subexpRecursiveCheckTrav(Node node) {
       
  1156         int r = 0;
       
  1157 
       
  1158         switch (node.getType()) {
       
  1159         case NodeType.LIST:
       
  1160         case NodeType.ALT:
       
  1161             ConsAltNode can = (ConsAltNode)node;
       
  1162             do {
       
  1163                 int ret = subexpRecursiveCheckTrav(can.car);
       
  1164                 if (ret == FOUND_CALLED_NODE) {
       
  1165                     r = FOUND_CALLED_NODE;
       
  1166                 }
       
  1167                 // else if (ret < 0) return ret; ???
       
  1168             } while ((can = can.cdr) != null);
       
  1169             break;
       
  1170 
       
  1171         case NodeType.QTFR:
       
  1172             QuantifierNode qn = (QuantifierNode)node;
       
  1173             r = subexpRecursiveCheckTrav(qn.target);
       
  1174             if (qn.upper == 0) {
       
  1175                 if (r == FOUND_CALLED_NODE) qn.isRefered = true;
       
  1176             }
       
  1177             break;
       
  1178 
       
  1179         case NodeType.ANCHOR:
       
  1180             AnchorNode an = (AnchorNode)node;
       
  1181             switch (an.type) {
       
  1182             case AnchorType.PREC_READ:
       
  1183             case AnchorType.PREC_READ_NOT:
       
  1184             case AnchorType.LOOK_BEHIND:
       
  1185             case AnchorType.LOOK_BEHIND_NOT:
       
  1186                 r = subexpRecursiveCheckTrav(an.target);
       
  1187                 break;
       
  1188             } // inner switch
       
  1189             break;
       
  1190 
       
  1191         case NodeType.ENCLOSE:
       
  1192             EncloseNode en = (EncloseNode)node;
       
  1193             if (!en.isRecursion()) {
       
  1194                 if (en.isCalled()) {
       
  1195                     en.setMark1();
       
  1196                     r = subexpRecursiveCheck(en.target);
       
  1197                     if (r != 0) en.setRecursion();
       
  1198                     en.clearMark1();
       
  1199                 }
       
  1200             }
       
  1201             r = subexpRecursiveCheckTrav(en.target);
       
  1202             if (en.isCalled()) r |= FOUND_CALLED_NODE;
       
  1203             break;
       
  1204 
       
  1205         default:
       
  1206             break;
       
  1207         } // switch
       
  1208 
       
  1209         return r;
       
  1210     }
       
  1211 
       
  1212     private void setCallAttr(CallNode cn) {
       
  1213         cn.target = env.memNodes[cn.groupNum]; // no setTarget in call nodes!
       
  1214         if (cn.target == null) newValueException(ERR_UNDEFINED_NAME_REFERENCE, cn.nameP, cn.nameEnd);
       
  1215 
       
  1216         ((EncloseNode)cn.target).setCalled();
       
  1217         env.btMemStart = BitStatus.bsOnAt(env.btMemStart, cn.groupNum);
       
  1218         cn.unsetAddrList = env.unsetAddrList;
       
  1219     }
       
  1220 
       
  1221     protected final void setupSubExpCall(Node node) {
       
  1222 
       
  1223         switch(node.getType()) {
       
  1224         case NodeType.LIST:
       
  1225             ConsAltNode ln = (ConsAltNode)node;
       
  1226             do {
       
  1227                 setupSubExpCall(ln.car);
       
  1228             } while ((ln = ln.cdr) != null);
       
  1229             break;
       
  1230 
       
  1231         case NodeType.ALT:
       
  1232             ConsAltNode can = (ConsAltNode)node;
       
  1233             do {
       
  1234                 setupSubExpCall(can.car);
       
  1235             } while ((can = can.cdr) != null);
       
  1236             break;
       
  1237 
       
  1238         case NodeType.QTFR:
       
  1239             setupSubExpCall(((QuantifierNode)node).target);
       
  1240             break;
       
  1241 
       
  1242         case NodeType.ENCLOSE:
       
  1243             setupSubExpCall(((EncloseNode)node).target);
       
  1244             break;
       
  1245 
       
  1246         case NodeType.CALL:
       
  1247             CallNode cn = (CallNode)node;
       
  1248 
       
  1249             if (cn.groupNum != 0) {
       
  1250                 int gNum = cn.groupNum;
       
  1251 
       
  1252                 if (Config.USE_NAMED_GROUP) {
       
  1253                     if (env.numNamed > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(env.option)) {
       
  1254                         newValueException(ERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED);
       
  1255                     }
       
  1256                 } // USE_NAMED_GROUP
       
  1257                 if (gNum > env.numMem) newValueException(ERR_UNDEFINED_GROUP_REFERENCE, cn.nameP, cn.nameEnd);
       
  1258                 setCallAttr(cn);
       
  1259             } else {
       
  1260                 if (Config.USE_NAMED_GROUP) {
       
  1261                     NameEntry ne = regex.nameToGroupNumbers(cn.name, cn.nameP, cn.nameEnd);
       
  1262 
       
  1263                     if (ne == null) {
       
  1264                         newValueException(ERR_UNDEFINED_NAME_REFERENCE, cn.nameP, cn.nameEnd);
       
  1265                     } else if (ne.backNum > 1) {
       
  1266                         newValueException(ERR_MULTIPLEX_DEFINITION_NAME_CALL, cn.nameP, cn.nameEnd);
       
  1267                     } else {
       
  1268                         cn.groupNum = ne.backRef1; // ne.backNum == 1 ? ne.backRef1 : ne.backRefs[0]; // ??? need to check ?
       
  1269                         setCallAttr(cn);
       
  1270                     }
       
  1271                 }
       
  1272             }
       
  1273             break;
       
  1274 
       
  1275         case NodeType.ANCHOR:
       
  1276             AnchorNode an = (AnchorNode)node;
       
  1277             switch (an.type) {
       
  1278             case AnchorType.PREC_READ:
       
  1279             case AnchorType.PREC_READ_NOT:
       
  1280             case AnchorType.LOOK_BEHIND:
       
  1281             case AnchorType.LOOK_BEHIND_NOT:
       
  1282                 setupSubExpCall(an.target);
       
  1283                 break;
       
  1284             }
       
  1285             break;
       
  1286 
       
  1287         } // switch
       
  1288     }
   669     }
  1289 
   670 
  1290     /* divide different length alternatives in look-behind.
   671     /* divide different length alternatives in look-behind.
  1291     (?<=A|B) ==> (?<=A)|(?<=B)
   672     (?<=A|B) ==> (?<=A)|(?<=B)
  1292     (?<!A|B) ==> (?<!A)(?<!B)
   673     (?<!A|B) ==> (?<!A)(?<!B)
  1519         /* ending */
   900         /* ending */
  1520         Node xnode = topRoot != null ? topRoot : prevNode.p;
   901         Node xnode = topRoot != null ? topRoot : prevNode.p;
  1521 
   902 
  1522         swap(node, xnode);
   903         swap(node, xnode);
  1523         return xnode;
   904         return xnode;
  1524     }
       
  1525 
       
  1526     private static final int CEC_THRES_NUM_BIG_REPEAT       = 512;
       
  1527     private static final int CEC_INFINITE_NUM               = 0x7fffffff;
       
  1528 
       
  1529     private static final int CEC_IN_INFINITE_REPEAT         = (1<<0);
       
  1530     private static final int CEC_IN_FINITE_REPEAT           = (1<<1);
       
  1531     private static final int CEC_CONT_BIG_REPEAT            = (1<<2);
       
  1532 
       
  1533     protected final int setupCombExpCheck(Node node, int state) {
       
  1534         int r = state;
       
  1535         int ret;
       
  1536 
       
  1537         switch (node.getType()) {
       
  1538         case NodeType.LIST:
       
  1539             ConsAltNode ln = (ConsAltNode)node;
       
  1540 
       
  1541             do {
       
  1542                 r = setupCombExpCheck(ln.car, r);
       
  1543                 //prev = ((ConsAltNode)node).car;
       
  1544             } while (r >= 0 && (ln = ln.cdr) != null);
       
  1545             break;
       
  1546 
       
  1547         case NodeType.ALT:
       
  1548             ConsAltNode an = (ConsAltNode)node;
       
  1549             do {
       
  1550                 ret = setupCombExpCheck(an.car, state);
       
  1551                 r |= ret;
       
  1552             } while (ret >= 0 && (an = an.cdr) != null);
       
  1553             break;
       
  1554 
       
  1555         case NodeType.QTFR:
       
  1556             QuantifierNode qn = (QuantifierNode)node;
       
  1557             int childState = state;
       
  1558             int addState = 0;
       
  1559             int varNum;
       
  1560 
       
  1561             if (!isRepeatInfinite(qn.upper)) {
       
  1562                 if (qn.upper > 1) {
       
  1563                     /* {0,1}, {1,1} are allowed */
       
  1564                     childState |= CEC_IN_FINITE_REPEAT;
       
  1565 
       
  1566                     /* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */
       
  1567                     if (env.backrefedMem == 0) {
       
  1568                         if (qn.target.getType() == NodeType.ENCLOSE) {
       
  1569                             EncloseNode en = (EncloseNode)qn.target;
       
  1570                             if (en.type == EncloseType.MEMORY) {
       
  1571                                 if (en.target.getType() == NodeType.QTFR) {
       
  1572                                     QuantifierNode q = (QuantifierNode)en.target;
       
  1573                                     if (isRepeatInfinite(q.upper) && q.greedy == qn.greedy) {
       
  1574                                         qn.upper = qn.lower == 0 ? 1 : qn.lower;
       
  1575                                         if (qn.upper == 1) childState = state;
       
  1576                                     }
       
  1577                                 }
       
  1578                             }
       
  1579                         }
       
  1580                     }
       
  1581                 }
       
  1582             }
       
  1583 
       
  1584             if ((state & CEC_IN_FINITE_REPEAT) != 0) {
       
  1585                 qn.combExpCheckNum = -1;
       
  1586             } else {
       
  1587                 if (isRepeatInfinite(qn.upper)) {
       
  1588                     varNum = CEC_INFINITE_NUM;
       
  1589                     childState |= CEC_IN_INFINITE_REPEAT;
       
  1590                 } else {
       
  1591                     varNum = qn.upper - qn.lower;
       
  1592                 }
       
  1593 
       
  1594                 if (varNum >= CEC_THRES_NUM_BIG_REPEAT) addState |= CEC_CONT_BIG_REPEAT;
       
  1595 
       
  1596                 if (((state & CEC_IN_INFINITE_REPEAT) != 0 && varNum != 0) ||
       
  1597                    ((state & CEC_CONT_BIG_REPEAT) != 0 && varNum >= CEC_THRES_NUM_BIG_REPEAT)) {
       
  1598                     if (qn.combExpCheckNum == 0) {
       
  1599                         env.numCombExpCheck++;
       
  1600                         qn.combExpCheckNum = env.numCombExpCheck;
       
  1601                         if (env.currMaxRegNum > env.combExpMaxRegNum) {
       
  1602                             env.combExpMaxRegNum = env.currMaxRegNum;
       
  1603                         }
       
  1604                     }
       
  1605                 }
       
  1606             }
       
  1607             r = setupCombExpCheck(qn.target, childState);
       
  1608             r |= addState;
       
  1609             break;
       
  1610 
       
  1611         case NodeType.ENCLOSE:
       
  1612             EncloseNode en = (EncloseNode)node;
       
  1613             switch( en.type) {
       
  1614             case EncloseNode.MEMORY:
       
  1615                 if (env.currMaxRegNum < en.regNum) {
       
  1616                     env.currMaxRegNum = en.regNum;
       
  1617                 }
       
  1618                 r = setupCombExpCheck(en.target, state);
       
  1619                 break;
       
  1620 
       
  1621             default:
       
  1622                 r = setupCombExpCheck(en.target, state);
       
  1623             } // inner switch
       
  1624             break;
       
  1625 
       
  1626         case NodeType.CALL:
       
  1627             if (Config.USE_SUBEXP_CALL) {
       
  1628                 CallNode cn = (CallNode)node;
       
  1629                 if (cn.isRecursion()) {
       
  1630                     env.hasRecursion = true;
       
  1631                 } else {
       
  1632                     r = setupCombExpCheck(cn.target, state);
       
  1633                 }
       
  1634             } // USE_SUBEXP_CALL
       
  1635             break;
       
  1636 
       
  1637         default:
       
  1638             break;
       
  1639 
       
  1640         } // switch
       
  1641 
       
  1642         return r;
       
  1643     }
   905     }
  1644 
   906 
  1645     private static final int IN_ALT                     = (1<<0);
   907     private static final int IN_ALT                     = (1<<0);
  1646     private static final int IN_NOT                     = (1<<1);
   908     private static final int IN_NOT                     = (1<<1);
  1647     private static final int IN_REPEAT                  = (1<<2);
   909     private static final int IN_REPEAT                  = (1<<2);
  1689 
   951 
  1690         case NodeType.CTYPE:
   952         case NodeType.CTYPE:
  1691         case NodeType.CANY:
   953         case NodeType.CANY:
  1692             break;
   954             break;
  1693 
   955 
  1694         case NodeType.CALL: // if (Config.USE_SUBEXP_CALL) ?
       
  1695             break;
       
  1696 
       
  1697         case NodeType.BREF:
   956         case NodeType.BREF:
  1698             BackRefNode br = (BackRefNode)node;
   957             BackRefNode br = (BackRefNode)node;
  1699             for (int i=0; i<br.backNum; i++) {
   958             for (int i=0; i<br.backNum; i++) {
  1700                 if (br.back[i] > env.numMem) newValueException(ERR_INVALID_BACKREF);
   959                 if (br.back[i] > env.numMem) newValueException(ERR_INVALID_BACKREF);
  1701                 env.backrefedMem = bsOnAt(env.backrefedMem, br.back[i]);
   960                 env.backrefedMem = bsOnAt(env.backrefedMem, br.back[i]);
  1702                 env.btMemStart = bsOnAt(env.btMemStart, br.back[i]);
   961                 env.btMemStart = bsOnAt(env.btMemStart, br.back[i]);
  1703                 if (Config.USE_BACKREF_WITH_LEVEL) {
       
  1704                     if (br.isNestLevel()) {
       
  1705                         env.btMemEnd = bsOnAt(env.btMemEnd, br.back[i]);
       
  1706                     }
       
  1707                 } // USE_BACKREF_AT_LEVEL
       
  1708                 ((EncloseNode)env.memNodes[br.back[i]]).setMemBackrefed();
   962                 ((EncloseNode)env.memNodes[br.back[i]]).setMemBackrefed();
  1709             }
   963             }
  1710             break;
   964             break;
  1711 
   965 
  1712         case NodeType.QTFR:
   966         case NodeType.QTFR:
  1914                 opt.length.set(1, 1);
  1168                 opt.length.set(1, 1);
  1915             }
  1169             }
  1916             break;
  1170             break;
  1917         }
  1171         }
  1918 
  1172 
  1919         case NodeType.CTYPE: {
       
  1920             int min;
       
  1921             int max = 1;
       
  1922             if (max == 1) {
       
  1923                 min = 1;
       
  1924                 CTypeNode cn = (CTypeNode)node;
       
  1925 
       
  1926                 switch (cn.ctype) {
       
  1927                 case CharacterType.WORD:
       
  1928                     if (cn.not) {
       
  1929                         for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
       
  1930                             if (!EncodingHelper.isWord(i)) {
       
  1931                                 opt.map.addChar(i);
       
  1932                             }
       
  1933                         }
       
  1934                     } else {
       
  1935                         for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
       
  1936                             if (EncodingHelper.isWord(i)) {
       
  1937                                 opt.map.addChar(i);
       
  1938                             }
       
  1939                         }
       
  1940                     }
       
  1941                     break;
       
  1942                 } // inner switch
       
  1943             } else {
       
  1944                 min = 1;
       
  1945             }
       
  1946             opt.length.set(min, max);
       
  1947             break;
       
  1948         }
       
  1949 
       
  1950         case NodeType.CANY: {
  1173         case NodeType.CANY: {
  1951             opt.length.set(1, 1);
  1174             opt.length.set(1, 1);
  1952             break;
  1175             break;
  1953         }
  1176         }
  1954 
  1177 
  2006             }
  1229             }
  2007             opt.length.set(min, max);
  1230             opt.length.set(min, max);
  2008             break;
  1231             break;
  2009         }
  1232         }
  2010 
  1233 
  2011         case NodeType.CALL: {
       
  2012             if (Config.USE_SUBEXP_CALL) {
       
  2013                 CallNode cn = (CallNode)node;
       
  2014                 if (cn.isRecursion()) {
       
  2015                     opt.length.set(0, MinMaxLen.INFINITE_DISTANCE);
       
  2016                 } else {
       
  2017                     int safe = oenv.options;
       
  2018                     oenv.options = ((EncloseNode)cn.target).option;
       
  2019                     optimizeNodeLeft(cn.target, opt, oenv);
       
  2020                     oenv.options = safe;
       
  2021                 }
       
  2022             } // USE_SUBEXP_CALL
       
  2023             break;
       
  2024         }
       
  2025 
  1234 
  2026         case NodeType.QTFR: {
  1235         case NodeType.QTFR: {
  2027             NodeOptInfo nopt = new NodeOptInfo();
  1236             NodeOptInfo nopt = new NodeOptInfo();
  2028             QuantifierNode qn = (QuantifierNode)node;
  1237             QuantifierNode qn = (QuantifierNode)node;
  2029             optimizeNodeLeft(qn.target, nopt, oenv);
  1238             optimizeNodeLeft(qn.target, nopt, oenv);
  2079                 optimizeNodeLeft(en.target, opt, oenv);
  1288                 optimizeNodeLeft(en.target, opt, oenv);
  2080                 oenv.options = save;
  1289                 oenv.options = save;
  2081                 break;
  1290                 break;
  2082 
  1291 
  2083             case EncloseType.MEMORY:
  1292             case EncloseType.MEMORY:
  2084                 if (Config.USE_SUBEXP_CALL && ++en.optCount > MAX_NODE_OPT_INFO_REF_COUNT) {
  1293                 if (++en.optCount > MAX_NODE_OPT_INFO_REF_COUNT) {
  2085                     int min = 0;
  1294                     int min = 0;
  2086                     int max = MinMaxLen.INFINITE_DISTANCE;
  1295                     int max = MinMaxLen.INFINITE_DISTANCE;
  2087                     if (en.isMinFixed()) min = en.minLength;
  1296                     if (en.isMinFixed()) min = en.minLength;
  2088                     if (en.isMaxFixed()) max = en.maxLength;
  1297                     if (en.isMaxFixed()) max = en.maxLength;
  2089                     opt.length.set(min, max);
  1298                     opt.length.set(min, max);