Skip to content

kixi-io/Ki.KD-Go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ki.KD-Go

Ki.KD-Go is the Go implementation of Ki Data / Ki Declarative Language.

It parses KD documents into Go types, supports snip resolution, and exposes a small helper API for working with tags, calls, maps, grids, coordinates, quantities, temporal values, and snips.

Reference docs for the language live at:

Status

The repository is in a good place for practical use:

  • parser/value behavior is driven by the Kotlin Ki.KD-JVM implementation
  • the main JVM parser and snip suites are covered in Go tests
  • the original JVM fixtures in examples/ parse in Go
  • helper/read APIs exist for the common Kotlin-style workflows

See jvm_test_parity_checklist.md for the current JVM-to-Go mapping.

Installation

go get github.com/kixi-io/Ki.KD-Go

The module path is:

import kikdgo "github.com/kixi-io/Ki.KD-Go"

Quick Start

package main

import (
	"fmt"
	"log"

	kikdgo "github.com/kixi-io/Ki.KD-Go"
)

func main() {
	doc, err := kikdgo.Parse(`
person "Alice" age=30 {
    email alice@example.com
}
`)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(doc.Name())                 // person
	fmt.Println(doc.Value())                // Alice
	fmt.Println(doc.GetAttributeOrNil("age")) // 30

	email := doc.GetChild("email")
	fmt.Println(email.Value()) // alice@example.com
}

Reading KD

Use Parse / Read for text, ParseFile / ReadFile for files, and ReadReader when you already have an io.Reader.

tag, err := kikdgo.Read(`server host="localhost" port=8080`)
tag, err := kikdgo.ReadFile("config.kd")

If the input contains a single top-level tag, that tag is returned directly. If it contains multiple top-level tags, they are wrapped in a root tag named root.

Reading with Snips

Plain Parse does not resolve snips. Use the snip-aware entrypoints when you want .snip(...) references expanded.

resolver := kikdgo.NewSnipResolver(kikdgo.DefaultSnipOptions())

tag, err := kikdgo.ReadFileWithSnips("app.kd", resolver)

Or parse text relative to a base directory:

tag, err := kikdgo.ReadWithSnips(`
app {
    .snip(shared/header)
}
`, "/path/to/project", nil)

Parsing a Single Literal

Use ReadLiteral when you want the first parsed value instead of the enclosing tag.

value, err := kikdgo.ReadLiteral(`2024/3/15`)
// value is kikdgo.LocalDate

Examples:

price, _ := kikdgo.ReadLiteral(`$29.99`)
when, _ := kikdgo.ReadLiteral(`2024/3/15@14:30:00-US/PST`)
rangeValue, _ := kikdgo.ReadLiteral(`1..<10`)

Formatting KD

Use Format for canonical KD literal output, Tag.String() for rendered tags/documents, and UnresolvedSnipString() when you want quoted snip literals shown in their original .snip(...) form.

value := kikdgo.NewQuantity(5, kikdgo.UnitCM)
fmt.Println(kikdgo.Format(value)) // 5cm:i
tag, _ := kikdgo.Parse(`person "Alice" age=30`)
fmt.Println(tag.String()) // person "Alice" age=30
doc, _ := kikdgo.Parse(`layout { ".snip(shared/header)" }`)
fmt.Println(doc.UnresolvedSnipString())

Working With Tags

Tag includes helper methods for the common config/document traversal cases:

  • GetChild, GetChildren
  • FindChild, FindChildren
  • Descendants
  • GetAttribute, HasAttribute, SetAttribute
  • GetProperty, HasProperty, GetProperties
  • ChildrenValues

Example:

config, _ := kikdgo.Parse(`
config env="prod" {
    host = "localhost"
    port = 8080
}
`)

host, _ := config.GetProperty("host")
env, _ := config.GetProperty("env")

fmt.Println(host) // localhost
fmt.Println(env)  // prod

GetProperty checks the tag's own attributes first, then immediate child attributes, which is useful for config-style KD.

Main Parsed Types

The parser produces native Go values where that preserves meaning, and explicit types where Kotlin distinguishes values more precisely.

Common outputs include:

  • string, rune, bool, int64, float32, float64, nil
  • kikdgo.Decimal
  • kikdgo.Email
  • kikdgo.Version
  • time.Duration
  • kikdgo.LocalDate
  • kikdgo.LocalDateTime
  • kikdgo.OffsetDateTime
  • kikdgo.KiTZDateTime
  • kikdgo.Quantity
  • kikdgo.Range
  • []any
  • kikdgo.KDMap
  • kikdgo.Call
  • kikdgo.GeoPoint
  • kikdgo.Coordinate
  • kikdgo.Grid
  • kikdgo.Snip

Most parsed value types now also have KD string renderers, so fmt.Println(value) is useful for Tag, Call, Range, Quantity, Coordinate, GeoPoint, Grid, and Snip.

Examples and Fixtures

The repository includes JVM parity fixtures in examples/:

  • KDTest.kd
  • KDTestWorld.kd
  • KDTestScience.kd

They are used by the Go test suite and are a good source of real parser examples.

Development

Run the full test suite with:

go test ./...

If you are changing parser behavior, read CONTRIBUTING.md first. The short version is:

  • treat Ki.KD-JVM as the contract
  • port or extend tests with the change
  • keep file names descriptive
  • preserve the existing small-file Go style

About

Go implementation of Ki.KD (Ki Declarative Language)

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages