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}