diff options
author | John MacFarlane <jgm@berkeley.edu> | 2014-11-08 08:15:49 -0800 |
---|---|---|
committer | John MacFarlane <jgm@berkeley.edu> | 2014-11-09 13:21:36 -0800 |
commit | c84db152b53edaa6373bcb89a96b5b30830f8185 (patch) | |
tree | 61b2e5d5c5269d269fb7a740764d7f05c6dcafba | |
parent | 98dfa2d659f844a927d8570c1becbbed2d1834ef (diff) |
Initial steps towards link parsing.
-rw-r--r-- | src/inlines.c | 131 |
1 files changed, 114 insertions, 17 deletions
diff --git a/src/inlines.c b/src/inlines.c index 9197ee0..bf76e1a 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -627,25 +627,120 @@ static int link_label(subject* subj, chunk *raw_label) } } -// Parse a link or the link portion of an image, or return a fallback. -static node_inl* handle_left_bracket(subject* subj) +// Return a link, an image, or a literal close bracket. +static node_inl* handle_close_bracket(subject* subj) { + int initial_pos; + int starturl, endurl, starttitle, endtitle, endall; + int n; + int sps; + chunk url, title; + opener_stack *ostack = subj->openers; + node_inl *link_text = NULL; + node_inl *tmp = NULL; + + advance(subj); // advance past ] + initial_pos = subj->pos; + + // look through stack of openers for a [ or ! + while (ostack) { + if (ostack->delim_char == '[' || ostack->delim_char == '!') { + break; + } + ostack = ostack->previous; + } + + if (ostack == NULL) { + return make_str(chunk_literal("]")); + } + + // If we got here, we matched a potential link/image text. + link_text = ostack->first_inline->next; + + // Now we check to see if it's a link/image. + + + if (peek_char(subj) == '(' && + ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) && + ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) { + + // try to parse an explicit link: + starturl = subj->pos + 1 + sps; // after ( + endurl = starturl + n; + starttitle = endurl + scan_spacechars(&subj->input, endurl); + + // ensure there are spaces btw url and title + endtitle = (starttitle == endurl) ? starttitle : + starttitle + scan_link_title(&subj->input, starttitle); + + endall = endtitle + scan_spacechars(&subj->input, endtitle); + + if (peek_at(subj, endall) == ')') { + subj->pos = endall + 1; + + url = chunk_dup(&subj->input, starturl, endurl - starturl); + title = chunk_dup(&subj->input, starttitle, endtitle - starttitle); + + tmp = link_text->next; + ostack->first_inline->content.literal = chunk_literal("X"); // TODO a kludge + ostack->first_inline->next = make_link(link_text, url, title); + return make_str(chunk_literal("X")); + } else { + goto noMatch; + } + } else { + goto noMatch; // for now + } + + // if found, check to see if we have a target: + // - followed by (inline link) + // - followed by [link label] that matches + // - followed by [], and our brackets have a label that matches + // - our brackets have a label that matches + + // if no target, remove the matching opener from the stack and return literal ]. + // if yes target, remove the matching opener and any later openers. + // return a link or an image. + + /* + chunk rawlabel_tmp; + chunk reflabel; + + // Check for reference link. + // First, see if there's another label: + subj->pos = subj->pos + scan_spacechars(&subj->input, endlabel); + reflabel = rawlabel; + + // if followed by a nonempty link label, we change reflabel to it: + if (peek_char(subj) == '[' && link_label(subj, &rawlabel_tmp)) { + if (rawlabel_tmp.len > 0) + reflabel = rawlabel_tmp; + } else { + subj->pos = endlabel; + } + + // lookup rawlabel in subject->reference_map: + ref = reference_lookup(subj->refmap, &reflabel); + if (ref != NULL) { // found + lab = parse_chunk_inlines(&rawlabel, NULL); + result = make_ref_link(lab, ref); + } else { + goto noMatch; + } + return result; + node_inl *lab = NULL; node_inl *result = NULL; reference *ref; - int n; - int sps; int found_label; - int endlabel, startpos, starturl, endurl, starttitle, endtitle, endall; chunk rawlabel; - chunk url, title; - startpos = subj->pos; found_label = link_label(subj, &rawlabel); endlabel = subj->pos; - if (found_label) { + if (found_label) + { if (peek_char(subj) == '(' && ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) && ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) { @@ -700,10 +795,11 @@ static node_inl* handle_left_bracket(subject* subj) return result; } } + */ noMatch: // If we fall through to here, it means we didn't match a link: - subj->pos = startpos + 1; // advance past [ - return make_str(chunk_literal("[")); + subj->pos = initial_pos; + return make_str(chunk_literal("]")); } // Parse a hard or soft linebreak, returning an inline. @@ -824,17 +920,18 @@ static int parse_inline(subject* subj, node_inl ** last) new = handle_strong_emph(subj, '*', last); break; case '[': - new = handle_left_bracket(subj); + advance(subj); + new = make_str(chunk_literal("[")); + subj->openers = push_opener(subj, 1, '[', new); + break; + case ']': + new = handle_close_bracket(subj); break; case '!': advance(subj); if (peek_char(subj) == '[') { - new = handle_left_bracket(subj); - if (new != NULL && new->tag == INL_LINK) { - new->tag = INL_IMAGE; - } else { - new = append_inlines(make_str(chunk_literal("!")), new); - } + new = make_str(chunk_literal("![")); + subj->openers = push_opener(subj, 1, '!', new); } else { new = make_str(chunk_literal("!")); } |