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