Skip to main content

lex_core/lex/ast/elements/
label.rs

1//! Label element
2//!
3//!     A label is a short identifier used by annotations and other elements. Labels are
4//!     components that carry a bit of information inside an element, only used in metadata.
5//!
6//!     Labels serve similar roles but have relevant differences from:
7//!         - Tags: An annotation can only have one label, while tags are typically multiple.
8//!         - IDs: labels are not unique, even in the same element
9//!
10//!     Labels support dot notation for namespaces:
11//!         Namespaced: lex.internal, plugin.myapp.custom
12//!         Namespaces are user defined, with the exception of the doc and lex namespaces
13//!         which are reserved.
14//!
15//! Syntax
16//!
17//!     <letter> (<letter> | <digit> | "_" | "-" | ".")*
18//!
19//!     Labels are used in data nodes, which have the syntax:
20//!         :: label params?
21//!
22//!     See [Data](super::data::Data) for how labels are used in data nodes.
23//!
24//!     Learn More:
25//!         - Labels spec: specs/v1/elements/label.lex
26
27use super::super::range::{Position, Range};
28use std::fmt;
29
30/// A label represents a named identifier in lex documents
31#[derive(Debug, Clone, PartialEq, Eq, Hash)]
32pub struct Label {
33    pub value: String,
34    pub location: Range,
35}
36
37impl Label {
38    fn default_location() -> Range {
39        Range::new(0..0, Position::new(0, 0), Position::new(0, 0))
40    }
41    pub fn new(value: String) -> Self {
42        Self {
43            value,
44            location: Self::default_location(),
45        }
46    }
47    pub fn from_string(value: &str) -> Self {
48        Self {
49            value: value.to_string(),
50            location: Self::default_location(),
51        }
52    }
53
54    /// Preferred builder: `at(location)`
55    pub fn at(mut self, location: Range) -> Self {
56        self.location = location;
57        self
58    }
59}
60
61impl fmt::Display for Label {
62    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63        write!(f, "{}", self.value)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_label() {
73        let location = super::super::super::range::Range::new(
74            0..0,
75            super::super::super::range::Position::new(1, 0),
76            super::super::super::range::Position::new(1, 10),
77        );
78        let label = Label::new("test".to_string()).at(location.clone());
79        assert_eq!(label.location, location);
80    }
81}