brdb 0.8.0

A library for reading and writing Brickadia's World files.
Documentation
use crate::{
    schema::{
        BrdbStructPropRaw, PlaintextEnumBody as EnumBody, PlaintextStructBody as StructBody,
        PlaintextVariantBody as VariantBody,
    },
    helpers::*
};

grammar;

/* A simple text parser for the following format (to be used for BRDB schemas):
enum MyEnum {
    Variant1 = 0,
    Variant2 = 1,
}
struct MyStruct {
    field1: str,
    field2: i32,
    field3: OtherStruct[],
    field4: u8[flat],
}
variant MyVariant {
    f64,
    i64,
    SomeStruct,
}
*/

match {
    r"\s*" => { }, // The default whitespace skipping is disabled if an `ignore pattern` is specified
    r"//[^\n\r]*[\n\r]*" => { }, // Skip `// comments`
    r"#[^\n\r]*[\n\r]*" => { }, // Skip `# comments`
    r"/\*[^*]*\*+(?:[^/*][^*]*\*+)*/" => { },  // Skip `/* comments */`
} else {
    _
}

pub Meta: (
    Vec<(String, EnumBody)>,
    Vec<(String, VariantBody)>,
    Vec<(String, StructBody)>
)
 = Decl+ => {
    let mut enums = Vec::new();
    let mut variants = Vec::new();
    let mut structs = Vec::new();
    for (e, v, s) in <> {
        if let Some(e) = e {
            enums.push(e);
        }
        if let Some(v) = v {
            variants.push(v);
        }
        if let Some(s) = s {
            structs.push(s);
        }
    }
    (enums, variants, structs)
};

Decl: (
    Option<(String, EnumBody)>,
    Option<(String, VariantBody)>,
    Option<(String, StructBody)>
) = {
    Enum => (Some(<>), None, None),
    Variant => (None, Some(<>), None),
    Struct => (None, None, Some(<>)),
};

Enum: (String, EnumBody) = "enum" <name:Ident> "{" <variants:Comma<EnumVariant>> "}" => {
    (name, variants)
};
EnumVariant: (String, i32) = <name:Ident> "=" <value:Integer> => {
    (name, value)
};

// A tagged union: an ordered list of member type names. The encoded value is a
// uint tag (the member index) followed by the value of that member type.
Variant: (String, VariantBody) = "variant" <name:Ident> "{" <members:Comma<Ident>> "}" => {
    (name, members)
};

Integer: i32 = { I32, Binary, Hex };
I32: i32 =
    r"-?\d+(_\d+)*" => remove_underscores(<>).parse::<i32>().unwrap();
Binary: i32 =
    r"0b[01]+(_[01]+)*" => i32::from_str_radix(&(&remove_underscores(&<>[2..])), 2).unwrap();
Hex: i32 =
    r"0x[0-9a-fA-F]+(_[0-9a-fA-F]+)*" => i32::from_str_radix(&remove_underscores(&<>[2..]), 16).unwrap();


Struct: (String, StructBody) = "struct" <name:Ident> "{" <fields:Comma<StructField>> "}" => (name, fields);

StructField: (String, BrdbStructPropRaw) = <name:Ident> ":" <ty:StructProp> => (name, ty);

StructProp: BrdbStructPropRaw = {
  <Ident> => BrdbStructPropRaw::Type(<>),
  <ty:Ident> "[]" => BrdbStructPropRaw::Array(ty),
  <ty:Ident> "[" "flat" "]" => BrdbStructPropRaw::FlatArray(ty),
  "{" <k_ty:Ident> ":" <v_ty:Ident> "}" => BrdbStructPropRaw::Map(
    k_ty,
    v_ty,
  ),
};

Ident: String = r"[a-zA-Z_](\w|\w::\w)*" => <>.to_string();
Comma<T>: Vec<T> = {
    () => vec![],
    <mut v:(<T> ",")*> <e:T> ","? => {
        v.push(e);
        v
    }
};