From a168c46c0455fc7bbcd3cd47e10516f4d46fde61 Mon Sep 17 00:00:00 2001 From: freestrings Date: Sat, 4 Apr 2020 16:43:55 +0900 Subject: [PATCH] Failure to match "$..['']", "$..['ref']", but succeeds on $..ref #43 --- src/parser/mod.rs | 19 +++++++++++++ src/parser/tokenizer.rs | 33 ++++++++++++++++++++- tests/paths.rs | 63 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 tests/paths.rs diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 174a5d0..51db86d 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -812,6 +812,25 @@ mod parser_tests { ]) ); + assert_eq!( + run("$.$a"), + Ok(vec![ + ParseToken::Absolute, + ParseToken::In, + ParseToken::Key("$a".to_owned()) + ]) + ); + + assert_eq!( + run("$.['$a']"), + Ok(vec![ + ParseToken::Absolute, + ParseToken::Array, + ParseToken::Key("$a".to_owned()), + ParseToken::ArrayEof, + ]) + ); + if run("$.").is_ok() { panic!(); } diff --git a/src/parser/tokenizer.rs b/src/parser/tokenizer.rs index 3b3215a..39ce14d 100644 --- a/src/parser/tokenizer.rs +++ b/src/parser/tokenizer.rs @@ -172,6 +172,37 @@ impl<'a> Tokenizer<'a> { } } + fn dolla(&mut self, pos: usize, ch: char) -> Result { + let fun = |c: &char| match c { + &CH_DOT + | &CH_ASTERISK + | &CH_LARRAY + | &CH_RARRAY + | &CH_LPAREN + | &CH_RPAREN + | &CH_AT + | &CH_QUESTION + | &CH_COMMA + | &CH_SEMICOLON + | &CH_LITTLE + | &CH_GREATER + | &CH_EQUAL + | &CH_AMPERSAND + | &CH_PIPE + | &CH_EXCLAMATION + => false, + _ => !c.is_whitespace(), + }; + let (_, mut vec) = self.input.take_while(fun).map_err(to_token_error)?; + vec.insert(0, ch); + + if vec.len() == 1 { + Ok(Token::Absolute(pos)) + } else { + Ok(Token::Key(pos, vec)) + } + } + fn quote(&mut self, ch: char) -> Result { let (_, mut val) = self .input @@ -309,7 +340,7 @@ impl<'a> Tokenizer<'a> { pub fn next_token(&mut self) -> Result { let (pos, ch) = self.input.next_char().map_err(to_token_error)?; match ch { - CH_DOLLA => Ok(Token::Absolute(pos)), + CH_DOLLA => self.dolla(pos, ch), CH_DOT => Ok(Token::Dot(pos)), CH_ASTERISK => Ok(Token::Asterisk(pos)), CH_LARRAY => Ok(Token::OpenArray(pos)), diff --git a/tests/paths.rs b/tests/paths.rs new file mode 100644 index 0000000..7b1cf91 --- /dev/null +++ b/tests/paths.rs @@ -0,0 +1,63 @@ +#[macro_use] +extern crate serde_json; + +use common::{select_and_then_compare, setup}; + +mod common; + +#[test] +fn dolla_token_in_path() { + setup(); + + select_and_then_compare( + "$..$ref", + json!({ + "Junk1": "This is a test to illustrate use of '$' in the attr for the expression $..['$ref'] ", + "$ref": "Match Root", + "Subset1":[ + {"Junk2": "Data...", + "$ref": "Match Subset1" + } + ], + "hierachy1":{ + "hierachy2.1":{ + "hierachy2.1.1":{ "$ref":"Match 2.1.1"}, + "hierachy2.1.2":{ "ref":"Match 2.1.2"}, + "hierachy2.1.3":{ "ref":"No Match 2.1.3"}, + "hierachy2.1.4":{ "$ref":"Match 2.1.4"}, + "hierachy2.1.5":{ "ref":"No Match 2.1.5"} + }, + "hierachy2.2":{ + "hierachy2.2.1":{ "ref":"No Match 2.2.1"}, + "hierachy2.2.2":{ "$ref":"Match 2.2.2"}, + "hierachy2.2.3":{ "ref":"No Match 2.2.3"}, + "hierachy2.2.4":{ "ref":"No Match 2.2.5"}, + "hierachy2.2.5":{ "$ref":"Match 2.2.5"} + }, + "hierachy2.3":{ + "hierachy2.3.1":{ "ref":"No Match 2.3.1"}, + "hierachy2.3.2":{ "ref":"No Match 2.3.2"}, + "hierachy2.3.3":{ "ref":"No Match 2.3.3"}, + "hierachy2.3.4":{ "ref":"No Match 2.3.4"}, + "hierachy2.3.5":{ "ref":"No Match 2.3.5"}, + "hierachy2.3.6":{ + "hierachy2.3.6.1":{ "$ref":"Match 2.3.6.1"}, + "hierachy2.3.6.2":{ "ref":"No Match 2.3.6.2"}, + "hierachy2.3.6.3":{ "ref":"No Match 2.3.6.3"}, + "hierachy2.3.6.4":{ "ref":"No Match 2.3.6.4"}, + "hierachy2.3.6.5":{ "ref":"No Match 2.3.6.5"} + } + } + } + }), + json!([ + "Match Root", + "Match Subset1", + "Match 2.1.1", + "Match 2.1.4", + "Match 2.2.2", + "Match 2.2.5", + "Match 2.3.6.1" + ]), + ); +} \ No newline at end of file