rucc_parse/scope.rs
1//! Scopes, and the typedef decision that rests on them.
2//!
3//! Design: `spec/06-lexer-and-parser.md` section 6.4.
4//!
5//! C's grammar is ambiguous without knowing which identifiers are type names, because `(A)*B`
6//! is a cast when `A` is a type and a multiplication when it is not. The parser resolves that
7//! here, against scopes it maintains itself, and there is no feedback channel to the lexer.
8//! Feeding the answer back to the lexer is the traditional approach and it makes the lexer's
9//! state depend on how far the parser has got, which is what makes lookahead and error recovery
10//! painful in the compilers that do it.
11//!
12//! # The hazards
13//!
14//! Each of these is a real bug in a real compiler, and each has a test below.
15//!
16//! A declarator introduces its name at the *end* of the declarator, not at the start, so
17//! `typedef int T; void f(int T, T x);` has `T` as a parameter name and `T x` is then an error,
18//! while `typedef int T; T T;` reads the specifier `T` as the type and then declares a variable
19//! of that name.
20//!
21//! Tags occupy a namespace of their own, so `struct S` does not disturb what a bare `S` means,
22//! and a typedef name shadowed by an inner declaration comes back when that scope closes.
23//!
24//! The scoping itself is [`ScopeMap`], in `rucc-base`, because semantic
25//! analysis needs the same structure with different values in it.
26//!
27//! # What is not here
28//!
29//! Two of C's four namespaces. Labels are function wide rather than block scoped and nothing
30//! about them is ambiguous, so the function parser collects them and this stack would only be
31//! in the way. Members belong to the record that declares them and are reached through a type
32//! rather than through a scope, which makes them semantic analysis's problem and not a parsing
33//! decision at all.
34
35use rucc_base::{ScopeMap, Symbol};
36
37/// What an identifier means where the parser is looking at it.
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum IdentKind {
40 /// Declared with `typedef`, so a use of it in a specifier list is a type name.
41 Typedef,
42 /// Declared as anything else: an object, a function, a parameter, an enumerator.
43 Ordinary,
44}
45
46/// Which keyword introduced a tag.
47///
48/// Kept because the three do not interchange, and because the diagnostic for using the wrong
49/// one has to name what was declared. Whether a mismatch is an error is semantic analysis's
50/// call; the parser only records what it saw.
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub enum TagKind {
53 /// `struct`.
54 Struct,
55 /// `union`.
56 Union,
57 /// `enum`.
58 Enum,
59}
60
61/// The scopes the parser keeps, across the namespaces it has to hold apart.
62#[derive(Debug, Default)]
63pub struct Scopes {
64 ordinary: ScopeMap<IdentKind>,
65 tags: ScopeMap<TagKind>,
66}
67
68impl Scopes {
69 /// Empty scopes, with the file scope open.
70 #[must_use]
71 pub fn new() -> Self {
72 Scopes::default()
73 }
74
75 /// Opens a scope in every namespace.
76 ///
77 /// Both are pushed together because C opens them together. A parameter list is a scope of
78 /// its own, which is why `void f(struct S *p);` declares a tag that is gone by the time the
79 /// next declaration is read, and getting that wrong in one namespace and not the other is
80 /// how the two drift out of step.
81 pub fn push(&mut self) {
82 self.ordinary.push();
83 self.tags.push();
84 }
85
86 /// Closes the innermost scope in every namespace.
87 ///
88 /// # Panics
89 ///
90 /// Panics on closing the file scope.
91 pub fn pop(&mut self) {
92 self.ordinary.pop();
93 self.tags.pop();
94 }
95
96 /// Whether the only open scope is the file scope.
97 #[inline]
98 #[must_use]
99 pub fn at_file_scope(&self) -> bool {
100 self.ordinary.at_file_scope()
101 }
102
103 /// How many scopes are open, the file scope counting as one.
104 #[inline]
105 #[must_use]
106 pub fn depth(&self) -> u32 {
107 self.ordinary.depth()
108 }
109
110 /// What `name` means here, and [`None`] when it has not been declared.
111 #[inline]
112 #[must_use]
113 pub fn ident(&self, name: Symbol) -> Option<IdentKind> {
114 self.ordinary.get(name)
115 }
116
117 /// Whether `name` in a specifier list is a type name.
118 ///
119 /// This is the answer the whole ambiguity turns on. An identifier that has not been
120 /// declared at all is not a type name: the declaration it is missing is an error, and
121 /// guessing that an unknown name is a type in the hope of a better parse produces a cascade
122 /// out of one typo.
123 #[inline]
124 #[must_use]
125 pub fn is_typedef_name(&self, name: Symbol) -> bool {
126 self.ordinary.get(name) == Some(IdentKind::Typedef)
127 }
128
129 /// Declares `name` in the innermost scope, and gives back what it was in that same scope.
130 ///
131 /// Called at the end of a declarator rather than at its start, which is what makes
132 /// `typedef int T; T T;` read the way C says it does.
133 pub fn declare(&mut self, name: Symbol, kind: IdentKind) -> Option<IdentKind> {
134 self.ordinary.declare(name, kind)
135 }
136
137 /// Declares a tag, and gives back what it was in the same scope.
138 pub fn declare_tag(&mut self, name: Symbol, kind: TagKind) -> Option<TagKind> {
139 self.tags.declare(name, kind)
140 }
141
142 /// What tag `name` names here.
143 #[inline]
144 #[must_use]
145 pub fn tag(&self, name: Symbol) -> Option<TagKind> {
146 self.tags.get(name)
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 /// Symbols the interner would have handed out. Nothing here reads a spelling, so the
155 /// numbers stand in for one.
156 const T: Symbol = Symbol::from_raw(1);
157 const X: Symbol = Symbol::from_raw(2);
158
159 #[test]
160 fn an_undeclared_name_is_not_a_type_name() {
161 let scopes = Scopes::new();
162 assert_eq!(scopes.ident(T), None);
163 assert!(!scopes.is_typedef_name(T));
164 }
165
166 #[test]
167 fn a_parameter_takes_the_name_away_from_the_typedef() {
168 // typedef int T; void f(int T, T x);
169 let mut scopes = Scopes::new();
170 scopes.declare(T, IdentKind::Typedef);
171 scopes.push();
172 assert!(scopes.is_typedef_name(T));
173 // The first parameter's declarator ends, and `T` is its name.
174 scopes.declare(T, IdentKind::Ordinary);
175 // Which is why the second parameter's `T` is no longer a type and `T x` is an error.
176 assert!(!scopes.is_typedef_name(T));
177 assert_eq!(scopes.ident(T), Some(IdentKind::Ordinary));
178 scopes.pop();
179 assert!(scopes.is_typedef_name(T));
180 }
181
182 #[test]
183 fn a_variable_may_take_the_name_of_the_typedef_that_gave_it_its_type() {
184 // typedef int T; T T;
185 let mut scopes = Scopes::new();
186 scopes.declare(T, IdentKind::Typedef);
187 // The specifier list is read first, while `T` is still a type name.
188 assert!(scopes.is_typedef_name(T));
189 // Then the declarator ends and the name is bound over the top of it, in the same scope,
190 // which is the redeclaration the caller reports.
191 assert_eq!(scopes.declare(T, IdentKind::Ordinary), Some(IdentKind::Typedef));
192 assert_eq!(scopes.ident(T), Some(IdentKind::Ordinary));
193 }
194
195 #[test]
196 fn a_typedef_is_exposed_again_when_the_inner_scope_closes() {
197 let mut scopes = Scopes::new();
198 scopes.declare(T, IdentKind::Typedef);
199 scopes.push();
200 assert_eq!(scopes.declare(T, IdentKind::Ordinary), None);
201 assert_eq!(scopes.ident(T), Some(IdentKind::Ordinary));
202 scopes.push();
203 assert_eq!(scopes.declare(T, IdentKind::Typedef), None);
204 assert!(scopes.is_typedef_name(T));
205 scopes.pop();
206 assert_eq!(scopes.ident(T), Some(IdentKind::Ordinary));
207 scopes.pop();
208 assert!(scopes.is_typedef_name(T));
209 }
210
211 #[test]
212 fn a_tag_does_not_disturb_the_ordinary_name() {
213 // typedef int T; struct T { int x; }; T v;
214 let mut scopes = Scopes::new();
215 scopes.declare(T, IdentKind::Typedef);
216 assert_eq!(scopes.declare_tag(T, TagKind::Struct), None);
217 assert_eq!(scopes.tag(T), Some(TagKind::Struct));
218 assert!(scopes.is_typedef_name(T));
219 assert_eq!(scopes.tag(X), None);
220 }
221
222 #[test]
223 fn a_binding_in_an_inner_scope_is_not_a_redeclaration() {
224 let mut scopes = Scopes::new();
225 assert_eq!(scopes.declare(X, IdentKind::Ordinary), None);
226 scopes.push();
227 assert_eq!(scopes.declare(X, IdentKind::Ordinary), None);
228 assert_eq!(scopes.declare(X, IdentKind::Typedef), Some(IdentKind::Ordinary));
229 scopes.pop();
230 }
231
232 #[test]
233 fn closing_a_scope_leaves_nothing_behind() {
234 let mut scopes = Scopes::new();
235 assert!(scopes.at_file_scope());
236 for _ in 0..64 {
237 scopes.push();
238 scopes.declare(X, IdentKind::Ordinary);
239 scopes.declare_tag(X, TagKind::Union);
240 }
241 assert_eq!(scopes.depth(), 65);
242 for _ in 0..64 {
243 scopes.pop();
244 }
245 assert!(scopes.at_file_scope());
246 assert_eq!(scopes.ident(X), None);
247 assert_eq!(scopes.tag(X), None);
248 }
249
250 #[test]
251 #[should_panic(expected = "the file scope is never closed")]
252 fn the_file_scope_cannot_be_closed() {
253 Scopes::new().pop();
254 }
255}