Skip to main content

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}