///|
/// TOML Value types that represent different TOML data types
pub(all) enum TomlValue {
TomlString(String)
TomlInteger(Int64)
TomlFloat(Double)
TomlBoolean(Bool)
TomlArray(Array[TomlValue])
TomlTable(Map[String, TomlValue])
TomlDateTime(TomlDateTime)
} derive(Eq, ToJson, Debug)
///|
/// Parser state (will implement methods later)
pub struct Parser {
tokens : Array[Token]
mut position : Int
}
///|
pub fn Parser::view(
self : Self,
skip_newlines? : Bool = false,
) -> ArrayView[Token] {
if skip_newlines {
loop self.view() {
[Newline(..), .. rest] => continue rest
rest => rest
}
} else {
self.tokens[self.position:]
}
}
///|
/// FIXME: expose upstream in the core
fn[T] ArrayView::start(self : ArrayView[T]) -> Int = "%arrayview.start"
///|
pub fn Parser::update_view(self : Parser, view : ArrayView[Token]) -> Unit {
let new_offset = view.start() // consistent
self.position = new_offset
}
///|
/// Create a new parser
pub fn Parser::new(tokens : Array[Token]) -> Parser {
{ tokens, position: 0 }
}
///|
/// Check if an array contains homogeneous types (TOML spec requirement)
pub fn TomlValue::is_homogeneous_array(arr : Array[TomlValue]) -> Bool {
match arr {
[] => true
[first, .. rest] => {
fn type_id(value : TomlValue) -> Int {
match value {
TomlString(_) => 0
TomlInteger(_) => 1
TomlFloat(_) => 2
TomlBoolean(_) => 3
TomlArray(_) => 4
TomlTable(_) => 5
TomlDateTime(_) => 6
}
}
let first_type = type_id(first)
rest.all(x => type_id(x) == first_type)
}
}
}
///|
/// Get the type name of a TomlValue for error messages
pub fn TomlValue::type_name(self : TomlValue) -> String {
match self {
TomlString(_) => "string"
TomlInteger(_) => "integer"
TomlFloat(_) => "float"
TomlBoolean(_) => "boolean"
TomlArray(_) => "array"
TomlTable(_) => "table"
TomlDateTime(_) => "datetime"
}
}
///|
/// Validate that a TomlValue follows TOML specification rules
pub fn TomlValue::validate(self : TomlValue) -> Bool {
match self {
TomlArray(arr) => {
// Check homogeneity
if !TomlValue::is_homogeneous_array(arr) {
return false
}
// Recursively validate nested values
for i = 0; i < arr.length(); i = i + 1 {
if !arr[i].validate() {
return false
}
}
true
}
TomlTable(table) => {
// Recursively validate all values in the table
let mut valid = true
table.each(fn(_key, value) { if !value.validate() { valid = false } })
valid
}
_ => true // All other types are always valid by themselves
}
}