diff --git a/src/parse.rs b/src/parse.rs index 8013c4f..d9d700e 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -5,7 +5,7 @@ mod names; mod terms; pub(crate) use helpers::word_boundary; -pub(crate) use literals::{boolean, integer, special_integer}; +pub(crate) use literals::{boolean, integer, special_integer, string}; pub use names::{function_or_predicate_name, variable_name}; pub use terms::term; pub use formulas::formula; diff --git a/src/parse/literals.rs b/src/parse/literals.rs index f80c013..0f816b3 100644 --- a/src/parse/literals.rs +++ b/src/parse/literals.rs @@ -2,10 +2,10 @@ use nom:: { IResult, branch::alt, - bytes::complete::tag, - character::complete::digit1, + bytes::complete::{escaped_transform, tag}, + character::complete::{digit1, none_of}, combinator::{map, map_res, opt, recognize}, - sequence::{pair, terminated}, + sequence::{delimited, pair, terminated}, }; use super::word_boundary; @@ -107,6 +107,43 @@ pub fn special_integer(i: &str) -> IResult<&str, crate::SpecialInteger> ))(i) } +pub fn string(i: &str) -> IResult<&str, String> +{ + map + ( + terminated + ( + delimited + ( + tag("\""), + escaped_transform + ( + none_of("\"\\"), + '\\', + alt + (( + tag("\""), + tag("\\"), + map + ( + tag("n"), + |_| "\n", + ), + map + ( + tag("t"), + |_| "\t", + ), + )), + ), + tag("\""), + ), + word_boundary, + ), + String::from, + )(i) +} + #[cfg(test)] mod tests { @@ -177,4 +214,36 @@ mod tests assert!(special_integer("a").is_err()); assert!(special_integer(" ").is_err()); } + + #[test] + fn parse_string() + { + assert_eq!(string("\"test 123\""), Ok(("", "test 123".to_string()))); + assert_eq!(string("\"123 test\""), Ok(("", "123 test".to_string()))); + assert_eq!(string("\" test 123 \""), Ok(("", " test 123 ".to_string()))); + assert_eq!(string("\"test 123\" \"rest"), Ok((" \"rest", "test 123".to_string()))); + assert_eq!(string("\"test 123\", \"rest"), Ok((", \"rest", "test 123".to_string()))); + assert_eq!(string("\"test\n123\""), Ok(("", "test\n123".to_string()))); + assert_eq!(string("\"test\\\"123\""), Ok(("", "test\"123".to_string()))); + assert_eq!(string("\"test\\\"123\\\"\""), Ok(("", "test\"123\"".to_string()))); + assert_eq!(string("\"\\\"test 123\\\"\""), Ok(("", "\"test 123\"".to_string()))); + assert_eq!(string("\"test\\\\123\""), Ok(("", "test\\123".to_string()))); + assert_eq!(string("\"test\\\\123\\\\\""), Ok(("", "test\\123\\".to_string()))); + assert_eq!(string("\"\\\\test 123\\\\\""), Ok(("", "\\test 123\\".to_string()))); + assert_eq!(string("\"test\\n123\""), Ok(("", "test\n123".to_string()))); + assert_eq!(string("\"test\\n123\\n\""), Ok(("", "test\n123\n".to_string()))); + assert_eq!(string("\"\\ntest 123\\n\""), Ok(("", "\ntest 123\n".to_string()))); + assert_eq!(string("\"test\\t123\""), Ok(("", "test\t123".to_string()))); + assert_eq!(string("\"test\\t123\\t\""), Ok(("", "test\t123\t".to_string()))); + assert_eq!(string("\"\\ttest 123\\t\""), Ok(("", "\ttest 123\t".to_string()))); + assert_eq!(string("\"test πŸ™‚ 123\""), Ok(("", "test πŸ™‚ 123".to_string()))); + assert_eq!(string("\"πŸ™‚test 123\""), Ok(("", "πŸ™‚test 123".to_string()))); + assert_eq!(string("\"test 123πŸ™‚\""), Ok(("", "test 123πŸ™‚".to_string()))); + assert!(string("\"test 123\"a").is_err()); + assert!(string("\"test\\i123\"").is_err()); + assert!(string("\"test").is_err()); + assert!(string("test").is_err()); + assert!(string("-").is_err()); + assert!(string(" ").is_err()); + } } diff --git a/src/parse/terms.rs b/src/parse/terms.rs index f870828..46bbb86 100644 --- a/src/parse/terms.rs +++ b/src/parse/terms.rs @@ -9,7 +9,7 @@ use nom:: sequence::{delimited, pair, preceded, terminated}, }; -use super::{Declarations, boolean, function_or_predicate_name, integer, special_integer, +use super::{Declarations, boolean, function_or_predicate_name, integer, special_integer, string, variable_name, word_boundary}; fn negative<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, crate::Term> @@ -58,43 +58,6 @@ fn absolute_value<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, crate::T )(i) } -pub fn string(i: &str) -> IResult<&str, crate::Term> -{ - map - ( - terminated - ( - delimited - ( - tag("\""), - escaped_transform - ( - none_of("\"\\"), - '\\', - alt - (( - tag("\""), - tag("\\"), - map - ( - tag("n"), - |_| "\n", - ), - map - ( - tag("t"), - |_| "\t", - ), - )), - ), - tag("\""), - ), - word_boundary, - ), - crate::Term::string, - )(i) -} - pub(crate) fn function_or_predicate<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, (&'i str, Option>>)> { @@ -241,7 +204,11 @@ fn term_precedence_0<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate |i| function(i, d), crate::Term::Function, ), - string, + map + ( + string, + crate::Term::String, + ), map ( |i| variable(i, d), @@ -736,38 +703,6 @@ mod tests assert_eq!(format_term("f( \n a \n + \n b \n , \n c \n + \n d \n)"), "f(a + b, c + d)"); } - #[test] - fn parse_string() - { - assert_eq!(string("\"test 123\""), Ok(("", Term::string("test 123".to_string())))); - assert_eq!(string("\"123 test\""), Ok(("", Term::string("123 test".to_string())))); - assert_eq!(string("\" test 123 \""), Ok(("", Term::string(" test 123 ".to_string())))); - assert_eq!(string("\"test 123\" \"rest"), Ok((" \"rest", Term::string("test 123".to_string())))); - assert_eq!(string("\"test 123\", \"rest"), Ok((", \"rest", Term::string("test 123".to_string())))); - assert_eq!(string("\"test\n123\""), Ok(("", Term::string("test\n123".to_string())))); - assert_eq!(string("\"test\\\"123\""), Ok(("", Term::string("test\"123".to_string())))); - assert_eq!(string("\"test\\\"123\\\"\""), Ok(("", Term::string("test\"123\"".to_string())))); - assert_eq!(string("\"\\\"test 123\\\"\""), Ok(("", Term::string("\"test 123\"".to_string())))); - assert_eq!(string("\"test\\\\123\""), Ok(("", Term::string("test\\123".to_string())))); - assert_eq!(string("\"test\\\\123\\\\\""), Ok(("", Term::string("test\\123\\".to_string())))); - assert_eq!(string("\"\\\\test 123\\\\\""), Ok(("", Term::string("\\test 123\\".to_string())))); - assert_eq!(string("\"test\\n123\""), Ok(("", Term::string("test\n123".to_string())))); - assert_eq!(string("\"test\\n123\\n\""), Ok(("", Term::string("test\n123\n".to_string())))); - assert_eq!(string("\"\\ntest 123\\n\""), Ok(("", Term::string("\ntest 123\n".to_string())))); - assert_eq!(string("\"test\\t123\""), Ok(("", Term::string("test\t123".to_string())))); - assert_eq!(string("\"test\\t123\\t\""), Ok(("", Term::string("test\t123\t".to_string())))); - assert_eq!(string("\"\\ttest 123\\t\""), Ok(("", Term::string("\ttest 123\t".to_string())))); - assert_eq!(string("\"test πŸ™‚ 123\""), Ok(("", Term::string("test πŸ™‚ 123".to_string())))); - assert_eq!(string("\"πŸ™‚test 123\""), Ok(("", Term::string("πŸ™‚test 123".to_string())))); - assert_eq!(string("\"test 123πŸ™‚\""), Ok(("", Term::string("test 123πŸ™‚".to_string())))); - assert!(string("\"test 123\"a").is_err()); - assert!(string("\"test\\i123\"").is_err()); - assert!(string("\"test").is_err()); - assert!(string("test").is_err()); - assert!(string("-").is_err()); - assert!(string(" ").is_err()); - } - #[test] fn parse_function() {