From 7ea024d047862b89c57b78cb8480009514221d24 Mon Sep 17 00:00:00 2001 From: Jake Stanger Date: Sun, 27 Nov 2022 23:57:23 +0000 Subject: [PATCH] fix(parser): panic when input references another input --- assets/inputs/input_references_input.corn | 6 ++++ .../outputs/json/input_references_input.json | 3 ++ .../outputs/toml/input_references_input.toml | 2 ++ .../outputs/yaml/input_references_input.yml | 2 ++ libcorn/src/parser.rs | 28 ++++++++++--------- libcorn/tests/de_tests.rs | 23 ++++++++------- libcorn/tests/parser_tests.rs | 1 + 7 files changed, 42 insertions(+), 23 deletions(-) create mode 100644 assets/inputs/input_references_input.corn create mode 100644 assets/outputs/json/input_references_input.json create mode 100644 assets/outputs/toml/input_references_input.toml create mode 100644 assets/outputs/yaml/input_references_input.yml diff --git a/assets/inputs/input_references_input.corn b/assets/inputs/input_references_input.corn new file mode 100644 index 0000000..3807b4a --- /dev/null +++ b/assets/inputs/input_references_input.corn @@ -0,0 +1,6 @@ +let { + $foo = "bar" + $baz = $foo +} in { + foo = $baz +} \ No newline at end of file diff --git a/assets/outputs/json/input_references_input.json b/assets/outputs/json/input_references_input.json new file mode 100644 index 0000000..c8c4105 --- /dev/null +++ b/assets/outputs/json/input_references_input.json @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} diff --git a/assets/outputs/toml/input_references_input.toml b/assets/outputs/toml/input_references_input.toml new file mode 100644 index 0000000..7ff7212 --- /dev/null +++ b/assets/outputs/toml/input_references_input.toml @@ -0,0 +1,2 @@ +foo = 'bar' + diff --git a/assets/outputs/yaml/input_references_input.yml b/assets/outputs/yaml/input_references_input.yml new file mode 100644 index 0000000..8218b15 --- /dev/null +++ b/assets/outputs/yaml/input_references_input.yml @@ -0,0 +1,2 @@ +foo: bar + diff --git a/libcorn/src/parser.rs b/libcorn/src/parser.rs index c1b286e..c9dc858 100644 --- a/libcorn/src/parser.rs +++ b/libcorn/src/parser.rs @@ -19,19 +19,24 @@ impl std::fmt::Display for Rule { } struct CornParser<'a> { + input_block: Option>, inputs: Inputs<'a>, } impl<'a> CornParser<'a> { pub fn new(input_block: Option>) -> Self { - let inputs = input_block - .map(|block| Self::parse_assign_block(block).unwrap()) - .unwrap_or_else(HashMap::new); - - Self { inputs } + let inputs = HashMap::new(); + Self { + input_block, + inputs, + } } - pub fn parse(self, object_block: Pair<'a, Rule>) -> Result { + pub fn parse(mut self, object_block: Pair<'a, Rule>) -> Result { + if let Some(input_block) = self.input_block.take() { + self.parse_assign_block(input_block).unwrap() + } + let value_block = self.parse_object(object_block)?; Ok(Value::Object(value_block)) } @@ -162,22 +167,19 @@ impl<'a> CornParser<'a> { /// Parses the `let { } in` block at the start of files, /// producing a populated HashMap as an output. - fn parse_assign_block(block: Pair<'a, Rule>) -> Result { + fn parse_assign_block(&mut self, block: Pair<'a, Rule>) -> Result<()> { assert_eq!(block.as_rule(), Rule::assign_block); - let mut inputs = HashMap::new(); - let parser = Self::new(None); - for pair in block.into_inner() { let mut assign_rules = pair.into_inner(); let name = assign_rules.next().unwrap().as_str(); - let value = parser.parse_value(assign_rules.next().unwrap())?; + let value = self.parse_value(assign_rules.next().unwrap())?; - inputs.insert(name, value); + self.inputs.insert(name, value); } - Ok(inputs) + Ok(()) } /// Attempts to get an input value from the `inputs` map. diff --git a/libcorn/tests/de_tests.rs b/libcorn/tests/de_tests.rs index 77ec96a..89fa2fd 100644 --- a/libcorn/tests/de_tests.rs +++ b/libcorn/tests/de_tests.rs @@ -12,7 +12,7 @@ macro_rules! generate_eq_tests { let test_name = stringify!($test_name); let input = fs::read_to_string(format!("../assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::<$test_type>(&input); + let config = from_str::<$test_type>(&input).unwrap(); let json_input = fs::read_to_string(format!("../assets/outputs/json/{test_name}.json")).unwrap(); let json_config = serde_json::from_str(&json_input).unwrap(); @@ -421,6 +421,7 @@ generate_eq_tests!( (environment_variable, Basic), (float, Float), (input, Input), + (input_references_input, Basic), (integer, Integer), (mixed_array, MixedArray), (null, Null), @@ -432,12 +433,14 @@ generate_eq_tests!( (very_compact, Compact) ); +// TODO: Several of these can use the macro, tidy + #[test] fn basic_new_type_enum() { let test_name = "basic"; let input = fs::read_to_string(format!("../assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input); + let config = from_str::(&input).unwrap(); let json_input = fs::read_to_string(format!("../assets/outputs/json/{test_name}.json")).unwrap(); @@ -451,7 +454,7 @@ fn basic_unit_enum() { let test_name = "basic"; let input = fs::read_to_string(format!("../assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input); + let config = from_str::(&input).unwrap(); let json_input = fs::read_to_string(format!("../assets/outputs/json/{test_name}.json")).unwrap(); @@ -465,7 +468,7 @@ fn basic_new_type() { let test_name = "basic"; let input = fs::read_to_string(format!("../assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input); + let config = from_str::(&input).unwrap(); let json_input = fs::read_to_string(format!("../assets/outputs/json/{test_name}.json")).unwrap(); @@ -479,7 +482,7 @@ fn bytes() { let test_name = "basic"; let input = fs::read_to_string(format!("../assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input); + let config = from_str::(&input).unwrap(); let json_input = fs::read_to_string(format!("../assets/outputs/json/{test_name}.json")).unwrap(); @@ -493,7 +496,7 @@ fn chained_enum() { let test_name = "chained"; let input = fs::read_to_string(format!("../assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input); + let config = from_str::(&input).unwrap(); let json_input = fs::read_to_string(format!("../assets/outputs/json/{test_name}.json")).unwrap(); @@ -507,7 +510,7 @@ fn mixed_array_enum() { let test_name = "mixed_array"; let input = fs::read_to_string(format!("../assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input); + let config = from_str::(&input).unwrap(); let json_input = fs::read_to_string(format!("../assets/outputs/json/{test_name}.json")).unwrap(); @@ -521,7 +524,7 @@ fn null_option() { let test_name = "null"; let input = fs::read_to_string(format!("../assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input); + let config = from_str::(&input).unwrap(); let json_input = fs::read_to_string(format!("../assets/outputs/json/{test_name}.json")).unwrap(); @@ -535,7 +538,7 @@ fn null_unit() { let test_name = "null"; let input = fs::read_to_string(format!("../assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input); + let config = from_str::(&input).unwrap(); let json_input = fs::read_to_string(format!("../assets/outputs/json/{test_name}.json")).unwrap(); @@ -549,7 +552,7 @@ fn str() { let test_name = "string"; let input = fs::read_to_string(format!("../assets/inputs/{test_name}.corn")).unwrap(); - let config = from_str::(&input); + let config = from_str::(&input).unwrap(); let json_input = fs::read_to_string(format!("../assets/outputs/json/{test_name}.json")).unwrap(); diff --git a/libcorn/tests/parser_tests.rs b/libcorn/tests/parser_tests.rs index 62d6fbf..9b238d5 100644 --- a/libcorn/tests/parser_tests.rs +++ b/libcorn/tests/parser_tests.rs @@ -85,6 +85,7 @@ generate_eq_tests!( environment_variable, float, input, + input_references_input, integer, mixed_array, null,