diff --git a/lalrpop/src/build/action.rs b/lalrpop/src/build/action.rs index 9a9ed79..1f72955 100644 --- a/lalrpop/src/build/action.rs +++ b/lalrpop/src/build/action.rs @@ -89,6 +89,8 @@ fn emit_user_action_code( // a (L, T, L) triple where the Ls are locations and // the T is the data. Ignore the locations and bind // the data to the name the user gave. + + // NEXTCOMMITFIXME let mut arguments: Vec = data .arg_patterns .iter() @@ -98,7 +100,11 @@ fn emit_user_action_code( .cloned() .map(|t| grammar.types.spanned_type(t)), ) - .map(|(p, t)| format!("(_, {}, _): {}", p, t)) + .map(|(p, t)| format!("(_, {} {}, _): {}", + if p.0 { "mut" } else { "" }, + p.1, + t) + ) .collect(); // If this is a reduce of an empty production, we will diff --git a/lalrpop/src/grammar/parse_tree.rs b/lalrpop/src/grammar/parse_tree.rs index 411f4a7..8c86222 100644 --- a/lalrpop/src/grammar/parse_tree.rs +++ b/lalrpop/src/grammar/parse_tree.rs @@ -446,8 +446,8 @@ pub enum SymbolKind { // Choose(Box), - // x:X - Name(Atom, Box), + // or + Name(bool, Atom, Box), // @L Lookahead, @@ -902,6 +902,7 @@ impl Display for Symbol { impl Display for SymbolKind { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { match *self { + // NEXTCOMMITFIXME SymbolKind::Expr(ref expr) => write!(fmt, "{}", expr), SymbolKind::Terminal(ref s) => write!(fmt, "{}", s), SymbolKind::Nonterminal(ref s) => write!(fmt, "{}", s), @@ -909,7 +910,8 @@ impl Display for SymbolKind { SymbolKind::Macro(ref m) => write!(fmt, "{}", m), SymbolKind::Repeat(ref r) => write!(fmt, "{}", r), SymbolKind::Choose(ref s) => write!(fmt, "<{}>", s), - SymbolKind::Name(ref n, ref s) => write!(fmt, "{}:{}", n, s), + SymbolKind::Name(m, ref n, ref s) => + write!(fmt, "{} {}:{}", if m { "mut" } else { "" }, n, s), SymbolKind::Lookahead => write!(fmt, "@L"), SymbolKind::Lookbehind => write!(fmt, "@R"), SymbolKind::Error => write!(fmt, "error"), diff --git a/lalrpop/src/grammar/repr.rs b/lalrpop/src/grammar/repr.rs index bd932e4..075caee 100644 --- a/lalrpop/src/grammar/repr.rs +++ b/lalrpop/src/grammar/repr.rs @@ -144,7 +144,7 @@ pub enum ActionFnDefnKind { /// An action fn written by a user. #[derive(Clone, PartialEq, Eq)] pub struct UserActionFnDefn { - pub arg_patterns: Vec, + pub arg_patterns: Vec<(bool, Atom)>, pub arg_types: Vec, pub code: String, } @@ -663,11 +663,12 @@ impl ActionFnDefn { impl UserActionFnDefn { fn to_fn_string(&self, defn: &ActionFnDefn, name: &str) -> String { + //NEXTCOMMITFIXME let arg_strings: Vec = self .arg_patterns .iter() .zip(self.arg_types.iter()) - .map(|(p, t)| format!("{}: {}", p, t)) + .map(|(p, t)| format!("{}{}: {}", if p.0 { "mut " } else { "" }, p.1, t)) .collect(); format!( diff --git a/lalrpop/src/normalize/lower/mod.rs b/lalrpop/src/normalize/lower/mod.rs index 8535216..1c93fa7 100644 --- a/lalrpop/src/normalize/lower/mod.rs +++ b/lalrpop/src/normalize/lower/mod.rs @@ -366,10 +366,11 @@ impl<'s> LowerState<'s> { Symbols::Named(names) => { // if there are named symbols, we want to give the // arguments the names that the user gave them: +//NEXTCOMMITFIXME let arg_patterns = patterns( names .iter() - .map(|&(index, ref name, _)| (index, name.clone())), + .map(|&(index, mutable, ref name, _)| (index, (mutable, name.clone()))), symbols.len(), ); @@ -377,10 +378,11 @@ impl<'s> LowerState<'s> { match norm_util::check_between_braces(&action) { norm_util::Presence::None => action, norm_util::Presence::Normal => { +//NEXTCOMMITFIXME let name_str: String = { let name_strs: Vec<_> = names .iter() - .map(|&(_, ref name, _)| name.as_ref()) + .map(|&(_, _, ref name, _)| name.as_ref()) .collect(); name_strs.join(", ") }; @@ -388,9 +390,10 @@ impl<'s> LowerState<'s> { } norm_util::Presence::InCurlyBrackets => { let name_str = { +//NEXTCOMMITFIXME let name_strs: Vec<_> = names .iter() - .map(|&(_, ref name, _)| format!("{0}:{0}", &*name)) + .map(|&(_, _, ref name, _)| format!("{0}:{0}", &*name)) .collect(); name_strs.join(", ") }; @@ -411,11 +414,12 @@ impl<'s> LowerState<'s> { } Symbols::Anon(indices) => { let names: Vec<_> = (0..indices.len()).map(|i| self.fresh_name(i)).collect(); +//NEXTCOMMITFIXME let arg_patterns = patterns( indices .iter() .map(|&(index, _)| index) - .zip(names.iter().cloned()), + .zip(names.iter().cloned().map(|n| (false, n))), symbols.len(), ); let name_str = { @@ -452,7 +456,7 @@ impl<'s> LowerState<'s> { match symbol.kind { pt::SymbolKind::Terminal(ref id) => r::Symbol::Terminal(id.clone()), pt::SymbolKind::Nonterminal(ref id) => r::Symbol::Nonterminal(id.clone()), - pt::SymbolKind::Choose(ref s) | pt::SymbolKind::Name(_, ref s) => self.symbol(s), + pt::SymbolKind::Choose(ref s) | pt::SymbolKind::Name(_, _, ref s) => self.symbol(s), pt::SymbolKind::Error => { self.uses_error_recovery = true; r::Symbol::Terminal(TerminalString::Error) @@ -475,21 +479,22 @@ impl<'s> LowerState<'s> { } } -fn patterns(mut chosen: I, num_args: usize) -> Vec -where - I: Iterator, +//NEXTCOMMITFIXME +fn patterns(mut chosen: I, num_args: usize) -> Vec<(bool, Atom)> + where I: Iterator { let blank = Atom::from("_"); let mut next_chosen = chosen.next(); let result = (0..num_args) +//NEXTCOMMITFIXME .map(|index| match next_chosen.clone() { - Some((chosen_index, ref chosen_name)) if chosen_index == index => { + Some((chosen_index, (mutable, ref chosen_name))) if chosen_index == index => { next_chosen = chosen.next(); - chosen_name.clone() + (mutable, chosen_name.clone()) } - _ => blank.clone(), + _ => (false, blank.clone()), }) .collect(); diff --git a/lalrpop/src/normalize/macro_expand/mod.rs b/lalrpop/src/normalize/macro_expand/mod.rs index dce0578..6abeb9e 100644 --- a/lalrpop/src/normalize/macro_expand/mod.rs +++ b/lalrpop/src/normalize/macro_expand/mod.rs @@ -136,7 +136,8 @@ impl MacroExpander { SymbolKind::Terminal(_) | SymbolKind::Nonterminal(_) | SymbolKind::Error => { return; } - SymbolKind::Choose(ref mut sym) | SymbolKind::Name(_, ref mut sym) => { +//FIXNEXTCOMMIT + SymbolKind::Choose(ref mut sym) | SymbolKind::Name(_, _, ref mut sym) => { self.replace_symbol(sym); return; } @@ -344,6 +345,7 @@ impl MacroExpander { symbol: &Symbol, ) -> Symbol { let kind = match symbol.kind { +//NEXTCOMMITFIXME SymbolKind::Expr(ref expr) => { SymbolKind::Expr(self.macro_expand_expr_symbol(args, expr)) } @@ -363,8 +365,8 @@ impl MacroExpander { SymbolKind::Choose(ref sym) => { SymbolKind::Choose(Box::new(self.macro_expand_symbol(args, sym))) } - SymbolKind::Name(ref id, ref sym) => { - SymbolKind::Name(id.clone(), Box::new(self.macro_expand_symbol(args, sym))) + SymbolKind::Name(mutable, ref id, ref sym) => { + SymbolKind::Name(mutable, id.clone(), Box::new(self.macro_expand_symbol(args, sym))) } SymbolKind::Lookahead => SymbolKind::Lookahead, SymbolKind::Lookbehind => SymbolKind::Lookbehind, @@ -386,10 +388,11 @@ impl MacroExpander { fn expand_expr_symbol(&mut self, span: Span, expr: ExprSymbol) -> NormResult { let name = NonterminalString(Atom::from(expr.canonical_form())); +//NEXTCOMMITFIXME let ty_ref = match norm_util::analyze_expr(&expr) { Symbols::Named(names) => { - let (_, ref ex_id, ex_sym) = names[0]; + let (_, _, ref ex_id, ex_sym) = names[0]; return_err!( span, "named symbols like `{}:{}` are only allowed at the top-level of a nonterminal", @@ -464,9 +467,11 @@ impl MacroExpander { Alternative { span, expr: ExprSymbol { +//NEXTCOMMITFIXME symbols: vec![Symbol::new( span, SymbolKind::Name( + false, v, Box::new(Symbol::new( span, @@ -511,9 +516,11 @@ impl MacroExpander { span, expr: ExprSymbol { symbols: vec![ +//NEXTCOMMITFIXME Symbol::new( span, SymbolKind::Name( + true, v, Box::new(Symbol::new( span, @@ -523,7 +530,7 @@ impl MacroExpander { ), Symbol::new( span, - SymbolKind::Name(e, Box::new(repeat.symbol.clone())), + SymbolKind::Name(false, e, Box::new(repeat.symbol.clone())), ), ], }, diff --git a/lalrpop/src/normalize/macro_expand/test.rs b/lalrpop/src/normalize/macro_expand/test.rs index d8f2521..73bc2fd 100644 --- a/lalrpop/src/normalize/macro_expand/test.rs +++ b/lalrpop/src/normalize/macro_expand/test.rs @@ -46,7 +46,7 @@ grammar; `(<"Id"> ",")+`: ::std::vec::Vec<#`(<"Id"> ",")`#> = { `(<"Id"> ",")` => vec![<>], - ",")+`> ",")`> => { let mut v = v; v.push(e); v }, + ",")+`> ",")`> => { v.push(e); v }, }; "##, ) diff --git a/lalrpop/src/normalize/norm_util.rs b/lalrpop/src/normalize/norm_util.rs index 974ae45..3799373 100644 --- a/lalrpop/src/normalize/norm_util.rs +++ b/lalrpop/src/normalize/norm_util.rs @@ -9,7 +9,7 @@ pub enum AlternativeAction<'a> { #[derive(Debug)] pub enum Symbols<'a> { - Named(Vec<(usize, Atom, &'a Symbol)>), + Named(Vec<(usize, bool, Atom, &'a Symbol)>), Anon(Vec<(usize, &'a Symbol)>), } @@ -24,12 +24,13 @@ pub fn analyze_action(alt: &Alternative) -> AlternativeAction<'_> { pub fn analyze_expr(expr: &ExprSymbol) -> Symbols<'_> { // First look for named symbols. +//NEXTCOMMITFIXME let named_symbols: Vec<_> = expr .symbols .iter() .enumerate() .filter_map(|(idx, sym)| match sym.kind { - SymbolKind::Name(ref id, ref sub) => Some((idx, id.clone(), &**sub)), + SymbolKind::Name(mutable, ref id, ref sub) => Some((idx, mutable, id.clone(), &**sub)), _ => None, }) .collect(); diff --git a/lalrpop/src/normalize/prevalidate/mod.rs b/lalrpop/src/normalize/prevalidate/mod.rs index 9888288..223c418 100644 --- a/lalrpop/src/normalize/prevalidate/mod.rs +++ b/lalrpop/src/normalize/prevalidate/mod.rs @@ -184,7 +184,8 @@ impl<'grammar> Validator<'grammar> { match norm_util::analyze_expr(&alternative.expr) { Symbols::Named(syms) => { if alternative.action.is_none() { - let sym = syms.iter().map(|&(_, _, sym)| sym).next().unwrap(); +//NEXTCOMMITFIXME + let sym = syms.iter().map(|&(_, _, _, sym)| sym).next().unwrap(); return_err!( sym.span, "named symbols (like `{}`) require a custom action", @@ -226,11 +227,12 @@ impl<'grammar> Validator<'grammar> { }) .collect(); +//NEXTCOMMITFIXME let named: Multimap> = expr .symbols .iter() .filter_map(|sym| match sym.kind { - SymbolKind::Name(ref nt, _) => Some((nt.clone(), sym)), + SymbolKind::Name(_, ref nt, _) => Some((nt.clone(), sym)), _ => None, }) .collect(); @@ -284,7 +286,8 @@ impl<'grammar> Validator<'grammar> { SymbolKind::Repeat(ref repeat) => { self.validate_symbol(&repeat.symbol)?; } - SymbolKind::Choose(ref sym) | SymbolKind::Name(_, ref sym) => { +//NEXTCOMMITFIXME + SymbolKind::Choose(ref sym) | SymbolKind::Name(_, _, ref sym) => { self.validate_symbol(sym)?; } SymbolKind::Lookahead | SymbolKind::Lookbehind => { diff --git a/lalrpop/src/normalize/resolve/mod.rs b/lalrpop/src/normalize/resolve/mod.rs index 4b59764..c7ecf3e 100644 --- a/lalrpop/src/normalize/resolve/mod.rs +++ b/lalrpop/src/normalize/resolve/mod.rs @@ -252,7 +252,8 @@ impl Validator { SymbolKind::Repeat(ref mut repeat) => { self.validate_symbol(scope, &mut repeat.symbol)?; } - SymbolKind::Choose(ref mut sym) | SymbolKind::Name(_, ref mut sym) => { +//NEXTCOMMITFIXME + SymbolKind::Choose(ref mut sym) | SymbolKind::Name(_, _, ref mut sym) => { self.validate_symbol(scope, sym)?; } SymbolKind::Lookahead | SymbolKind::Lookbehind | SymbolKind::Error => {} diff --git a/lalrpop/src/normalize/token_check/mod.rs b/lalrpop/src/normalize/token_check/mod.rs index d5338de..a8fe6d9 100644 --- a/lalrpop/src/normalize/token_check/mod.rs +++ b/lalrpop/src/normalize/token_check/mod.rs @@ -249,9 +249,13 @@ impl<'grammar> Validator<'grammar> { SymbolKind::Repeat(ref repeat) => { self.validate_symbol(&repeat.symbol)?; } - SymbolKind::Choose(ref sym) | SymbolKind::Name(_, ref sym) => { + SymbolKind::Choose(ref sym) | SymbolKind::Name(_, _, ref sym) => { self.validate_symbol(sym)?; } + SymbolKind::Choose(ref sym) | + SymbolKind::Name(_, _, ref sym) => { + try!(self.validate_symbol(sym)); + } SymbolKind::Lookahead | SymbolKind::Lookbehind | SymbolKind::Error => {} SymbolKind::AmbiguousId(ref id) => { panic!("ambiguous id `{}` encountered after name resolution", id) diff --git a/lalrpop/src/normalize/tyinfer/mod.rs b/lalrpop/src/normalize/tyinfer/mod.rs index 9155981..e965ba2 100644 --- a/lalrpop/src/normalize/tyinfer/mod.rs +++ b/lalrpop/src/normalize/tyinfer/mod.rs @@ -355,7 +355,7 @@ impl<'grammar> TypeInferencer<'grammar> { SymbolKind::Terminal(ref id) => Ok(self.types.terminal_type(id).clone()), SymbolKind::Nonterminal(ref id) => self.nonterminal_type(id), SymbolKind::Choose(ref s) => self.symbol_type(&s.kind), - SymbolKind::Name(_, ref s) => self.symbol_type(&s.kind), + SymbolKind::Name(_, _, ref s) => self.symbol_type(&s.kind), SymbolKind::Error => Ok(self.types.error_recovery_type().clone()), SymbolKind::Repeat(..) diff --git a/lalrpop/src/parser/lrgrammar.lalrpop b/lalrpop/src/parser/lrgrammar.lalrpop index e658252..9fffa3a 100644 --- a/lalrpop/src/parser/lrgrammar.lalrpop +++ b/lalrpop/src/parser/lrgrammar.lalrpop @@ -7,7 +7,7 @@ use util::strip; use lalrpop_util::ParseError; use super::Top; - +//do grammar<'input>(text: &'input str); pub Top: Top = { @@ -187,8 +187,8 @@ ExprSymbol: ExprSymbol = Symbol* => ExprSymbol { symbols: <> }; Symbol: Symbol = { - "<" @L ":" ">" => - Symbol::new(Span(lo, hi), SymbolKind::Name(l, Box::new(s))), + "<" @L ":" ">" => + Symbol::new(Span(lo, hi), SymbolKind::Name(m.is_some(), l, Box::new(s))), "<" ">" => Symbol::new(Span(lo, hi), SymbolKind::Choose(Box::new(s))),