Unify and generalize keywords and symbols parsing

Signed-off-by: Victor Porof <vporof@mozilla.com>
This commit is contained in:
Victor Porof 2017-02-02 11:52:34 +01:00
parent 72da5722ae
commit 9ee0ac8e00
2 changed files with 31 additions and 13 deletions

View file

@ -73,28 +73,27 @@ namespace_divider = "."
namespace_separator = "/" namespace_separator = "/"
// TODO: Be more picky here // 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_initial = [a-z] / [A-Z] / [0-9] / [*!_?$%&=<>]
symbol_char_subsequent = [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* / "." ) symbol_name = ( symbol_char_initial+ / "." ) ( symbol_char_subsequent* / "." )
keyword_prefix = ":" 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 = 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) types::to_symbol(ns, n)
} }
pub keyword -> Value = 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) types::to_keyword(ns, n)
} }

View file

@ -105,17 +105,36 @@ fn test_text() {
fn test_symbol() { fn test_symbol() {
assert_eq!(symbol("$").unwrap(), s_plain("$")); assert_eq!(symbol("$").unwrap(), s_plain("$"));
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/world").unwrap(), s_ns("hello", "world"));
//assert_eq!(symbol("hello").unwrap(), s_plain("hello")); 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] #[test]
fn test_keyword() { fn test_keyword() {
assert_eq!(keyword(":hello/world").unwrap(), k_ns("hello", "world")); 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(":symbol").unwrap(), k_plain("symbol"));
assert_eq!(keyword(":hello").unwrap(), k_plain("hello")); 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] #[test]