amtoml

A comprehensive TOML (Tom's Obvious, Minimal Language) parser for MoonBit with full support for TOML v1.0.0 specification including tables, arrays, dotted keys, and inline tables.

toml
parser
config
configuration
serialization
moon add tonyfettes/amtoml@0.1.0
Download zip
Version
0.1.0
License
Apache-2.0
Last updated
9 months ago
Downloads
19
README

#amtoml - A TOML Parser for MoonBit

amtoml is a comprehensive TOML (Tom's Obvious, Minimal Language) parser implementation in MoonBit. It provides a complete solution for parsing TOML configuration files into MoonBit data structures.

#Features

  • Complete TOML Support: Parses key-value pairs, tables, arrays, inline tables, and array of tables
  • Dotted Keys: Full support for nested table structures using dotted keys
  • Multiple Data Types: Strings (basic and literal), integers, floats, booleans
  • String Escapes: Proper handling of escape sequences in basic strings
  • Comments: Full support for TOML comments
  • Error Handling: Comprehensive error reporting with position information
  • Type-Safe: Strong typing with TomlValue enum for all TOML data types

#Installation

Add to your moon.mod.json:

{ "deps": { "tonyfettes/amtoml": "*" } }

#Usage

test "basic usage" {
let toml_input =
#|title = "TOML Example"
#|version = "1.0.0"
#|
#|[database]
#|server = "192.168.1.1"
#|ports = [8000, 8001, 8002]
#|enabled = true
#|

// Parse the TOML string
let result = @tonyfettes/amtoml.parse_toml(toml_input)

// Check if parsing succeeded
inspect(result is Ok(_), content="true")

// Access the parsed data
let table = result.unwrap()
inspect(table.get("title"), content=(
#|Some(String("TOML Example"))
))
inspect(table.get("version"), content=(
#|Some(String("1.0.0"))
))

// Access nested tables
match table.get("database") {
Some(TomlValue::Table(db)) => {
inspect(db.get("server"), content=(
#|Some(String("192.168.1.1"))
))
inspect(db.get("enabled"), content="Some(Boolean(true))")
}
_ => fail("Expected database table")
}
}

#Data Types

The parser represents TOML values using the TomlValue enum:

test "toml value types" {
// String values
let str_val = TomlValue::String("hello")
inspect(str_val.to_string(), content="String(hello)")

// Integer values (Int64)
let int_val = TomlValue::Integer(42L)
inspect(int_val.to_string(), content="Integer(42)")

// Float values (Double)
let float_val = TomlValue::Float(3.14)
inspect(float_val.to_string(), content="Float(3.14)")

// Boolean values
let bool_val = TomlValue::Boolean(true)
inspect(bool_val.to_string(), content="Boolean(true)")

// Arrays
let arr_val = TomlValue::Array([
TomlValue::Integer(1L),
TomlValue::Integer(2L),
])
inspect(arr_val.to_string(), content="Array([Integer(1), Integer(2)])")

// Tables (Maps)
let table : Map[String, TomlValue] = {}
table["key"] = TomlValue::String("value")
let _table_val = TomlValue::Table(table)
}

#Advanced Features

#Dotted Keys

test "dotted keys example" {
let input =
#|name.first = "Tom"
#|name.last = "Preston-Werner"
#|

let result = @tonyfettes/amtoml.parse_toml(input)
inspect(result is Ok(_), content="true")

let table = result.unwrap()
match table.get("name") {
Some(TomlValue::Table(tbl)) => {
inspect(tbl.get("first"), content=(
#|Some(String("Tom"))
))
inspect(tbl.get("last"), content=(
#|Some(String("Preston-Werner"))
))
}
_ => fail("Expected name table")
}
}

#Array of Tables

test "array of tables example" {
let input =
#|[[products]]
#|name = "Hammer"
#|sku = 738594937
#|
#|[[products]]
#|name = "Nail"
#|sku = 284758393
#|

let result = @tonyfettes/amtoml.parse_toml(input)
inspect(result is Ok(_), content="true")

let table = result.unwrap()
match table.get("products") {
Some(TomlValue::Array(arr)) => {
inspect(arr.length(), content="2")
match arr.get(0) {
Some(TomlValue::Table(product)) =>
inspect(product.get("name"), content=(
#|Some(String("Hammer"))
))
_ => fail("Expected product table")
}
}
_ => fail("Expected products array")
}
}

#Inline Tables

test "inline tables example" {
let input =
#|point = { x = 1, y = 2 }
#|color = { r = 255, g = 128, b = 0 }
#|

let result = @tonyfettes/amtoml.parse_toml(input)
inspect(result is Ok(_), content="true")

let table = result.unwrap()
match table.get("point") {
Some(TomlValue::Table(tbl)) => {
inspect(tbl.get("x"), content="Some(Integer(1))")
inspect(tbl.get("y"), content="Some(Integer(2))")
}
_ => fail("Expected point table")
}
}

#Error Handling

The parser provides detailed error information:

test "error handling example" {
let input =
#|name = "Tom"
#|name = "Jerry" # Duplicate key!
#|

let result = @tonyfettes/amtoml.parse_toml(input)
inspect(result is Err(_), content="true")

// Error types include:
// - UnexpectedChar: Unexpected character in input
// - UnexpectedEof: Unexpected end of file
// - InvalidEscape: Invalid escape sequence
// - InvalidNumber: Invalid number format
// - InvalidKey: Invalid key format
// - InvalidValue: Invalid value format
// - DuplicateKey: Duplicate key in table
// - InvalidTable: Invalid table definition
}

#API Reference

#Main Functions

  • parse(input: String) -> Map[String, TomlValue] raise ParseError
    • Parses a TOML string and returns the result or raises an error

  • parse_toml(input: String) -> Result[Map[String, TomlValue], ParseError]
    • Parses a TOML string and returns a Result type for error handling

#TomlValue Methods

  • to_string() -> String
    • Converts a TomlValue to a human-readable string representation

#Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

#License

This project is available under the same license as specified in the LICENSE file.

#TOML Specification

This parser implements the TOML v1.0.0 specification. For more information about TOML, visit https://toml.io.

#
ParseError

pub(all) suberror ParseError {
UnexpectedChar(Int, Char)
UnexpectedEof
InvalidEscape(Int, Char)
InvalidNumber(Int, String)
InvalidKey(Int, String)
InvalidValue(Int, String)
DuplicateKey(String)
InvalidTable(String)
}

Error types for TOML parsing
impl Eq for ParseError
impl Show for ParseError

#
Lexer

type Lexer

Lexer state

#
Lexer::next_token

fn Lexer::next_token(self : Lexer) -> Token raise ParseError

Get next token

#
Parser

type Parser

Parser state

#
Parser::new

fn Parser::new(input : String) -> Parser raise ParseError

Create a new parser

#
Token

type Token

Token types for lexer
impl Eq for Token
impl Show for Token

#
TomlValue

pub(all) enum TomlValue {
String(String)
Integer(Int64)
Float(Double)
Boolean(Bool)
DateTime(String)
Array(Array[TomlValue])
Table(Map[String, TomlValue])
}

TOML Value types
impl Eq for TomlValue
impl Show for TomlValue

#
TomlValue::to_string

fn TomlValue::to_string(self : TomlValue) -> String

Convert TomlValue to JSON-like string for debugging

#
parse

fn parse(input : String) -> Map[String, TomlValue] raise ParseError

Parse TOML document

#
parse_toml

fn parse_toml(input : String) -> Result[Map[String, TomlValue], ParseError]

Parse TOML string and return Result

Source Files