<commit_before>/*
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.joni;

import static org.joni.BitStatus.bsAll;
import static org.joni.BitStatus.bsAt;
import static org.joni.BitStatus.bsClear;
import static org.joni.BitStatus.bsOnAt;
import static org.joni.BitStatus.bsOnAtSimple;
import static org.joni.Option.isCaptureGroup;
import static org.joni.Option.isFindCondition;
import static org.joni.Option.isIgnoreCase;
import static org.joni.Option.isMultiline;
import static org.joni.ast.ListNode.newAlt;
import static org.joni.ast.ListNode.newList;
import static org.joni.ast.QuantifierNode.isRepeatInfinite;

import org.jcodings.CaseFoldCodeItem;
import org.jcodings.ObjPtr;
import org.jcodings.Ptr;
import org.jcodings.constants.CharacterType;
import org.joni.ast.AnchorNode;
import org.joni.ast.BackRefNode;
import org.joni.ast.CClassNode;
import org.joni.ast.CTypeNode;
import org.joni.ast.CallNode;
import org.joni.ast.EncloseNode;
import org.joni.ast.ListNode;
import org.joni.ast.Node;
import org.joni.ast.QuantifierNode;
import org.joni.ast.StringNode;
import org.joni.constants.AnchorType;
import org.joni.constants.EncloseType;
import org.joni.constants.NodeType;
import org.joni.constants.StackPopLevel;
import org.joni.constants.TargetInfo;

final class Analyser extends Parser {

    protected Analyser(Regex regex, Syntax syntax, byte[]bytes, int p, int end) {
        super(regex, syntax, bytes, p, end);
    }

    protected final void compile() {
        if (Config.DEBUG) Config.log.println(regex.encStringToString(bytes, getBegin(), getEnd()));
        reset();

        regex.numMem = 0;
        regex.numRepeat = 0;
        regex.numNullCheck = 0;
        //regex.repeatRangeAlloc = 0;
        regex.repeatRangeLo = null;
        regex.repeatRangeHi = null;
        regex.numCombExpCheck = 0;

        if (Config.USE_CEC) regex.numCombExpCheck = 0;


        Node root = parseRegexp(); // onig_parse_make_tree
        regex.numMem = env.numMem;

        if (Config.USE_NAMED_GROUP) {
            /* mixed use named group and no-named group */
            if (env.numNamed > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(regex.options)) {
                if (env.numNamed != env.numMem) {
                    root = disableNoNameGroupCapture(root);
                } else {
                    numberedRefCheck(root);
                }
            }
        } // USE_NAMED_GROUP

        if (Config.USE_NAMED_GROUP) {
            if (env.numCall > 0) {
                env.unsetAddrList = new UnsetAddrList(env.numCall);
                setupSubExpCall(root);
                // r != 0 ???
                subexpRecursiveCheckTrav(root);
                // r < 0 -< err, FOUND_CALLED_NODE = 1
                subexpInfRecursiveCheckTrav(root);
                // r != 0  recursion infinite ???
                regex.numCall = env.numCall;
            } else {
                regex.numCall = 0;
            }
        } // USE_NAMED_GROUP

        if (Config.DEBUG_PARSE_TREE && Config.DEBUG_PARSE_TREE_RAW) Config.log.println("<RAW TREE>\n" + root + "\n");

        Node.RootNode top = Node.newRoot(root);
        setupTree(root, 0);
        root = top.getRoot();

        if (Config.DEBUG_PARSE_TREE) Config.log.println("<TREE>\n" + root + "\n");

        regex.captureHistory = env.captureHistory;
        regex.btMemStart = env.btMemStart;
        regex.btMemEnd = env.btMemEnd;

        if (isFindCondition(regex.options)) {
            regex.btMemEnd = bsAll();
        } else {
            regex.btMemEnd = env.btMemEnd;
            regex.btMemEnd |= regex.captureHistory;
        }

        if (Config.USE_CEC) {
            if (env.backrefedMem == 0 || (Config.USE_SUBEXP_CALL && env.numCall == 0)) {
                setupCombExpCheck(root, 0);

                if (Config.USE_SUBEXP_CALL && env.hasRecursion) {
                    env.numCombExpCheck = 0;
                } else { // USE_SUBEXP_CALL
                    if (env.combExpMaxRegNum > 0) {
                        for (int i=1; i<env.combExpMaxRegNum; i++) {
                            if (bsAt(env.backrefedMem, i)) {
                                env.numCombExpCheck = 0;
                                break;
                            }
                        }
                    }
                }

            } // USE_SUBEXP_CALL
            regex.numCombExpCheck = env.numCombExpCheck;
        } // USE_COMBINATION_EXPLOSION_CHECK

        regex.clearOptimizeInfo();

        if (!Config.DONT_OPTIMIZE) setOptimizedInfoFromTree(root);

        env.memNodes = null;

        new ArrayCompiler(this).compile(root);

        if (regex.numRepeat != 0 || regex.btMemEnd != 0) {
            regex.stackPopLevel = StackPopLevel.ALL;
        } else {
            if (regex.btMemStart != 0) {
                regex.stackPopLevel = StackPopLevel.MEM_START;
            } else {
                regex.stackPopLevel = StackPopLevel.FREE;
            }
        }

        if (Config.DEBUG_COMPILE) {
            if (Config.USE_NAMED_GROUP) Config.log.print(regex.nameTableToString());
            Config.log.println("stack used: " + regex.requireStack);
            if (Config.USE_STRING_TEMPLATES) Config.log.print("templates: " + regex.templateNum + "\n");
            Config.log.println(new ByteCodePrinter(regex).byteCodeListToString());
        } // DEBUG_COMPILE
    }

    private void noNameDisableMapFor_listAlt(Node node, int[]map, Ptr counter) {
        ListNode can = (ListNode)node;
        do {
            can.setValue(noNameDisableMap(can.value, map, counter));
        } while ((can = can.tail) != null);
    }

    private void noNameDisableMapFor_quantifier(Node node, int[]map, Ptr counter) {
        QuantifierNode qn = (QuantifierNode)node;
        Node target = qn.target;
        Node old = target;
        target = noNameDisableMap(target, map, counter);

        if (target != old) {
            qn.setTarget(target);
            if (target.getType() == NodeType.QTFR) qn.reduceNestedQuantifier((QuantifierNode)target);
        }
    }

    private Node noNameDisableMapFor_enclose(Node node, int[]map, Ptr counter) {
        EncloseNode en = (EncloseNode)node;
        if (en.type == EncloseType.MEMORY) {
            if (en.isNamedGroup()) {
                counter.p++;
                map[en.regNum] = counter.p;
                en.regNum = counter.p;
                en.setTarget(noNameDisableMap(en.target, map, counter));<commit_msg>turn off syntax specific options after compilation<commit_after>/*
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.joni;

import static org.joni.BitStatus.bsAll;
import static org.joni.BitStatus.bsAt;
import static org.joni.BitStatus.bsClear;
import static org.joni.BitStatus.bsOnAt;
import static org.joni.BitStatus.bsOnAtSimple;
import static org.joni.Option.isCaptureGroup;
import static org.joni.Option.isFindCondition;
import static org.joni.Option.isIgnoreCase;
import static org.joni.Option.isMultiline;
import static org.joni.ast.ListNode.newAlt;
import static org.joni.ast.ListNode.newList;
import static org.joni.ast.QuantifierNode.isRepeatInfinite;

import org.jcodings.CaseFoldCodeItem;
import org.jcodings.ObjPtr;
import org.jcodings.Ptr;
import org.jcodings.constants.CharacterType;
import org.joni.ast.AnchorNode;
import org.joni.ast.BackRefNode;
import org.joni.ast.CClassNode;
import org.joni.ast.CTypeNode;
import org.joni.ast.CallNode;
import org.joni.ast.EncloseNode;
import org.joni.ast.ListNode;
import org.joni.ast.Node;
import org.joni.ast.QuantifierNode;
import org.joni.ast.StringNode;
import org.joni.constants.AnchorType;
import org.joni.constants.EncloseType;
import org.joni.constants.NodeType;
import org.joni.constants.StackPopLevel;
import org.joni.constants.TargetInfo;

final class Analyser extends Parser {

    protected Analyser(Regex regex, Syntax syntax, byte[]bytes, int p, int end) {
        super(regex, syntax, bytes, p, end);
    }

    protected final void compile() {
        if (Config.DEBUG) Config.log.println(regex.encStringToString(bytes, getBegin(), getEnd()));
        reset();

        regex.numMem = 0;
        regex.numRepeat = 0;
        regex.numNullCheck = 0;
        //regex.repeatRangeAlloc = 0;
        regex.repeatRangeLo = null;
        regex.repeatRangeHi = null;
        regex.numCombExpCheck = 0;

        if (Config.USE_CEC) regex.numCombExpCheck = 0;


        Node root = parseRegexp(); // onig_parse_make_tree
        regex.numMem = env.numMem;

        if (Config.USE_NAMED_GROUP) {
            /* mixed use named group and no-named group */
            if (env.numNamed > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(regex.options)) {
                if (env.numNamed != env.numMem) {
                    root = disableNoNameGroupCapture(root);
                } else {
                    numberedRefCheck(root);
                }
            }
        } // USE_NAMED_GROUP

        if (Config.USE_NAMED_GROUP) {
            if (env.numCall > 0) {
                env.unsetAddrList = new UnsetAddrList(env.numCall);
                setupSubExpCall(root);
                // r != 0 ???
                subexpRecursiveCheckTrav(root);
                // r < 0 -< err, FOUND_CALLED_NODE = 1
                subexpInfRecursiveCheckTrav(root);
                // r != 0  recursion infinite ???
                regex.numCall = env.numCall;
            } else {
                regex.numCall = 0;
            }
        } // USE_NAMED_GROUP

        if (Config.DEBUG_PARSE_TREE && Config.DEBUG_PARSE_TREE_RAW) Config.log.println("<RAW TREE>\n" + root + "\n");

        Node.RootNode top = Node.newRoot(root);
        setupTree(root, 0);
        root = top.getRoot();

        if (Config.DEBUG_PARSE_TREE) Config.log.println("<TREE>\n" + root + "\n");

        regex.captureHistory = env.captureHistory;
        regex.btMemStart = env.btMemStart;
        regex.btMemEnd = env.btMemEnd;

        if (isFindCondition(regex.options)) {
            regex.btMemEnd = bsAll();
        } else {
            regex.btMemEnd = env.btMemEnd;
            regex.btMemEnd |= regex.captureHistory;
        }

        if (Config.USE_CEC) {
            if (env.backrefedMem == 0 || (Config.USE_SUBEXP_CALL && env.numCall == 0)) {
                setupCombExpCheck(root, 0);

                if (Config.USE_SUBEXP_CALL && env.hasRecursion) {
                    env.numCombExpCheck = 0;
                } else { // USE_SUBEXP_CALL
                    if (env.combExpMaxRegNum > 0) {
                        for (int i=1; i<env.combExpMaxRegNum; i++) {
                            if (bsAt(env.backrefedMem, i)) {
                                env.numCombExpCheck = 0;
                                break;
                            }
                        }
                    }
                }

            } // USE_SUBEXP_CALL
            regex.numCombExpCheck = env.numCombExpCheck;
        } // USE_COMBINATION_EXPLOSION_CHECK

        regex.clearOptimizeInfo();

        if (!Config.DONT_OPTIMIZE) setOptimizedInfoFromTree(root);

        env.memNodes = null;

        new ArrayCompiler(this).compile(root);

        if (regex.numRepeat != 0 || regex.btMemEnd != 0) {
            regex.stackPopLevel = StackPopLevel.ALL;
        } else {
            if (regex.btMemStart != 0) {
                regex.stackPopLevel = StackPopLevel.MEM_START;
            } else {
                regex.stackPopLevel = StackPopLevel.FREE;
            }
        }

        if (Config.DEBUG_COMPILE) {
            if (Config.USE_NAMED_GROUP) Config.log.print(regex.nameTableToString());
            Config.log.println("stack used: " + regex.requireStack);
            if (Config.USE_STRING_TEMPLATES) Config.log.print("templates: " + regex.templateNum + "\n");
            Config.log.println(new ByteCodePrinter(regex).byteCodeListToString());
        } // DEBUG_COMPILE

        regex.options &= ~syntax.options;
    }

    private void noNameDisableMapFor_listAlt(Node node, int[]map, Ptr counter) {
        ListNode can = (ListNode)node;
        do {
            can.setValue(noNameDisableMap(can.value, map, counter));
        } while ((can = can.tail) != null);
    }

    private void noNameDisableMapFor_quantifier(Node node, int[]map, Ptr counter) {
        QuantifierNode qn = (QuantifierNode)node;
        Node target = qn.target;
        Node old = target;
        target = noNameDisableMap(target, map, counter);

        if (target != old) {
            qn.setTarget(target);
            if (target.getType() == NodeType.QTFR) qn.reduceNestedQuantifier((QuantifierNode)target);
        }
    }

    private Node noNameDisableMapFor_enclose(Node node, int[]map, Ptr counter) {
        EncloseNode en = (EncloseNode)node;
        if (en.type == EncloseType.MEMORY) {
            if (en.isNamedGroup()) {
                counter.p++;
                map[en.regNum] = counter.p;
                en.regNum = counter.p;
                en.setTarget(noNameDisableMap(en.target, map, counter));
{'fraction_non_alphanumeric': 0.10248940677966102, 'fraction_numerical': 0.0031779661016949155, 'mean_word_length': 2.2490858249085823, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '91099', 'n_tokens_mistral': 4572, 'n_tokens_neox': 4385, 'n_words': 1049}