mirror of
https://github.com/fluencelabs/lalrpop
synced 2025-03-16 17:00:53 +00:00
Make a general prefix we can use for later
This commit is contained in:
parent
5c71e53c6b
commit
fadd3f2c66
@ -13,6 +13,7 @@ pub use grammar::parse_tree::{NonterminalString, Span, TerminalString};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Grammar {
|
||||
pub prefix: String,
|
||||
pub action_fn_defns: Vec<ActionFnDefn>,
|
||||
pub productions: Map<NonterminalString, Vec<Production>>,
|
||||
pub conversions: Map<TerminalString, TerminalString>,
|
||||
@ -166,7 +167,8 @@ impl ActionFnDefn {
|
||||
}
|
||||
|
||||
impl Grammar {
|
||||
pub fn new(action_fn_defns: Vec<ActionFnDefn>,
|
||||
pub fn new(prefix: String,
|
||||
action_fn_defns: Vec<ActionFnDefn>,
|
||||
flat_productions: Vec<Production>,
|
||||
conversions: Vec<(TerminalString, TerminalString)>,
|
||||
types: Types)
|
||||
@ -180,6 +182,7 @@ impl Grammar {
|
||||
}
|
||||
|
||||
Grammar {
|
||||
prefix: prefix,
|
||||
action_fn_defns: action_fn_defns,
|
||||
productions: productions,
|
||||
conversions: conversions.into_iter().collect(),
|
||||
|
@ -13,11 +13,12 @@ use grammar::repr as r;
|
||||
mod test;
|
||||
|
||||
pub fn lower(grammar: pt::Grammar, types: r::Types) -> NormResult<r::Grammar> {
|
||||
let state = LowerState::new(types);
|
||||
let state = LowerState::new(types, &grammar);
|
||||
state.lower(grammar)
|
||||
}
|
||||
|
||||
struct LowerState {
|
||||
prefix: String,
|
||||
action_fn_defns: Vec<r::ActionFnDefn>,
|
||||
productions: Vec<r::Production>,
|
||||
conversions: Vec<(TerminalString, TerminalString)>,
|
||||
@ -25,8 +26,9 @@ struct LowerState {
|
||||
}
|
||||
|
||||
impl LowerState {
|
||||
fn new(types: r::Types) -> LowerState {
|
||||
fn new(types: r::Types, grammar: &pt::Grammar) -> LowerState {
|
||||
LowerState {
|
||||
prefix: find_prefix(&grammar),
|
||||
action_fn_defns: vec![],
|
||||
productions: vec![],
|
||||
conversions: vec![],
|
||||
@ -58,7 +60,8 @@ impl LowerState {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(r::Grammar::new(self.action_fn_defns,
|
||||
Ok(r::Grammar::new(self.prefix,
|
||||
self.action_fn_defns,
|
||||
self.productions,
|
||||
self.conversions,
|
||||
self.types))
|
||||
@ -101,7 +104,7 @@ impl LowerState {
|
||||
}
|
||||
Symbols::Anon(indices) => {
|
||||
let names: Vec<_> =
|
||||
(0..indices.len()).map(|i| fresh_name(i, &action)).collect();
|
||||
(0..indices.len()).map(|i| self.fresh_name(i)).collect();
|
||||
let arg_patterns =
|
||||
patterns(indices.iter().map(|&(index, _)| index)
|
||||
.zip(names.iter().cloned()),
|
||||
@ -141,6 +144,10 @@ impl LowerState {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fresh_name(&self, i: usize) -> InternedString {
|
||||
intern(&format!("{}{}", self.prefix, i))
|
||||
}
|
||||
}
|
||||
|
||||
fn patterns<I>(mut chosen: I, num_args: usize) -> Vec<InternedString>
|
||||
@ -168,18 +175,27 @@ fn patterns<I>(mut chosen: I, num_args: usize) -> Vec<InternedString>
|
||||
result
|
||||
}
|
||||
|
||||
fn fresh_name(counter: usize, action_str: &str) -> InternedString {
|
||||
let mut name = format!("__{}", counter);
|
||||
// Find a unique prefix like `__` or `___` that doesn't appear
|
||||
// anywhere in any action strings. Obviously this is stricter than
|
||||
// needed, since the action string might be like `print("__1")`, in
|
||||
// which case we'll detect a false conflict (or it might contain a
|
||||
// variable named `__1x`, etc). But so what.
|
||||
fn find_prefix(grammar: &pt::Grammar) -> String {
|
||||
let mut prefix = format!("__");
|
||||
|
||||
// Check whether this string appears anywhere in the action. If
|
||||
// so, keep appending an underscore until it doesn't. :) Obviously
|
||||
// this is stricter than needed, since the action string might be
|
||||
// like `print("__1")`, in which case we'll detect a false
|
||||
// conflict (or it might contain a variable named `__1x`,
|
||||
// etc). But so what.
|
||||
while action_str.contains(&name) {
|
||||
name.push('_');
|
||||
while
|
||||
grammar.items
|
||||
.iter()
|
||||
.filter_map(|i| match *i {
|
||||
pt::GrammarItem::TokenType(_) => None,
|
||||
pt::GrammarItem::Nonterminal(ref nt) => Some(nt),
|
||||
})
|
||||
.flat_map(|nt| nt.alternatives.iter())
|
||||
.filter_map(|alt| alt.action.as_ref())
|
||||
.any(|s| s.contains(&prefix))
|
||||
{
|
||||
prefix.push('_');
|
||||
}
|
||||
|
||||
intern(&name)
|
||||
prefix
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user