nemicosm/hidl/src/grammar.lalrpop

171 lines
3.8 KiB
Plaintext

use crate::ast::*;
grammar();
// Skip over comments
match {
r"\s*" => { },
r"//[^\n\r]*[\n\r]*" => { },
_
}
pub Namespace: Namespace = {
"namespace" <name:Ident>
<interfaces:List<Interface>>
<types:List<TypeDef>>
<extensions:List<Extension>>
=> Namespace{<>}
}
Extension: Extension = {
"extension" <name:Ident> "{"
<version:Version?>
<interface:ImplicitInterface>
<interfaces:List<ExtensionInterface>>
<types:List<TypeDef>>
"}"
=> Extension{name, version: version.unwrap_or_default(), interface, interfaces, types}
}
Interface: Interface = {
"interface" <name:Ident> "{"
<v:Version?>
<e:Events?>
<m:Methods?>
"}" => Interface { name, version: v.unwrap_or_default(), events: e.unwrap_or_default(), methods: m.unwrap_or_default() }
}
ExtensionInterface: ExtensionInterface = {
"interface" <name:Ident> "{"
<version:Version?>
<e:Events?>
<m:Methods?>
"}" => ExtensionInterface { name, version, events: e.unwrap_or_default(), methods: m.unwrap_or_default() }
}
ImplicitInterface: ImplicitInterface = {
"interface" "{"
<e:Events?>
<m:Methods?>
"}" => ImplicitInterface { events: e.unwrap_or_default(), methods: m.unwrap_or_default() }
}
Version: Version = {
"version" <Num> <Num> <Num> => (<>)
}
Events: Vec<Func> = { "events" "{" <List<Func>> "}" => <> }
Methods: Vec<Func> = { "methods" "{" <List<Func>> "}" => <> }
Func: Func = {
<name:Ident> "(" <args: Comma<Arg>> ")" <ret:("->" <Type>)?> => Func{<>}
}
Arg: Arg = {
<name:Ident> ":" <ty:Type> => Arg{<>}
}
// Argument types
Type: Type = {
PrimType => Type::Primitive(<>),
Ident => Type::Custom(<>),
IntType => Type::IntType(<>),
"[]" <Type> => Type::Array(Box::new(<>)),
}
PrimType: PrimType = {
"string" => PrimType::String,
"object" => PrimType::Object,
"uuid" => PrimType::Uuid,
"bytes" => PrimType::Bytes,
"bool" => PrimType::Bool,
"matrix4x4" => PrimType::Matrix4x4,
"f32" => PrimType::F32,
"f64" => PrimType::F64,
}
// These are seperate as only they can back an enum
IntType: IntType = {
"u8" => IntType::U8,
"u16" => IntType::U16,
"u32" => IntType::U32,
"u64" => IntType::U64,
"u128" => IntType::U128,
"vu8" => IntType::VU8,
"vu16" => IntType::VU16,
"vu32" => IntType::VU32,
"vu64" => IntType::VU64,
"vu128" => IntType::VU128,
"i8" => IntType::I8,
"i16" => IntType::I16,
"i32" => IntType::I32,
"i64" => IntType::I64,
"i128" => IntType::I128,
"vi8" => IntType::VI8,
"vi16" => IntType::VI16,
"vi32" => IntType::VI32,
"vi64" => IntType::VI64,
"vi128" => IntType::VI128,
}
// Typedefs
TypeDef: TypeDef = {
"struct" <name:Ident> <s:Struct> => TypeDef{name, kind: TypeKind::Struct(s)},
"enum" <name:Ident> "(" <backing:IntType> ")" <fields:Enum>
=> TypeDef{name, kind: TypeKind::Enum(Enum{fields, backing})},
// Enum => TypeDef::Enum(<>),
}
Struct: Struct = { "{" <fields:List<StructField>> "}" => Struct{<>} }
StructField: StructField = {
<name:Ident> ":" <ty:Type> => StructField{<>}
}
Enum: Vec<EnumField> = { "{" <List<EnumField>> "}" => <> }
EnumField: EnumField = {
<name:Ident> <value:("=" <Int>)?> => EnumField{<>}
}
// Terminals
// Num: u8 = {
// r"[0-9]+" => <>.parse().unwrap()
// }
Num: u8 = {
// TODO: This is a bit hacky, but it works for now
Int => <>.try_into().unwrap(),
}
Int: i64 = {
r"(-)?[0-9]+" => <>.parse().unwrap()
}
Ident: String = { r"[a-zA-Z][a-zA-Z0-9_]*" => <>.to_owned() }
// Combinators
List<T>: Vec<T> = {
<v:(<T>)*> => v
};
Comma<T>: Vec<T> = {
<v:(<T> ",")*> <e:T?> => match e {
None=> v,
Some(e) => {
let mut v = v;
v.push(e);
v
}
}
};