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);
}
}
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;
}
}
}
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();
}
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;
}
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);
}
}
Aggregations