diff --git a/edn/src/edn.rustpeg b/edn/src/edn.rustpeg index d012ad16..3dc619e6 100644 --- a/edn/src/edn.rustpeg +++ b/edn/src/edn.rustpeg @@ -73,28 +73,27 @@ namespace_divider = "." namespace_separator = "/" // TODO: Be more picky here +// Keywords follow the rules of symbols, except they can (and must) begin with : +// e.g. :fred or :my/fred. See https://github.com/edn-format/edn#keywords symbol_char_initial = [a-z] / [A-Z] / [0-9] / [*!_?$%&=<>] symbol_char_subsequent = [a-z] / [A-Z] / [0-9] / [-*!_?$%&=<>] -symbol_namespace = symbol_char_initial+ (namespace_divider symbol_char_subsequent+)* +symbol_namespace = symbol_char_initial symbol_char_subsequent* (namespace_divider symbol_char_subsequent+)* symbol_name = ( symbol_char_initial+ / "." ) ( symbol_char_subsequent* / "." ) keyword_prefix = ":" -// TODO: More chars here? -keyword_namespace_char = [a-z] / [A-Z] / [0-9] -keyword_namespace = keyword_namespace_char+ (namespace_divider keyword_namespace_char+)* - -keyword_name_char = [a-z] / [A-Z] / [0-9] / "." -keyword_name = keyword_name_char+ - pub symbol -> Value = - ns:( sns:$(symbol_namespace) namespace_separator { sns })? n:$(symbol_name) { + ns:( sns:$(symbol_namespace) namespace_separator { + sns + })? n:$(symbol_name) { types::to_symbol(ns, n) } pub keyword -> Value = - keyword_prefix ns:( kns:$(keyword_namespace) namespace_separator { kns })? n:$(keyword_name) { + keyword_prefix ns:( sns:$(symbol_namespace) namespace_separator { + sns + })? n:$(symbol_name) { types::to_keyword(ns, n) } diff --git a/edn/tests/tests.rs b/edn/tests/tests.rs index 4d42d21e..f34603c9 100644 --- a/edn/tests/tests.rs +++ b/edn/tests/tests.rs @@ -105,17 +105,36 @@ fn test_text() { fn test_symbol() { assert_eq!(symbol("$").unwrap(), s_plain("$")); assert_eq!(symbol(".").unwrap(), s_plain(".")); - //assert_eq!(symbol("r_r").unwrap(), s_plain("r_r")); - //assert_eq!(symbol("$symbol").unwrap(), s_plain("$symbol")); - //assert_eq!(symbol("hello").unwrap(), s_plain("hello")); + + assert_eq!(symbol("hello/world").unwrap(), s_ns("hello", "world")); + assert_eq!(symbol("foo-bar/baz-boz").unwrap(), s_ns("foo-bar", "baz-boz")); + + assert_eq!(symbol("foo-bar/baz_boz").unwrap(), s_ns("foo-bar", "baz_boz")); + assert_eq!(symbol("foo_bar/baz-boz").unwrap(), s_ns("foo_bar", "baz-boz")); + assert_eq!(symbol("foo_bar/baz_boz").unwrap(), s_ns("foo_bar", "baz_boz")); + + assert_eq!(symbol("symbol").unwrap(), s_plain("symbol")); + assert_eq!(symbol("hello").unwrap(), s_plain("hello")); + assert_eq!(symbol("foo-bar").unwrap(), s_plain("foo-bar")); + assert_eq!(symbol("foo_bar").unwrap(), s_plain("foo_bar")); } #[test] fn test_keyword() { assert_eq!(keyword(":hello/world").unwrap(), k_ns("hello", "world")); + assert_eq!(keyword(":foo-bar/baz-boz").unwrap(), k_ns("foo-bar", "baz-boz")); + + assert_eq!(keyword(":foo-bar/baz_boz").unwrap(), k_ns("foo-bar", "baz_boz")); + assert_eq!(keyword(":foo_bar/baz-boz").unwrap(), k_ns("foo_bar", "baz-boz")); + assert_eq!(keyword(":foo_bar/baz_boz").unwrap(), k_ns("foo_bar", "baz_boz")); assert_eq!(keyword(":symbol").unwrap(), k_plain("symbol")); assert_eq!(keyword(":hello").unwrap(), k_plain("hello")); + assert_eq!(keyword(":foo-bar").unwrap(), k_plain("foo-bar")); + assert_eq!(keyword(":foo_bar").unwrap(), k_plain("foo_bar")); + + assert!(keyword(":").is_err()); + assert!(keyword(":foo/").is_err()); } #[test]