Skip to content

Latest commit

 

History

63 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

yaml

A YAML subset parser library for hica. Parses the YAML that real-world config files actually use: maps, lists, scalars, comments, and nesting.

Installation

1. Add the package

hica add yaml
hica fetch

This records the dependency in hica.hml and downloads the package into vendor/.

2. Import

import "yaml"

Supported YAML

  • Scalars: strings (bare, single-quoted, double-quoted with escape sequences), integers (decimal, hex 0x, octal 0o), floats (decimal, scientific, .inf, .nan), booleans, null
  • Block maps: key: value with indentation nesting
  • Block sequences: - item lists, compact nested mappings (- name: foo)
  • Block scalars: literal (|) and folded (>) with chomping (-, +), explicit indentation indicators (|2, >4), and empty line preservation
  • Multi-line scalars: plain scalar line folding, multi-line quoted strings
  • Flow collections: sequences ([a, b, c]), mappings ({key: val}), nested, trailing commas
  • Complex keys: flow sequences/mappings as mapping keys (? [a, b])
  • Comments: inline (# ...), full-line, inside flow collections, between multi-line scalars
  • Document markers: --- and ... stripped automatically
  • Multi-document streams: yaml_parse_all returns all documents
  • Tags: !!str, !!int, !local, !<uri> — stripped during parse, !!str coerces to string
  • Anchors & aliases: &name anchors and *name references
  • Duplicate keys: last value wins
  • Tab rejection: tabs in indentation produce clear errors
  • Nested structures: maps in maps, lists in maps, maps in lists, flow inside block

API

Types

type Yaml {
  YStr(value: string),
  YInt(value: int),
  YFloat(value: float),
  YBool(value: bool),
  YNull,
  YList(items: list<Yaml>),
  YMap(entries: list<(string, Yaml)>)
}

Parsing

yaml_parse(input: string) : result<Yaml, string>      // first document
yaml_parse_all(input: string) : result<list<Yaml>, string>  // all documents

Pipe-friendly navigation

Chain operations with |> or . to navigate nested YAML:

let host = yaml_parse(input)
  |> yaml_ok
  |> at("database")
  |> at("host")
  |> as_str

// host : maybe<string>

Hica supports Uniform Function Call Syntax (UFCS) with a dot-notation, the above can be written like this:

let host = yaml_parse(input)
  .yaml_ok
  .at("database")
  .at("host")
  .as_str
Function Signature Purpose
yaml_ok result<Yaml, string> -> maybe<Yaml> Convert parse result to maybe
at maybe<Yaml>, string -> maybe<Yaml> Navigate into a map key
nth maybe<Yaml>, int -> maybe<Yaml> Index into a list
as_str maybe<Yaml> -> maybe<string> Extract string value
as_int maybe<Yaml> -> maybe<int> Extract int value
as_float maybe<Yaml> -> maybe<float> Extract float value
as_bool maybe<Yaml> -> maybe<bool> Extract bool value
as_list maybe<Yaml> -> maybe<list<Yaml>> Extract list
as_map maybe<Yaml> -> maybe<list<(string, Yaml)>> Extract map entries

Defaults

let port = yaml_parse(input)
  |> yaml_ok
  |> at("database")
  |> at("port")
let p = int_or(port, 5432)
Function Signature
str_or maybe<Yaml>, string -> string
int_or maybe<Yaml>, int -> int
float_or maybe<Yaml>, float -> float
bool_or maybe<Yaml>, bool -> bool

Inspection

Function Signature Purpose
has_key maybe<Yaml>, string -> bool Check if map has key
keys maybe<Yaml> -> list<string> Get map keys
yaml_length maybe<Yaml> -> int Count list/map entries

Direct accessors

For when you already have a Yaml value (not wrapped in maybe):

Function Signature
yaml_get Yaml, string -> maybe<Yaml>
yaml_str Yaml -> maybe<string>
yaml_int Yaml -> maybe<int>
yaml_float Yaml -> maybe<float>
yaml_bool Yaml -> maybe<bool>
yaml_list Yaml -> maybe<list<Yaml>>
yaml_map Yaml -> maybe<list<(string, Yaml)>>

Display

yaml_show(y: Yaml) : string        // compact one-line representation
yaml_pretty(y: Yaml, indent: int) : string  // indented multi-line output

Serialization

Emit valid YAML from Yaml values:

yaml_emit(y: Yaml) : string       // block-style (human-readable, indented)
yaml_emit_flow(y: Yaml) : string  // flow-style (compact, single-line)

Example:

let data = YMap([("name", YStr("myapp")), ("port", YInt(8080))])
println(yaml_emit(data))
// name: myapp
// port: 8080

println(yaml_emit_flow(data))
// {name: myapp, port: 8080}

Examples

See the examples/ directory for runnable programs:

Run an example:

hica run examples/basic_parsing.hc

License

MIT

Releases

Contributors