///| Source location attached to parsed configuration items and diagnostics.
pub struct Span {
file : String
line : Int
column : Int
} derive(@debug.Debug, Eq)
///| Creates a location object for synthetic values.
pub fn span(file : String, line : Int, column : Int) -> Span {
{ file, line, column }
}
///| Severity used by diagnostics and validation reports.
pub enum Severity {
Error
Warning
Info
} derive(@debug.Debug, Eq)
///| A user-facing parser, merge, or validation message.
pub struct Diagnostic {
severity : Severity
code : String
message : String
span : Span?
hint : String?
} derive(@debug.Debug, Eq)
///| Creates an error diagnostic.
pub fn error(code : String, message : String, span~ : Span? = None, hint~ : String? = None) -> Diagnostic {
{ severity: Error, code, message, span, hint }
}
///| Creates a warning diagnostic.
pub fn warning(code : String, message : String, span~ : Span? = None, hint~ : String? = None) -> Diagnostic {
{ severity: Warning, code, message, span, hint }
}
///| Creates an informational diagnostic.
pub fn info(code : String, message : String, span~ : Span? = None, hint~ : String? = None) -> Diagnostic {
{ severity: Info, code, message, span, hint }
}
///| One parsed key/value assignment.
pub struct ConfigEntry {
section : String
key : String
value : String
source : String
span : Span
comments : Array[String]
} derive(@debug.Debug, Eq)
///| A full configuration document plus non-fatal diagnostics.
pub struct ConfigDocument {
name : String
entries : Array[ConfigEntry]
diagnostics : Array[Diagnostic]
} derive(@debug.Debug, Eq)
///| The result of a parser operation.
pub struct ParseResult {
document : ConfigDocument
ok : Bool
} derive(@debug.Debug, Eq)
///| Options shared by the INI and properties parsers.
pub struct ParseOptions {
allow_colon_separator : Bool
allow_empty_value : Bool
preserve_comments : Bool
strict_sections : Bool
} derive(@debug.Debug, Eq)
///| Default parser options for tolerant configuration files.
pub fn default_parse_options() -> ParseOptions {
{
allow_colon_separator: true,
allow_empty_value: true,
preserve_comments: true,
strict_sections: false,
}
}
///| Creates parser options for callers that need strict or custom behavior.
pub fn parse_options(
allow_colon_separator? : Bool = true,
allow_empty_value? : Bool = true,
preserve_comments? : Bool = true,
strict_sections? : Bool = false,
) -> ParseOptions {
{
allow_colon_separator,
allow_empty_value,
preserve_comments,
strict_sections,
}
}
///| Builds an empty document with a stable name.
pub fn empty_document(name : String) -> ConfigDocument {
{ name, entries: [], diagnostics: [] }
}
///| Returns the number of error diagnostics.
pub fn error_count(diagnostics : Array[Diagnostic]) -> Int {
let mut count = 0
for item in diagnostics {
if item.severity == Error {
count = count + 1
}
}
count
}
///| Returns true when the diagnostic list has no errors.
pub fn diagnostics_ok(diagnostics : Array[Diagnostic]) -> Bool {
error_count(diagnostics) == 0
}
///| Creates a normalized path-like key using section and key parts.
pub fn entry_path(section : String, key : String) -> String {
if section == "" {
key
} else {
section + "." + key
}
}
///| Returns the canonical path for an entry.
pub fn ConfigEntry::path(self : ConfigEntry) -> String {
entry_path(self.section, self.key)
}