Allow <mut name:E> in patterns

This commit is contained in:
CreepySkeleton 2019-07-13 19:30:32 +03:00
parent 2bd51e0888
commit 14eeff42a5
20 changed files with 5604 additions and 5380 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
target target
*~ *~
TAGS TAGS
**/*.bak

View File

@ -7,11 +7,7 @@ grammar;
pub Items: Vec<(usize, usize)> = { pub Items: Vec<(usize, usize)> = {
<@L> <@R> => vec![(<>)], <@L> <@R> => vec![(<>)],
<v:Items> <e:Spanned<"+">> => { <mut v:Items> <e:Spanned<"+">> => { v.push(e); v },
let mut v = v;
v.push(e);
v
},
<v:Items> "-" => v <v:Items> "-" => v
}; };

View File

@ -78,6 +78,10 @@ lalrpop_mod!(loc);
lalrpop_mod!(loc_issue_90); lalrpop_mod!(loc_issue_90);
mod loc_issue_90_lib; mod loc_issue_90_lib;
/// tests that user can use `<mut v:E+> <e:T> => { v.push(e); v }` instead of
/// `<v:E+> <e:T> => { let mut v = v; v.push(e); v }`
lalrpop_mod!(mut_name);
/// test that uses `super` in paths in various places /// test that uses `super` in paths in various places
lalrpop_mod!(use_super); lalrpop_mod!(use_super);
@ -134,6 +138,7 @@ lalrpop_mod!(
lalrpop_mod!( lalrpop_mod!(
#[deny(bare_trait_objects)] #[deny(bare_trait_objects)]
#[allow(unused)]
dyn_argument dyn_argument
); );
@ -886,6 +891,14 @@ fn test_match_alternatives() {
); );
} }
#[test]
fn test_mut_name() {
assert_eq!(
mut_name::MutParser::new().parse("1, 2, 3: 4"),
Ok(vec![1, 2, 3, 4])
);
}
#[test] #[test]
fn issue_113() { fn issue_113() {
assert!(error_issue_113::ItemsParser::new().parse("+").is_err()); assert!(error_issue_113::ItemsParser::new().parse("+").is_err());
@ -938,7 +951,7 @@ fn verify_lalrpop_generates_itself() {
let copied_grammar_file = Path::new(out_dir).join(lrgrammar); let copied_grammar_file = Path::new(out_dir).join(lrgrammar);
// Don't remove the .rs file that already exist // Don't remove the .rs file that already exist
fs::copy(&grammar_file, &copied_grammar_file).unwrap(); fs::copy(&grammar_file, &copied_grammar_file).expect("no grammar file found");
assert!(Command::new("../target/debug/lalrpop") assert!(Command::new("../target/debug/lalrpop")
.args(&[ .args(&[
@ -951,7 +964,7 @@ fn verify_lalrpop_generates_itself() {
.expect("grammar path is not UTF-8") .expect("grammar path is not UTF-8")
]) ])
.status() .status()
.unwrap() .expect("lalrpop run failed")
.success()); .success());
let actual = fs::read_to_string(grammar_file.with_extension("rs")).unwrap(); let actual = fs::read_to_string(grammar_file.with_extension("rs")).unwrap();

View File

@ -14,11 +14,7 @@ extern {
pub Items: Vec<(usize, usize)> = { pub Items: Vec<(usize, usize)> = {
<@L> <@R> => vec![(<>)], <@L> <@R> => vec![(<>)],
<v:Items> <e:Spanned<"+">> => { <mut v:Items> <e:Spanned<"+">> => { v.push(e); v },
let mut v = v;
v.push(e);
v
},
<v:Items> "-" => v <v:Items> "-" => v
}; };

View File

@ -0,0 +1,11 @@
grammar;
Comma<T>: Vec<T> = {
<mut v: (<T> ",")*> <e:T> => { v.push(e); v }
}
pub Mut: Vec<i32> = {
<mut vect:Comma<Num>> ":" <e:Num> => { vect.push(e); vect }
}
Num: i32 = r"[0-9]+" => <>.parse().unwrap();

View File

@ -24,7 +24,7 @@ fn find_lalrpop_binary(prefix: &str) -> Option<PathBuf> {
} }
} }
fn main_() -> Result<(), Box<Error>> { fn main_() -> Result<(), Box<dyn Error>> {
let grammar_file = "src/parser/lrgrammar.lalrpop"; let grammar_file = "src/parser/lrgrammar.lalrpop";
println!(r#"cargo:rerun-if-changed={}"#, grammar_file); println!(r#"cargo:rerun-if-changed={}"#, grammar_file);

View File

@ -89,8 +89,6 @@ fn emit_user_action_code<W: Write>(
// a (L, T, L) triple where the Ls are locations and // a (L, T, L) triple where the Ls are locations and
// the T is the data. Ignore the locations and bind // the T is the data. Ignore the locations and bind
// the data to the name the user gave. // the data to the name the user gave.
// NEXTCOMMITFIXME
let mut arguments: Vec<String> = data let mut arguments: Vec<String> = data
.arg_patterns .arg_patterns
.iter() .iter()
@ -100,11 +98,7 @@ fn emit_user_action_code<W: Write>(
.cloned() .cloned()
.map(|t| grammar.types.spanned_type(t)), .map(|t| grammar.types.spanned_type(t)),
) )
.map(|(p, t)| format!("(_, {} {}, _): {}", .map(|(name, ty)| format!("(_, {}, _): {}", name, ty))
if p.0 { "mut" } else { "" },
p.1,
t)
)
.collect(); .collect();
// If this is a reduce of an empty production, we will // If this is a reduce of an empty production, we will

View File

@ -447,7 +447,7 @@ pub enum SymbolKind {
Choose(Box<Symbol>), Choose(Box<Symbol>),
// <x:X> or <mut x:X> // <x:X> or <mut x:X>
Name(bool, Atom, Box<Symbol>), Name(Name, Box<Symbol>),
// @L // @L
Lookahead, Lookahead,
@ -458,6 +458,12 @@ pub enum SymbolKind {
Error, Error,
} }
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Name {
pub mutable: bool,
pub name: Atom,
}
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum TerminalString { pub enum TerminalString {
Literal(TerminalLiteral), Literal(TerminalLiteral),
@ -692,6 +698,16 @@ impl Symbol {
} }
} }
impl Name {
pub fn new(mutable: bool, name: Atom) -> Self {
Name { mutable, name }
}
pub fn immut(name: Atom) -> Self {
Name::new(false, name)
}
}
impl Display for Visibility { impl Display for Visibility {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self { match *self {
@ -902,7 +918,6 @@ impl Display for Symbol {
impl Display for SymbolKind { impl Display for SymbolKind {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self { match *self {
// NEXTCOMMITFIXME
SymbolKind::Expr(ref expr) => write!(fmt, "{}", expr), SymbolKind::Expr(ref expr) => write!(fmt, "{}", expr),
SymbolKind::Terminal(ref s) => write!(fmt, "{}", s), SymbolKind::Terminal(ref s) => write!(fmt, "{}", s),
SymbolKind::Nonterminal(ref s) => write!(fmt, "{}", s), SymbolKind::Nonterminal(ref s) => write!(fmt, "{}", s),
@ -910,8 +925,7 @@ impl Display for SymbolKind {
SymbolKind::Macro(ref m) => write!(fmt, "{}", m), SymbolKind::Macro(ref m) => write!(fmt, "{}", m),
SymbolKind::Repeat(ref r) => write!(fmt, "{}", r), SymbolKind::Repeat(ref r) => write!(fmt, "{}", r),
SymbolKind::Choose(ref s) => write!(fmt, "<{}>", s), SymbolKind::Choose(ref s) => write!(fmt, "<{}>", s),
SymbolKind::Name(m, ref n, ref s) => SymbolKind::Name(ref n, ref s) => write!(fmt, "{}:{}", n, s),
write!(fmt, "{} {}:{}", if m { "mut" } else { "" }, n, s),
SymbolKind::Lookahead => write!(fmt, "@L"), SymbolKind::Lookahead => write!(fmt, "@L"),
SymbolKind::Lookbehind => write!(fmt, "@R"), SymbolKind::Lookbehind => write!(fmt, "@R"),
SymbolKind::Error => write!(fmt, "error"), SymbolKind::Error => write!(fmt, "error"),
@ -919,6 +933,16 @@ impl Display for SymbolKind {
} }
} }
impl Display for Name {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
if self.mutable {
write!(fmt, "mut {}", self.name)
} else {
Display::fmt(&self.name, fmt)
}
}
}
impl Display for RepeatSymbol { impl Display for RepeatSymbol {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
write!(fmt, "{}{}", self.symbol, self.op) write!(fmt, "{}{}", self.symbol, self.op)

View File

@ -13,7 +13,7 @@ use util::Sep;
// These concepts we re-use wholesale // These concepts we re-use wholesale
pub use grammar::parse_tree::{ pub use grammar::parse_tree::{
Annotation, InternToken, Lifetime, NonterminalString, Path, Span, TerminalLiteral, Annotation, InternToken, Lifetime, NonterminalString, Path, Span, TerminalLiteral,
TerminalString, TypeBound, TypeParameter, Visibility, TerminalString, TypeBound, TypeParameter, Visibility, Name
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -144,7 +144,7 @@ pub enum ActionFnDefnKind {
/// An action fn written by a user. /// An action fn written by a user.
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub struct UserActionFnDefn { pub struct UserActionFnDefn {
pub arg_patterns: Vec<(bool, Atom)>, pub arg_patterns: Vec<Name>,
pub arg_types: Vec<TypeRepr>, pub arg_types: Vec<TypeRepr>,
pub code: String, pub code: String,
} }
@ -663,12 +663,11 @@ impl ActionFnDefn {
impl UserActionFnDefn { impl UserActionFnDefn {
fn to_fn_string(&self, defn: &ActionFnDefn, name: &str) -> String { fn to_fn_string(&self, defn: &ActionFnDefn, name: &str) -> String {
//NEXTCOMMITFIXME
let arg_strings: Vec<String> = self let arg_strings: Vec<String> = self
.arg_patterns .arg_patterns
.iter() .iter()
.zip(self.arg_types.iter()) .zip(self.arg_types.iter())
.map(|(p, t)| format!("{}{}: {}", if p.0 { "mut " } else { "" }, p.1, t)) .map(|(name, ty)| format!("{}: {}", name, ty))
.collect(); .collect();
format!( format!(

View File

@ -61,8 +61,11 @@ pub trait Content: Debug {
/// those with `op`, appending the final result into `wrap_items`. /// those with `op`, appending the final result into `wrap_items`.
/// Useful for "modifier" content items like `Styled` that do not /// Useful for "modifier" content items like `Styled` that do not
/// affect wrapping. /// affect wrapping.
fn into_wrap_items_map<OP, C>(content: Box<dyn Content>, wrap_items: &mut Vec<Box<dyn Content>>, op: OP) fn into_wrap_items_map<OP, C>(
where content: Box<dyn Content>,
wrap_items: &mut Vec<Box<dyn Content>>,
op: OP,
) where
OP: FnMut(Box<dyn Content>) -> C, OP: FnMut(Box<dyn Content>) -> C,
C: Content + 'static, C: Content + 'static,
{ {

View File

@ -5,7 +5,7 @@ use collections::{map, Map};
use grammar::consts::CFG; use grammar::consts::CFG;
use grammar::parse_tree as pt; use grammar::parse_tree as pt;
use grammar::parse_tree::{ use grammar::parse_tree::{
read_algorithm, GrammarItem, InternToken, Lifetime, NonterminalString, Path, TerminalString, read_algorithm, GrammarItem, InternToken, Lifetime, NonterminalString, Path, TerminalString, Name
}; };
use grammar::pattern::{Pattern, PatternKind}; use grammar::pattern::{Pattern, PatternKind};
use grammar::repr as r; use grammar::repr as r;
@ -366,11 +366,11 @@ impl<'s> LowerState<'s> {
Symbols::Named(names) => { Symbols::Named(names) => {
// if there are named symbols, we want to give the // if there are named symbols, we want to give the
// arguments the names that the user gave them: // arguments the names that the user gave them:
//NEXTCOMMITFIXME let arg_names = names
let arg_patterns = patterns(
names
.iter() .iter()
.map(|&(index, mutable, ref name, _)| (index, (mutable, name.clone()))), .map(|(index, name, _)| (*index, name.clone()));
let arg_patterns = patterns(
arg_names,
symbols.len(), symbols.len(),
); );
@ -378,11 +378,10 @@ impl<'s> LowerState<'s> {
match norm_util::check_between_braces(&action) { match norm_util::check_between_braces(&action) {
norm_util::Presence::None => action, norm_util::Presence::None => action,
norm_util::Presence::Normal => { norm_util::Presence::Normal => {
//NEXTCOMMITFIXME
let name_str: String = { let name_str: String = {
let name_strs: Vec<_> = names let name_strs: Vec<_> = names
.iter() .iter()
.map(|&(_, _, ref name, _)| name.as_ref()) .map(|&(_, ref name, _)| name.name.as_ref())
.collect(); .collect();
name_strs.join(", ") name_strs.join(", ")
}; };
@ -390,10 +389,9 @@ impl<'s> LowerState<'s> {
} }
norm_util::Presence::InCurlyBrackets => { norm_util::Presence::InCurlyBrackets => {
let name_str = { let name_str = {
//NEXTCOMMITFIXME
let name_strs: Vec<_> = names let name_strs: Vec<_> = names
.iter() .iter()
.map(|&(_, _, ref name, _)| format!("{0}:{0}", &*name)) .map(|&(_, ref name, _)| format!("{0}:{0}", &*name.name))
.collect(); .collect();
name_strs.join(", ") name_strs.join(", ")
}; };
@ -414,14 +412,14 @@ impl<'s> LowerState<'s> {
} }
Symbols::Anon(indices) => { Symbols::Anon(indices) => {
let names: Vec<_> = (0..indices.len()).map(|i| self.fresh_name(i)).collect(); let names: Vec<_> = (0..indices.len()).map(|i| self.fresh_name(i)).collect();
//NEXTCOMMITFIXME
let p_indices = indices.iter().map(|&(index, _)| index);
let p_names = names.iter().cloned().map(Name::immut);
let arg_patterns = patterns( let arg_patterns = patterns(
indices p_indices.zip(p_names),
.iter()
.map(|&(index, _)| index)
.zip(names.iter().cloned().map(|n| (false, n))),
symbols.len(), symbols.len(),
); );
let name_str = { let name_str = {
let name_strs: Vec<_> = names.iter().map(AsRef::as_ref).collect(); let name_strs: Vec<_> = names.iter().map(AsRef::as_ref).collect();
name_strs.join(", ") name_strs.join(", ")
@ -456,7 +454,7 @@ impl<'s> LowerState<'s> {
match symbol.kind { match symbol.kind {
pt::SymbolKind::Terminal(ref id) => r::Symbol::Terminal(id.clone()), pt::SymbolKind::Terminal(ref id) => r::Symbol::Terminal(id.clone()),
pt::SymbolKind::Nonterminal(ref id) => r::Symbol::Nonterminal(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 => { pt::SymbolKind::Error => {
self.uses_error_recovery = true; self.uses_error_recovery = true;
r::Symbol::Terminal(TerminalString::Error) r::Symbol::Terminal(TerminalString::Error)
@ -479,22 +477,21 @@ impl<'s> LowerState<'s> {
} }
} }
//NEXTCOMMITFIXME fn patterns<I>(mut chosen: I, num_args: usize) -> Vec<Name>
fn patterns<I>(mut chosen: I, num_args: usize) -> Vec<(bool, Atom)> where
where I: Iterator<Item = (usize, (bool, Atom))> I: Iterator<Item = (usize, Name)>,
{ {
let blank = Atom::from("_"); let blank = Atom::from("_");
let mut next_chosen = chosen.next(); let mut next_chosen = chosen.next();
let result = (0..num_args) let result = (0..num_args)
//NEXTCOMMITFIXME
.map(|index| match next_chosen.clone() { .map(|index| match next_chosen.clone() {
Some((chosen_index, (mutable, ref chosen_name))) if chosen_index == index => { Some((chosen_index, ref chosen_name)) if chosen_index == index => {
next_chosen = chosen.next(); next_chosen = chosen.next();
(mutable, chosen_name.clone()) chosen_name.clone()
} }
_ => (false, blank.clone()), _ => Name::immut(blank.clone()),
}) })
.collect(); .collect();

View File

@ -1,8 +1,8 @@
use grammar::consts::INLINE; use grammar::consts::INLINE;
use grammar::parse_tree::{ use grammar::parse_tree::{
ActionKind, Alternative, Annotation, Condition, ConditionOp, ExprSymbol, Grammar, GrammarItem, ActionKind, Alternative, Annotation, Condition, ConditionOp, ExprSymbol, Grammar, GrammarItem,
MacroSymbol, NonterminalData, NonterminalString, Path, RepeatOp, RepeatSymbol, Span, Symbol, MacroSymbol, Name, NonterminalData, NonterminalString, Path, RepeatOp, RepeatSymbol, Span,
SymbolKind, TerminalLiteral, TerminalString, TypeRef, Visibility, Symbol, SymbolKind, TerminalLiteral, TerminalString, TypeRef, Visibility,
}; };
use normalize::norm_util::{self, Symbols}; use normalize::norm_util::{self, Symbols};
use normalize::resolve; use normalize::resolve;
@ -136,8 +136,7 @@ impl MacroExpander {
SymbolKind::Terminal(_) | SymbolKind::Nonterminal(_) | SymbolKind::Error => { SymbolKind::Terminal(_) | SymbolKind::Nonterminal(_) | SymbolKind::Error => {
return; return;
} }
//FIXNEXTCOMMIT SymbolKind::Choose(ref mut sym) | SymbolKind::Name(_, ref mut sym) => {
SymbolKind::Choose(ref mut sym) | SymbolKind::Name(_, _, ref mut sym) => {
self.replace_symbol(sym); self.replace_symbol(sym);
return; return;
} }
@ -345,7 +344,6 @@ impl MacroExpander {
symbol: &Symbol, symbol: &Symbol,
) -> Symbol { ) -> Symbol {
let kind = match symbol.kind { let kind = match symbol.kind {
//NEXTCOMMITFIXME
SymbolKind::Expr(ref expr) => { SymbolKind::Expr(ref expr) => {
SymbolKind::Expr(self.macro_expand_expr_symbol(args, expr)) SymbolKind::Expr(self.macro_expand_expr_symbol(args, expr))
} }
@ -365,9 +363,10 @@ impl MacroExpander {
SymbolKind::Choose(ref sym) => { SymbolKind::Choose(ref sym) => {
SymbolKind::Choose(Box::new(self.macro_expand_symbol(args, sym))) SymbolKind::Choose(Box::new(self.macro_expand_symbol(args, sym)))
} }
SymbolKind::Name(mutable, ref id, ref sym) => { SymbolKind::Name(ref id, ref sym) => SymbolKind::Name(
SymbolKind::Name(mutable, id.clone(), Box::new(self.macro_expand_symbol(args, sym))) Name::new(id.mutable, id.name.clone()),
} Box::new(self.macro_expand_symbol(args, sym)),
),
SymbolKind::Lookahead => SymbolKind::Lookahead, SymbolKind::Lookahead => SymbolKind::Lookahead,
SymbolKind::Lookbehind => SymbolKind::Lookbehind, SymbolKind::Lookbehind => SymbolKind::Lookbehind,
SymbolKind::Error => SymbolKind::Error, SymbolKind::Error => SymbolKind::Error,
@ -388,11 +387,10 @@ impl MacroExpander {
fn expand_expr_symbol(&mut self, span: Span, expr: ExprSymbol) -> NormResult<GrammarItem> { fn expand_expr_symbol(&mut self, span: Span, expr: ExprSymbol) -> NormResult<GrammarItem> {
let name = NonterminalString(Atom::from(expr.canonical_form())); let name = NonterminalString(Atom::from(expr.canonical_form()));
//NEXTCOMMITFIXME
let ty_ref = let ty_ref =
match norm_util::analyze_expr(&expr) { match norm_util::analyze_expr(&expr) {
Symbols::Named(names) => { Symbols::Named(names) => {
let (_, _, ref ex_id, ex_sym) = names[0]; let (_, ref ex_id, ex_sym) = names[0];
return_err!( return_err!(
span, span,
"named symbols like `{}:{}` are only allowed at the top-level of a nonterminal", "named symbols like `{}:{}` are only allowed at the top-level of a nonterminal",
@ -467,12 +465,10 @@ impl MacroExpander {
Alternative { Alternative {
span, span,
expr: ExprSymbol { expr: ExprSymbol {
//NEXTCOMMITFIXME
symbols: vec![Symbol::new( symbols: vec![Symbol::new(
span, span,
SymbolKind::Name( SymbolKind::Name(
false, Name::immut(v),
v,
Box::new(Symbol::new( Box::new(Symbol::new(
span, span,
SymbolKind::Repeat(plus_repeat), SymbolKind::Repeat(plus_repeat),
@ -516,12 +512,10 @@ impl MacroExpander {
span, span,
expr: ExprSymbol { expr: ExprSymbol {
symbols: vec![ symbols: vec![
//NEXTCOMMITFIXME
Symbol::new( Symbol::new(
span, span,
SymbolKind::Name( SymbolKind::Name(
true, Name::immut(v),
v,
Box::new(Symbol::new( Box::new(Symbol::new(
span, span,
SymbolKind::Nonterminal(name), SymbolKind::Nonterminal(name),
@ -530,7 +524,10 @@ impl MacroExpander {
), ),
Symbol::new( Symbol::new(
span, span,
SymbolKind::Name(false, e, Box::new(repeat.symbol.clone())), SymbolKind::Name(
Name::immut(e),
Box::new(repeat.symbol.clone()),
),
), ),
], ],
}, },

View File

@ -46,7 +46,7 @@ grammar;
`(<"Id"> ",")+`: ::std::vec::Vec<#`(<"Id"> ",")`#> = { `(<"Id"> ",")+`: ::std::vec::Vec<#`(<"Id"> ",")`#> = {
`(<"Id"> ",")` => vec![<>], `(<"Id"> ",")` => vec![<>],
<v:`(<"Id"> ",")+`> <e:`(<"Id"> ",")`> => { v.push(e); v }, <v:`(<"Id"> ",")+`> <e:`(<"Id"> ",")`> => { let mut v = v; v.push(e); v },
}; };
"##, "##,
) )

View File

@ -1,5 +1,4 @@
use grammar::parse_tree::{ActionKind, Alternative, ExprSymbol, Symbol, SymbolKind}; use grammar::parse_tree::{ActionKind, Alternative, ExprSymbol, Symbol, SymbolKind, Name};
use string_cache::DefaultAtom as Atom;
#[derive(Debug)] #[derive(Debug)]
pub enum AlternativeAction<'a> { pub enum AlternativeAction<'a> {
@ -9,7 +8,7 @@ pub enum AlternativeAction<'a> {
#[derive(Debug)] #[derive(Debug)]
pub enum Symbols<'a> { pub enum Symbols<'a> {
Named(Vec<(usize, bool, Atom, &'a Symbol)>), Named(Vec<(usize, Name, &'a Symbol)>),
Anon(Vec<(usize, &'a Symbol)>), Anon(Vec<(usize, &'a Symbol)>),
} }
@ -24,13 +23,12 @@ pub fn analyze_action(alt: &Alternative) -> AlternativeAction<'_> {
pub fn analyze_expr(expr: &ExprSymbol) -> Symbols<'_> { pub fn analyze_expr(expr: &ExprSymbol) -> Symbols<'_> {
// First look for named symbols. // First look for named symbols.
//NEXTCOMMITFIXME
let named_symbols: Vec<_> = expr let named_symbols: Vec<_> = expr
.symbols .symbols
.iter() .iter()
.enumerate() .enumerate()
.filter_map(|(idx, sym)| match sym.kind { .filter_map(|(idx, sym)| match sym.kind {
SymbolKind::Name(mutable, ref id, ref sub) => Some((idx, mutable, id.clone(), &**sub)), SymbolKind::Name(ref id, ref sub) => Some((idx, id.clone(), &**sub)),
_ => None, _ => None,
}) })
.collect(); .collect();

View File

@ -184,8 +184,7 @@ impl<'grammar> Validator<'grammar> {
match norm_util::analyze_expr(&alternative.expr) { match norm_util::analyze_expr(&alternative.expr) {
Symbols::Named(syms) => { Symbols::Named(syms) => {
if alternative.action.is_none() { if alternative.action.is_none() {
//NEXTCOMMITFIXME let sym = syms.iter().map(|&(_, _, sym)| sym).next().unwrap();
let sym = syms.iter().map(|&(_, _, _, sym)| sym).next().unwrap();
return_err!( return_err!(
sym.span, sym.span,
"named symbols (like `{}`) require a custom action", "named symbols (like `{}`) require a custom action",
@ -227,12 +226,11 @@ impl<'grammar> Validator<'grammar> {
}) })
.collect(); .collect();
//NEXTCOMMITFIXME
let named: Multimap<Atom, Vec<&Symbol>> = expr let named: Multimap<Atom, Vec<&Symbol>> = expr
.symbols .symbols
.iter() .iter()
.filter_map(|sym| match sym.kind { .filter_map(|sym| match sym.kind {
SymbolKind::Name(_, ref nt, _) => Some((nt.clone(), sym)), SymbolKind::Name(ref nt, _) => Some((nt.name.clone(), sym)),
_ => None, _ => None,
}) })
.collect(); .collect();
@ -286,8 +284,7 @@ impl<'grammar> Validator<'grammar> {
SymbolKind::Repeat(ref repeat) => { SymbolKind::Repeat(ref repeat) => {
self.validate_symbol(&repeat.symbol)?; self.validate_symbol(&repeat.symbol)?;
} }
//NEXTCOMMITFIXME SymbolKind::Choose(ref sym) | SymbolKind::Name(_, ref sym) => {
SymbolKind::Choose(ref sym) | SymbolKind::Name(_, _, ref sym) => {
self.validate_symbol(sym)?; self.validate_symbol(sym)?;
} }
SymbolKind::Lookahead | SymbolKind::Lookbehind => { SymbolKind::Lookahead | SymbolKind::Lookbehind => {

View File

@ -252,8 +252,7 @@ impl Validator {
SymbolKind::Repeat(ref mut repeat) => { SymbolKind::Repeat(ref mut repeat) => {
self.validate_symbol(scope, &mut repeat.symbol)?; self.validate_symbol(scope, &mut repeat.symbol)?;
} }
//NEXTCOMMITFIXME SymbolKind::Choose(ref mut sym) | SymbolKind::Name(_, ref mut sym) => {
SymbolKind::Choose(ref mut sym) | SymbolKind::Name(_, _, ref mut sym) => {
self.validate_symbol(scope, sym)?; self.validate_symbol(scope, sym)?;
} }
SymbolKind::Lookahead | SymbolKind::Lookbehind | SymbolKind::Error => {} SymbolKind::Lookahead | SymbolKind::Lookbehind | SymbolKind::Error => {}

View File

@ -249,13 +249,9 @@ impl<'grammar> Validator<'grammar> {
SymbolKind::Repeat(ref repeat) => { SymbolKind::Repeat(ref repeat) => {
self.validate_symbol(&repeat.symbol)?; 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)?; self.validate_symbol(sym)?;
} }
SymbolKind::Choose(ref sym) |
SymbolKind::Name(_, _, ref sym) => {
try!(self.validate_symbol(sym));
}
SymbolKind::Lookahead | SymbolKind::Lookbehind | SymbolKind::Error => {} SymbolKind::Lookahead | SymbolKind::Lookbehind | SymbolKind::Error => {}
SymbolKind::AmbiguousId(ref id) => { SymbolKind::AmbiguousId(ref id) => {
panic!("ambiguous id `{}` encountered after name resolution", id) panic!("ambiguous id `{}` encountered after name resolution", id)

View File

@ -355,7 +355,7 @@ impl<'grammar> TypeInferencer<'grammar> {
SymbolKind::Terminal(ref id) => Ok(self.types.terminal_type(id).clone()), SymbolKind::Terminal(ref id) => Ok(self.types.terminal_type(id).clone()),
SymbolKind::Nonterminal(ref id) => self.nonterminal_type(id), SymbolKind::Nonterminal(ref id) => self.nonterminal_type(id),
SymbolKind::Choose(ref s) => self.symbol_type(&s.kind), 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::Error => Ok(self.types.error_recovery_type().clone()),
SymbolKind::Repeat(..) SymbolKind::Repeat(..)

View File

@ -7,7 +7,7 @@ use util::strip;
use lalrpop_util::ParseError; use lalrpop_util::ParseError;
use super::Top; use super::Top;
//do
grammar<'input>(text: &'input str); grammar<'input>(text: &'input str);
pub Top: Top = { pub Top: Top = {
@ -81,13 +81,9 @@ TypeBoundParameter: TypeBoundParameter<TypeRef> = {
}; };
Plus<T>: Vec<T> = { Plus<T>: Vec<T> = {
<v:(<T> "+")*> <e:T?> => match e { <mut v:(<T> "+")*> <e:T?> => match e {
None => v, None => v,
Some(e) => { Some(e) => { v.push(e); v }
let mut v = v;
v.push(e);
v
}
} }
}; };
@ -188,7 +184,7 @@ ExprSymbol: ExprSymbol =
Symbol: Symbol = { Symbol: Symbol = {
<lo:@L> "<" <m:"mut"?> @L <l:Id> ":" <s:Symbol0> ">" <hi:@R> => <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))), Symbol::new(Span(lo, hi), SymbolKind::Name(Name::new(m.is_some(), l), Box::new(s))),
<lo:@L> "<" <s:Symbol0> ">" <hi:@R> => <lo:@L> "<" <s:Symbol0> ">" <hi:@R> =>
Symbol::new(Span(lo, hi), SymbolKind::Choose(Box::new(s))), Symbol::new(Span(lo, hi), SymbolKind::Choose(Box::new(s))),

File diff suppressed because it is too large Load Diff