Reading — step 1 of 5
Learn
The Delimiter Stack
The emphasis lesson built a guarded regex and then admitted where it still parts
company with the spec: a*"quoted"* gets emphasised when it should not. That is
not a bug you can patch with another lookaround. Emphasis is not a regular
language, and the appendix to the spec gives an algorithm instead. This is it.
Where does a regex actually break?
Not on the easy cases. It breaks when two candidate spans overlap.
A regex matches the first opener with a later closer, so it swallows the second
** as content. The spec resolves the same input the other way — when two spans
share a closing delimiter, the one that opens later wins — giving
**foo <strong>bar baz</strong>, with the leading pair left as literal text.
Nesting has the same shape: *a **b** c* needs the inner pair matched first and
the outer pair to survive across it, and no single substitution does both.
What goes on the stack?
Not characters — delimiter runs. A run is a maximal sequence of * (or of
_), and it is pushed with its length plus two booleans: can this run open, and
can it close. Those come from the spec's flanking rules, which look at exactly
one character on each side, treating the line ends as whitespace.
Row three is the case the regex could not reach: a run preceded by a letter and followed by punctuation is not left-flanking, so it cannot open, so the line has a closer and no opener and stays literal. Two booleans, no lookarounds.
Matching openers to closers
The scan is asymmetric, and that asymmetry is the whole algorithm.
Forward to find a closer, then backwards to the nearest opener — nearest, not
first, which is what makes the later-opening span win. Everything between the two
becomes the new node's content, and any delimiter runs caught in the middle are
rendered as plain asterisks: an unmatched * is text, always.
Spending is per delimiter, not per run. A run of two that matches a run of one gives up a single asterisk and stays on the stack with one left, which is how a closer can serve twice.
What this leaves out
Runs of three or more, where strong and em combine — the emphasis lesson covers
those and tells you which order this course's tests expect. The _ variants add
two word-boundary clauses to the same booleans. And a spec rule blocks a match
when the two run lengths sum to a multiple of three; none of the inputs here
reach it.
Your exercise
Build the stack, match the runs, emit the tags.
The mistake the grader catches is scanning back to the first opener instead of
the nearest. A hidden test feeds **foo **bar baz**; the nearest opener gives
**foo <strong>bar baz</strong>, and the first one gives
<strong>foo **bar baz</strong> — the same wrong answer the regex produced above.
Walk backwards from the closer and stop at the first run you can use.
The second is resuming in the wrong place. After a match the closer may still
have delimiters left, so restart the scan at it rather than after it;
**a *b* c** needs the outer pair matched on a second visit.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…