///|
pub(all) enum ParseProblem {
BadFieldCount(Int, String)
UnknownKind(Int, String)
} derive(Debug, Eq)
///|
pub(all) struct ParseReport {
tokens : Array[Token]
problems : Array[ParseProblem]
} derive(Debug, Eq)
///|
pub fn parse_tokens(input : String) -> ParseReport {
let tokens : Array[Token] = []
let problems : Array[ParseProblem] = []
let lines = input.split("\n").to_array()
for index, raw_line in lines {
let line = raw_line.to_owned().trim().to_owned()
if line != "" && !line.has_prefix("#") {
let fields = [
for field in line.split("|").to_array() => {
field.to_owned().trim().to_owned()
}
]
if fields.length() != 4 {
problems.push(BadFieldCount(index + 1, line))
} else {
match token_from_fields(fields[0], fields[1], fields[2], fields[3]) {
Some(token) => tokens.push(token)
None => problems.push(UnknownKind(index + 1, fields[0]))
}
}
}
}
{ tokens, problems }
}
///|
pub fn ParseProblem::message(self : ParseProblem) -> String {
match self {
BadFieldCount(line, text) =>
"line \{line}: expected `kind | name | value | description`, got `\{text}`"
UnknownKind(line, kind) => "line \{line}: unknown token kind `\{kind}`"
}
}
///|
fn token_from_fields(
kind : String,
name : String,
value : String,
description : String,
) -> Token? {
match kind {
"color" => Some(Token::color(name, value, description~))
"font-size" | "font" => Some(Token::font_size(name, value, description~))
"spacing" | "space" => Some(Token::spacing(name, value, description~))
"radius" => Some(Token::radius(name, value, description~))
"shadow" => Some(Token::shadow(name, value, description~))
_ => None
}
}