@@ -33,8 +33,9 @@ class Scanner
33
33
34
34
def initialize ( s , index : 0 )
35
35
@s = s # input string
36
- @i = index # current index in string
36
+ @i = index # current index in string, the iterator looks at this character
37
37
@cur = nil # current node we're populating
38
+ @curifree = nil # last index in string for current node that we haven't added to a child node yet
38
39
@ancestors = [ Node . new ( @s , @i ) ] # nesting hierarchy
39
40
@iterator = :beginning # scan_iteration_<iterator> to use for parsing
40
41
@dest = :contains # append current node to this attribute on parent
@@ -79,6 +80,7 @@ def scan_iteration_standard
79
80
# after bracket check for 'and' to not lose text
80
81
if is_and_sep? ( @i +1 )
81
82
@i += and_sep_len ( @i +1 )
83
+ @curifree = @i # don't include 'and' in cur name
82
84
add_child
83
85
end
84
86
elsif is_notes_start? # usually a dot marks the start of notes
@@ -147,7 +149,11 @@ def parent
147
149
end
148
150
149
151
def cur
150
- @cur ||= Node . new ( @s , @i )
152
+ if !@cur
153
+ @cur ||= Node . new ( @s , @i )
154
+ @curifree = @i
155
+ end
156
+ @cur
151
157
end
152
158
153
159
def is_sep? ( chars : SEP_CHARS )
@@ -201,16 +207,19 @@ def add_child
201
207
cur . ends ( @i -1 )
202
208
parent . send ( @dest ) << cur
203
209
@cur = nil
210
+ @curifree = nil
204
211
end
205
212
206
213
def open_parent ( **options )
207
214
name_until_here
208
215
@ancestors << cur
209
216
@cur = Node . new ( @s , @i + 1 , **options )
217
+ @curifree = @i + 1
210
218
end
211
219
212
220
def close_parent
213
221
return unless @ancestors . count > 1
222
+ @curifree = @i + 1
214
223
@cur = @ancestors . pop
215
224
while @cur . auto_close
216
225
add_child
@@ -227,15 +236,15 @@ def close_all_ancestors
227
236
end
228
237
229
238
def name_until_here
230
- cur . name ||= begin
231
- i , j = cur . interval . first , @i - 1
232
- i += mark_len ( i ) # skip any mark in front
233
- # Set name if there is any. There is one corner-case that needs to be avoided when
234
- # a nesting was opened without a name, which would set the name to the nesting text.
235
- # In this case, the name starts with an open-nesting symbol, which should never happen.
236
- if j >= i && !"([:" . include? ( @s [ i ] )
237
- Node . new ( @s , i .. j )
238
- end
239
+ return unless @curifree # no cur started yet
240
+ i , j = @curifree , @i - 1
241
+ i += mark_len ( i ) # skip any mark in front
242
+ # Set name if there is any. There is one corner-case that needs to be avoided when
243
+ # a nesting was opened without a name, which would set the name to the nesting text.
244
+ # In this case, the name starts with an open-nesting symbol, which should never happen.
245
+ if j >= i && !"([:" . include? ( @s [ i ] )
246
+ cur . name_parts << Node . new ( @s , i .. j )
247
+ @curifree = @i
239
248
end
240
249
end
241
250
0 commit comments