1 //! Lower
2 //!
3 
4 use crate::collections::{map, Map};
5 use crate::grammar::consts::CFG;
6 use crate::grammar::parse_tree as pt;
7 use crate::grammar::parse_tree::{
8     read_algorithm, GrammarItem, InternToken, Lifetime, MatchMapping, Name, NonterminalString,
9     Path, TerminalString,
10 };
11 use crate::grammar::pattern::{Pattern, PatternKind};
12 use crate::grammar::repr as r;
13 use crate::normalize::norm_util::{self, Symbols};
14 use crate::normalize::NormResult;
15 use crate::session::Session;
16 use string_cache::DefaultAtom as Atom;
17 
lower(session: &Session, grammar: pt::Grammar, types: r::Types) -> NormResult<r::Grammar>18 pub fn lower(session: &Session, grammar: pt::Grammar, types: r::Types) -> NormResult<r::Grammar> {
19     let state = LowerState::new(session, types, &grammar);
20     state.lower(grammar)
21 }
22 
23 struct LowerState<'s> {
24     session: &'s Session,
25     prefix: String,
26     action_fn_defns: Vec<r::ActionFnDefn>,
27     nonterminals: Map<NonterminalString, r::NonterminalData>,
28     conversions: Vec<(TerminalString, Pattern<r::TypeRepr>)>,
29     intern_token: Option<InternToken>,
30     types: r::Types,
31     uses_error_recovery: bool,
32 }
33 
34 impl<'s> LowerState<'s> {
new(session: &'s Session, types: r::Types, grammar: &pt::Grammar) -> Self35     fn new(session: &'s Session, types: r::Types, grammar: &pt::Grammar) -> Self {
36         LowerState {
37             session,
38             prefix: grammar.prefix.clone(),
39             action_fn_defns: vec![],
40             nonterminals: map(),
41             conversions: vec![],
42             types,
43             intern_token: None,
44             uses_error_recovery: false,
45         }
46     }
47 
lower(mut self, grammar: pt::Grammar) -> NormResult<r::Grammar>48     fn lower(mut self, grammar: pt::Grammar) -> NormResult<r::Grammar> {
49         let start_symbols = self.synthesize_start_symbols(&grammar);
50 
51         let mut uses = vec![];
52         let mut token_span = None;
53         let internal_token_path = Path {
54             absolute: false,
55             ids: vec![Atom::from("Token")],
56         };
57 
58         for item in grammar.items {
59             match item {
60                 pt::GrammarItem::Use(data) => {
61                     uses.push(data);
62                 }
63 
64                 pt::GrammarItem::MatchToken(_) => {
65                     // The declarations in the match token are handled
66                     // fully by the `token_check` when it constructs the
67                     //  `InternToken` -- there is nothing left to do here.
68                 }
69 
70                 pt::GrammarItem::InternToken(data) => {
71                     token_span = Some(grammar.span);
72                     let span = grammar.span;
73                     let input_str = r::TypeRepr::Ref {
74                         lifetime: Some(Lifetime::input()),
75                         mutable: false,
76                         referent: Box::new(r::TypeRepr::Nominal(r::NominalTypeRepr {
77                             path: r::Path::str(),
78                             types: vec![],
79                         })),
80                     };
81                     self.conversions
82                         .extend(data.match_entries.iter().enumerate().filter_map(
83                             |(index, match_entry)| match &match_entry.user_name {
84                                 MatchMapping::Terminal(user_name) => {
85                                     let pattern = Pattern {
86                                         span,
87                                         kind: PatternKind::TupleStruct(
88                                             internal_token_path.clone(),
89                                             vec![
90                                                 Pattern {
91                                                     span,
92                                                     kind: PatternKind::Usize(index),
93                                                 },
94                                                 Pattern {
95                                                     span,
96                                                     kind: PatternKind::Choose(input_str.clone()),
97                                                 },
98                                             ],
99                                         ),
100                                     };
101 
102                                     Some((user_name.clone(), pattern))
103                                 }
104                                 MatchMapping::Skip => None,
105                             },
106                         ));
107                     self.intern_token = Some(data);
108                 }
109 
110                 pt::GrammarItem::ExternToken(data) => {
111                     if let Some(enum_token) = data.enum_token {
112                         token_span = Some(enum_token.type_span);
113                         self.conversions
114                             .extend(enum_token.conversions.iter().map(|conversion| {
115                                 (
116                                     conversion.from.clone(),
117                                     conversion.to.map(&mut |t| t.type_repr()),
118                                 )
119                             }));
120                     }
121                 }
122 
123                 pt::GrammarItem::Nonterminal(nt) => {
124                     let nt_name = &nt.name;
125                     let productions: Vec<_> = nt
126                         .alternatives
127                         .into_iter()
128                         .map(|alt| {
129                             let nt_type = self.types.nonterminal_type(nt_name).clone();
130                             let symbols = self.symbols(&alt.expr.symbols);
131                             let action = self.action_kind(nt_type, &alt.expr, &symbols, alt.action);
132                             r::Production {
133                                 nonterminal: nt_name.clone(),
134                                 span: alt.span,
135                                 symbols,
136                                 action,
137                             }
138                         })
139                         .collect();
140                     self.nonterminals.insert(
141                         nt_name.clone(),
142                         r::NonterminalData {
143                             name: nt_name.clone(),
144                             visibility: nt.visibility.clone(),
145                             annotations: nt.annotations,
146                             span: nt.span,
147                             productions,
148                         },
149                     );
150                 }
151             }
152         }
153 
154         let parameters = grammar
155             .parameters
156             .iter()
157             .map(|p| r::Parameter {
158                 name: p.name.clone(),
159                 ty: p.ty.type_repr(),
160             })
161             .collect();
162 
163         let where_clauses = grammar
164             .where_clauses
165             .iter()
166             .flat_map(|wc| self.lower_where_clause(wc))
167             .collect();
168 
169         let mut algorithm = r::Algorithm::default();
170 
171         // FIXME Error recovery only works for parse tables so temporarily only generate parse tables for
172         // testing
173         if self.session.unit_test && !self.uses_error_recovery {
174             algorithm.codegen = r::LrCodeGeneration::TestAll;
175         }
176 
177         read_algorithm(&grammar.annotations, &mut algorithm);
178 
179         let mut all_terminals: Vec<_> = self
180             .conversions
181             .iter()
182             .map(|c| c.0.clone())
183             .chain(if self.uses_error_recovery {
184                 Some(TerminalString::Error)
185             } else {
186                 None
187             })
188             .collect();
189         all_terminals.sort();
190 
191         let terminal_bits: Map<_, _> = all_terminals.iter().cloned().zip(0..).collect();
192 
193         Ok(r::Grammar {
194             uses_error_recovery: self.uses_error_recovery,
195             prefix: self.prefix,
196             start_nonterminals: start_symbols,
197             uses,
198             action_fn_defns: self.action_fn_defns,
199             nonterminals: self.nonterminals,
200             conversions: self.conversions.into_iter().collect(),
201             types: self.types,
202             token_span: token_span.unwrap(),
203             type_parameters: grammar.type_parameters,
204             parameters,
205             where_clauses,
206             algorithm,
207             intern_token: self.intern_token,
208             terminals: r::TerminalSet {
209                 all: all_terminals,
210                 bits: terminal_bits,
211             },
212             module_attributes: grammar.module_attributes,
213         })
214     }
215 
synthesize_start_symbols( &mut self, grammar: &pt::Grammar, ) -> Map<NonterminalString, NonterminalString>216     fn synthesize_start_symbols(
217         &mut self,
218         grammar: &pt::Grammar,
219     ) -> Map<NonterminalString, NonterminalString> {
220         let session = self.session;
221         grammar
222             .items
223             .iter()
224             .filter_map(GrammarItem::as_nonterminal)
225             .filter(|nt| nt.visibility.is_pub())
226             .filter(|nt| cfg_active(session, nt))
227             .map(|nt| {
228                 // create a synthetic symbol `__Foo` for each public symbol `Foo`
229                 // with a rule like:
230                 //
231                 //     __Foo = Foo;
232                 let fake_name =
233                     pt::NonterminalString(Atom::from(format!("{}{}", self.prefix, nt.name)));
234                 let nt_type = self.types.nonterminal_type(&nt.name).clone();
235                 self.types.add_type(fake_name.clone(), nt_type.clone());
236                 let expr = pt::ExprSymbol {
237                     symbols: vec![pt::Symbol::new(
238                         nt.span,
239                         pt::SymbolKind::Nonterminal(fake_name.clone()),
240                     )],
241                 };
242                 let symbols = vec![r::Symbol::Nonterminal(nt.name.clone())];
243                 let action_fn = self.action_fn(nt_type, false, &expr, &symbols, None);
244                 let production = r::Production {
245                     nonterminal: fake_name.clone(),
246                     symbols,
247                     action: action_fn,
248                     span: nt.span,
249                 };
250                 self.nonterminals.insert(
251                     fake_name.clone(),
252                     r::NonterminalData {
253                         name: fake_name.clone(),
254                         visibility: nt.visibility.clone(),
255                         annotations: vec![],
256                         span: nt.span,
257                         productions: vec![production],
258                     },
259                 );
260                 (nt.name.clone(), fake_name)
261             })
262             .collect()
263     }
264 
265     /// When we lower where clauses into `repr::WhereClause`, they get
266     /// flattened; so we may go from `T: Foo + Bar` into `[T: Foo, T:
267     /// Bar]`. We also convert to `TypeRepr` and so forth.
lower_where_clause(&mut self, wc: &pt::WhereClause<pt::TypeRef>) -> Vec<r::WhereClause>268     fn lower_where_clause(&mut self, wc: &pt::WhereClause<pt::TypeRef>) -> Vec<r::WhereClause> {
269         match wc {
270             pt::WhereClause::Lifetime { lifetime, bounds } => bounds
271                 .iter()
272                 .map(|bound| r::WhereClause::Bound {
273                     subject: r::TypeRepr::Lifetime(lifetime.clone()),
274                     bound: pt::TypeBound::Lifetime(bound.clone()),
275                 })
276                 .collect(),
277 
278             pt::WhereClause::Type { forall, ty, bounds } => bounds
279                 .iter()
280                 .map(|bound| r::WhereClause::Bound {
281                     subject: ty.type_repr(),
282                     bound: bound.map(pt::TypeRef::type_repr),
283                 })
284                 .map(|bound| {
285                     if forall.is_empty() {
286                         bound
287                     } else {
288                         r::WhereClause::Forall {
289                             binder: forall.clone(),
290                             clause: Box::new(bound),
291                         }
292                     }
293                 })
294                 .collect(),
295         }
296     }
297 
action_kind( &mut self, nt_type: r::TypeRepr, expr: &pt::ExprSymbol, symbols: &[r::Symbol], action: Option<pt::ActionKind>, ) -> r::ActionFn298     fn action_kind(
299         &mut self,
300         nt_type: r::TypeRepr,
301         expr: &pt::ExprSymbol,
302         symbols: &[r::Symbol],
303         action: Option<pt::ActionKind>,
304     ) -> r::ActionFn {
305         match action {
306             Some(pt::ActionKind::Lookahead) => self.lookahead_action_fn(),
307             Some(pt::ActionKind::Lookbehind) => self.lookbehind_action_fn(),
308             Some(pt::ActionKind::User(string)) => {
309                 self.action_fn(nt_type, false, &expr, &symbols, Some(string))
310             }
311             Some(pt::ActionKind::Fallible(string)) => {
312                 self.action_fn(nt_type, true, &expr, &symbols, Some(string))
313             }
314             None => self.action_fn(nt_type, false, &expr, &symbols, None),
315         }
316     }
317 
lookahead_action_fn(&mut self) -> r::ActionFn318     fn lookahead_action_fn(&mut self) -> r::ActionFn {
319         let action_fn_defn = r::ActionFnDefn {
320             fallible: false,
321             ret_type: self.types.terminal_loc_type(),
322             kind: r::ActionFnDefnKind::Lookaround(r::LookaroundActionFnDefn::Lookahead),
323         };
324 
325         self.add_action_fn(action_fn_defn)
326     }
327 
lookbehind_action_fn(&mut self) -> r::ActionFn328     fn lookbehind_action_fn(&mut self) -> r::ActionFn {
329         let action_fn_defn = r::ActionFnDefn {
330             fallible: false,
331             ret_type: self.types.terminal_loc_type(),
332             kind: r::ActionFnDefnKind::Lookaround(r::LookaroundActionFnDefn::Lookbehind),
333         };
334 
335         self.add_action_fn(action_fn_defn)
336     }
337 
action_fn( &mut self, nt_type: r::TypeRepr, fallible: bool, expr: &pt::ExprSymbol, symbols: &[r::Symbol], action: Option<String>, ) -> r::ActionFn338     fn action_fn(
339         &mut self,
340         nt_type: r::TypeRepr,
341         fallible: bool,
342         expr: &pt::ExprSymbol,
343         symbols: &[r::Symbol],
344         action: Option<String>,
345     ) -> r::ActionFn {
346         let normalized_symbols = norm_util::analyze_expr(expr);
347 
348         let action = match action {
349             Some(s) => s,
350             None => {
351                 // If the user declared a type `()`, or we inferred
352                 // it, then there is only one possible action that
353                 // will type-check (`()`), so supply that. Otherwise,
354                 // default is to include all selected items.
355                 if nt_type.is_unit() {
356                     "()".to_string()
357                 } else {
358                     let len = match &normalized_symbols {
359                         Symbols::Named(names) => names.len(),
360                         Symbols::Anon(indices) => indices.len(),
361                     };
362                     if len == 1 {
363                         "<>".to_string()
364                     } else {
365                         "(<>)".to_string()
366                     }
367                 }
368             }
369         };
370 
371         // Note that the action fn takes ALL of the symbols in `expr`
372         // as arguments, and some of them are simply dropped based on
373         // the user's selections.
374 
375         // The set of argument types is thus the type of all symbols:
376         let arg_types: Vec<r::TypeRepr> =
377             symbols.iter().map(|s| s.ty(&self.types)).cloned().collect();
378 
379         let action_fn_defn = match normalized_symbols {
380             Symbols::Named(names) => {
381                 // if there are named symbols, we want to give the
382                 // arguments the names that the user gave them:
383                 let arg_names = names.iter().map(|(index, name, _)| (*index, name.clone()));
384                 let arg_patterns = patterns(arg_names, symbols.len());
385 
386                 let action = {
387                     match norm_util::check_between_braces(&action) {
388                         norm_util::Presence::None => action,
389                         norm_util::Presence::Normal => {
390                             let name_str: String = {
391                                 let name_strs: Vec<_> = names
392                                     .iter()
393                                     .map(|&(_, ref name, _)| name.name.as_ref())
394                                     .collect();
395                                 name_strs.join(", ")
396                             };
397                             action.replace("<>", &name_str)
398                         }
399                         norm_util::Presence::InCurlyBrackets => {
400                             let name_str = {
401                                 let name_strs: Vec<_> = names
402                                     .iter()
403                                     .map(|&(_, ref name, _)| format!("{0}:{0}", &*name.name))
404                                     .collect();
405                                 name_strs.join(", ")
406                             };
407                             action.replace("<>", &name_str)
408                         }
409                     }
410                 };
411 
412                 r::ActionFnDefn {
413                     fallible,
414                     ret_type: nt_type,
415                     kind: r::ActionFnDefnKind::User(r::UserActionFnDefn {
416                         arg_patterns,
417                         arg_types,
418                         code: action,
419                     }),
420                 }
421             }
422             Symbols::Anon(indices) => {
423                 let names: Vec<_> = (0..indices.len()).map(|i| self.fresh_name(i)).collect();
424 
425                 let p_indices = indices.iter().map(|&(index, _)| index);
426                 let p_names = names.iter().cloned().map(Name::immut);
427                 let arg_patterns = patterns(p_indices.zip(p_names), symbols.len());
428 
429                 let name_str = {
430                     let name_strs: Vec<_> = names.iter().map(AsRef::as_ref).collect();
431                     name_strs.join(", ")
432                 };
433                 let action = action.replace("<>", &name_str);
434                 r::ActionFnDefn {
435                     fallible,
436                     ret_type: nt_type,
437                     kind: r::ActionFnDefnKind::User(r::UserActionFnDefn {
438                         arg_patterns,
439                         arg_types,
440                         code: action,
441                     }),
442                 }
443             }
444         };
445 
446         self.add_action_fn(action_fn_defn)
447     }
448 
add_action_fn(&mut self, action_fn_defn: r::ActionFnDefn) -> r::ActionFn449     fn add_action_fn(&mut self, action_fn_defn: r::ActionFnDefn) -> r::ActionFn {
450         let index = r::ActionFn::new(self.action_fn_defns.len());
451         self.action_fn_defns.push(action_fn_defn);
452         index
453     }
454 
symbols(&mut self, symbols: &[pt::Symbol]) -> Vec<r::Symbol>455     fn symbols(&mut self, symbols: &[pt::Symbol]) -> Vec<r::Symbol> {
456         symbols.iter().map(|sym| self.symbol(sym)).collect()
457     }
458 
symbol(&mut self, symbol: &pt::Symbol) -> r::Symbol459     fn symbol(&mut self, symbol: &pt::Symbol) -> r::Symbol {
460         match symbol.kind {
461             pt::SymbolKind::Terminal(ref id) => r::Symbol::Terminal(id.clone()),
462             pt::SymbolKind::Nonterminal(ref id) => r::Symbol::Nonterminal(id.clone()),
463             pt::SymbolKind::Choose(ref s) | pt::SymbolKind::Name(_, ref s) => self.symbol(s),
464             pt::SymbolKind::Error => {
465                 self.uses_error_recovery = true;
466                 r::Symbol::Terminal(TerminalString::Error)
467             }
468 
469             pt::SymbolKind::Macro(..)
470             | pt::SymbolKind::Repeat(..)
471             | pt::SymbolKind::Expr(..)
472             | pt::SymbolKind::AmbiguousId(_)
473             | pt::SymbolKind::Lookahead
474             | pt::SymbolKind::Lookbehind => unreachable!(
475                 "symbol `{}` should have been normalized away by now",
476                 symbol
477             ),
478         }
479     }
480 
fresh_name(&self, i: usize) -> Atom481     fn fresh_name(&self, i: usize) -> Atom {
482         Atom::from(format!("{}{}", self.prefix, i))
483     }
484 }
485 
patterns<I>(mut chosen: I, num_args: usize) -> Vec<Name> where I: Iterator<Item = (usize, Name)>,486 fn patterns<I>(mut chosen: I, num_args: usize) -> Vec<Name>
487 where
488     I: Iterator<Item = (usize, Name)>,
489 {
490     let blank = Atom::from("_");
491 
492     let mut next_chosen = chosen.next();
493 
494     let result = (0..num_args)
495         .map(|index| match next_chosen.clone() {
496             Some((chosen_index, ref chosen_name)) if chosen_index == index => {
497                 next_chosen = chosen.next();
498                 chosen_name.clone()
499             }
500             _ => Name::immut(blank.clone()),
501         })
502         .collect();
503 
504     debug_assert!(next_chosen.is_none());
505 
506     result
507 }
508 
cfg_active(session: &Session, nt: &pt::NonterminalData) -> bool509 fn cfg_active(session: &Session, nt: &pt::NonterminalData) -> bool {
510     let cfg_atom = Atom::from(CFG);
511     nt.annotations
512         .iter()
513         .filter(|ann| ann.id == cfg_atom)
514         .all(|ann| {
515             ann.arg.as_ref().map_or(false, |&(_, ref feature)| {
516                 session
517                     .features
518                     .as_ref()
519                     .map_or(false, |features| features.contains(feature))
520             })
521         })
522 }
523