325325 yamlArray
326326 yamlNull
327327
328- YamlNode * {.acyclic .} = object
328+ YamlNode * {.acyclic .} = ref object
329329 case kind* : YamlValueKind
330330 of yamlInteger:
331331 intValue* : int64
@@ -344,6 +344,108 @@ type
344344 YAMLObject * = OrderedTableRef [string , YamlNode ]
345345 # # Represents a simple
346346
347+ proc newYamlString * (s: string ): YamlNode =
348+ # # Create a new YamlNode of kind yamlString
349+ YamlNode (kind: yamlString, strValue: s)
350+
351+ proc newYamlFloat * (f: float64 ): YamlNode =
352+ # # Create a new YamlNode of kind yamlFloat
353+ YamlNode (kind: yamlFloat, floatValue: f)
354+
355+ proc newYamlInteger * (i: int64 ): YamlNode =
356+ # # Create a new YamlNode of kind yamlInteger
357+ YamlNode (kind: yamlInteger, intValue: i)
358+
359+ proc newYamlBoolean * (b: bool ): YamlNode =
360+ # # Create a new YamlNode of kind yamlBoolean
361+ YamlNode (kind: yamlBoolean, boolValue: b)
362+
363+ proc newYamlNull * (): YamlNode =
364+ # # Create a new YamlNode of kind yamlNull
365+ YamlNode (kind: yamlNull)
366+
367+ proc newYamlObject * (): YamlNode =
368+ # # Create a new YamlNode of kind yamlObject
369+ YamlNode (kind: yamlObject, objValue: newOrderedTable [string , YamlNode ]())
370+
371+ proc newYamlArray * (): YamlNode =
372+ # # Create a new YamlNode of kind yamlArray
373+ YamlNode (kind: yamlArray, arrValue: @ [])
374+
375+ proc get * (n: YamlNode , key: string ): YamlNode =
376+ # # Recursively access nested YAML data using dot-separated keys.
377+ # # Example: get(config, "user.name")
378+ if n == nil or key.len == 0 :
379+ return nil
380+ if '.' notin key:
381+ if n.kind == yamlObject and n.objValue.hasKey (key):
382+ return n.objValue[key]
383+ else :
384+ return nil
385+ let dotIdx = key.find ('.' )
386+ let head = key[0 ..< dotIdx]
387+ let tail = key[dotIdx+ 1 .. ^ 1 ]
388+ let nextNode =
389+ if n.kind == yamlObject and n.objValue.hasKey (head):
390+ n.objValue[head]
391+ else :
392+ nil
393+ if nextNode == nil :
394+ return nil
395+ return get (nextNode, tail)
396+
397+ proc get * (obj: YamlObject , key: string ): YamlNode =
398+ # # Access a value from a YAMLObject using a key
399+ if obj.hasKey (key):
400+ return obj[key]
401+ else :
402+ return nil
403+
404+ proc put * (obj: YamlObject , key: string , value: YamlNode ) =
405+ # # Insert or update a key-value pair in a YAMLObject
406+ obj[key] = value
407+
408+ proc getStr * (n: YamlNode ): string =
409+ # # Get string value or "" if not a string node
410+ if n != nil and n.kind == yamlString:
411+ result = n.strValue
412+
413+ proc getInt * (n: YamlNode ): int64 =
414+ # # Get integer value or 0 if not an integer node
415+ if n != nil and n.kind == yamlInteger:
416+ result = n.intValue
417+
418+ proc getFloat * (n: YamlNode ): float64 =
419+ # # Get float value or 0.0 if not a float node
420+ if n != nil and n.kind == yamlFloat:
421+ result = n.floatValue
422+
423+ proc getBool * (n: YamlNode ): bool =
424+ # # Get boolean value or false if not a boolean node
425+ if n != nil and n.kind == yamlBoolean:
426+ result = n.boolValue
427+
428+ proc getArray * (n: YamlNode ): seq [YamlNode ] =
429+ # # Get array value or empty seq if not an array node
430+ if n != nil and n.kind == yamlArray:
431+ result = n.arrValue
432+
433+ proc getObject * (n: YamlNode ): OrderedTableRef [string , YamlNode ] =
434+ # # Get object value or empty table if not an object node
435+ if n != nil and n.kind == yamlObject:
436+ result = n.objValue
437+
438+ proc getValue * (v: YamlNode ): string =
439+ # # Get the string representation of a YamlNode value (for debugging)
440+ case v.kind
441+ of yamlNull: " null"
442+ of yamlBoolean: $ v.boolValue
443+ of yamlInteger: $ v.intValue
444+ of yamlFloat: $ v.floatValue
445+ of yamlString: v.strValue
446+ of yamlObject: " {...}"
447+ of yamlArray: " [...]"
448+
347449proc advance (p: var YamlParser ) {.inline .} =
348450 p.prev = p.curr
349451 p.curr = p.next
@@ -389,21 +491,35 @@ proc parseSequence(p: var YamlParser, indent: int): seq[YamlNode]
389491proc parseInlineArray (p: var YamlParser ): YamlNode
390492proc parseInlineObject (p: var YamlParser ): YamlNode
391493
392- proc parsePlainUnquoted (p: var YamlParser ): YamlNode =
393- # # Parse plain scalar on the same line (e.g.: title: hello world)
494+ proc parsePlainUnquoted (p: var YamlParser , inlineMode = false ): YamlNode =
495+ # # Parse plain scalar on the same line.
496+ # # In inline mode, stop at ',', ']' and '}'.
394497 let lineNo = p.curr.line
395- var parts: seq [string ] = @ []
396- var firstTok = p.curr
498+ let firstTok = p.curr
499+ var count = 0
500+ var buf = " "
397501
398- while p.curr.kind in {ytkIdentifier, ytkInteger, ytkFloat} and p.curr.line == lineNo:
399- parts.add (p.curr.value)
502+ while p.curr.kind != ytkEOF and p.curr.line == lineNo:
503+ if p.curr.kind == ytkComment:
504+ break
505+ if inlineMode and p.curr.kind in {ytkComma, ytkRB, ytkRC}:
506+ break
507+
508+ if count > 0 and p.curr.wsno > 0 :
509+ buf.add (repeat (' ' , p.curr.wsno))
510+
511+ # prefer token value; fallback to token text
512+ # for punctuation-like tokens
513+ let part = if p.curr.value.len > 0 : p.curr.value else : tokenText (p.curr)
514+ buf.add (part)
515+
516+ inc count
400517 advance (p)
401518
402- if parts.len == 1 :
403- # preserve bool/null/integer/float behavior
404- result = getScalarValue (firstTok)
519+ if count == 1 :
520+ result = getScalarValue (firstTok) # preserves bool/int/float/null coercion
405521 else :
406- result = YamlNode (kind: yamlString, strValue: parts. join ( " " ) )
522+ result = YamlNode (kind: yamlString, strValue: buf )
407523
408524proc parseBlockString (p: var YamlParser , parentIndent: int , folded: bool ): YamlNode =
409525 # # Parse YAML block scalar after '|' or '>'
@@ -529,29 +645,32 @@ proc parseMapping(p: var YamlParser, indent: int): YAMLObject =
529645 result [key] = YamlNode (kind: yamlNull)
530646
531647proc parseValue (p: var YamlParser , parentIndent: int ): YamlNode =
648+ let inlineMode = parentIndent < 0
532649 case p.curr.kind
533650 of ytkIdentifier:
534651 if p.next.kind == ytkColon and p.curr.indent > parentIndent:
535652 let obj = parseMapping (p, p.curr.indent)
536653 result = YamlNode (kind: yamlObject, objValue: obj)
537654 else :
538- result = parsePlainUnquoted (p)
655+ result = parsePlainUnquoted (p, inlineMode )
539656 of ytkString, ytkFloat, ytkInteger:
540- result = parseScalar (p )
657+ result = parsePlainUnquoted (p, inlineMode )
541658 of ytkLB:
542659 result = parseInlineArray (p)
543660 of ytkLC:
544661 result = parseInlineObject (p)
545662 of ytkDash:
546- let arr = parseSequence (p, p.curr.indent) # use indentation, not wsno
663+ let arr = parseSequence (p, p.curr.indent)
547664 result = YamlNode (kind: yamlArray, arrValue: arr)
548665 of ytkPipe:
549666 result = parseBlockString (p, parentIndent, folded = false )
550667 of ytkGT:
551668 result = parseBlockString (p, parentIndent, folded = true )
552669 else :
553- raise newException (ValueError ,
554- " Unexpected value token " & $ p.curr.kind & " at line " & $ p.curr.line & " , col " & $ p.curr.col)
670+ raise newException (
671+ ValueError ,
672+ " Unexpected value token " & $ p.curr.kind & " at line " & $ p.curr.line & " , col " & $ p.curr.col
673+ )
555674
556675proc parseRoot (p: var YamlParser ): YAMLObject =
557676 result = parseMapping (p, 0 )
@@ -576,7 +695,7 @@ proc nimStringLiteral(s: string): string =
576695#
577696# Dump hook to for converting YAMLObject to JSON
578697#
579- proc dumpHook (s: var string , v: YamlNode ) =
698+ proc dumpHook * (s: var string , v: YamlNode ) =
580699 case v.kind
581700 of yamlNull:
582701 s.add (" null" )
0 commit comments