cmark

My personal build of CMark ✏️

Commit
23c24d88401a4dbb8319c8c1fc6bbb0c44fb29cb
Parent
5f56a1988ff8edfc020c97e37dbf834b499157d6
Author
John MacFarlane <jgm@berkeley.edu>
Date

Added last_closer to Inline object.

This helps us avoid unneeded backtracking in pathological input of the form:

*a **a *a **a *a etc.

If we get to position k without finding a closing delimiter, then backtrack to 1, we can assume we won't find a closing delimiter when parsing forward again.

This could no doubt be polished up, e.g. by making it sensitive to the kind of delimiter.

Diffstat

1 file changed, 19 insertions, 6 deletions

Status File Name N° Changes Insertions Deletions
Modified js/stmd.js 25 19 6
diff --git a/js/stmd.js b/js/stmd.js
@@ -291,14 +291,19 @@ var parseEmphasis = function() {
   this.pos += numdelims;
 
   var next_inline;
+  var last_closer = null;
 
-    var delims_to_match = numdelims;
-    while (true) {
+  var delims_to_match = numdelims;
+  while (this.last_closer === null || this.last_closer >= this.pos) {
         res = this.scanDelims(c);
         numclosedelims = res.numdelims;
         if (res.can_close) {
+            if (last_closer < this.pos) {
+                last_closer = this.pos;
+            }
             if (numclosedelims === 3 && delims_to_match === 3) {
                 this.pos += 3;
+                this.last_closer = null;
                 return {t: 'Strong', c: [{t: 'Emph', c: inlines}]};
             } else if (numclosedelims >= 2 && delims_to_match >= 2) {
                 delims_to_match -= 2;
@@ -310,18 +315,24 @@ var parseEmphasis = function() {
                 inlines = [{t: 'Emph', c: inlines}];
             }
             if (delims_to_match === 0) {
+                this.last_closer = null;
                 return inlines[0];
             }
         } else if (next_inline = this.parseInline()) {
             inlines.push(next_inline);
         } else {
-            // didn't find closing delimiter
-            this.pos = startpos + numdelims;
-            return {t: 'Str', c: this.subject.slice(startpos, startpos + numdelims)};
+            break;
         }
     }
 
-    return null;
+    // didn't find closing delimiter
+    this.pos = startpos + numdelims;
+    if (last_closer === null) {
+        this.last_closer = startpos;
+    } else {
+        this.last_closer = last_closer;
+    }
+    return {t: 'Str', c: this.subject.slice(startpos, startpos + numdelims)};
 };
 
 // Attempt to parse link title (sans quotes), returning the string
@@ -654,6 +665,7 @@ var parseInlines = function(s, refmap) {
   this.pos = 0;
   this.refmap = refmap || {};
   this.memo = {};
+  this.last_closer = null;
   var inlines = [];
   var next_inline;
   while (next_inline = this.parseInline()) {
@@ -670,6 +682,7 @@ function InlineParser(){
     pos: 0,
     refmap: {},
     memo: {},
+    last_closer: null,
     match: match,
     peek: peek,
     spnl: spnl,