diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-10-01 15:03:37 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-10-01 15:03:37 +0200 |
| commit | 7fcad452b87c8bd31a9b7dfba78c1b1a92d33dd9 (patch) | |
| tree | c1e82792456be54fd41e7b143be302dcd874e30b /src/syntax/ident.rs | |
| parent | aafd3c95cacd829b647cfab1533de5d4833b9a04 (diff) | |
Reorganize ast types 🏕
Diffstat (limited to 'src/syntax/ident.rs')
| -rw-r--r-- | src/syntax/ident.rs | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/syntax/ident.rs b/src/syntax/ident.rs new file mode 100644 index 00000000..5ab7c73c --- /dev/null +++ b/src/syntax/ident.rs @@ -0,0 +1,58 @@ +//! Unicode identifiers. + +use std::ops::Deref; + +use unicode_xid::UnicodeXID; + +/// An identifier as defined by unicode with a few extra permissible characters. +/// +/// This is defined as in the [Unicode Standard], but allows additionally +/// `-` and `_` as starting and continuing characters. +/// +/// [Unicode Standard]: http://www.unicode.org/reports/tr31/ +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct Ident(pub String); + +impl Ident { + /// Create a new identifier from a string checking that it is a valid. + pub fn new(ident: impl AsRef<str> + Into<String>) -> Option<Self> { + if is_ident(ident.as_ref()) { + Some(Self(ident.into())) + } else { + None + } + } + + /// Return a reference to the underlying string. + pub fn as_str(&self) -> &str { + self + } +} + +impl AsRef<str> for Ident { + fn as_ref(&self) -> &str { + self + } +} + +impl Deref for Ident { + type Target = str; + + fn deref(&self) -> &Self::Target { + self.0.as_str() + } +} + +/// Whether the string is a valid identifier. +pub fn is_ident(string: &str) -> bool { + let mut chars = string.chars(); + if matches!(chars.next(), Some(c) if c.is_xid_start() || is_also_ok(c)) { + chars.all(|c| c.is_xid_continue() || is_also_ok(c)) + } else { + false + } +} + +fn is_also_ok(c: char) -> bool { + c == '-' || c == '_' +} |
