Search in sources :

Example 86 with BasedSequence

use of com.vladsch.flexmark.util.sequence.BasedSequence in project flexmark-java by vsch.

the class InlineParserImpl method processDelimiters.

@Override
public void processDelimiters(Delimiter stackBottom) {
    Map<Character, Delimiter> openersBottom = new HashMap<Character, Delimiter>();
    // find first closer above stackBottom:
    Delimiter closer = lastDelimiter;
    while (closer != null && closer.previous != stackBottom) {
        closer = closer.previous;
    }
    // move forward, looking for closers, and handling each
    while (closer != null) {
        char delimiterChar = closer.delimiterChar;
        DelimiterProcessor delimiterProcessor = delimiterProcessors.get(delimiterChar);
        if (!closer.canClose || delimiterProcessor == null) {
            closer = closer.next;
            continue;
        }
        char openingDelimiterChar = delimiterProcessor.getOpeningCharacter();
        // found delimiter closer. now look back for first matching opener:
        int useDelims = 0;
        boolean openerFound = false;
        boolean potentialOpenerFound = false;
        Delimiter opener = closer.previous;
        while (opener != null && opener != stackBottom && opener != openersBottom.get(delimiterChar)) {
            if (opener.canOpen && opener.delimiterChar == openingDelimiterChar) {
                potentialOpenerFound = true;
                useDelims = delimiterProcessor.getDelimiterUse(opener, closer);
                if (useDelims > 0) {
                    openerFound = true;
                    break;
                }
            }
            opener = opener.previous;
        }
        if (!openerFound) {
            if (!potentialOpenerFound) {
                // Set lower bound for future searches for openers.
                // Only do this when we didn't even have a potential
                // opener (one that matches the character and can open).
                // If an opener was rejected because of the number of
                // delimiters (e.g. because of the "multiple of 3" rule),
                // we want to consider it next time because the number
                // of delimiters can change as we continue processing.
                openersBottom.put(delimiterChar, closer.previous);
                if (!closer.canOpen) {
                    // We can remove a closer that can't be an opener,
                    // once we've seen there's no matching opener:
                    removeDelimiterKeepNode(closer);
                }
            }
            closer = closer.next;
            continue;
        }
        // Remove number of used delimiters from stack and inline nodes.
        opener.numDelims -= useDelims;
        closer.numDelims -= useDelims;
        removeDelimitersBetween(opener, closer);
        // // The delimiter processor can re-parent the nodes between opener and closer,
        // // so make sure they're contiguous already.
        // mergeTextNodes(openerNode.getNext(), closerNode.getPrevious());
        opener.numDelims += useDelims;
        closer.numDelims += useDelims;
        delimiterProcessor.process(opener, closer, useDelims);
        opener.numDelims -= useDelims;
        closer.numDelims -= useDelims;
        // No delimiter characters left to process, so we can remove delimiter and the now empty node.
        if (opener.numDelims == 0) {
            removeDelimiterAndNode(opener);
        } else {
            // adjust number of characters in the node by keeping outer of numDelims
            opener.node.setChars(opener.node.getChars().subSequence(0, opener.numDelims));
        }
        if (closer.numDelims == 0) {
            Delimiter next = closer.next;
            removeDelimiterAndNode(closer);
            closer = next;
        } else {
            // adjust number of characters in the node by keeping outer of numDelims
            BasedSequence chars = closer.node.getChars();
            int length = chars.length();
            closer.node.setChars(chars.subSequence(length - closer.numDelims, length));
            closer.setIndex(closer.getIndex() + useDelims);
        }
    }
    // removeIndex all delimiters
    while (lastDelimiter != null && lastDelimiter != stackBottom) {
        removeDelimiterKeepNode(lastDelimiter);
    }
}
Also used : DelimiterProcessor(com.vladsch.flexmark.parser.delimiter.DelimiterProcessor) AsteriskDelimiterProcessor(com.vladsch.flexmark.internal.inline.AsteriskDelimiterProcessor) UnderscoreDelimiterProcessor(com.vladsch.flexmark.internal.inline.UnderscoreDelimiterProcessor) BasedSequence(com.vladsch.flexmark.util.sequence.BasedSequence)

Example 87 with BasedSequence

use of com.vladsch.flexmark.util.sequence.BasedSequence in project flexmark-java by vsch.

the class InlineParserImpl method parseLinkDestination.

/**
 * Attempt to parse link destination,
 *
 * @return the string or null if no match.
 */
@Override
public BasedSequence parseLinkDestination() {
    BasedSequence res = match(myParsing.LINK_DESTINATION_ANGLES);
    if (res != null) {
        return res;
    } else {
        if (options.linksAllowMatchedParentheses) {
            // allow matched parenthesis
            BasedSequence matched = match(myParsing.LINK_DESTINATION_MATCHED_PARENS);
            if (matched != null) {
                int openCount = 0;
                int iMax = matched.length();
                for (int i = 0; i < iMax; i++) {
                    char c = matched.charAt(i);
                    if (c == '\\') {
                        // escape
                        i++;
                    } else if (c == '(') {
                        openCount++;
                    } else if (c == ')') {
                        if (openCount == 0) {
                            // truncate to this and leave ')' to be parsed
                            index -= iMax - i;
                            matched = matched.subSequence(0, i);
                            break;
                        }
                        openCount--;
                    }
                }
                return options.spaceInLinkUrls ? matched.trimEnd(BasedSequence.SPACE) : matched;
            }
            return null;
        } else {
            // spec 0.27 compatibility
            final BasedSequence matched = match(myParsing.LINK_DESTINATION);
            return matched != null && options.spaceInLinkUrls ? matched.trimEnd(BasedSequence.SPACE) : matched;
        }
    }
}
Also used : BasedSequence(com.vladsch.flexmark.util.sequence.BasedSequence)

Example 88 with BasedSequence

use of com.vladsch.flexmark.util.sequence.BasedSequence in project flexmark-java by vsch.

the class InlineParserImpl method preProcessBlock.

/*
     *  ParagraphPreProcessor implementation
     */
@Override
public int preProcessBlock(Paragraph block, ParserState state) {
    BasedSequence contentChars = block.getChars();
    // try parsing the beginning as link reference definitions:
    int leadingSpaces = contentChars.countLeading(BasedSequence.WHITESPACE_NO_EOL_CHARS);
    int length = contentChars.length();
    while (leadingSpaces <= 3 && length > 3 + leadingSpaces && contentChars.charAt(leadingSpaces) == '[') {
        if (leadingSpaces > 0) {
            contentChars = contentChars.subSequence(leadingSpaces, length);
            length -= leadingSpaces;
        }
        int pos = parseReference(block, contentChars);
        if (pos == 0)
            break;
        contentChars = contentChars.subSequence(pos, length);
        length = contentChars.length();
        leadingSpaces = contentChars.countLeading(BasedSequence.WHITESPACE_NO_EOL_CHARS);
    }
    return contentChars.getStartOffset() - block.getChars().getStartOffset();
}
Also used : BasedSequence(com.vladsch.flexmark.util.sequence.BasedSequence)

Example 89 with BasedSequence

use of com.vladsch.flexmark.util.sequence.BasedSequence in project flexmark-java by vsch.

the class InlineParserImpl method processCustomCharacters.

private boolean processCustomCharacters() {
    char c = peek();
    CharacterNodeFactory factory = customSpecialCharacterFactoryMap.get(c);
    if (factory == null)
        return false;
    Node node = factory.create();
    node.setChars(input.subSequence(index, index + 1));
    if (currentText != null) {
        BasedSequence prevText = SegmentedSequence.of(currentText, BasedSequence.NULL);
        currentText = null;
        // see if need to trim some off the end
        int pos = prevText.length();
        BasedSequence skipped = null;
        while (pos > 0 && factory.skipPrev(prevText.charAt(pos - 1))) pos--;
        if (pos < prevText.length()) {
            skipped = prevText.subSequence(pos);
            prevText = prevText.subSequence(0, pos);
        }
        block.appendChild(new Text(prevText));
        if (skipped != null && factory.wantSkippedWhitespace()) {
            block.appendChild(new WhiteSpace(skipped));
        }
    }
    appendNode(node);
    if (customSpecialCharacterNodes == null)
        customSpecialCharacterNodes = new ArrayList<Node>();
    customSpecialCharacterNodes.add(node);
    int pos = index + 1;
    do {
        index++;
        c = peek();
    } while (c != '\0' && factory.skipNext(c));
    if (pos < index && factory.wantSkippedWhitespace()) {
        block.appendChild(new WhiteSpace(input.subSequence(pos, index)));
    }
    return true;
}
Also used : BasedSequence(com.vladsch.flexmark.util.sequence.BasedSequence) CharacterNodeFactory(com.vladsch.flexmark.parser.block.CharacterNodeFactory)

Example 90 with BasedSequence

use of com.vladsch.flexmark.util.sequence.BasedSequence in project flexmark-java by vsch.

the class InlineParserImpl method mergeIfNeeded.

@Override
public void mergeIfNeeded(Text first, Text last) {
    if (first != null && last != null && first != last) {
        ArrayList<BasedSequence> sb = new ArrayList<BasedSequence>();
        sb.add(first.getChars());
        Node node = first.getNext();
        Node stop = last.getNext();
        while (node != stop) {
            sb.add(node.getChars());
            Node unlink = node;
            node = node.getNext();
            unlink.unlink();
        }
        BasedSequence literal = SegmentedSequence.of(sb, first.getChars());
        first.setChars(literal);
    }
}
Also used : BasedSequence(com.vladsch.flexmark.util.sequence.BasedSequence)

Aggregations

BasedSequence (com.vladsch.flexmark.util.sequence.BasedSequence)91 Matcher (java.util.regex.Matcher)13 Node (com.vladsch.flexmark.ast.Node)6 ArrayList (java.util.ArrayList)5 MacroClose (com.vladsch.flexmark.ext.xwiki.macros.MacroClose)3 ReplacedTextMapper (com.vladsch.flexmark.util.sequence.ReplacedTextMapper)3 Text (com.vladsch.flexmark.ast.Text)2 AttributesNode (com.vladsch.flexmark.ext.attributes.AttributesNode)2 FootnoteBlock (com.vladsch.flexmark.ext.footnotes.FootnoteBlock)2 Macro (com.vladsch.flexmark.ext.xwiki.macros.Macro)2 Pair (com.vladsch.flexmark.util.Pair)2 RepeatedCharSequence (com.vladsch.flexmark.util.sequence.RepeatedCharSequence)2 Block (com.vladsch.flexmark.ast.Block)1 BulletListItem (com.vladsch.flexmark.ast.BulletListItem)1 Link (com.vladsch.flexmark.ast.Link)1 ListItem (com.vladsch.flexmark.ast.ListItem)1 NodeIterator (com.vladsch.flexmark.ast.NodeIterator)1 OrderedListItem (com.vladsch.flexmark.ast.OrderedListItem)1 Parsing (com.vladsch.flexmark.ast.util.Parsing)1 TextCollectingVisitor (com.vladsch.flexmark.ast.util.TextCollectingVisitor)1