@@ -8,7 +8,9 @@ const nodes = @import("nodes.zig");
88const strings = @import ("strings.zig" );
99const Options = @import ("options.zig" ).Options ;
1010const scanners = @import ("scanners.zig" );
11- const Reference = @import ("parser.zig" ).Reference ;
11+ const parser_mod = @import ("parser.zig" );
12+ const Reference = parser_mod .Reference ;
13+ const RefMap = parser_mod .RefMap ;
1214
1315const MAX_BACKTICKS = 80 ;
1416const MAX_LINK_LABEL_LENGTH = 1000 ;
@@ -17,18 +19,19 @@ pub const ParseError = error{ OutOfMemory, InvalidUtf8 };
1719
1820pub const Subject = struct {
1921 allocator : mem.Allocator ,
20- refmap : * std . StringHashMap ( Reference ) ,
22+ refmap : * RefMap ,
2123 options : * const Options ,
2224 input : []const u8 ,
2325 pos : usize = 0 ,
2426 last_delimiter : ? * Delimiter = null ,
2527 brackets : ArrayList (Bracket ),
2628 backticks : [MAX_BACKTICKS + 1 ]usize = [_ ]usize {0 } ** (MAX_BACKTICKS + 1 ),
2729 scanned_for_backticks : bool = false ,
30+ no_link_openers : bool = true ,
2831 special_chars : * const [256 ]bool ,
2932 skip_chars : * const [256 ]bool ,
3033
31- pub fn init (allocator : mem.Allocator , refmap : * std . StringHashMap ( Reference ) , options : * const Options , special_chars : * const [256 ]bool , skip_chars : * const [256 ]bool , input : []const u8 ) Subject {
34+ pub fn init (allocator : mem.Allocator , refmap : * RefMap , options : * const Options , special_chars : * const [256 ]bool , skip_chars : * const [256 ]bool , input : []const u8 ) Subject {
3235 const s = Subject {
3336 .allocator = allocator ,
3437 .refmap = refmap ,
@@ -136,20 +139,12 @@ pub const Subject = struct {
136139 return inl ;
137140 }
138141
139- pub fn processEmphasis (self : * Subject , stack_bottom : ? * Delimiter ) ! void {
142+ pub fn processEmphasis (self : * Subject , stack_bottom : usize ) ! void {
140143 var closer = self .last_delimiter ;
141144
142- var openers_bottom : [3 ][128 ]? * Delimiter = [_ ][128 ]? * Delimiter {[_ ]? * Delimiter {null } ** 128 } ** 3 ;
143- for (& openers_bottom ) | * i | {
144- i ['*' ] = stack_bottom ;
145- i ['_' ] = stack_bottom ;
146- i ['\' ' ] = stack_bottom ;
147- i ['"' ] = stack_bottom ;
148- if (self .options .extensions .strikethrough )
149- i ['~' ] = stack_bottom ;
150- }
145+ var openers_bottom : [3 ][128 ]usize = [_ ][128 ]usize {[_ ]usize {stack_bottom } ** 128 } ** 3 ;
151146
152- while (closer != null and closer .? .prev != stack_bottom ) {
147+ while (closer != null and closer .? .prev != null and closer .? . prev .? . position > stack_bottom ) {
153148 closer = closer .? .prev ;
154149 }
155150
@@ -158,7 +153,7 @@ pub const Subject = struct {
158153 var opener = closer .? .prev ;
159154 var opener_found = false ;
160155
161- while (opener != null and opener != openers_bottom [closer .? .length % 3 ][closer .? .delim_char ]) {
156+ while (opener != null and opener .? . position > openers_bottom [closer .? .length % 3 ][closer .? .delim_char ]) {
162157 if (opener .? .can_open and opener .? .delim_char == closer .? .delim_char ) {
163158 const odd_match = (closer .? .can_open or opener .? .can_close ) and ((opener .? .length + closer .? .length ) % 3 == 0 ) and ! (opener .? .length % 3 == 0 and closer .? .length % 3 == 0 );
164159 if (! odd_match ) {
@@ -204,7 +199,7 @@ pub const Subject = struct {
204199 if (! opener_found ) {
205200 const ix = old_closer .? .length % 3 ;
206201 openers_bottom [ix ][old_closer .? .delim_char ] =
207- old_closer .? .prev ;
202+ if ( old_closer .? .prev ) | p | p . position else stack_bottom ;
208203
209204 if (! old_closer .? .can_open ) {
210205 self .removeDelimiter (old_closer .? );
@@ -215,7 +210,7 @@ pub const Subject = struct {
215210 }
216211 }
217212
218- while (self .last_delimiter != null and self .last_delimiter != stack_bottom ) {
213+ while (self .last_delimiter != null and self .last_delimiter .? . position > stack_bottom ) {
219214 self .removeDelimiter (self .last_delimiter .? );
220215 }
221216 }
@@ -541,6 +536,7 @@ pub const Subject = struct {
541536 .can_close = can_close ,
542537 .prev = self .last_delimiter ,
543538 .next = null ,
539+ .position = self .pos ,
544540 };
545541 if (delimiter .prev ) | prev | {
546542 prev .next = delimiter ;
@@ -612,12 +608,13 @@ pub const Subject = struct {
612608 const len = self .brackets .items .len ;
613609 if (len > 0 )
614610 self .brackets .items [len - 1 ].bracket_after = true ;
611+ if (kind == .Link )
612+ self .no_link_openers = false ;
615613 try self .brackets .append (.{
616- .previous_delimiter = self .last_delimiter ,
614+ .delimiter_position = if ( self .last_delimiter ) | d | d . position else 0 ,
617615 .inl_text = inl_text ,
618616 .position = self .pos ,
619617 .kind = kind ,
620- .active = true ,
621618 .bracket_after = false ,
622619 });
623620 }
@@ -631,12 +628,12 @@ pub const Subject = struct {
631628 return try self .makeInline (.{ .Text = try self .allocator .dupe (u8 , "]" ) });
632629 }
633630
634- if (! self .brackets .items [brackets_len - 1 ].active ) {
631+ const kind = self .brackets .items [brackets_len - 1 ].kind ;
632+
633+ if (kind != .Image and self .no_link_openers ) {
635634 _ = self .brackets .pop ();
636635 return try self .makeInline (.{ .Text = try self .allocator .dupe (u8 , "]" ) });
637636 }
638-
639- const kind = self .brackets .items [brackets_len - 1 ].kind ;
640637 const after_link_text_pos = self .pos ;
641638
642639 var sps : usize = 0 ;
@@ -678,7 +675,7 @@ pub const Subject = struct {
678675
679676 const normalized = try strings .normalizeLabel (self .allocator , label orelse "" );
680677 defer self .allocator .free (normalized );
681- const maybe_ref = if (label != null ) self .refmap .get (normalized ) else null ;
678+ const maybe_ref = if (label != null ) self .refmap .lookup (normalized ) else null ;
682679
683680 if (maybe_ref ) | ref | {
684681 try self .closeBracketMatch (kind , try self .allocator .dupe (u8 , ref .url ), try self .allocator .dupe (u8 , ref .title ));
@@ -748,23 +745,12 @@ pub const Subject = struct {
748745 inl .append (tmp );
749746 }
750747 self .brackets .items [brackets_len - 1 ].inl_text .detachDeinit ();
751- const previous_delimiter = self .brackets .items [brackets_len - 1 ].previous_delimiter ;
752- try self .processEmphasis (previous_delimiter );
748+ try self .processEmphasis (self .brackets .items [brackets_len - 1 ].delimiter_position );
753749 _ = self .brackets .pop ();
754750 brackets_len -= 1 ;
755751
756752 if (kind == .Link ) {
757- var i : i32 = @intCast (brackets_len );
758- i -= 1 ;
759- while (i >= 0 ) : (i -= 1 ) {
760- if (self .brackets .items [@intCast (i )].kind == .Link ) {
761- if (! self .brackets .items [@intCast (i )].active ) {
762- break ;
763- } else {
764- self .brackets .items [@intCast (i )].active = false ;
765- }
766- }
767- }
753+ self .no_link_openers = true ;
768754 }
769755 }
770756
@@ -849,14 +835,14 @@ const Delimiter = struct {
849835 can_close : bool ,
850836 prev : ? * Delimiter ,
851837 next : ? * Delimiter ,
838+ position : usize ,
852839};
853840
854841const Bracket = struct {
855- previous_delimiter : ? * Delimiter ,
842+ delimiter_position : usize ,
856843 inl_text : * nodes.AstNode ,
857844 position : usize ,
858845 kind : BracketKind ,
859- active : bool ,
860846 bracket_after : bool ,
861847};
862848
0 commit comments