sml-go
Pure-Go parser for the Simple Markup Language (SML) — a concise,
tree-structured markup language designed for UI layouts and CMS content.
This library is the Go port of the C++ reference implementation from
Forge4D / SMLCore.Native and serves as the
parsing foundation for a server-side CMS that compiles SML sources into
static HTML.
What is SML?
SML describes nested elements with typed key/value properties:
Page {
title: "Welcome"
lang: "de"
// line comments are supported
Hero {
heading: "Hallo Welt"
image: @Assets.hero
visible: true
}
/* block comments too */
Grid {
columns: 3
gap: 16
Card { title: "Eins" body: "…" }
Card { title: "Zwei" body: "…" }
Card { title: "Drei" body: "…" }
}
}
Property value types
| Kind |
Example |
Description |
string |
"Hello" |
Double-quoted, supports \n \r \t \\ \" |
number |
42, 3.14, .5 |
Integer or float, normalised on parse |
bool |
true, false |
Boolean literal |
identifier |
main, @Res.key |
Bare word or resource reference |
tuple |
20,20 / top|left |
Comma- or pipe-separated value list |
Installation
go get codeberg.org/crowdware/sml-go
Requires Go 1.22 or later. No external dependencies.
Quick start
package main
import (
"fmt"
"log"
sml "codeberg.org/crowdware/sml-go"
)
func main() {
source := `
Window {
title: "Hello World"
width: 800
Row {
Label { text: "A" }
Label { text: "B" }
}
}
`
doc, err := sml.ParseDocument(source)
if err != nil {
log.Fatal(err)
}
root := &doc.Roots[0]
fmt.Println(root.Name) // Window
fmt.Println(root.GetValue("title", "")) // Hello World
fmt.Println(doc.CountNodes()) // 4
// Export the AST as JSON
j, _ := doc.ToJSON()
fmt.Println(j)
}
API reference
ParseDocument
func ParseDocument(source string) (*Document, error)
Parses an SML source string. Returns the document tree or a descriptive
error with line/column information.
Document
type Document struct {
Roots []Node
}
func (d *Document) CountNodes() int64
func (d *Document) ToJSON() (string, error)
ToJSON produces the canonical AST JSON used by the SML toolchain:
{
"roots": [
{
"name": "Window",
"properties": [
{ "name": "title", "kind": "string", "value": "Hello" }
],
"children": []
}
]
}
Node
type Node struct {
Name string
Properties []Property
Children []Node
}
func (n *Node) HasProperty(key string) bool
func (n *Node) FindProperty(key string) *Property
func (n *Node) GetValue(key, fallback string) string
Property lookup is case-insensitive: GetValue("Title", "") matches a
property declared as title:.
Property
type Property struct {
Name string
Kind ValueKind // String | Number | Bool | Identifier | Tuple
Value string
}
Running the tests
go test ./...
The test suite mirrors the C++ conformance tests from SMLCore.Native:
- Spec tests – core API: single node, nested nodes, JSON round-trip,
unterminated string error
- Parser tests – conformance: floats, tuples, comments, resource refs,
multiline strings, identifier properties, unknown nodes
- Edge-case tests – block comments, booleans, negative numbers,
case-insensitive lookup, empty documents, multiple roots
SML syntax reference
document = element*
element = IDENT '{' element_body '}'
element_body = ( property | element )*
property = IDENT ':' value ( (',' | '|') value )*
value = STRING | NUMBER | BOOL | IDENT
Comments: // line comment and /* block comment */
Resource references: @Namespace.key — parsed as Identifier
Tuples: padding: 4,8 (comma) or anchors: top|bottom (pipe)
Escape sequences in strings: \n, \r, \t, \", \\
License
Copyright (C) 2026 CrowdWare
SPDX-License-Identifier: GPL-3.0-or-later
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version. See LICENSE for details.