Compare commits

..

2 Commits

Author SHA1 Message Date
Elijah Voigt 1a6bafa65e I think I'm going to burn this down and start over... 1 year ago
Elijah Voigt 4bd5773dde Tokenizer test 1 year ago

@ -20,68 +20,74 @@ impl From<nom::Err<nom::error::Error<&str>>> for SaveEntityParseError {
} }
} }
fn parse_bool(i: &str) -> IResult<&str, bool> {
alt((tag("true"), tag("false")))(i).map(|(s, val)| match val {
"true" => (s, true),
"false" => (s, false),
_ => panic!("Bools must be `true` or `false`!"),
})
}
fn parse_xyz(i: &str) -> IResult<&str, (f32, f32, f32)> { #[derive(Debug, PartialEq)]
tuple((float, space1, float, space1, float))(i).map(|(s, (x, _, y, _, z))| (s, (x, y, z))) enum Token {
Tag(String),
Str(String),
Num(f32),
} }
fn parse_wxyz(i: &str) -> IResult<&str, (f32, f32, f32, f32)> { ///
tuple((float, space1, float, space1, float, space1, float))(i) /// Simple function to tokenize a string into an array of Token values
.map(|(s, (w, _, x, _, y, _, z))| (s, (w, x, y, z))) ///
pub(crate) fn tokenize(line: &str) -> Vec<Token> {
line.split(" ")
.map(|piece| {
if let Ok(n) = piece.parse::<f32>() {
Token::Num(n)
} else if let Ok((_, (_, s, _))) = tuple((
tag::<&str, &str, ()>("\""),
take_until1("\""),
tag::<&str, &str, ()>("\""),
))(piece)
{
Token::Str(s.into())
} else {
Token::Tag(piece.into())
}
})
.collect()
} }
fn parse_string(i: &str) -> IResult<&str, &str> { #[test]
let (rem, (_, out, _)) = tuple((tag("\""), take_until1("\""), tag("\"")))(i)?; fn test_tokenize() {
Ok((rem, out)) let line = "foo \"bar\" 1.23 baz \"asdf\" etc";
assert_eq!(
tokenize(line),
vec![
Token::Tag("foo".into()),
Token::Str("bar".into()),
Token::Num(1.23),
Token::Tag("baz".into()),
Token::Str("asdf".into()),
Token::Tag("etc".into())
]
);
} }
/// ///
/// Returns reflected `Transform` /// Returns reflected `Transform`
/// ///
pub(crate) fn parse_save_transform(line: &str) -> Result<Box<dyn Reflect>, SaveEntityParseError> { pub(crate) fn parse_save_transform(tokens: &Vec<Token>) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
let (rem, _) = tag("transform")(line)?;
let mut transform = Transform::default(); let mut transform = Transform::default();
let mut curr = rem.trim_start(); // Tag(Transform),
for _ in 0..3 { // Tag(Translation), Number, Number, Number
if let Ok((rem, (_, _, (x, y, z)))) = // Tag(Rotation), Number, Number, Number, Number
tuple((tag("translation"), space1, parse_xyz))(curr.trim_start()) // Tag(Scale), Number, Number, Number
{
transform.translation = Vec3::new(x, y, z);
curr = rem.trim_start();
} else if let Ok((rem, (_, _, (x, y, z, w)))) =
tuple((tag("rotation"), space1, parse_wxyz))(curr.trim_start())
{
transform.rotation = Quat::from_xyzw(x, y, z, w);
curr = rem.trim_start();
} else if let Ok((rem, (_, _, (x, y, z)))) =
tuple((tag("scale"), space1, parse_xyz))(curr.trim_start())
{
transform.scale = Vec3::new(x, y, z);
curr = rem.trim_start();
} else {
return Err(SaveEntityParseError::Transform);
}
}
// Assert there are no trailing characters on the line // return Err(SaveEntityParseError::Transform);
debug_assert_eq!(curr, "");
Ok(transform.clone_value()) todo!("parse_save_transform");
} }
#[test] #[test]
fn test_parse_transform() { fn test_parse_transform() {
let line = "transform translation 1.0 2.0 3.0 rotation 0.1 0.2 0.3 1.0 scale 1.1 1.2 1.3"; let line = "transform translation 1.0 2.0 3.0 rotation 0.1 0.2 0.3 1.0 scale 1.1 1.2 1.3";
let parsed = parse_save_transform(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_transform(&tokens).unwrap();
let expected = Transform { let expected = Transform {
translation: Vec3::new(1.0, 2.0, 3.0), translation: Vec3::new(1.0, 2.0, 3.0),
rotation: Quat::from_xyzw(0.1, 0.2, 0.3, 1.0), rotation: Quat::from_xyzw(0.1, 0.2, 0.3, 1.0),
@ -97,22 +103,18 @@ fn test_parse_transform() {
/// ///
/// Returns a reflected `Name` /// Returns a reflected `Name`
/// ///
pub(crate) fn parse_save_name(line: &str) -> Result<Box<dyn Reflect>, SaveEntityParseError> { pub(crate) fn parse_save_name(tokens: &Vec<Token>) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
let (remainder, _) = tag("name")(line)?; todo!("parse_save_name");
let n = remainder.trim().to_string();
if n.is_empty() { // Err(SaveEntityParseError::Name)
Err(SaveEntityParseError::Name)
} else {
let name = Name::new(n);
Ok(name.clone_value())
}
} }
#[test] #[test]
fn test_parse_name() { fn test_parse_name() {
{ {
let line = "name Van"; let line = "name Van";
let parsed = parse_save_name(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_name(&tokens).unwrap();
let expected = Name::new("Van"); let expected = Name::new("Van");
assert!(expected assert!(expected
@ -122,7 +124,8 @@ fn test_parse_name() {
} }
{ {
let line = "name Big Mike"; let line = "name Big Mike";
let parsed = parse_save_name(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_name(&tokens).unwrap();
let expected = Name::new("Big Mike"); let expected = Name::new("Big Mike");
assert!(expected assert!(expected
@ -150,23 +153,23 @@ impl Component for SaveModel {
/// ///
/// Returns a reflected `SaveModel` /// Returns a reflected `SaveModel`
/// ///
pub(crate) fn parse_save_model(line: &str) -> Result<Box<dyn Reflect>, SaveEntityParseError> { pub(crate) fn parse_save_model(tokens: &Vec<Token>) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
let (rem, (_, _, gltf_path, _, scene_name)) = todo!("parse_save_model");
tuple((tag("model"), space1, parse_string, space1, parse_string))(line)?;
debug_assert!(rem == "");
/*
Ok(SaveModel { Ok(SaveModel {
gltf_file: gltf_path.into(), gltf_file: gltf_path.into(),
scene_name: scene_name.into(), scene_name: scene_name.into(),
} }
.clone_value()) .clone_value())
*/
} }
#[test] #[test]
fn test_parse_model() { fn test_parse_model() {
let line = "model \"models/foo.glb\" \"My Scene\""; let line = "model \"models/foo.glb\" \"My Scene\"";
let parsed = parse_save_model(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_model(&tokens).unwrap();
let expected = SaveModel { let expected = SaveModel {
gltf_file: "models/foo.glb".into(), gltf_file: "models/foo.glb".into(),
scene_name: "My Scene".into(), scene_name: "My Scene".into(),
@ -197,46 +200,19 @@ impl Component for SaveCameraRenderTarget {
/// ///
/// Returns a reflected `SaveCameraRenderTarget /// Returns a reflected `SaveCameraRenderTarget
/// ///
pub(crate) fn parse_save_camera(line: &str) -> Result<Box<dyn Reflect>, SaveEntityParseError> { pub(crate) fn parse_save_camera(tokens: &Vec<Token>) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
if let Ok((rem, _camera)) = tag::<&str, &str, ()>("camera")(line) { todo!("parse_save_camera");
if let Ok((rem, (_, _target))) = tuple((space1::<&str, ()>, tag("target")))(rem) {
if let Ok((rem, (_, _window))) = tuple((space1::<&str, ()>, tag("window")))(rem) {
// Camera + target + window + UUID
if let Ok((rem, (_, path))) =
tuple((space1::<&str, nom::error::Error<&str>>, parse_string))(rem)
{
debug_assert!(rem == "");
Ok(SaveCameraRenderTarget::Window(path.into()).clone_value())
// Camera + target + widow
} else {
debug_assert!(rem == "");
Ok(SaveCameraRenderTarget::Default.clone_value())
}
// camera + target
} else {
debug_assert!(rem == "");
Err(SaveEntityParseError::Camera)
}
// Just camera
} else {
debug_assert!(rem == "");
Ok(SaveCameraRenderTarget::Default.clone_value())
}
// Nothing parsed well // Nothing parsed well
} else { // Err(SaveEntityParseError::Camera)
Err(SaveEntityParseError::Camera)
}
} }
#[test] #[test]
fn test_parse_camera() { fn test_parse_camera() {
{ {
let line = "camera"; let line = "camera";
let parsed = parse_save_camera(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_camera(&tokens).unwrap();
let expected = SaveCameraRenderTarget::Default; let expected = SaveCameraRenderTarget::Default;
assert!(expected assert!(expected
.clone_value() .clone_value()
@ -245,7 +221,8 @@ fn test_parse_camera() {
} }
{ {
let line = "camera target window"; let line = "camera target window";
let parsed = parse_save_camera(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_camera(&tokens).unwrap();
let expected = SaveCameraRenderTarget::Default; let expected = SaveCameraRenderTarget::Default;
assert!(expected assert!(expected
.clone_value() .clone_value()
@ -254,12 +231,14 @@ fn test_parse_camera() {
} }
{ {
let line = "camera target"; let line = "camera target";
let parsed = parse_save_camera(line); let tokens = tokenize(line);
let parsed = parse_save_camera(&tokens);
assert!(parsed.is_err()); assert!(parsed.is_err());
} }
{ {
let line = "camera target window \"some.entity\""; let line = "camera target window \"some.entity\"";
let parsed = parse_save_camera(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_camera(&tokens).unwrap();
let expected = SaveCameraRenderTarget::Window("some.entity".into()); let expected = SaveCameraRenderTarget::Window("some.entity".into());
assert!(expected assert!(expected
.clone_value() .clone_value()
@ -268,7 +247,8 @@ fn test_parse_camera() {
} }
{ {
let line = "notcamera"; let line = "notcamera";
let parsed = parse_save_camera(line); let tokens = tokenize(line);
let parsed = parse_save_camera(&tokens);
assert!(parsed.is_err()); assert!(parsed.is_err());
} }
} }
@ -295,18 +275,17 @@ impl Component for SaveParent {
/// ///
/// Returns a reflected `SaveParent` /// Returns a reflected `SaveParent`
/// ///
pub(crate) fn parse_save_parent(line: &str) -> Result<Box<dyn Reflect>, SaveEntityParseError> { pub(crate) fn parse_save_parent(tokens: &Vec<Token>) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
let (rem, (_, _, parent_file)) = tuple((tag("parent"), space1, parse_string))(line)?; todo!("parse_save_parent");
debug_assert!(rem.is_empty());
Ok(SaveParent(parent_file.into()).clone_value()) // Ok(SaveParent(parent_file.into()).clone_value())
} }
#[test] #[test]
fn test_parse_parent() { fn test_parse_parent() {
let line = "parent \"some_other_file.entity\""; let line = "parent \"some_other_file.entity\"";
let parsed = parse_save_parent(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_parent(&tokens).unwrap();
let expected = SaveParent("some_other_file.entity".into()); let expected = SaveParent("some_other_file.entity".into());
assert!(expected assert!(expected
.clone_value() .clone_value()
@ -320,25 +299,24 @@ fn test_parse_parent() {
/// ///
/// Returns a reflected `Window` /// Returns a reflected `Window`
/// ///
pub(crate) fn parse_save_window(line: &str) -> Result<Box<dyn Reflect>, SaveEntityParseError> { pub(crate) fn parse_save_window(tokens: &Vec<Token>) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
let (rem, (_, _, window_title)) = tuple((tag("window"), space1, parse_string))(line)?; todo!("parse_save_window");
let (rem, (_, _, _, visibility)) = tuple((space1, tag("visible"), space1, parse_bool))(rem)?;
debug_assert!(rem.is_empty());
/*
Ok(Window { Ok(Window {
title: window_title.into(), title: window_title.into(),
visible: visibility, visible: visibility,
..default() ..default()
} }
.clone_value()) .clone_value())
*/
} }
#[test] #[test]
fn test_parse_window() { fn test_parse_window() {
let line = "window \"Editor\" visible false"; let line = "window \"Editor\" visible false";
let parsed = parse_save_window(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_window(&tokens).unwrap();
let expected = Window { let expected = Window {
visible: false, visible: false,
title: "Editor".into(), title: "Editor".into(),
@ -358,29 +336,24 @@ fn test_parse_window() {
/// ///
/// Returns a reflected `Text` /// Returns a reflected `Text`
/// ///
pub(crate) fn parse_save_ui_text(line: &str) -> Result<Box<dyn Reflect>, SaveEntityParseError> { pub(crate) fn parse_save_ui_text(tokens: &Vec<Token>) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
let (rem, (_tag_text, _space1, text)) = tuple((tag("uiText"), space1, parse_string))(line)?; todo!("parse_save_ui_text");
let (rem, (_space, _tag_color, _space1, _hash, hex_color)) =
tuple((space1, tag("color"), space1, char('#'), hex_digit1))(rem)?;
let (rem, (_space, _tag_size, _space1, font_size)) =
tuple((space1, tag("size"), space1, float))(rem)?;
debug_assert!(rem.is_empty());
/*
let style = TextStyle { let style = TextStyle {
color: Color::Srgba(Srgba::hex(hex_color).unwrap()), color: Color::Srgba(Srgba::hex(hex_color).unwrap()),
font_size, font_size,
..default() ..default()
}; };
Ok(Text::from_section(text, style).clone_value()) Ok(Text::from_section(text, style).clone_value())
*/
} }
#[test] #[test]
fn test_save_ui_text() { fn test_save_ui_text() {
let line = "uiText \"This is the text\" color #caffee size 14.6"; let line = "uiText \"This is the text\" color #caffee size 14.6";
let parsed = parse_save_ui_text(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_ui_text(&tokens).unwrap();
let expected = Text::from_section( let expected = Text::from_section(
"This is the text", "This is the text",
TextStyle { TextStyle {
@ -402,8 +375,8 @@ fn test_save_ui_text() {
pub(crate) fn parse_save_tag<T: Component + Reflect + Default>( pub(crate) fn parse_save_tag<T: Component + Reflect + Default>(
t: &str, t: &str,
) -> impl FnOnce(&str) -> Result<Box<dyn Reflect>, SaveEntityParseError> + '_ { ) -> impl FnOnce(&str) -> Result<Box<dyn Reflect>, SaveEntityParseError> + '_ {
move |line: &str| -> Result<Box<dyn Reflect>, SaveEntityParseError> { move |tokens: &Vec<Token>| -> Result<Box<dyn Reflect>, SaveEntityParseError> {
Ok(tag(t)(line).map(|_| T::default().clone_value())?) todo!("parse_save_tag")
} }
} }
@ -414,7 +387,8 @@ struct TestingTag;
#[test] #[test]
fn test_save_tag() { fn test_save_tag() {
let line = "testing"; let line = "testing";
let parsed = parse_save_tag::<TestingTag>("testing")(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_tag::<TestingTag>("testing")(&tokens).unwrap();
let expected = TestingTag; let expected = TestingTag;
assert!(expected assert!(expected
.clone_value() .clone_value()
@ -441,21 +415,16 @@ impl Component for SaveTargetCamera {
/// ///
/// Returns reflected `SaveTargetCamera` /// Returns reflected `SaveTargetCamera`
pub(crate) fn parse_save_target_camera( pub(crate) fn parse_save_target_camera(
line: &str, tokens: &Vec<Token>,
) -> Result<Box<dyn Reflect>, SaveEntityParseError> { ) -> Result<Box<dyn Reflect>, SaveEntityParseError> {
Ok( todo!("parse_save_target_camera")
tuple((tag("targetCamera"), space1, parse_string))(line).map(
|(_, (_, _, target_camera_entity_file))| {
SaveTargetCamera(target_camera_entity_file.into()).clone_value()
},
)?,
)
} }
#[test] #[test]
fn test_target_camera() { fn test_target_camera() {
let line = "targetCamera \"./level-camera.entity\""; let line = "targetCamera \"./level-camera.entity\"";
let parsed = parse_save_target_camera(line).unwrap(); let tokens = tokenize(line);
let parsed = parse_save_target_camera(&tokens).unwrap();
let expected = SaveTargetCamera("./level-camera.entity".into()); let expected = SaveTargetCamera("./level-camera.entity".into());
assert!(expected assert!(expected

@ -54,9 +54,12 @@ impl SaveEntity {
// track if this line matched any components // track if this line matched any components
let mut good = false; let mut good = false;
// Tokenize the line
let tokens = parser::tokenize(line);
// Run line against all parsers // Run line against all parsers
for f in fns { for f in fns {
if let Ok(v) = f(line) { if let Ok(v) = f(&tokens) {
entity.components.push(v); entity.components.push(v);
good = true; good = true;
} }

Loading…
Cancel
Save