mirror of
https://github.com/fluencelabs/lalrpop
synced 2025-03-16 17:00:53 +00:00
Add support for <mut x:X> allowing for mutable x in action code.
Fixes #136.
This commit is contained in:
parent
abbc3aff54
commit
2bd51e0888
@ -89,6 +89,8 @@ fn emit_user_action_code<W: Write>(
|
||||
// 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<String> = data
|
||||
.arg_patterns
|
||||
.iter()
|
||||
@ -98,7 +100,11 @@ fn emit_user_action_code<W: Write>(
|
||||
.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
|
||||
|
@ -446,8 +446,8 @@ pub enum SymbolKind {
|
||||
// <X>
|
||||
Choose(Box<Symbol>),
|
||||
|
||||
// x:X
|
||||
Name(Atom, Box<Symbol>),
|
||||
// <x:X> or <mut x:X>
|
||||
Name(bool, Atom, Box<Symbol>),
|
||||
|
||||
// @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"),
|
||||
|
@ -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<Atom>,
|
||||
pub arg_patterns: Vec<(bool, Atom)>,
|
||||
pub arg_types: Vec<TypeRepr>,
|
||||
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<String> = 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!(
|
||||
|
@ -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<I>(mut chosen: I, num_args: usize) -> Vec<Atom>
|
||||
where
|
||||
I: Iterator<Item = (usize, Atom)>,
|
||||
//NEXTCOMMITFIXME
|
||||
fn patterns<I>(mut chosen: I, num_args: usize) -> Vec<(bool, Atom)>
|
||||
where I: Iterator<Item = (usize, (bool, Atom))>
|
||||
{
|
||||
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();
|
||||
|
||||
|
@ -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<GrammarItem> {
|
||||
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())),
|
||||
),
|
||||
],
|
||||
},
|
||||
|
@ -46,7 +46,7 @@ grammar;
|
||||
|
||||
`(<"Id"> ",")+`: ::std::vec::Vec<#`(<"Id"> ",")`#> = {
|
||||
`(<"Id"> ",")` => vec![<>],
|
||||
<v:`(<"Id"> ",")+`> <e:`(<"Id"> ",")`> => { let mut v = v; v.push(e); v },
|
||||
<v:`(<"Id"> ",")+`> <e:`(<"Id"> ",")`> => { v.push(e); v },
|
||||
};
|
||||
"##,
|
||||
)
|
||||
|
@ -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();
|
||||
|
@ -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<Atom, Vec<&Symbol>> = 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 => {
|
||||
|
@ -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 => {}
|
||||
|
@ -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)
|
||||
|
@ -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(..)
|
||||
|
@ -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 = {
|
||||
<lo:@L> "<" @L <l:Id> ":" <s:Symbol0> ">" <hi:@R> =>
|
||||
Symbol::new(Span(lo, hi), SymbolKind::Name(l, Box::new(s))),
|
||||
<lo:@L> "<" <m:"mut"?> @L <l:Id> ":" <s:Symbol0> ">" <hi:@R> =>
|
||||
Symbol::new(Span(lo, hi), SymbolKind::Name(m.is_some(), l, Box::new(s))),
|
||||
|
||||
<lo:@L> "<" <s:Symbol0> ">" <hi:@R> =>
|
||||
Symbol::new(Span(lo, hi), SymbolKind::Choose(Box::new(s))),
|
||||
|
Loading…
x
Reference in New Issue
Block a user