sml

package module
v0.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 17, 2026 License: GPL-3.0 Imports: 5 Imported by: 0

README

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.

Documentation

Overview

Package sml implements a parser for the Simple Markup Language (SML).

SML is a concise, tree-structured markup language used for UI layouts and CMS content. Elements are declared by name with optional key/value properties and nested child elements:

Window {
    title: "Hello World"
    width: 800
    Row {
        Label { text: "A" }
        Label { text: "B" }
    }
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Document

type Document struct {
	Roots []Node
}

Document is the result of a successful parse.

func ParseDocument

func ParseDocument(source string) (*Document, error)

ParseDocument parses an SML source string and returns the resulting document. It returns an error on any lexer or parser failure.

func (*Document) CountNodes

func (d *Document) CountNodes() int64

CountNodes returns the total number of nodes in the document tree (all roots plus all their descendants).

func (*Document) ToJSON

func (d *Document) ToJSON() (string, error)

ToJSON serialises the document to the canonical AST JSON format used by the SML toolchain. The format is:

{"roots":[{"name":"…","properties":[…],"children":[…]}]}

type Node

type Node struct {
	Name       string
	Properties []Property
	Children   []Node
}

Node is a single element in the SML tree.

func (*Node) FindProperty

func (n *Node) FindProperty(key string) *Property

FindProperty returns the first property matching key (case-insensitive), or nil if none is found.

func (*Node) GetValue

func (n *Node) GetValue(key, fallback string) string

GetValue returns the value of the property matching key, or fallback if the property does not exist. Matching is case-insensitive.

func (*Node) HasProperty

func (n *Node) HasProperty(key string) bool

HasProperty reports whether the node has a property matching key (case-insensitive).

type Property

type Property struct {
	Name  string
	Kind  ValueKind
	Value string
}

Property is a named value attached to a Node.

type ValueKind

type ValueKind int

ValueKind describes the type of a property value.

const (
	ValueKindString     ValueKind = iota // quoted string: "hello"
	ValueKindNumber                      // numeric literal: 42, 3.14, .5
	ValueKindBool                        // true or false
	ValueKindIdentifier                  // bare word or resource ref: main, @Strings.key
	ValueKindTuple                       // comma- or pipe-separated list: 20,20  top|bottom
)

func (ValueKind) String

func (k ValueKind) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL