class TocParsing extends Parsing {
        final Pattern TOC_BLOCK_START;
        //private static Pattern TOC_BLOCK_CONTINUE = Pattern.compile("^.+$");

        public TocParsing(DataHolder options) {
            super(options);
            if (CASE_SENSITIVE_TOC_TAG.get(options)) {
                this.TOC_BLOCK_START = Pattern.compile("^\\[TOC(?:\\s+([^\\]]+))?]:\\s*#(?:\\s+(" + super.LINK_TITLE_STRING + "))?\\s*$");
            } else {
                this.TOC_BLOCK_START = Pattern.compile("^\\[(?i:TOC)(?:\\s+([^\\]]+))?]:\\s*#(?:\\s+(" + super.LINK_TITLE_STRING + "))?\\s*$");
            }
        }
    }

    static int HAVE_HTML = 1;
    static int HAVE_HEADING = 2;
    static int HAVE_LIST = 4;
    static int HAVE_BLANK_LINE = 8;

    final private SimTocBlock block;
    final private TocOptions options;
    private int haveChildren = 0;
    private BasedSequence blankLineSpacer = BasedSequence.NULL;

    SimTocBlockParser(DataHolder options, BasedSequence tocChars, BasedSequence styleChars, BasedSequence titleChars) {
        this.options = new TocOptions(options, true);
        block = new SimTocBlock(tocChars, styleChars, titleChars);
    }

    @Override
    public Block getBlock() {
        return block;
    }

    @Override
    public BlockContinue tryContinue(ParserState state) {
        // we stop on a blank line if blank line spacer is not enabled or we already had one
        if ((!options.isBlankLineSpacer || haveChildren != 0) && state.isBlank()) {
            return BlockContinue.none();
        } else {
            if (state.isBlank()) {
                haveChildren |= HAVE_BLANK_LINE;
                blankLineSpacer = state.getLine();
            }
            return BlockContinue.atIndex(state.getIndex());
        }
    }

    @Override
    public boolean canContain(ParserState state, BlockParser blockParser, Block block) {<FILL_FUNCTION_BODY>

        if (block instanceof HtmlBlock) {
            if ((haveChildren & ~HAVE_BLANK_LINE) == 0) {
                haveChildren |= HAVE_HTML;
                return true;
            }
        } else if (block instanceof Heading) {
            if ((haveChildren & ~HAVE_BLANK_LINE) == 0) {
                haveChildren |= HAVE_HEADING;
                return true;
            }
        } else if (block instanceof ListBlock) {
            if ((haveChildren & (HAVE_HTML | HAVE_LIST)) == 0) {
                haveChildren |= HAVE_LIST;
                return true;
            }
        }
        return false;
    
<methods>public non-sealed void <init>() ,public void addLine(com.vladsch.flexmark.parser.block.ParserState, com.vladsch.flexmark.util.sequence.BasedSequence) ,public boolean breakOutOnDoubleBlankLine() ,public boolean canContain(com.vladsch.flexmark.parser.block.ParserState, com.vladsch.flexmark.parser.block.BlockParser, com.vladsch.flexmark.util.ast.Block) ,public boolean canInterruptBy(com.vladsch.flexmark.parser.block.BlockParserFactory) ,public final void finalizeClosedBlock() ,public com.vladsch.flexmark.util.ast.BlockContent getBlockContent() ,public com.vladsch.flexmark.util.data.MutableDataHolder getDataHolder() ,public boolean isClosed() ,public boolean isContainer() ,public boolean isInterruptible() ,public boolean isParagraphParser() ,public boolean isPropagatingLastBlankLine(com.vladsch.flexmark.parser.block.BlockParser) ,public boolean isRawText() ,public void parseInlines(com.vladsch.flexmark.parser.InlineParser) ,public void removeBlankLines() <variables>private boolean isClosed,private com.vladsch.flexmark.util.data.MutableDataSet mutableData