antlr4_runtime/
generated.rs1use std::sync::{Arc, OnceLock};
2
3use crate::atn::parser_atn::ParserAtn;
4use crate::atn::serialized::SerializedAtn;
5use crate::recognizer::{RecognizerData, RecognizerMetadata};
6use crate::vocabulary::Vocabulary;
7
8#[derive(Debug)]
9pub struct GrammarMetadata {
10 grammar_file_name: &'static str,
11 rule_names: &'static [&'static str],
12 literal_names: &'static [Option<&'static str>],
13 symbolic_names: &'static [Option<&'static str>],
14 display_names: &'static [Option<&'static str>],
15 channel_names: &'static [&'static str],
16 mode_names: &'static [&'static str],
17 serialized_atn: &'static [i32],
18 recognizer_metadata: OnceLock<Arc<RecognizerMetadata>>,
19}
20
21impl Clone for GrammarMetadata {
22 fn clone(&self) -> Self {
23 Self {
24 grammar_file_name: self.grammar_file_name,
25 rule_names: self.rule_names,
26 literal_names: self.literal_names,
27 symbolic_names: self.symbolic_names,
28 display_names: self.display_names,
29 channel_names: self.channel_names,
30 mode_names: self.mode_names,
31 serialized_atn: self.serialized_atn,
32 recognizer_metadata: OnceLock::from(Arc::clone(self.cached_recognizer_metadata())),
33 }
34 }
35}
36
37impl GrammarMetadata {
38 #[allow(clippy::too_many_arguments)]
40 pub const fn new(
41 grammar_file_name: &'static str,
42 rule_names: &'static [&'static str],
43 literal_names: &'static [Option<&'static str>],
44 symbolic_names: &'static [Option<&'static str>],
45 display_names: &'static [Option<&'static str>],
46 channel_names: &'static [&'static str],
47 mode_names: &'static [&'static str],
48 serialized_atn: &'static [i32],
49 ) -> Self {
50 Self {
51 grammar_file_name,
52 rule_names,
53 literal_names,
54 symbolic_names,
55 display_names,
56 channel_names,
57 mode_names,
58 serialized_atn,
59 recognizer_metadata: OnceLock::new(),
60 }
61 }
62
63 pub const fn grammar_file_name(&self) -> &'static str {
64 self.grammar_file_name
65 }
66
67 pub const fn rule_names(&self) -> &'static [&'static str] {
68 self.rule_names
69 }
70
71 pub const fn channel_names(&self) -> &'static [&'static str] {
72 self.channel_names
73 }
74
75 pub const fn mode_names(&self) -> &'static [&'static str] {
76 self.mode_names
77 }
78
79 pub fn vocabulary(&self) -> Vocabulary {
80 Vocabulary::new(
81 self.literal_names.iter().copied(),
82 self.symbolic_names.iter().copied(),
83 self.display_names.iter().copied(),
84 )
85 }
86
87 pub fn recognizer_data(&self) -> RecognizerData {
90 RecognizerData::from_shared(Arc::clone(self.cached_recognizer_metadata()))
91 }
92
93 fn cached_recognizer_metadata(&self) -> &Arc<RecognizerMetadata> {
94 self.recognizer_metadata.get_or_init(|| {
95 Arc::new(RecognizerMetadata::from_static(
96 self.grammar_file_name,
97 self.rule_names,
98 self.channel_names,
99 self.mode_names,
100 self.vocabulary(),
101 ))
102 })
103 }
104
105 pub const fn serialized_atn(&self) -> SerializedAtn<'_> {
108 SerializedAtn::from_i32(self.serialized_atn)
109 }
110}
111
112pub trait GeneratedLexer {
113 fn metadata() -> &'static GrammarMetadata;
114}
115
116pub trait GeneratedParser {
117 fn metadata() -> &'static GrammarMetadata;
118
119 fn parser_atn() -> &'static ParserAtn;
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 static META: GrammarMetadata = GrammarMetadata::new(
128 "Mini.g4",
129 &["file"],
130 &[None, Some("'x'")],
131 &[None, Some("X")],
132 &[None, None],
133 &["DEFAULT_TOKEN_CHANNEL", "HIDDEN"],
134 &["DEFAULT_MODE"],
135 &[4, 1, 1, 0, 0, 0],
136 );
137
138 #[test]
139 fn metadata_builds_vocabulary() {
140 assert_eq!(META.grammar_file_name(), "Mini.g4");
141 assert_eq!(META.vocabulary().display_name(1), "'x'");
142 }
143
144 #[test]
145 fn cloned_metadata_shares_the_cache_before_explicit_initialization() {
146 let original = GrammarMetadata::new(
147 "Clone.g4",
148 &["start"],
149 &[None, Some("'x'")],
150 &[None, Some("X")],
151 &[None, None],
152 &["DEFAULT_TOKEN_CHANNEL"],
153 &["DEFAULT_MODE"],
154 &[],
155 );
156 let cloned = original.clone();
157 let first = original.recognizer_data();
158 let second = cloned.recognizer_data();
159
160 assert!(std::ptr::eq(first.rule_names(), second.rule_names()));
161 assert!(std::ptr::eq(first.vocabulary(), second.vocabulary()));
162 }
163}