@@ -393,16 +393,72 @@ extension DSLTree.Node {
393393 switch self {
394394
395395 case let . orderedChoice( v) : return v
396- case let . concatenation( v) : return v
397-
396+ case let . concatenation( v) : return v
397+
398398 case let . capture( _, _, n, _) : return [ n]
399399 case let . nonCapturingGroup( _, n) : return [ n]
400400 case let . quantification( _, _, n) : return [ n]
401401 case let . ignoreCapturesInTypedOutput( n) : return [ n]
402+ case let . limitCaptureNesting( n) : return [ n]
403+
404+ case let . conditional( _, t, f) : return [ t, f]
405+
406+ case . trivia, . empty, . quotedLiteral,
407+ . consumer, . matcher, . characterPredicate,
408+ . customCharacterClass, . atom:
409+ return [ ]
410+
411+ case let . absentFunction( abs) :
412+ return abs. ast. children. map ( \. dslTreeNode)
413+ }
414+ }
415+
416+ public var coalescedChildren : [ DSLTree . Node ] {
417+ // Before converting a concatenation in a tree to list form, we need to
418+ // flatten out any nested concatenations, and coalesce any adjacent
419+ // characters and scalars, forming quoted literals of their contents,
420+ // over which we can perform grapheme breaking.
421+
422+ func flatten( _ node: DSLTree . Node ) -> [ DSLTree . Node ] {
423+ switch node {
424+ case . concatenation( let ch) :
425+ return ch. flatMap ( flatten)
426+ case . ignoreCapturesInTypedOutput( let n) , . limitCaptureNesting( let n) :
427+ return flatten ( n)
428+ default :
429+ return [ node]
430+ }
431+ }
402432
403- case let . limitCaptureNesting( n) :
404- // This is a transparent wrapper
405- return n. children
433+ switch self {
434+ case let . orderedChoice( v) : return v
435+ case let . concatenation( v) :
436+ let children = v
437+ . flatMap ( flatten)
438+ . coalescing ( with: " " , into: DSLTree . Node. quotedLiteral) { str, node in
439+ switch node {
440+ case . atom( let a) :
441+ guard let c = a. literalCharacterValue else { return false }
442+ str. append ( c)
443+ return true
444+ case . quotedLiteral( let q) :
445+ str += q
446+ return true
447+ case . trivia:
448+ // Trivia can be completely ignored if we've already coalesced
449+ // something.
450+ return !str. isEmpty
451+ default :
452+ return false
453+ }
454+ }
455+ return children
456+
457+ case let . capture( _, _, n, _) : return [ n]
458+ case let . nonCapturingGroup( _, n) : return [ n]
459+ case let . quantification( _, _, n) : return [ n]
460+ case let . ignoreCapturesInTypedOutput( n) : return [ n]
461+ case let . limitCaptureNesting( n) : return [ n]
406462
407463 case let . conditional( _, t, f) : return [ t, f]
408464
0 commit comments