When we're parsing inlines and we hit
* or _ characters[ or ![we insert a text node with the literal content, and add a pointer to this text node to the delimiter stack.
The delimiter stack is a doubly linked list. Each element contains a pointer to a text node, plus information about
[, ![, *, _)When we hit a ] character, we call the look_for_link_or_image procedure (see below).
When we hit the end of the input, we call the process_emphasis procedure (see below), with stack_bottom = NULL.
look_for_link_or_imageStarting at the top of the delimiter stack, we look backwards through the stack for a [ or ![ delimiter.
If we don't find one, we return a literal text node ].
If we do find one, but it's not active, we remove the inactive delimiter from the stack, and return a literal text node ].
If we find one and it's active, then we parse ahead to see if we have an inline link/image, reference link/image, compact reference link/image, or shortcut reference link/image.
If we don't, then we remove the [ or ![ delimiter from the delimiter stack and return a literal text node ].
If we do, then
We return a link or image node whose children are the inlines after the text node pointed to by the opening delimiter.
We run process_emphasis on these inlines, with the [ opener as stack_bottom.
We remove the opening delimiter.
If we have a link (and not an image), we also set all [ delimiters before the opening delimiter to inactive. (This will prevent us from getting links within links.)
process_emphasisParameter stack_bottom sets a lower bound to how far we descend in the delimiter stack. If it is NULL, we can go all the way to the bottom. Otherwise, we stop before visiting stack_bottom.
Let current_position point to the element on the delimiter just above stack_bottom (or the first element if stack_bottom is NULL).
We keep track of the openers_bottom for each delimiter type (*, _). Initialize this to stack_bottom.
Then we repeat the following until we run out of potential closers:
Move current_position forward in the delimiter stack (if needed) until we find the first potential closer with delimiter * or _. (This will be the potential closer closest to the beginning of the input -- the first one in parse order.)
Now, look back in the stack (staying above stack_bottom and the openers_bottom for this delimiter type) for the first matching potential opener (“matching” means same delimiter).
If one is found:
current_position to the next element in the stack.If none in found:
openers_bottom to the element before current_position. (We know that there are no openers for this kind of closer up to and including this point, so this puts a lower bound on future searches.)current_position is not a potential opener, remove it from the delimiter stack (since we know it can't be a closer either).current_position to the next element in the stack.Repeat.
After we're done, remove all delimiters above stack_bottom from the delimiter stack.