Migrate from lalrpop-intern to string-cache.

Fixes #158.
This commit is contained in:
Ahmed Charles 2018-01-31 12:14:17 +00:00
parent 50fb8a5d74
commit 1a487a0ae6
54 changed files with 595 additions and 593 deletions

View File

@ -1,6 +1,6 @@
language: rust
rust:
- 1.18.0
- 1.20.0
- beta
- nightly
script:

View File

@ -26,6 +26,7 @@ regex = "0.2.1"
regex-syntax = "0.4.0"
petgraph = "0.4.4"
rustc-serialize = "0.3"
string_cache = "0.7.1"
term = "0.4.5"
unicode-xid = "0.0.4"
@ -36,10 +37,6 @@ rand = "0.3"
path = "../lalrpop-util"
version = "0.14.0" # LALRPOP
[dependencies.lalrpop-intern]
path = "../lalrpop-intern"
version = "0.14.0" # LALRPOP
[build-dependencies.lalrpop-snap]
path = "../lalrpop-snap"
version = "0.14.0" # LALRPOP

View File

@ -168,7 +168,7 @@ fn emit_inline_action_code<W: Write>(grammar: &r::Grammar,
.iter()
.flat_map(|sym| {
match *sym {
r::InlinedSymbol::Original(s) => vec![s],
r::InlinedSymbol::Original(ref s) => vec![s.clone()],
r::InlinedSymbol::Inlined(_, ref syms) => syms.clone(),
}
})

View File

@ -347,7 +347,7 @@ fn emit_recursive_ascent(session: &Session, grammar: &r::Grammar, report_file :
exit(1);
}
for (&user_nt, &start_nt) in &grammar.start_nonterminals {
for (user_nt, start_nt) in &grammar.start_nonterminals {
// We generate these, so there should always be exactly 1
// production. Otherwise the LR(1) algorithm doesn't know
// where to stop!
@ -360,7 +360,7 @@ fn emit_recursive_ascent(session: &Session, grammar: &r::Grammar, report_file :
let _lr1_tls = lr1::Lr1Tls::install(grammar.terminals.clone());
let lr1result = lr1::build_states(&grammar, start_nt);
let lr1result = lr1::build_states(&grammar, start_nt.clone());
if session.emit_report {
let mut output_report_file = try!(fs::File::create(&report_file));
try!(lr1::generate_report(&mut output_report_file, &lr1result));
@ -378,21 +378,25 @@ fn emit_recursive_ascent(session: &Session, grammar: &r::Grammar, report_file :
match grammar.algorithm.codegen {
r::LrCodeGeneration::RecursiveAscent =>
try!(lr1::codegen::ascent::compile(&grammar,
user_nt,
start_nt,
user_nt.clone(),
start_nt.clone(),
&states,
"super",
&mut rust)),
r::LrCodeGeneration::TableDriven =>
try!(lr1::codegen::parse_table::compile(&grammar,
user_nt,
start_nt,
user_nt.clone(),
start_nt.clone(),
&states,
"super",
&mut rust)),
r::LrCodeGeneration::TestAll =>
try!(lr1::codegen::test_all::compile(&grammar, user_nt, start_nt, &states, &mut rust)),
try!(lr1::codegen::test_all::compile(&grammar,
user_nt.clone(),
start_nt.clone(),
&states,
&mut rust)),
}
rust!(rust,

View File

@ -15,7 +15,7 @@ pub fn random_parse_tree(grammar: &Grammar, symbol: NonterminalString) -> ParseT
loop {
// sometimes, the random walk overflows the stack, so we have a max, and if
// it is exceeded, we just try again
if let Some(result) = gen.nonterminal(symbol) {
if let Some(result) = gen.nonterminal(symbol.clone()) {
return result;
}
gen.depth = 0;
@ -37,11 +37,11 @@ impl<'grammar> Generator<'grammar> {
}
self.depth += 1;
let productions = self.grammar.productions_for(nt);
let productions = self.grammar.productions_for(&nt);
let index: usize = self.rng.gen_range(0, productions.len());
let production = &productions[index];
let trees: Option<Vec<_>> = production.symbols.iter()
.map(|&sym| self.symbol(sym))
.map(|sym| self.symbol(sym.clone()))
.collect();
trees.map(|trees| ParseTree::Nonterminal(nt, trees))
}
@ -63,7 +63,7 @@ impl ParseTree {
fn push_terminals(&self, vec: &mut Vec<TerminalString>) {
match *self {
ParseTree::Terminal(s) => vec.push(s),
ParseTree::Terminal(ref s) => vec.push(s.clone()),
ParseTree::Nonterminal(_, ref trees) => {
for tree in trees {
tree.push_terminals(vec);

View File

@ -5,7 +5,7 @@ some pre-expansion and so forth before creating the proper AST.
*/
use intern::{intern, InternedString};
use string_cache::DefaultAtom as Atom;
use lexer::dfa::DFA;
use grammar::consts::{LALR, RECURSIVE_ASCENT, TABLE_DRIVEN, TEST_ALL};
use grammar::repr::{self as r, NominalTypeRepr, TypeRepr};
@ -171,7 +171,7 @@ pub struct ExternToken {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AssociatedType {
pub type_span: Span,
pub type_name: InternedString,
pub type_name: Atom,
pub type_ref: TypeRef,
}
@ -192,7 +192,7 @@ pub struct Conversion {
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Path {
pub absolute: bool,
pub ids: Vec<InternedString>,
pub ids: Vec<Atom>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@ -207,16 +207,16 @@ pub enum TypeRef {
},
Ref {
lifetime: Option<InternedString>,
lifetime: Option<Atom>,
mutable: bool,
referent: Box<TypeRef>,
},
// 'x ==> only should appear within nominal types, but what do we care
Lifetime(InternedString),
Lifetime(Atom),
// Foo or Bar ==> treated specially since macros may care
Id(InternedString),
Id(Atom),
// <N> ==> type of a nonterminal, emitted by macro expansion
OfSymbol(SymbolKind),
@ -226,12 +226,12 @@ pub enum TypeRef {
pub enum WhereClause<T> {
// 'a: 'b + 'c
Lifetime {
lifetime: InternedString,
bounds: Vec<InternedString>,
lifetime: Atom,
bounds: Vec<Atom>,
},
// where for<'a> &'a T: Debug + Into<usize>
Type {
forall: Option<Vec<InternedString>>,
forall: Option<Vec<Atom>>,
ty: T,
bounds: Vec<TypeBound<T>>,
}
@ -242,8 +242,8 @@ impl<T> WhereClause<T> {
where F: FnMut(&T) -> U
{
match *self {
WhereClause::Lifetime { lifetime, ref bounds } => WhereClause::Lifetime {
lifetime: lifetime,
WhereClause::Lifetime { ref lifetime, ref bounds } => WhereClause::Lifetime {
lifetime: lifetime.clone(),
bounds: bounds.clone(),
},
WhereClause::Type { ref forall, ref ty, ref bounds } => WhereClause::Type {
@ -258,10 +258,10 @@ impl<T> WhereClause<T> {
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum TypeBound<T> {
// The `'a` in `T: 'a`.
Lifetime(InternedString),
Lifetime(Atom),
// `for<'a> FnMut(&'a usize)`
Fn {
forall: Option<Vec<InternedString>>,
forall: Option<Vec<Atom>>,
path: Path,
parameters: Vec<T>,
ret: Option<T>,
@ -269,7 +269,7 @@ pub enum TypeBound<T> {
// `some::Trait` or `some::Trait<Param, ...>` or `some::Trait<Item = Assoc>`
// or `for<'a> Trait<'a, T>`
Trait {
forall: Option<Vec<InternedString>>,
forall: Option<Vec<Atom>>,
path: Path,
parameters: Vec<TypeBoundParameter<T>>,
}
@ -280,7 +280,7 @@ impl<T> TypeBound<T> {
where F: FnMut(&T) -> U
{
match *self {
TypeBound::Lifetime(l) => TypeBound::Lifetime(l),
TypeBound::Lifetime(ref l) => TypeBound::Lifetime(l.clone()),
TypeBound::Fn { ref forall, ref path, ref parameters, ref ret } => TypeBound::Fn {
forall: forall.clone(),
path: path.clone(),
@ -299,11 +299,11 @@ impl<T> TypeBound<T> {
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum TypeBoundParameter<T> {
// 'a
Lifetime(InternedString),
Lifetime(Atom),
// `T` or `'a`
TypeParameter(T),
// `Item = T`
Associated(InternedString, T),
Associated(Atom, T),
}
impl<T> TypeBoundParameter<T> {
@ -311,20 +311,20 @@ impl<T> TypeBoundParameter<T> {
where F: FnMut(&T) -> U
{
match *self {
TypeBoundParameter::Lifetime(l) =>
TypeBoundParameter::Lifetime(l),
TypeBoundParameter::Lifetime(ref l) =>
TypeBoundParameter::Lifetime(l.clone()),
TypeBoundParameter::TypeParameter(ref t) =>
TypeBoundParameter::TypeParameter(f(t)),
TypeBoundParameter::Associated(id, ref t) =>
TypeBoundParameter::Associated(id, f(t)),
TypeBoundParameter::Associated(ref id, ref t) =>
TypeBoundParameter::Associated(id.clone(), f(t)),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum TypeParameter {
Lifetime(InternedString),
Id(InternedString),
Lifetime(Atom),
Id(Atom),
}
impl TypeParameter {
@ -338,7 +338,7 @@ impl TypeParameter {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Parameter {
pub name: InternedString,
pub name: Atom,
pub ty: TypeRef,
}
@ -371,7 +371,7 @@ pub struct NonterminalData {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Annotation {
pub id_span: Span,
pub id: InternedString,
pub id: Atom,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@ -399,7 +399,7 @@ pub enum ActionKind {
pub struct Condition {
pub span: Span,
pub lhs: NonterminalString, // X
pub rhs: InternedString, // "Foo"
pub rhs: Atom, // "Foo"
pub op: ConditionOp,
}
@ -430,7 +430,7 @@ pub enum SymbolKind {
Expr(ExprSymbol),
// foo, before name resolution
AmbiguousId(InternedString),
AmbiguousId(Atom),
// "foo" and foo (after name resolution)
Terminal(TerminalString),
@ -448,7 +448,7 @@ pub enum SymbolKind {
Choose(Box<Symbol>),
// x:X
Name(InternedString, Box<Symbol>),
Name(Atom, Box<Symbol>),
// @L
Lookahead,
@ -459,34 +459,34 @@ pub enum SymbolKind {
Error
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum TerminalString {
Literal(TerminalLiteral),
Bare(InternedString),
Bare(Atom),
Error,
}
impl TerminalString {
pub fn as_literal(&self) -> Option<TerminalLiteral> {
match *self {
TerminalString::Literal(l) => Some(l),
TerminalString::Literal(ref l) => Some(l.clone()),
_ => None
}
}
pub fn display_len(&self) -> usize {
match *self {
TerminalString::Literal(x) => x.display_len(),
TerminalString::Bare(x) => x.len(),
TerminalString::Literal(ref x) => x.display_len(),
TerminalString::Bare(ref x) => x.len(),
TerminalString::Error => "error".len()
}
}
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum TerminalLiteral {
Quoted(InternedString),
Regex(InternedString),
Quoted(Atom),
Regex(Atom),
}
impl TerminalLiteral {
@ -502,14 +502,14 @@ impl TerminalLiteral {
pub fn display_len(&self) -> usize {
match *self {
TerminalLiteral::Quoted(x) => x.len(),
TerminalLiteral::Regex(x) => x.len() + "####r".len(),
TerminalLiteral::Quoted(ref x) => x.len(),
TerminalLiteral::Regex(ref x) => x.len() + "####r".len(),
}
}
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct NonterminalString(pub InternedString);
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct NonterminalString(pub Atom);
impl NonterminalString
{
@ -549,11 +549,11 @@ pub struct MacroSymbol {
}
impl TerminalString {
pub fn quoted(i: InternedString) -> TerminalString {
pub fn quoted(i: Atom) -> TerminalString {
TerminalString::Literal(TerminalLiteral::Quoted(i))
}
pub fn regex(i: InternedString) -> TerminalString {
pub fn regex(i: Atom) -> TerminalString {
TerminalString::Literal(TerminalLiteral::Regex(i))
}
}
@ -673,7 +673,7 @@ impl Display for Visibility {
impl<T: Display> Display for WhereClause<T> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self {
WhereClause::Lifetime { lifetime, ref bounds } => {
WhereClause::Lifetime { ref lifetime, ref bounds } => {
write!(fmt, "{}:", lifetime)?;
for (i, b) in bounds.iter().enumerate() {
if i != 0 {
@ -711,7 +711,7 @@ impl<T: Display> Display for WhereClause<T> {
impl<T: Display> Display for TypeBound<T> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self {
TypeBound::Lifetime(l) => {
TypeBound::Lifetime(ref l) => {
write!(fmt, "{}", l)
}
TypeBound::Fn { ref forall, ref path, ref parameters, ref ret } => {
@ -774,13 +774,13 @@ impl<T: Display> Display for TypeBound<T> {
impl<T: Display> Display for TypeBoundParameter<T> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self {
TypeBoundParameter::Lifetime(l) => {
TypeBoundParameter::Lifetime(ref l) => {
write!(fmt, "{}", l)
}
TypeBoundParameter::TypeParameter(ref t) => {
write!(fmt, "{}", t)
}
TypeBoundParameter::Associated(id, ref t) => {
TypeBoundParameter::Associated(ref id, ref t) => {
write!(fmt, "{} = {}", id, t)
}
}
@ -790,9 +790,9 @@ impl<T: Display> Display for TypeBoundParameter<T> {
impl Display for TerminalString {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self {
TerminalString::Literal(s) =>
TerminalString::Literal(ref s) =>
write!(fmt, "{}", s),
TerminalString::Bare(s) =>
TerminalString::Bare(ref s) =>
write!(fmt, "{}", s),
TerminalString::Error =>
write!(fmt, "error"),
@ -809,10 +809,10 @@ impl Debug for TerminalString {
impl Display for TerminalLiteral {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self {
TerminalLiteral::Quoted(s) =>
write!(fmt, "{:?}", s), // the Debug impl adds the `"` and escaping
TerminalLiteral::Regex(s) =>
write!(fmt, "r#{:?}#", s), // FIXME -- need to determine proper number of #
TerminalLiteral::Quoted(ref s) =>
write!(fmt, "{:?}", s.as_ref()), // the Debug impl adds the `"` and escaping
TerminalLiteral::Regex(ref s) =>
write!(fmt, "r#{:?}#", s.as_ref()), // FIXME -- need to determine proper number of #
}
}
}
@ -866,7 +866,7 @@ impl Display for SymbolKind {
write!(fmt, "{}", r),
SymbolKind::Choose(ref s) =>
write!(fmt, "<{}>", s),
SymbolKind::Name(n, ref s) =>
SymbolKind::Name(ref n, ref s) =>
write!(fmt, "{}:{}", n, s),
SymbolKind::Lookahead =>
write!(fmt, "@L"),
@ -901,7 +901,7 @@ impl Display for ExprSymbol {
}
impl ExternToken {
pub fn associated_type(&self, name: InternedString) -> Option<&AssociatedType> {
pub fn associated_type(&self, name: Atom) -> Option<&AssociatedType> {
self.associated_types.iter()
.filter(|a| a.type_name == name)
.next()
@ -935,8 +935,8 @@ impl Display for MacroSymbol {
impl Display for TypeParameter {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self {
TypeParameter::Lifetime(s) => write!(fmt, "{}", s),
TypeParameter::Id(s) => write!(fmt, "{}", s),
TypeParameter::Lifetime(ref s) => write!(fmt, "{}", s),
TypeParameter::Id(ref s) => write!(fmt, "{}", s),
}
}
}
@ -958,11 +958,11 @@ impl Display for TypeRef {
write!(fmt, "`{}`", s),
TypeRef::Ref { lifetime: None, mutable: false, ref referent } =>
write!(fmt, "&{}", referent),
TypeRef::Ref { lifetime: Some(l), mutable: false, ref referent } =>
TypeRef::Ref { lifetime: Some(ref l), mutable: false, ref referent } =>
write!(fmt, "&{} {}", l, referent),
TypeRef::Ref { lifetime: None, mutable: true, ref referent } =>
write!(fmt, "&mut {}", referent),
TypeRef::Ref { lifetime: Some(l), mutable: true, ref referent } =>
TypeRef::Ref { lifetime: Some(ref l), mutable: true, ref referent } =>
write!(fmt, "&{} mut {}", l, referent),
}
}
@ -981,17 +981,17 @@ impl TypeRef {
path: path.clone(),
types: types.iter().map(TypeRef::type_repr).collect()
}),
TypeRef::Lifetime(id) =>
TypeRepr::Lifetime(id),
TypeRef::Id(id) =>
TypeRef::Lifetime(ref id) =>
TypeRepr::Lifetime(id.clone()),
TypeRef::Id(ref id) =>
TypeRepr::Nominal(NominalTypeRepr {
path: Path::from_id(id),
path: Path::from_id(id.clone()),
types: vec![]
}),
TypeRef::OfSymbol(_) =>
unreachable!("OfSymbol produced by parser"),
TypeRef::Ref { lifetime, mutable, ref referent } =>
TypeRepr::Ref { lifetime: lifetime,
TypeRef::Ref { ref lifetime, mutable, ref referent } =>
TypeRepr::Ref { lifetime: lifetime.clone(),
mutable: mutable,
referent: Box::new(referent.type_repr()) },
}
@ -999,7 +999,7 @@ impl TypeRef {
}
impl Path {
pub fn from_id(id: InternedString) -> Path {
pub fn from_id(id: Atom) -> Path {
Path {
absolute: false,
ids: vec![id]
@ -1009,34 +1009,34 @@ impl Path {
pub fn usize() -> Path {
Path {
absolute: false,
ids: vec![intern("usize")]
ids: vec![Atom::from("usize")]
}
}
pub fn str() -> Path {
Path {
absolute: false,
ids: vec![intern("str")]
ids: vec![Atom::from("str")]
}
}
pub fn vec() -> Path {
Path {
absolute: true,
ids: vec![intern("std"), intern("vec"), intern("Vec")]
ids: vec![Atom::from("std"), Atom::from("vec"), Atom::from("Vec")]
}
}
pub fn option() -> Path {
Path {
absolute: true,
ids: vec![intern("std"), intern("option"), intern("Option")]
ids: vec![Atom::from("std"), Atom::from("option"), Atom::from("Option")]
}
}
pub fn as_id(&self) -> Option<InternedString> {
pub fn as_id(&self) -> Option<Atom> {
if !self.absolute && self.ids.len() == 1 {
Some(self.ids[0])
Some(self.ids[0].clone())
} else {
None
}
@ -1045,13 +1045,13 @@ impl Path {
pub fn read_algorithm(annotations: &[Annotation], algorithm: &mut r::Algorithm) {
for annotation in annotations {
if annotation.id == intern(LALR) {
if annotation.id == Atom::from(LALR) {
algorithm.lalr = true;
} else if annotation.id == intern(TABLE_DRIVEN) {
} else if annotation.id == Atom::from(TABLE_DRIVEN) {
algorithm.codegen = r::LrCodeGeneration::TableDriven;
} else if annotation.id == intern(RECURSIVE_ASCENT) {
} else if annotation.id == Atom::from(RECURSIVE_ASCENT) {
algorithm.codegen = r::LrCodeGeneration::RecursiveAscent;
} else if annotation.id == intern(TEST_ALL) {
} else if annotation.id == Atom::from(TEST_ALL) {
algorithm.codegen = r::LrCodeGeneration::TestAll;
} else {
panic!("validation permitted unknown annotation: {:?}",

View File

@ -6,7 +6,7 @@ representations.
*/
use intern::{InternedString};
use string_cache::DefaultAtom as Atom;
use grammar::parse_tree::{Path, Span};
use std::fmt::{Display, Formatter, Error};
use util::Sep;
@ -20,7 +20,7 @@ pub struct Pattern<T> {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FieldPattern<T> {
pub field_span: Span,
pub field_name: InternedString,
pub field_name: Atom,
pub pattern: Pattern<T>,
}
@ -35,7 +35,7 @@ pub enum PatternKind<T> {
Underscore,
DotDot,
Choose(T),
CharLiteral(InternedString),
CharLiteral(Atom),
}
impl<T> Pattern<T> {
@ -79,8 +79,8 @@ impl<T> PatternKind<T> {
PatternKind::Usize(n),
PatternKind::Choose(ref ty) =>
PatternKind::Choose(map_fn(ty)),
PatternKind::CharLiteral(c) =>
PatternKind::CharLiteral(c),
PatternKind::CharLiteral(ref c) =>
PatternKind::CharLiteral(c.clone()),
}
}
}
@ -88,7 +88,7 @@ impl<T> PatternKind<T> {
impl<T> FieldPattern<T> {
pub fn map<U>(&self, map_fn: &mut FnMut(&T) -> U) -> FieldPattern<U> {
FieldPattern {
field_name: self.field_name,
field_name: self.field_name.clone(),
field_span: self.field_span,
pattern: self.pattern.map(map_fn)
}
@ -126,7 +126,7 @@ impl<T:Display> Display for PatternKind<T> {
write!(fmt, "{}", n),
PatternKind::Choose(ref ty) =>
write!(fmt, "{}", ty),
PatternKind::CharLiteral(c) =>
PatternKind::CharLiteral(ref c) =>
write!(fmt, "'{}'", c),
}
}

View File

@ -4,7 +4,7 @@
* representation incrementally.
*/
use intern::{intern, InternedString};
use string_cache::DefaultAtom as Atom;
use grammar::pattern::{Pattern};
use message::Content;
use std::fmt::{Debug, Display, Formatter, Error};
@ -100,7 +100,7 @@ pub enum LrCodeGeneration {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Parameter {
pub name: InternedString,
pub name: Atom,
pub ty: TypeRepr,
}
@ -114,7 +114,7 @@ pub struct Production {
pub span: Span,
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Symbol {
Nonterminal(NonterminalString),
Terminal(TerminalString),
@ -137,7 +137,7 @@ pub enum ActionFnDefnKind {
/// An action fn written by a user.
#[derive(Clone, PartialEq, Eq)]
pub struct UserActionFnDefn {
pub arg_patterns: Vec<InternedString>,
pub arg_patterns: Vec<Atom>,
pub arg_types: Vec<TypeRepr>,
pub code: String,
}
@ -177,12 +177,12 @@ pub enum TypeRepr {
Tuple(Vec<TypeRepr>),
Nominal(NominalTypeRepr),
Associated {
type_parameter: InternedString,
id: InternedString,
type_parameter: Atom,
id: Atom,
},
Lifetime(InternedString),
Lifetime(Atom),
Ref {
lifetime: Option<InternedString>,
lifetime: Option<Atom>,
mutable: bool,
referent: Box<TypeRepr>,
},
@ -227,13 +227,13 @@ impl TypeRepr {
None => vec![],
})
.collect(),
TypeRepr::Associated { type_parameter, .. } =>
vec![TypeParameter::Id(type_parameter)],
TypeRepr::Lifetime(l) =>
vec![TypeParameter::Lifetime(l)],
TypeRepr::Associated { ref type_parameter, .. } =>
vec![TypeParameter::Id(type_parameter.clone())],
TypeRepr::Lifetime(ref l) =>
vec![TypeParameter::Lifetime(l.clone())],
TypeRepr::Ref { ref lifetime, mutable: _, ref referent } =>
lifetime.iter()
.map(|&id| TypeParameter::Lifetime(id))
.map(|id| TypeParameter::Lifetime(id.clone()))
.chain(referent.referenced())
.collect(),
}
@ -280,16 +280,16 @@ impl Types {
types.parse_error_type = TypeRepr::Nominal(NominalTypeRepr {
path: Path {
absolute: false,
ids: vec![intern(&format!("{}lalrpop_util", prefix)),
intern("ParseError")],
ids: vec![Atom::from(format!("{}lalrpop_util", prefix)),
Atom::from("ParseError")],
},
types: args.clone(),
});
types.error_recovery_type = TypeRepr::Nominal(NominalTypeRepr {
path: Path {
absolute: false,
ids: vec![intern(&format!("{}lalrpop_util", prefix)),
intern("ErrorRecovery")],
ids: vec![Atom::from(format!("{}lalrpop_util", prefix)),
Atom::from("ErrorRecovery")],
},
types: args,
});
@ -321,13 +321,13 @@ impl Types {
pub fn error_type(&self) -> TypeRepr {
self.error_type.clone()
.unwrap_or_else(|| TypeRepr::Ref {
lifetime: Some(intern("'static")),
lifetime: Some(Atom::from("'static")),
mutable: false,
referent: Box::new(TypeRepr::str()),
})
}
pub fn terminal_type(&self, id: TerminalString) -> &TypeRepr {
pub fn terminal_type(&self, id: &TerminalString) -> &TypeRepr {
self.terminal_types.get(&id).unwrap_or(&self.terminal_token_type)
}
@ -337,11 +337,11 @@ impl Types {
.collect()
}
pub fn lookup_nonterminal_type(&self, id: NonterminalString) -> Option<&TypeRepr> {
pub fn lookup_nonterminal_type(&self, id: &NonterminalString) -> Option<&TypeRepr> {
self.nonterminal_types.get(&id)
}
pub fn nonterminal_type(&self, id: NonterminalString) -> &TypeRepr {
pub fn nonterminal_type(&self, id: &NonterminalString) -> &TypeRepr {
&self.nonterminal_types[&id]
}
@ -384,17 +384,17 @@ impl Display for TypeRepr {
write!(fmt, "({})", Sep(", ", types)),
TypeRepr::Nominal(ref data) =>
write!(fmt, "{}", data),
TypeRepr::Associated { type_parameter, id } =>
TypeRepr::Associated { ref type_parameter, ref id } =>
write!(fmt, "{}::{}", type_parameter, id),
TypeRepr::Lifetime(id) =>
TypeRepr::Lifetime(ref id) =>
write!(fmt, "{}", id),
TypeRepr::Ref { lifetime: None, mutable: false, ref referent } =>
write!(fmt, "&{}", referent),
TypeRepr::Ref { lifetime: Some(l), mutable: false, ref referent } =>
TypeRepr::Ref { lifetime: Some(ref l), mutable: false, ref referent } =>
write!(fmt, "&{} {}", l, referent),
TypeRepr::Ref { lifetime: None, mutable: true, ref referent } =>
write!(fmt, "&mut {}", referent),
TypeRepr::Ref { lifetime: Some(l), mutable: true, ref referent } =>
TypeRepr::Ref { lifetime: Some(ref l), mutable: true, ref referent } =>
write!(fmt, "&{} mut {}", l, referent),
}
}
@ -445,8 +445,8 @@ impl Symbol {
pub fn ty<'ty>(&self, t: &'ty Types) -> &'ty TypeRepr {
match *self {
Symbol::Terminal(id) => t.terminal_type(id),
Symbol::Nonterminal(id) => t.nonterminal_type(id),
Symbol::Terminal(ref id) => t.terminal_type(id),
Symbol::Nonterminal(ref id) => t.nonterminal_type(id),
}
}
}
@ -454,8 +454,8 @@ impl Symbol {
impl Display for Symbol {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self {
Symbol::Nonterminal(id) => write!(fmt, "{}", id),
Symbol::Terminal(id) => write!(fmt, "{}", id),
Symbol::Nonterminal(ref id) => write!(fmt, "{}", id.clone()),
Symbol::Terminal(ref id) => write!(fmt, "{}", id.clone()),
}
}
}
@ -519,7 +519,7 @@ impl InlineActionFnDefn {
self.symbols
.iter()
.map(|inline_sym| match *inline_sym {
InlinedSymbol::Original(s) =>
InlinedSymbol::Original(ref s) =>
format!("{}", s),
InlinedSymbol::Inlined(a, ref s) =>
format!("{:?}({})", a, Sep(", ", s)),
@ -531,12 +531,12 @@ impl InlineActionFnDefn {
}
impl Grammar {
pub fn pattern(&self, t: TerminalString) -> &Pattern<TypeRepr> {
&self.conversions[&t]
pub fn pattern(&self, t: &TerminalString) -> &Pattern<TypeRepr> {
&self.conversions[t]
}
pub fn productions_for(&self, nonterminal: NonterminalString) -> &[Production] {
match self.nonterminals.get(&nonterminal) {
pub fn productions_for(&self, nonterminal: &NonterminalString) -> &[Production] {
match self.nonterminals.get(nonterminal) {
Some(v) => &v.productions[..],
None => &[], // this...probably shouldn't happen actually?
}

View File

@ -1,7 +1,7 @@
use std::collections::{HashMap};
use grammar::parse_tree::TypeRef;
use intern::InternedString;
use string_cache::DefaultAtom as Atom;
#[cfg(test)]
mod test;
@ -11,12 +11,12 @@ pub struct TokenDefinition {
enum_type: TypeRef,
// map from a custom string, like `"("` to a variant name like LPAREN
token_map: HashMap<InternedString, InternedString>,
token_map: HashMap<Atom, Atom>,
}
impl TokenDefinition {
pub fn new(enum_type: TypeRef,
token_map: Vec<(InternedString, InternedString)>)
token_map: Vec<(Atom, Atom)>)
-> TokenDefinition
{
TokenDefinition {

View File

@ -36,7 +36,6 @@ mod __intern_token {
*/
use intern;
use lexer::re;
use grammar::parse_tree::InternToken;
use grammar::repr::{Grammar, TerminalLiteral};
@ -77,12 +76,12 @@ pub fn compile<W: Write>(
// create a vector of rust string literals with the text of each
// regular expression
let regex_strings: Vec<String> = intern::read(|interner| {
let regex_strings: Vec<String> = {
intern_token.match_entries
.iter()
.map(|match_entry| match match_entry.match_literal {
TerminalLiteral::Quoted(s) => re::parse_literal(interner.data(s)),
TerminalLiteral::Regex(s) => re::parse_regex(interner.data(s)).unwrap(),
TerminalLiteral::Quoted(ref s) => re::parse_literal(&s),
TerminalLiteral::Regex(ref s) => re::parse_regex(&s).unwrap(),
})
.map(|regex| {
// make sure all regex are anchored at the beginning of the input
@ -94,7 +93,7 @@ pub fn compile<W: Write>(
format!("{:?}", regex_str)
})
.collect()
});
};
rust!(out, "let {}strs: &[&str] = &[", prefix);
for literal in &regex_strings {

View File

@ -14,11 +14,11 @@ extern crate bit_set;
extern crate diff;
extern crate ena;
extern crate itertools;
extern crate lalrpop_intern as intern;
extern crate lalrpop_util;
extern crate petgraph;
extern crate regex;
extern crate regex_syntax;
extern crate string_cache;
extern crate term;
extern crate unicode_xid;

View File

@ -95,7 +95,7 @@ impl<'grammar, L: LookaheadBuild> LR<'grammar, L> {
let mut conflicts = vec![];
// create the starting state
kernel_set.add_state(Kernel::start(self.items(self.start_nt,
kernel_set.add_state(Kernel::start(self.items(&self.start_nt,
0,
&self.start_lookahead)));
@ -178,7 +178,7 @@ impl<'grammar, L: LookaheadBuild> LR<'grammar, L> {
}
fn items(&self,
id: NonterminalString,
id: &NonterminalString,
index: usize,
lookahead: &L)
-> Vec<Item<'grammar, L>>
@ -237,7 +237,7 @@ impl<'grammar, L: LookaheadBuild> LR<'grammar, L> {
//
// (a) FIRST(remainder)
// (b) if remainder may match epsilon, also our lookahead.
for new_item in L::epsilon_moves(self, nt, remainder, &lookahead) {
for new_item in L::epsilon_moves(self, &nt, remainder, &lookahead) {
let new_item0 = new_item.to_lr0();
if map.push(new_item0, new_item.lookahead) {
stack.push(new_item0);
@ -317,7 +317,7 @@ pub trait LookaheadBuild: Lookahead {
// items, we have to add multiple items where we consider the
// lookahead from `FIRST(...s, L)`.
fn epsilon_moves<'grammar>(lr: &LR<'grammar, Self>,
nt: NonterminalString,
nt: &NonterminalString,
remainder: &[Symbol],
lookahead: &Self)
-> Vec<Item<'grammar, Self>>;
@ -325,7 +325,7 @@ pub trait LookaheadBuild: Lookahead {
impl LookaheadBuild for Nil {
fn epsilon_moves<'grammar>(lr: &LR<'grammar, Self>,
nt: NonterminalString,
nt: &NonterminalString,
_remainder: &[Symbol],
lookahead: &Nil)
-> Vec<LR0Item<'grammar>>
@ -336,7 +336,7 @@ impl LookaheadBuild for Nil {
impl LookaheadBuild for TokenSet {
fn epsilon_moves<'grammar>(lr: &LR<'grammar, Self>,
nt: NonterminalString,
nt: &NonterminalString,
remainder: &[Symbol],
lookahead: &Self)
-> Vec<LR1Item<'grammar>>

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use generate;
use grammar::repr::*;
use test_util::{compare, expect_debug, normalized_grammar};
@ -13,7 +13,7 @@ use tls::Tls;
use super::{LR, use_lane_table, build_lr0_states, build_lr1_states};
fn nt(t: &str) -> NonterminalString {
NonterminalString(intern(t))
NonterminalString(Atom::from(t))
}
const ITERATIONS: usize = 22;
@ -22,7 +22,7 @@ fn random_test<'g>(grammar: &Grammar,
states: &'g [LR1State<'g>],
start_symbol: NonterminalString) {
for i in 0..ITERATIONS {
let input_tree = generate::random_parse_tree(grammar, start_symbol);
let input_tree = generate::random_parse_tree(grammar, start_symbol.clone());
let output_tree = interpret(&states, input_tree.terminals()).unwrap();
println!("test {}", i);
@ -35,7 +35,7 @@ fn random_test<'g>(grammar: &Grammar,
macro_rules! tokens {
($($x:expr),*) => {
vec![$(TerminalString::quoted(intern($x))),*]
vec![$(TerminalString::quoted(Atom::from($x))),*]
}
}
@ -46,7 +46,7 @@ fn items<'g>(grammar: &'g Grammar, nonterminal: &str, index: usize, la: Token)
let lr1: LR<TokenSet> = LR::new(&grammar, nt(nonterminal), set.clone());
let items =
lr1.transitive_closure(
lr1.items(nt(nonterminal), index, &set));
lr1.items(&nt(nonterminal), index, &set));
items
}
@ -134,7 +134,7 @@ grammar;
// execute it on some sample inputs.
let tree = interpret(&states, tokens!["N", "-", "(", "N", "-", "N", ")"]).unwrap();
assert_eq!(
&format!("{:?}", tree)[..],
&format!("{}", tree)[..],
r#"[S: [E: [E: [T: "N"]], "-", [T: "(", [E: [E: [T: "N"]], "-", [T: "N"]], ")"]]]"#);
// incomplete:

View File

@ -109,15 +109,15 @@ pub fn collapse_to_lalr_states<'grammar>(lr_states: &[LR1State<'grammar>])
let lalr1_index = remap[lr1_index];
let lalr1_state = &mut lalr1_states[lalr1_index.0];
for (&terminal, &lr1_state) in &lr1_state.shifts {
for (terminal, &lr1_state) in &lr1_state.shifts {
let target_state = remap[lr1_state.0];
let prev = lalr1_state.shifts.insert(terminal, target_state);
let prev = lalr1_state.shifts.insert(terminal.clone(), target_state);
assert!(prev.unwrap_or(target_state) == target_state);
}
for (&nt, lr1_state) in &lr1_state.gotos {
for (nt, lr1_state) in &lr1_state.gotos {
let target_state = remap[lr1_state.0];
let prev = lalr1_state.gotos.insert(nt, target_state);
let prev = lalr1_state.gotos.insert(nt.clone(), target_state);
assert!(prev.unwrap_or(target_state) == target_state); // as above
}

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use grammar::repr::*;
use lr1::tls::Lr1Tls;
use test_util::{normalized_grammar};
@ -7,12 +7,12 @@ use super::build_lalr_states;
use super::super::interpret::interpret;
fn nt(t: &str) -> NonterminalString {
NonterminalString(intern(t))
NonterminalString(Atom::from(t))
}
macro_rules! tokens {
($($x:expr),*) => {
vec![$(TerminalString::quoted(intern($x))),*]
vec![$(TerminalString::quoted(Atom::from($x))),*]
}
}

View File

@ -212,7 +212,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent,
// making different enums per state, but this would mean we
// have to unwrap and rewrap as we pass up the stack, which
// seems silly
for &nt in self.grammar.nonterminals.keys() {
for ref nt in self.grammar.nonterminals.keys() {
let ty = self.types.spanned_type(self.types.nonterminal_type(nt).clone());
rust!(self.out, "{}({}),", Escape(nt), ty);
}
@ -248,7 +248,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent,
rust!(self.out,
"(None, {}Nonterminal::{}((_, {}nt, _))) => {{",
self.prefix,
Escape(self.start_symbol),
Escape(&self.start_symbol),
self.prefix);
rust!(self.out, "Ok({}nt)", self.prefix);
rust!(self.out, "}}");
@ -316,7 +316,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent,
rust!(self.out, "match {}lookahead {{", self.prefix);
// first emit shifts:
for (&terminal, &next_index) in &this_state.shifts {
for (terminal, &next_index) in &this_state.shifts {
let sym_name = format!("{}sym{}", self.prefix, inputs.len());
try!(self.consume_terminal(terminal, sym_name));
@ -339,9 +339,9 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent,
})
.collect();
for (production, tokens) in reductions {
for (index, &token) in tokens.iter().enumerate() {
let pattern = match token {
Token::Terminal(s) => format!("Some({})", self.match_terminal_pattern(s)),
for (index, token) in tokens.iter().enumerate() {
let pattern = match *token {
Token::Terminal(ref s) => format!("Some({})", self.match_terminal_pattern(s)),
Token::Error => panic!("Error recovery is not implemented for recursive ascent parsers"),
Token::EOF => format!("None"),
};
@ -371,7 +371,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent,
this_state.shifts.contains_key(terminal) ||
this_state.reductions
.iter()
.any(|&(ref t, _)| t.contains(Token::Terminal(*terminal)))
.any(|&(ref t, _)| t.contains(&Token::Terminal(terminal.clone())))
});
rust!(self.out, "return Err({}lalrpop_util::ParseError::UnrecognizedToken {{", self.prefix);
rust!(self.out, "token: {}lookahead,", self.prefix);
@ -432,7 +432,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent,
self.prefix);
rust!(self.out, "match {}nt {{", self.prefix);
for (&nt, &next_index) in &this_state.gotos {
for (ref nt, &next_index) in &this_state.gotos {
// The nonterminal we are shifting becomes symN, where
// N is the number of inputs to this state (which are
// numbered sym0..sym(N-1)). It is never optional
@ -841,7 +841,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent,
"let {}nt = {}Nonterminal::{}((",
self.prefix,
self.prefix,
Escape(production.nonterminal));
Escape(&production.nonterminal));
rust!(self.out, "{}start,", self.prefix);
rust!(self.out, "{}nt,", self.prefix);
rust!(self.out, "{}end,", self.prefix);
@ -859,7 +859,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent,
}
/// Emit a pattern that matches `id` but doesn't extract any data.
fn match_terminal_pattern(&mut self, id: TerminalString) -> String {
fn match_terminal_pattern(&mut self, id: &TerminalString) -> String {
let pattern = self.grammar
.pattern(id)
.map(&mut |_| "_");
@ -869,7 +869,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent,
/// Emit a pattern that matches `id` and extracts its value, storing
/// that value as `let_name`.
fn consume_terminal(&mut self, id: TerminalString, let_name: String) -> io::Result<()> {
fn consume_terminal(&mut self, id: &TerminalString, let_name: String) -> io::Result<()> {
let mut pattern_names = vec![];
let pattern = self.grammar.pattern(id).map(&mut |_| {
let index = pattern_names.len();

View File

@ -140,7 +140,7 @@ impl<'codegen, 'grammar, W: Write, C> CodeGenerator<'codegen, 'grammar, W, C> {
type_parameters,
parameters,
format!("Result<{}, {}>",
self.types.nonterminal_type(self.start_symbol),
self.types.nonterminal_type(&self.start_symbol),
parse_error_type),
where_clauses));
rust!(self.out, "{{");

View File

@ -3,7 +3,7 @@
use collections::{Map, Set};
use grammar::parse_tree::WhereClause;
use grammar::repr::*;
use intern::intern;
use string_cache::DefaultAtom as Atom;
use lr1::core::*;
use lr1::lookahead::Token;
use rust::RustWrite;
@ -379,15 +379,15 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
rust!(self.out, " {{");
// make one variant per terminal
for &term in &self.grammar.terminals.all {
let name = self.variant_name_for_symbol(Symbol::Terminal(term));
for term in &self.grammar.terminals.all {
let name = self.variant_name_for_symbol(&Symbol::Terminal(term.clone()));
let ty = self.types.terminal_type(term).clone();
rust!(self.out, "{}({}),", name, ty);
}
// make one variant per nonterminal
for &nt in self.grammar.nonterminals.keys() {
let name = self.variant_name_for_symbol(Symbol::Nonterminal(nt));
for nt in self.grammar.nonterminals.keys() {
let name = self.variant_name_for_symbol(&Symbol::Nonterminal(nt.clone()));
let ty = self.types.nonterminal_type(nt).clone();
rust!(self.out, "{}({}),", name, ty);
}
@ -413,9 +413,9 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
let custom = &self.custom;
let iterator = self.grammar.terminals.all.iter().map(|terminal| {
if let Some(new_state) = state.shifts.get(&terminal) {
(new_state.0 as i32 + 1, Comment::Goto(Token::Terminal(*terminal), new_state.0))
(new_state.0 as i32 + 1, Comment::Goto(Token::Terminal(terminal.clone()), new_state.0))
} else {
Self::write_reduction(custom, state, Token::Terminal(*terminal))
Self::write_reduction(custom, state, &Token::Terminal(terminal.clone()))
}
});
try!(self.out.write_table_row(iterator))
@ -429,7 +429,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
self.prefix);
for (index, state) in self.states.iter().enumerate() {
rust!(self.out, "// State {}", index);
let reduction = Self::write_reduction(&self.custom, state, Token::EOF);
let reduction = Self::write_reduction(&self.custom, state, &Token::EOF);
try!(self.out.write_table_row(Some(reduction)));
}
rust!(self.out, "];");
@ -439,10 +439,10 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
for (index, state) in self.states.iter().enumerate() {
rust!(self.out, "// State {}", index);
let iterator = self.grammar.nonterminals.keys().map(|nonterminal| {
if let Some(&new_state) = state.gotos.get(nonterminal) {
(new_state.0 as i32 + 1, Comment::Goto(*nonterminal, new_state.0))
if let Some(&new_state) = state.gotos.get(&nonterminal) {
(new_state.0 as i32 + 1, Comment::Goto(nonterminal, new_state.0))
} else {
(0, Comment::Error(*nonterminal))
(0, Comment::Error(nonterminal))
}
});
try!(self.out.write_table_row(iterator));
@ -454,7 +454,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
Ok(())
}
fn write_reduction<'s>(custom: &TableDriven<'grammar>, state: &'s LR1State, token: Token) -> (i32, Comment<'s, Token>) {
fn write_reduction<'s>(custom: &TableDriven<'grammar>, state: &'s LR1State, token: &Token) -> (i32, Comment<'s, Token>) {
let reduction = state.reductions
.iter()
.filter(|&&(ref t, _)| t.contains(token))
@ -462,10 +462,10 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
.next();
if let Some(production) = reduction {
let action = custom.reduce_indices[production];
(-(action as i32 + 1), Comment::Reduce(token, production))
(-(action as i32 + 1), Comment::Reduce(token.clone(), production))
} else {
// Otherwise, this is an error. Store 0.
(0, Comment::Error(token))
(0, Comment::Error(token.clone()))
}
}
@ -672,8 +672,8 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
integer = integer,
lookahead = lookahead,
p = self.prefix);
for (&terminal, index) in self.grammar.terminals.all.iter().zip(0..) {
if terminal == TerminalString::Error {
for (terminal, index) in self.grammar.terminals.all.iter().zip(0..) {
if *terminal == TerminalString::Error {
continue;
}
let pattern = self.grammar.pattern(terminal).map(&mut |_| "_");
@ -699,8 +699,8 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
"let {}symbol = match {}integer {{",
self.prefix,
self.prefix);
for (&terminal, index) in self.grammar.terminals.all.iter().zip(0..) {
if terminal == TerminalString::Error {
for (terminal, index) in self.grammar.terminals.all.iter().zip(0..) {
if *terminal == TerminalString::Error {
continue;
}
rust!(self.out, "{} => match {}lookahead.1 {{", index, self.prefix);
@ -718,7 +718,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
pattern = format!("{}tok @ {}", self.prefix, pattern);
}
let variant_name = self.variant_name_for_symbol(Symbol::Terminal(terminal));
let variant_name = self.variant_name_for_symbol(&Symbol::Terminal(terminal.clone()));
rust!(self.out,
"{} => {}Symbol::{}(({})),",
pattern,
@ -736,7 +736,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
}
fn emit_reduce_actions(&mut self) -> io::Result<()> {
let success_type = self.types.nonterminal_type(self.start_symbol);
let success_type = self.types.nonterminal_type(&self.start_symbol);
let parse_error_type = self.types.parse_error_type();
let loc_type = self.types.terminal_loc_type();
let spanned_symbol_type = self.spanned_symbol_type();
@ -750,7 +750,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
format!("_: {}", self.phantom_data_type())];
try!(self.out.write_pub_fn_header(self.grammar,
&Visibility::Pub(Some(Path::from_id(intern("crate")))),
&Visibility::Pub(Some(Path::from_id(Atom::from("crate")))),
format!("{}reduce", self.prefix),
vec![],
parameters,
@ -810,7 +810,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
rust!(self.out, "// {:?}", production);
// Pop each of the symbols and their associated states.
for (index, &symbol) in production.symbols.iter().enumerate().rev() {
for (index, symbol) in production.symbols.iter().enumerate().rev() {
let name = self.variant_name_for_symbol(symbol);
rust!(self.out,
"let {}sym{} = {}pop_{}({}symbols);",
@ -910,7 +910,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
len = production.symbols.len());
// push the produced value on the stack
let name = self.variant_name_for_symbol(Symbol::Nonterminal(production.nonterminal));
let name = self.variant_name_for_symbol(&Symbol::Nonterminal(production.nonterminal.clone()));
rust!(self.out,
"{}symbols.push(({}start, {}Symbol::{}({}nt), {}end));",
self.prefix,
@ -925,29 +925,29 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
let index = self.custom
.all_nonterminals
.iter()
.position(|&x| x == production.nonterminal)
.position(|x| *x == production.nonterminal)
.unwrap();
rust!(self.out, "{}", index);
Ok(())
}
fn variant_name_for_symbol(&mut self, s: Symbol) -> String {
match s {
Symbol::Nonterminal(nt) => format!("Nt{}", Escape(nt)),
Symbol::Terminal(t) => format!("Term{}", Escape(t)),
fn variant_name_for_symbol(&mut self, s: &Symbol) -> String {
match *s {
Symbol::Nonterminal(ref nt) => format!("Nt{}", Escape(nt)),
Symbol::Terminal(ref t) => format!("Term{}", Escape(t)),
}
}
fn emit_downcast_fns(&mut self) -> io::Result<()> {
for &term in &self.grammar.terminals.all {
let name = self.variant_name_for_symbol(Symbol::Terminal(term));
for term in &self.grammar.terminals.all {
let name = self.variant_name_for_symbol(&Symbol::Terminal(term.clone()));
let ty = self.types.terminal_type(term).clone();
try!(self.emit_downcast_fn(&name, ty));
}
for &nt in self.grammar.nonterminals.keys() {
let name = self.variant_name_for_symbol(Symbol::Nonterminal(nt));
for nt in self.grammar.nonterminals.keys() {
let name = self.variant_name_for_symbol(&Symbol::Nonterminal(nt.clone()));
let ty = self.types.nonterminal_type(nt).clone();
try!(self.emit_downcast_fn(&name, ty));
}
@ -1111,7 +1111,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
let loc_type = self.types.terminal_loc_type();
let prefix = self.prefix;
let actions_per_state = self.grammar.terminals.all.len();
let start_type = self.types.nonterminal_type(self.start_symbol);
let start_type = self.types.nonterminal_type(&self.start_symbol);
// The tokenizr, when we supply it, returns parse
// errors. Otherwise, it returns custom user errors.
@ -1638,7 +1638,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
let nt = self.custom
.all_nonterminals
.iter()
.position(|&x| x == production.nonterminal)
.position(|x| *x == production.nonterminal)
.unwrap();
rust!(self.out, "{} => {{", index);
if DEBUG_PRINT {
@ -1729,7 +1729,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
} else {
&self.grammar.terminals.all
};
for &terminal in all_terminals {
for terminal in all_terminals {
// Three # should hopefully be enough to prevent any
// reasonable terminal from escaping the literal
rust!(self.out, "r###\"{}\"###,", terminal);

View File

@ -49,8 +49,8 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TestAll> {
rust!(this.out, "mod {}ascent {{", this.prefix);
try!(super::ascent::compile(this.grammar,
this.user_start_symbol,
this.start_symbol,
this.user_start_symbol.clone(),
this.start_symbol.clone(),
this.states,
"super::super::super",
this.out));
@ -64,8 +64,8 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TestAll> {
rust!(this.out, "mod {}parse_table {{", this.prefix);
try!(super::parse_table::compile(this.grammar,
this.user_start_symbol,
this.start_symbol,
this.user_start_symbol.clone(),
this.start_symbol.clone(),
this.states,
"super::super::super",
this.out));

View File

@ -67,16 +67,16 @@ impl<'grammar, L: Lookahead> Item<'grammar, L> {
self.index < self.production.symbols.len()
}
pub fn can_shift_nonterminal(&self, nt: NonterminalString) -> bool {
pub fn can_shift_nonterminal(&self, nt: &NonterminalString) -> bool {
match self.shift_symbol() {
Some((Symbol::Nonterminal(shifted), _)) => shifted == nt,
Some((Symbol::Nonterminal(shifted), _)) => shifted == *nt,
_ => false,
}
}
pub fn can_shift_terminal(&self, term: TerminalString) -> bool {
pub fn can_shift_terminal(&self, term: &TerminalString) -> bool {
match self.shift_symbol() {
Some((Symbol::Terminal(shifted), _)) => shifted == term,
Some((Symbol::Terminal(shifted), _)) => shifted == *term,
_ => false,
}
}
@ -87,7 +87,7 @@ impl<'grammar, L: Lookahead> Item<'grammar, L> {
pub fn shifted_item(&self) -> Option<(Symbol, Item<'grammar, L>)> {
if self.can_shift() {
Some((self.production.symbols[self.index],
Some((self.production.symbols[self.index].clone(),
Item { production: self.production,
index: self.index + 1,
lookahead: self.lookahead.clone() }))
@ -98,7 +98,7 @@ impl<'grammar, L: Lookahead> Item<'grammar, L> {
pub fn shift_symbol(&self) -> Option<(Symbol, &[Symbol])> {
if self.can_shift() {
Some((self.production.symbols[self.index], &self.production.symbols[self.index+1..]))
Some((self.production.symbols[self.index].clone(), &self.production.symbols[self.index+1..]))
} else {
None
}
@ -130,13 +130,13 @@ pub struct State<'grammar, L: Lookahead> {
pub type LR0State<'grammar> = State<'grammar, Nil>;
pub type LR1State<'grammar> = State<'grammar, TokenSet>;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Action<'grammar> {
Shift(TerminalString, StateIndex),
Reduce(&'grammar Production),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Conflict<'grammar, L> {
// when in this state...
pub state: StateIndex,
@ -186,7 +186,7 @@ impl Display for Token {
match *self {
Token::EOF => write!(fmt, "EOF"),
Token::Error => write!(fmt, "Error"),
Token::Terminal(s) => write!(fmt, "{}", s),
Token::Terminal(ref s) => write!(fmt, "{}", s),
}
}
}
@ -278,7 +278,7 @@ impl<'grammar, L: Lookahead> State<'grammar, L> {
let mut returnable_nonterminals: Vec<_> =
self.items.vec.iter()
.filter(|item| item.index > 0)
.map(|item| item.production.nonterminal)
.map(|item| item.production.nonterminal.clone())
.dedup()
.collect();
if returnable_nonterminals.len() == 1 {

View File

@ -200,10 +200,10 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
.begin_wrap();
let builder = match conflict.lookahead {
Token::Terminal(term) => {
Token::Terminal(ref term) => {
builder
.text("At that point, if the next token is a")
.push(term)
.push(term.clone())
.verbatimed()
.styled(Tls::session().cursor_symbol)
.punctuated(",")
@ -224,8 +224,8 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
reduce, "First");
match conflict.action {
Action::Shift(lookahead, _) =>
self.describe_shift(builder, styles, lookahead,
Action::Shift(ref lookahead, _) =>
self.describe_shift(builder, styles, lookahead.clone(),
action, "Alternatively"),
Action::Reduce(production) =>
self.describe_reduce(builder, styles, production,
@ -251,7 +251,7 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
// | |
// +-NT2-----------------------+
let nt1 = example.reductions[0].nonterminal;
let nt1 = example.reductions[0].nonterminal.clone();
builder
.begin_lines()
@ -291,7 +291,7 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
.text(production.symbols.len())
.text("token(s) from the stack")
.text("and produce a")
.push(production.nonterminal)
.push(production.nonterminal.clone())
.verbatimed()
.punctuated(".")
.text("This might then yield a parse tree like")
@ -341,7 +341,7 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
.styled(Tls::session().hint_text)
.text("It appears you could resolve this problem by replacing")
.text("uses of")
.push(nonterminal)
.push(nonterminal.clone())
.verbatimed()
.text("with")
.text(symbol) // intentionally disable coloring here, looks better
@ -410,14 +410,14 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
.begin_wrap()
.text(format!("and looking at a token `{:?}`", conflict.lookahead))
.text("we can reduce to a")
.push(conflict.production.nonterminal)
.push(conflict.production.nonterminal.clone())
.verbatimed();
builder = match conflict.action {
Action::Shift(..) =>
builder.text("but we can also shift"),
Action::Reduce(prod) =>
builder.text("but we can also reduce to a")
.text(prod.nonterminal)
.text(prod.nonterminal.clone())
.verbatimed()
};
builder.end()
@ -432,13 +432,13 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
Action::Shift(..) => self.shift_examples(conflict),
Action::Reduce(production) => self.reduce_examples(conflict.state,
production,
conflict.lookahead)
conflict.lookahead.clone())
};
// Find examples from the conflicting reduce.
let mut reduce_examples = self.reduce_examples(conflict.state,
conflict.production,
conflict.lookahead);
conflict.lookahead.clone());
// Prefer shorter examples to longer ones.
action_examples.sort_by(|e, f| e.symbols.len().cmp(&f.symbols.len()));
@ -498,17 +498,17 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
// Consider whether to call this a precedence
// error. We do this if we are stuck between reducing
// `T = T S T` and shifting `S`.
if let Action::Shift(term, _) = conflict.action {
let nt = conflict.production.nonterminal;
if let Action::Shift(ref term, _) = conflict.action {
let nt = &conflict.production.nonterminal;
if conflict.production.symbols.len() == 3 &&
conflict.production.symbols[0] == Symbol::Nonterminal(nt) &&
conflict.production.symbols[1] == Symbol::Terminal(term) &&
conflict.production.symbols[2] == Symbol::Nonterminal(nt)
conflict.production.symbols[0] == Symbol::Nonterminal(nt.clone()) &&
conflict.production.symbols[1] == Symbol::Terminal(term.clone()) &&
conflict.production.symbols[2] == Symbol::Nonterminal(nt.clone())
{
return ConflictClassification::Precedence {
shift: action.clone(),
reduce: reduce.clone(),
nonterminal: conflict.production.nonterminal,
nonterminal: nt.clone(),
};
}
}
@ -541,7 +541,7 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
debug!("try_classify_question: action_examples={:?}", action_examples);
debug!("try_classify_question: reduce_examples={:?}", reduce_examples);
let nt = conflict.production.nonterminal;
let nt = &conflict.production.nonterminal;
let nt_productions = self.grammar.productions_for(nt);
if nt_productions.len() == 2 {
for &(i, j) in &[(0, 1), (1, 0)] {
@ -552,8 +552,8 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
return Some(ConflictClassification::SuggestQuestion {
shift: action_examples[0].clone(),
reduce: reduce_examples[0].clone(),
nonterminal: nt,
symbol: nt_productions[j].symbols[0],
nonterminal: nt.clone(),
symbol: nt_productions[j].symbols[0].clone(),
});
}
}
@ -588,11 +588,11 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
.cartesian_product(reduce_examples)
.filter_map(|(shift, reduce)| {
if self.try_classify_inline_example(shift, reduce) {
let nt = reduce.reductions[0].nonterminal;
let nt = &reduce.reductions[0].nonterminal;
Some(ConflictClassification::SuggestInline {
shift: shift.clone(),
reduce: reduce.clone(),
nonterminal: nt,
nonterminal: nt.clone(),
})
} else {
None
@ -661,7 +661,7 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
// are distinct so that we are not introducing a cycle.
let mut duplicates = set();
if reduce.reductions[0..i+1].iter()
.any(|r| !duplicates.insert(r.nonterminal)) {
.any(|r| !duplicates.insert(r.nonterminal.clone())) {
return false;
}
@ -671,8 +671,8 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
.iter()
.zip(reduce_upcoming)
.filter_map(|(shift_sym, reduce_sym)| match (shift_sym, reduce_sym) {
(&ExampleSymbol::Symbol(shift_sym),
&ExampleSymbol::Symbol(reduce_sym)) => {
(&ExampleSymbol::Symbol(ref shift_sym),
&ExampleSymbol::Symbol(ref reduce_sym)) => {
if shift_sym == reduce_sym {
// same symbol on both; we'll be able to shift them
None
@ -683,9 +683,9 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
// potentially overlapping, though we could
// supply the actual lookahead for more precision.
let shift_first =
self.first_sets.first0(&[shift_sym]);
self.first_sets.first0(&[shift_sym.clone()]);
let reduce_first =
self.first_sets.first0(&[reduce_sym]);
self.first_sets.first0(&[reduce_sym.clone()]);
if shift_first.is_disjoint(&reduce_first) {
Some(true)
} else {
@ -747,7 +747,7 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
-> Set<LR0Item<'grammar>> {
// Lookahead must be a terminal, not EOF.
// Find an item J like `Bar = ... (*) L ...`.
let lookahead = Symbol::Terminal(conflict.lookahead.unwrap_terminal());
let lookahead = Symbol::Terminal(conflict.lookahead.unwrap_terminal().clone());
state.items.vec.iter()
.filter(|i| i.can_shift())
.filter(|i| i.production.symbols[i.index] == lookahead)
@ -767,7 +767,7 @@ fn token_conflicts<'grammar>(conflicts: &[Conflict<'grammar, TokenSet>])
state: conflict.state,
lookahead: token,
production: conflict.production,
action: conflict.action,
action: conflict.action.clone(),
})
})
.collect()

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use grammar::repr::*;
use lr1::build_states;
use lr1::tls::Lr1Tls;
@ -8,7 +8,7 @@ use tls::Tls;
use super::{ConflictClassification, ErrorReportingCx};
fn nt(t: &str) -> NonterminalString {
NonterminalString(intern(t))
NonterminalString(Atom::from(t))
}
#[test]
@ -106,7 +106,7 @@ fn suggest_question_conflict() {
symbol,
} => {
assert_eq!(nonterminal, nt("OPT_L"));
assert_eq!(symbol, Symbol::Terminal(TerminalString::quoted(intern("L"))));
assert_eq!(symbol, Symbol::Terminal(TerminalString::quoted(Atom::from("L"))));
}
r => panic!("wrong classification {:#?}", r)
}

View File

@ -48,7 +48,7 @@ pub struct Example {
pub reductions: Vec<Reduction>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ExampleSymbol {
Symbol(Symbol),
Epsilon,
@ -61,7 +61,7 @@ pub struct ExampleStyles {
pub after_cursor: Style,
}
#[derive(Copy, Clone, Debug)]
#[derive(Clone, Debug)]
pub struct Reduction {
pub start: usize,
pub end: usize,
@ -76,7 +76,7 @@ impl Example {
fn lengths(&self) -> Vec<usize> {
self.symbols.iter()
.map(|s| match *s {
ExampleSymbol::Symbol(s) => format!("{}", s).chars().count(),
ExampleSymbol::Symbol(ref s) => format!("{}", s).chars().count(),
ExampleSymbol::Epsilon => 1, // display as " "
})
.chain(Some(0))
@ -103,8 +103,8 @@ impl Example {
}
};
if let &ExampleSymbol::Symbol(s) = symbol {
builder = builder.push(s).styled(style);
if let &ExampleSymbol::Symbol(ref s) = symbol {
builder = builder.push(s.clone()).styled(style);
}
}
@ -165,7 +165,7 @@ impl Example {
// A1 B2 C3 D4 E5 F6
// | |
// +-LongLabel22-+
for &Reduction { start, end, nonterminal } in &self.reductions {
for &Reduction { start, end, ref nonterminal } in &self.reductions {
let nt_len = format!("{}", nonterminal).chars().count();
// Number of symbols we are reducing. This should always
@ -325,13 +325,13 @@ impl Example {
let column = positions[index];
match *ex_symbol {
ExampleSymbol::Symbol(Symbol::Terminal(term)) => {
ExampleSymbol::Symbol(Symbol::Terminal(ref term)) => {
view.write_chars(0,
column,
term.to_string().chars(),
style.with(session.terminal_symbol));
}
ExampleSymbol::Symbol(Symbol::Nonterminal(nt)) => {
ExampleSymbol::Symbol(Symbol::Nonterminal(ref nt)) => {
view.write_chars(0,
column,
nt.to_string().chars(),

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use grammar::repr::*;
use test_util::expect_debug;
use tls::Tls;
@ -6,11 +6,11 @@ use tls::Tls;
use super::{Example, ExampleSymbol, Reduction};
fn nt(t: &str) -> NonterminalString {
NonterminalString(intern(t))
NonterminalString(Atom::from(t))
}
fn term(t: &str) -> TerminalString {
TerminalString::quoted(intern(t))
TerminalString::quoted(Atom::from(t))
}
macro_rules! sym {

View File

@ -20,10 +20,10 @@ impl FirstSets {
changed = false;
for production in grammar.nonterminals.values()
.flat_map(|p| &p.productions) {
let nt = production.nonterminal;
let nt = &production.nonterminal;
let lookahead = this.first0(&production.symbols);
let first_set =
this.map.entry(nt).or_insert_with(|| TokenSet::new());
this.map.entry(nt.clone()).or_insert_with(|| TokenSet::new());
changed |= first_set.union_with(&lookahead);
}
}
@ -40,14 +40,14 @@ impl FirstSets {
for symbol in symbols {
match *symbol {
Symbol::Terminal(t) => {
result.insert(Token::Terminal(t));
Symbol::Terminal(ref t) => {
result.insert(Token::Terminal(t.clone()));
return result;
}
Symbol::Nonterminal(nt) => {
Symbol::Nonterminal(ref nt) => {
let mut empty_prod = false;
match self.map.get(&nt) {
match self.map.get(nt) {
None => {
// This should only happen during set
// construction; it corresponds to an

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use grammar::repr::*;
use lr1::lookahead::{Token, TokenSet};
use lr1::lookahead::Token::EOF;
@ -7,15 +7,15 @@ use test_util::{normalized_grammar};
use super::FirstSets;
pub fn nt(t: &str) -> Symbol {
Symbol::Nonterminal(NonterminalString(intern(t)))
Symbol::Nonterminal(NonterminalString(Atom::from(t)))
}
pub fn term(t: &str) -> Symbol {
Symbol::Terminal(TerminalString::quoted(intern(t)))
Symbol::Terminal(TerminalString::quoted(Atom::from(t)))
}
fn la(t: &str) -> Token {
Token::Terminal(TerminalString::quoted(intern(t)))
Token::Terminal(TerminalString::quoted(Atom::from(t)))
}
fn first0(first: &FirstSets,

View File

@ -68,7 +68,7 @@ impl<'grammar, L> Machine<'grammar, L>
self.state_stack.push(StateIndex(0));
let mut token = tokens.next();
while let Some(terminal) = token {
while let Some(terminal) = token.clone() {
let state = self.top_state();
println!("state={:?}", state);
@ -76,14 +76,14 @@ impl<'grammar, L> Machine<'grammar, L>
// check whether we can shift this token
if let Some(&next_index) = state.shifts.get(&terminal) {
self.data_stack.push(ParseTree::Terminal(terminal));
self.data_stack.push(ParseTree::Terminal(terminal.clone()));
self.state_stack.push(next_index);
token = tokens.next();
} else if let Some(production) = L::reduction(state, Token::Terminal(terminal)) {
} else if let Some(production) = L::reduction(state, &Token::Terminal(terminal.clone())) {
let more = self.reduce(production);
assert!(more);
} else {
return Err((state, Token::Terminal(terminal)));
return Err((state, Token::Terminal(terminal.clone())));
}
}
@ -98,7 +98,7 @@ impl<'grammar, L> Machine<'grammar, L>
// drain now for EOF
loop {
let state = self.top_state();
match L::reduction(state, Token::EOF) {
match L::reduction(state, &Token::EOF) {
None => {
return Err((state, Token::EOF));
}
@ -130,7 +130,7 @@ impl<'grammar, L> Machine<'grammar, L>
}
// construct the new, reduced tree and push it on the stack
let tree = ParseTree::Nonterminal(production.nonterminal, popped);
let tree = ParseTree::Nonterminal(production.nonterminal.clone(), popped);
self.data_stack.push(tree);
// recover the state and extract the "Goto" action
@ -156,21 +156,21 @@ impl Debug for ParseTree {
impl Display for ParseTree {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self {
ParseTree::Nonterminal(id, ref trees) => write!(fmt, "[{}: {}]", id, Sep(", ", trees)),
ParseTree::Terminal(id) => write!(fmt, "{}", id),
ParseTree::Nonterminal(ref id, ref trees) => write!(fmt, "[{}: {}]", id, Sep(", ", trees)),
ParseTree::Terminal(ref id) => write!(fmt, "{}", id),
}
}
}
pub trait LookaheadInterpret: Lookahead {
fn reduction<'grammar>(state: &State<'grammar, Self>,
token: Token)
token: &Token)
-> Option<&'grammar Production>;
}
impl LookaheadInterpret for Nil {
fn reduction<'grammar>(state: &State<'grammar, Self>,
_token: Token)
_token: &Token)
-> Option<&'grammar Production>
{
state.reductions.iter()
@ -181,7 +181,7 @@ impl LookaheadInterpret for Nil {
impl LookaheadInterpret for TokenSet {
fn reduction<'grammar>(state: &State<'grammar, Self>,
token: Token)
token: &Token)
-> Option<&'grammar Production>
{
state.reductions.iter()

View File

@ -37,7 +37,7 @@ impl<'grammar> LaneTableConstruct<'grammar> {
pub fn construct(self) -> Result<Vec<LR1State<'grammar>>, LR1TableConstructionError<'grammar>> {
let states = {
match build::build_lr0_states(self.grammar, self.start_nt) {
match build::build_lr0_states(self.grammar, self.start_nt.clone()) {
Ok(states) => {
// In this case, the grammar is actually
// LR(0). This is very rare -- it means that the
@ -225,13 +225,13 @@ impl<'grammar> LaneTableConstruct<'grammar> {
-> LaneTable<'grammar> {
let state_graph = StateGraph::new(states);
let mut tracer = LaneTracer::new(self.grammar,
self.start_nt,
self.start_nt.clone(),
states,
&self.first_sets,
&state_graph,
actions.len());
for (i, &action) in actions.iter().enumerate() {
tracer.start_trace(inconsistent_state, ConflictIndex::new(i), action);
for (i, action) in actions.iter().enumerate() {
tracer.start_trace(inconsistent_state, ConflictIndex::new(i), action.clone());
}
tracer.into_table()
}

View File

@ -85,7 +85,7 @@ impl<'trace, 'grammar, L: Lookahead> LaneTracer<'trace, 'grammar, L> {
// reached by shifting T. Those predecessors will contain
// an item like `X = ...p (*) T ...s`, which we will then
// process in turn.
let shifted_symbol = item.production.symbols[item.index - 1];
let shifted_symbol = item.production.symbols[item.index - 1].clone();
let unshifted_item = Item { index: item.index - 1, ..item };
let predecessors = self.state_graph.predecessors(state, shifted_symbol);
for predecessor in predecessors {
@ -114,8 +114,8 @@ impl<'trace, 'grammar, L: Lookahead> LaneTracer<'trace, 'grammar, L> {
// have to recurse and search with the previous item.
let state_items = &self.states[state.0].items.vec;
let nonterminal = item.production.nonterminal;
if nonterminal == self.start_nt {
let nonterminal = &item.production.nonterminal;
if *nonterminal == self.start_nt {
// as a special case, if the `X` above is the special, synthetic
// start-terminal, then the only thing that comes afterwards is EOF.
self.table.add_lookahead(state, conflict, &TokenSet::eof());

View File

@ -21,6 +21,6 @@ fn conflicting_actions<'grammar, L: Lookahead>(state: &State<'grammar, L>)
{
let conflicts = L::conflicts(state);
let reductions = conflicts.iter().map(|c| Action::Reduce(c.production));
let actions = conflicts.iter().map(|c| c.action);
let actions = conflicts.iter().map(|c| c.action.clone());
reductions.chain(actions).collect()
}

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use grammar::repr::*;
use test_util::{expect_debug, normalized_grammar};
use lr1::build;
@ -15,7 +15,7 @@ use super::table::*;
macro_rules! tokens {
($($x:expr),*) => {
vec![$(TerminalString::quoted(intern($x))),*]
vec![$(TerminalString::quoted(Atom::from($x))),*]
}
}
@ -31,11 +31,11 @@ fn sym(t: &str) -> Symbol {
}
fn term(t: &str) -> TerminalString {
TerminalString::quoted(intern(t))
TerminalString::quoted(Atom::from(t))
}
fn nt(t: &str) -> NonterminalString {
NonterminalString(intern(t))
NonterminalString(Atom::from(t))
}
fn traverse(states: &[LR0State], tokens: &[&str]) -> StateIndex {
@ -122,10 +122,10 @@ fn build_table<'grammar>(grammar: &'grammar Grammar,
&first_sets,
&state_graph,
conflicting_items.len());
for (i, &conflicting_item) in conflicting_items.iter().enumerate() {
for (i, conflicting_item) in conflicting_items.iter().enumerate() {
tracer.start_trace(inconsistent_state.index,
ConflictIndex::new(i),
conflicting_item);
conflicting_item.clone());
}
tracer.into_table()

View File

@ -35,7 +35,7 @@ impl Lookahead for Nil {
let mut conflicts = vec![];
for (&terminal, &next_state) in &this_state.shifts {
for (terminal, &next_state) in &this_state.shifts {
conflicts.extend(
this_state.reductions
.iter()
@ -43,7 +43,7 @@ impl Lookahead for Nil {
state: index,
lookahead: Nil,
production: production,
action: Action::Shift(terminal, next_state),
action: Action::Shift(terminal.clone(), next_state),
}));
}
@ -66,7 +66,7 @@ impl Lookahead for Nil {
/// I have semi-arbitrarily decided to use the term "token" to mean
/// either one of the terminals of our language, or else the
/// pseudo-symbol EOF that represents "end of input".
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Token {
EOF,
Error,
@ -82,25 +82,25 @@ impl Lookahead for TokenSet {
-> Vec<Conflict<'grammar, Self>> {
let mut conflicts = vec![];
for (&terminal, &next_state) in &this_state.shifts {
let token = Token::Terminal(terminal);
for (terminal, &next_state) in &this_state.shifts {
let token = Token::Terminal(terminal.clone());
let inconsistent =
this_state.reductions
.iter()
.filter_map(|&(ref reduce_tokens, production)| {
if reduce_tokens.contains(token) {
if reduce_tokens.contains(&token) {
Some(production)
} else {
None
}
});
let set = TokenSet::from(token);
let set = TokenSet::from(token.clone());
for production in inconsistent {
conflicts.push(Conflict {
state: this_state.index,
lookahead: set.clone(),
production: production,
action: Action::Shift(terminal, next_state),
action: Action::Shift(terminal.clone(), next_state),
});
}
}
@ -129,9 +129,9 @@ impl Lookahead for TokenSet {
}
impl Token {
pub fn unwrap_terminal(self) -> TerminalString {
match self {
Token::Terminal(t) => t,
pub fn unwrap_terminal(&self) -> &TerminalString {
match *self {
Token::Terminal(ref t) => t,
Token::EOF | Token::Error => panic!("`unwrap_terminal()` invoked but with EOF or Error"),
}
}
@ -181,11 +181,11 @@ impl TokenSet {
})
}
fn bit(&self, lookahead: Token) -> usize {
match lookahead {
fn bit(&self, lookahead: &Token) -> usize {
match *lookahead {
Token::EOF => self.eof_bit(),
Token::Error => self.eof_bit() + 1,
Token::Terminal(t) => with(|terminals| terminals.bits[&t])
Token::Terminal(ref t) => with(|terminals| terminals.bits[t])
}
}
@ -194,7 +194,7 @@ impl TokenSet {
}
pub fn insert(&mut self, lookahead: Token) -> bool {
let bit = self.bit(lookahead);
let bit = self.bit(&lookahead);
self.bit_set.insert(bit)
}
@ -215,7 +215,7 @@ impl TokenSet {
TokenSet { bit_set: bit_set }
}
pub fn contains(&self, token: Token) -> bool {
pub fn contains(&self, token: &Token) -> bool {
self.bit_set.contains(self.bit(token))
}
@ -263,7 +263,7 @@ impl<'iter> Iterator for TokenSetIter<'iter> {
} else if bit == terminals.all.len() {
Token::EOF
} else {
Token::Terminal(terminals.all[bit])
Token::Terminal(terminals.all[bit].clone())
}
})
})

View File

@ -146,7 +146,7 @@ impl<'report, W> ReportGenerator<'report, W>
{
try!(writeln!(self.out, ""));
match conflict.action {
Action::Shift(terminal, state) => {
Action::Shift(ref terminal, state) => {
let max_width = max(terminal.display_len(),
conflict.production.nonterminal.len());
try!(writeln!(self.out, "{}shift/reduce conflict", INDENT_STRING));

View File

@ -31,13 +31,13 @@ impl StateGraph {
graph.extend_with_edges(
state.shifts
.iter()
.map(|(&terminal, &state)| {
(Symbol::Terminal(terminal), state)
.map(|(terminal, &state)| {
(Symbol::Terminal(terminal.clone()), state)
})
.chain(
state.gotos
.iter()
.map(|(&nt, &state)| (Symbol::Nonterminal(nt), state)))
.map(|(nt, &state)| (Symbol::Nonterminal(nt.clone()), state)))
.map(|(symbol, successor)| {
(NodeIndex::new(i), NodeIndex::new(successor.0), symbol)
}));

View File

@ -28,7 +28,7 @@ impl<'trace, 'grammar> Tracer<'trace, 'grammar> {
// some epsilon reductions first if ...s is non-empty. We want
// to trace back until we have (at least) one element of
// context for the reduction.
let nonterminal = item.production.nonterminal; // X
let nonterminal = &item.production.nonterminal; // X
// Add an edge
//
@ -36,7 +36,7 @@ impl<'trace, 'grammar> Tracer<'trace, 'grammar> {
//
// because to reach that item we pushed `...p` from the start
// of `X` and afterwards we expect to see `...s`.
self.trace_graph.add_edge(nonterminal, item, item.symbol_sets());
self.trace_graph.add_edge(nonterminal.clone(), item, item.symbol_sets());
// Walk back to the set of states S where we had:
//
@ -61,9 +61,9 @@ impl<'trace, 'grammar> Tracer<'trace, 'grammar> {
// searching.
fn trace_reduce_from_state(&mut self,
item_state: StateIndex,
nonterminal: NonterminalString) // "Y"
nonterminal: &NonterminalString) // "Y"
{
if !self.visited_set.insert((item_state, nonterminal)) {
if !self.visited_set.insert((item_state, nonterminal.clone())) {
return;
}
for pred_item in self.states[item_state.0]
@ -90,7 +90,7 @@ impl<'trace, 'grammar> Tracer<'trace, 'grammar> {
// [Z = ...p (*) Y ...s] -(...p,Y,...s)-> [Y]
//
// and stop.
self.trace_graph.add_edge(pred_item.to_lr0(), nonterminal, symbol_sets);
self.trace_graph.add_edge(pred_item.to_lr0(), nonterminal.clone(), symbol_sets);
} else {
// Add an edge
//
@ -98,8 +98,8 @@ impl<'trace, 'grammar> Tracer<'trace, 'grammar> {
//
// because we can reduce by consuming `...p`
// tokens, and continue tracing.
self.trace_graph.add_edge(pred_item.production.nonterminal,
nonterminal,
self.trace_graph.add_edge(pred_item.production.nonterminal.clone(),
nonterminal.clone(),
symbol_sets);
self.trace_reduce_item(item_state, pred_item.to_lr0());

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use grammar::repr::*;
use lr1::build_states;
use lr1::core::Item;
@ -12,11 +12,11 @@ use tls::Tls;
use super::super::Tracer;
fn nt(t: &str) -> NonterminalString {
NonterminalString(intern(t))
NonterminalString(Atom::from(t))
}
fn term(t: &str) -> TerminalString {
TerminalString::quoted(intern(t))
TerminalString::quoted(Atom::from(t))
}
macro_rules! terms {
@ -71,7 +71,7 @@ fn backtrace1() {
let semi_item = states[top_state.0].items
.vec
.iter()
.filter(|item| item.lookahead.contains(semi))
.filter(|item| item.lookahead.contains(&semi))
.next()
.unwrap();
@ -259,7 +259,7 @@ fn backtrace_filter() {
let lr1_item = states[top_state.0].items
.vec
.iter()
.filter(|item| item.lookahead.contains(semi))
.filter(|item| item.lookahead.contains(&semi))
.next()
.unwrap();

View File

@ -46,10 +46,10 @@ impl<'trace, 'grammar> Tracer<'trace, 'grammar> {
let pred_states = self.state_graph.trace_back(item_state, symbol_sets.prefix);
// Add the edge `[X] -{...p,Token,...s}-> [X = ...p (*) Token ...s]`
self.trace_graph.add_edge(item.production.nonterminal, item, symbol_sets);
self.trace_graph.add_edge(item.production.nonterminal.clone(), item, symbol_sets);
for pred_state in pred_states {
self.trace_epsilon_edges(pred_state, item.production.nonterminal);
self.trace_epsilon_edges(pred_state, &item.production.nonterminal);
}
self.trace_graph
@ -69,9 +69,9 @@ impl<'trace, 'grammar> Tracer<'trace, 'grammar> {
// So search for items like Z.
fn trace_epsilon_edges(&mut self,
item_state: StateIndex,
nonterminal: NonterminalString) // "Y"
nonterminal: &NonterminalString) // "Y"
{
if self.visited_set.insert((item_state, nonterminal)) {
if self.visited_set.insert((item_state, nonterminal.clone())) {
for pred_item in self.states[item_state.0].items.vec.iter() {
if pred_item.can_shift_nonterminal(nonterminal) {
if pred_item.index > 0 {
@ -79,13 +79,13 @@ impl<'trace, 'grammar> Tracer<'trace, 'grammar> {
//
// [Z = ...p (*) Y ...s] -(...p,Y,...s)-> [Y]
self.trace_graph.add_edge(pred_item,
nonterminal,
nonterminal.clone(),
pred_item.symbol_sets());
} else {
// Trace back any incoming edges to [Z = ...p (*) Y ...].
let pred_nonterminal = pred_item.production.nonterminal;
self.trace_graph.add_edge(pred_nonterminal,
nonterminal,
let pred_nonterminal = &pred_item.production.nonterminal;
self.trace_graph.add_edge(pred_nonterminal.clone(),
nonterminal.clone(),
pred_item.symbol_sets());
self.trace_epsilon_edges(item_state, pred_nonterminal);
}

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use grammar::repr::*;
use lr1::build_states;
use lr1::core::*;
@ -10,7 +10,7 @@ use tls::Tls;
use super::super::Tracer;
fn nt(t: &str) -> NonterminalString {
NonterminalString(intern(t))
NonterminalString(Atom::from(t))
}
#[test]

View File

@ -53,7 +53,7 @@ pub struct TraceGraph<'grammar> {
indices: Map<TraceGraphNode<'grammar>, NodeIndex>,
}
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
pub enum TraceGraphNode<'grammar> {
Nonterminal(NonterminalString),
Item(LR0Item<'grammar>),
@ -72,7 +72,7 @@ impl<'grammar> TraceGraph<'grammar> {
{
let node = node.into();
let graph = &mut self.graph;
*self.indices.entry(node)
*self.indices.entry(node.clone())
.or_insert_with(|| graph.add_node(node))
}
@ -145,12 +145,12 @@ impl<'grammar> Debug for TraceGraphEdge<'grammar> {
impl<'grammar> Debug for TraceGraph<'grammar> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
let mut s = fmt.debug_list();
for (&node, &index) in &self.indices {
for (node, &index) in &self.indices {
for edge in self.graph.edges_directed(index, EdgeDirection::Outgoing)
{
let label = edge.weight();
s.entry(&TraceGraphEdge { from: node,
to: self.graph[edge.target()],
s.entry(&TraceGraphEdge { from: node.clone(),
to: self.graph[edge.target()].clone(),
label: (label.prefix,
label.cursor,
label.suffix) });
@ -349,7 +349,7 @@ impl<'graph, 'grammar> PathEnumerator<'graph, 'grammar> {
let cursor = symbols.len();
match self.stack[1].symbol_sets.cursor {
Some(&s) => symbols.push(ExampleSymbol::Symbol(s)),
Some(s) => symbols.push(ExampleSymbol::Symbol(s.clone())),
None => if self.stack[1].symbol_sets.prefix.is_empty() {
symbols.push(ExampleSymbol::Epsilon)
} else {
@ -370,8 +370,8 @@ impl<'graph, 'grammar> PathEnumerator<'graph, 'grammar> {
.rev()
.map(|state| {
let nonterminal = match self.graph.graph[state.index] {
TraceGraphNode::Nonterminal(nonterminal) => nonterminal,
TraceGraphNode::Item(item) => item.production.nonterminal,
TraceGraphNode::Nonterminal(ref nonterminal) => nonterminal.clone(),
TraceGraphNode::Item(ref item) => item.production.nonterminal.clone(),
};
let reduction = Reduction {
start: cursors.0,

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use grammar::repr::*;
use lr1::core::*;
use test_util::expect_debug;
@ -6,7 +6,7 @@ use tls::Tls;
macro_rules! nt {
($x:ident) => {
NonterminalString(intern(stringify!($x)))
NonterminalString(Atom::from(stringify!($x)))
}
}

View File

@ -1,6 +1,6 @@
#![allow(dead_code)]
use intern::intern;
use string_cache::DefaultAtom as Atom;
use normalize::{NormError, NormResult};
use petgraph::graph::{Graph, NodeIndex};
use grammar::consts::INLINE;
@ -46,11 +46,11 @@ impl<'grammar> NonterminalGraph<'grammar> {
}
fn create_nodes(&mut self) {
let inline = intern(INLINE);
for (&name, data) in &self.grammar.nonterminals {
let inline = Atom::from(INLINE);
for (name, data) in &self.grammar.nonterminals {
if data.annotations.iter().any(|a| a.id == inline) {
let index = self.graph.add_node(name);
self.nonterminal_map.insert(name, index);
let index = self.graph.add_node(name.clone());
self.nonterminal_map.insert(name.clone(), index);
}
}
}
@ -62,10 +62,10 @@ impl<'grammar> NonterminalGraph<'grammar> {
None => continue, // this is not an inlined nonterminal
};
for &symbol in &production.symbols {
match symbol {
Symbol::Nonterminal(to) => {
if let Some(&to_index) = self.nonterminal_map.get(&to) {
for symbol in &production.symbols {
match *symbol {
Symbol::Nonterminal(ref to) => {
if let Some(&to_index) = self.nonterminal_map.get(to) {
self.graph.add_edge(from_index, to_index, ());
}
}
@ -90,7 +90,7 @@ impl<'grammar> NonterminalGraph<'grammar> {
source: NodeIndex)
-> NormResult<()>
{
let nt = *self.graph.node_weight(source).unwrap();
let nt = self.graph.node_weight(source).unwrap();
match states[source.index()] {
WalkState::NotVisited => {
@ -99,7 +99,7 @@ impl<'grammar> NonterminalGraph<'grammar> {
try!(self.walk(states, result, target));
}
states[source.index()] = WalkState::Visited;
result.push(nt);
result.push(nt.clone());
Ok(())
}
WalkState::Visited => {

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use grammar::repr::NonterminalString;
use normalize::lower_helper;
use parser;
@ -40,7 +40,7 @@ fn test_inline_order() {
#[inline] C: () = A;
"#).unwrap();
let grammar = lower_helper(&Session::test(), grammar, true).unwrap();
let a = NonterminalString(intern("A"));
let c = NonterminalString(intern("C"));
let a = NonterminalString(Atom::from("A"));
let c = NonterminalString(Atom::from("C"));
assert_eq!(inline_order(&grammar).unwrap(), vec![a, c]);
}

View File

@ -13,26 +13,26 @@ mod test;
pub fn inline(mut grammar: Grammar) -> NormResult<Grammar> {
let order = try!(graph::inline_order(&grammar));
for nt in order {
inline_nt(&mut grammar, nt);
inline_nt(&mut grammar, &nt);
}
Ok(grammar)
}
fn inline_nt(grammar: &mut Grammar, inline_nt: NonterminalString) {
fn inline_nt(grammar: &mut Grammar, inline_nt: &NonterminalString) {
let inline_productions: Vec<_> = grammar.productions_for(inline_nt).iter().cloned().collect();
for (_, data) in &mut grammar.nonterminals {
let mut new_productions = vec![];
let mut new_action_fn_defns = vec![];
for into_production in &data.productions {
if !into_production.symbols.contains(&Symbol::Nonterminal(inline_nt)) {
if !into_production.symbols.contains(&Symbol::Nonterminal(inline_nt.clone())) {
new_productions.push(into_production.clone());
continue;
}
let mut inliner = Inliner {
action_fn_defns: &grammar.action_fn_defns,
inline_nonterminal: inline_nt,
inline_nonterminal: inline_nt.clone(),
into_production: into_production,
inline_fallible: 0,
inline_productions: &inline_productions,
@ -104,20 +104,20 @@ impl<'a> Inliner<'a> {
let prod_symbols: Vec<Symbol> =
self.new_symbols.iter()
.flat_map(|sym| match *sym {
InlinedSymbol::Original(s) => vec![s],
InlinedSymbol::Original(ref s) => vec![s.clone()],
InlinedSymbol::Inlined(_, ref s) => s.clone(),
})
.collect();
self.new_productions.push(Production {
nonterminal: self.into_production.nonterminal,
nonterminal: self.into_production.nonterminal.clone(),
span: self.into_production.span,
symbols: prod_symbols,
action: action_fn,
});
} else {
let next_symbol = into_symbols[0];
match next_symbol {
Symbol::Nonterminal(n) if n == self.inline_nonterminal => {
let next_symbol = &into_symbols[0];
match *next_symbol {
Symbol::Nonterminal(ref n) if *n == self.inline_nonterminal => {
// Replace the current symbol with each of the
// `inline_productions` in turn.
for inline_production in self.inline_productions {
@ -142,7 +142,7 @@ impl<'a> Inliner<'a> {
}
}
_ => {
self.new_symbols.push(InlinedSymbol::Original(next_symbol));
self.new_symbols.push(InlinedSymbol::Original(next_symbol.clone()));
self.inline(&into_symbols[1..]);
self.new_symbols.pop();
}

View File

@ -1,6 +1,6 @@
use grammar::parse_tree::NonterminalString;
use grammar::repr::Grammar;
use intern::intern;
use string_cache::DefaultAtom as Atom;
use normalize::{self, NormResult};
use parser;
use session::Session;
@ -53,7 +53,7 @@ fn sri() {
};
"#).unwrap();
let nt = NonterminalString(intern("E"));
let nt = NonterminalString(Atom::from("E"));
// After inlining, we expect:
//
@ -62,7 +62,7 @@ fn sri() {
// E = "&" "L" E
//
// Note that the `()` also gets inlined.
let e_productions = grammar.productions_for(nt);
let e_productions = grammar.productions_for(&nt);
assert_eq!(e_productions.len(), 3);
assert_eq!(format!("{:?}", e_productions[0].symbols), r#"["L"]"#);
assert_eq!(format!("{:?}", e_productions[1].symbols), r#"["&", E]"#);
@ -86,10 +86,10 @@ ET: () = {
"enum" "{" "}" => ()
};
"#).unwrap();
let nt = NonterminalString(intern("E"));
let nt = NonterminalString(Atom::from("E"));
// The problem in issue #55 was that we would inline both `AT*`
// the same way, so we ended up with `E = X { ET }` and `E = X {
// AT+ ET AT+ }` but not `E = X { AT+ ET }` or `E = X { ET AT+ }`.
assert!(grammar.productions_for(nt).len() == 4);
assert!(grammar.productions_for(&nt).len() == 4);
}

View File

@ -1,7 +1,7 @@
//! Lower
//!
use intern::{self, intern, InternedString};
use string_cache::DefaultAtom as Atom;
use normalize::NormResult;
use normalize::norm_util::{self, Symbols};
use grammar::consts::*;
@ -49,7 +49,7 @@ impl<'s> LowerState<'s> {
let mut token_span = None;
let internal_token_path = Path {
absolute: false,
ids: vec![intern("Token")],
ids: vec![Atom::from("Token")],
};
for item in grammar.items {
@ -68,7 +68,7 @@ impl<'s> LowerState<'s> {
token_span = Some(grammar.span);
let span = grammar.span;
let input_str = r::TypeRepr::Ref {
lifetime: Some(intern(INPUT_LIFETIME)),
lifetime: Some(Atom::from(INPUT_LIFETIME)),
mutable: false,
referent: Box::new(r::TypeRepr::Nominal(r::NominalTypeRepr {
path: r::Path::str(),
@ -94,7 +94,7 @@ impl<'s> LowerState<'s> {
]),
};
(match_entry.user_name, pattern)
(match_entry.user_name.clone(), pattern)
}));
self.intern_token = Some(data);
}
@ -105,7 +105,7 @@ impl<'s> LowerState<'s> {
self.conversions.extend(enum_token.conversions
.iter()
.map(|conversion| {
(conversion.from,
(conversion.from.clone(),
conversion.to.map(&mut |t| {
t.type_repr()
}))
@ -114,7 +114,7 @@ impl<'s> LowerState<'s> {
}
pt::GrammarItem::Nonterminal(nt) => {
let nt_name = nt.name;
let nt_name = &nt.name;
let productions: Vec<_> = nt.alternatives
.into_iter()
.map(|alt| {
@ -127,16 +127,16 @@ impl<'s> LowerState<'s> {
&symbols,
alt.action);
r::Production {
nonterminal: nt_name,
nonterminal: nt_name.clone(),
span: alt.span,
symbols: symbols,
action: action,
}
})
.collect();
self.nonterminals.insert(nt_name,
self.nonterminals.insert(nt_name.clone(),
r::NonterminalData {
name: nt_name,
name: nt_name.clone(),
visibility: nt.visibility.clone(),
annotations: nt.annotations,
span: nt.span,
@ -150,7 +150,7 @@ impl<'s> LowerState<'s> {
.iter()
.map(|p| {
r::Parameter {
name: p.name,
name: p.name.clone(),
ty: p.ty.type_repr(),
}
})
@ -173,7 +173,7 @@ impl<'s> LowerState<'s> {
let mut all_terminals: Vec<_> = self.conversions
.iter()
.map(|c| c.0)
.map(|c| c.0.clone())
.chain(if self.uses_error_recovery {
Some(TerminalString::Error)
} else {
@ -222,32 +222,32 @@ impl<'s> LowerState<'s> {
// with a rule like:
//
// __Foo = Foo;
let fake_name = pt::NonterminalString(intern(&format!("{}{}",
self.prefix,
nt.name)));
let nt_type = self.types.nonterminal_type(nt.name).clone();
self.types.add_type(fake_name, nt_type.clone());
let fake_name = pt::NonterminalString(Atom::from(format!("{}{}",
self.prefix,
nt.name)));
let nt_type = self.types.nonterminal_type(&nt.name).clone();
self.types.add_type(fake_name.clone(), nt_type.clone());
let expr = pt::ExprSymbol {
symbols: vec![pt::Symbol::new(nt.span,
pt::SymbolKind::Nonterminal(fake_name))],
pt::SymbolKind::Nonterminal(fake_name.clone()))],
};
let symbols = vec![r::Symbol::Nonterminal(nt.name)];
let symbols = vec![r::Symbol::Nonterminal(nt.name.clone())];
let action_fn = self.action_fn(nt_type, false, &expr, &symbols, None);
let production = r::Production {
nonterminal: fake_name,
nonterminal: fake_name.clone(),
symbols: symbols,
action: action_fn,
span: nt.span,
};
self.nonterminals.insert(fake_name,
self.nonterminals.insert(fake_name.clone(),
r::NonterminalData {
name: fake_name,
name: fake_name.clone(),
visibility: nt.visibility.clone(),
annotations: vec![],
span: nt.span,
productions: vec![production],
});
(nt.name, fake_name)
(nt.name.clone(), fake_name)
})
.collect()
}
@ -327,7 +327,7 @@ 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:
let arg_patterns = patterns(names.iter().map(|&(index, name, _)| (index, name)),
let arg_patterns = patterns(names.iter().map(|&(index, ref name, _)| (index, name.clone())),
symbols.len());
@ -337,17 +337,17 @@ impl<'s> LowerState<'s> {
action
}
norm_util::Presence::Normal => {
let name_str : String = intern::read(|interner| {
let name_strs: Vec<_> = names.iter().map(|&(_,name,_)| interner.data(name)).collect();
let name_str : String = {
let name_strs: Vec<_> = names.iter().map(|&(_,ref name,_)| name.as_ref()).collect();
name_strs.join(", ")
});
};
action.replace("<>", &name_str)
}
norm_util::Presence::InCurlyBrackets => {
let name_str = intern::read(|interner| {
let name_strs: Vec<_> = names.iter().map(|&(_,name,_)| format!("{0}:{0}", interner.data(name))).collect();
let name_str = {
let name_strs: Vec<_> = names.iter().map(|&(_,ref name,_)| format!("{0}:{0}", &*name)).collect();
name_strs.join(", ")
});
};
action.replace("<>", &name_str)
}
}
@ -370,10 +370,10 @@ impl<'s> LowerState<'s> {
.map(|&(index, _)| index)
.zip(names.iter().cloned()),
symbols.len());
let name_str = intern::read(|interner| {
let name_strs: Vec<_> = names.iter().map(|&n| interner.data(n)).collect();
let name_str = {
let name_strs: Vec<_> = names.iter().map(|n| n.as_ref()).collect();
name_strs.join(", ")
});
};
let action = action.replace("<>", &name_str);
r::ActionFnDefn {
fallible: fallible,
@ -402,8 +402,8 @@ impl<'s> LowerState<'s> {
fn symbol(&mut self, symbol: &pt::Symbol) -> r::Symbol {
match symbol.kind {
pt::SymbolKind::Terminal(id) => r::Symbol::Terminal(id),
pt::SymbolKind::Nonterminal(id) => r::Symbol::Nonterminal(id),
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::Error => {
self.uses_error_recovery = true;
@ -422,26 +422,26 @@ impl<'s> LowerState<'s> {
}
}
fn fresh_name(&self, i: usize) -> InternedString {
intern(&format!("{}{}", self.prefix, i))
fn fresh_name(&self, i: usize) -> Atom {
Atom::from(format!("{}{}", self.prefix, i))
}
}
fn patterns<I>(mut chosen: I, num_args: usize) -> Vec<InternedString>
where I: Iterator<Item = (usize, InternedString)>
fn patterns<I>(mut chosen: I, num_args: usize) -> Vec<Atom>
where I: Iterator<Item = (usize, Atom)>
{
let blank = intern("_");
let blank = Atom::from("_");
let mut next_chosen = chosen.next();
let result = (0..num_args)
.map(|index| {
match next_chosen {
Some((chosen_index, chosen_name)) if chosen_index == index => {
match next_chosen.clone() {
Some((chosen_index, ref chosen_name)) if chosen_index == index => {
next_chosen = chosen.next();
chosen_name
chosen_name.clone()
}
_ => blank,
_ => blank.clone(),
}
})
.collect();

View File

@ -1,5 +1,5 @@
use std::collections::{HashMap, HashSet};
use intern::{intern, read, InternedString};
use string_cache::DefaultAtom as Atom;
use grammar::consts::INLINE;
use grammar::parse_tree::{ActionKind, Alternative, Annotation,
Condition, ConditionOp,
@ -32,7 +32,7 @@ pub fn expand_macros(input: Grammar) -> NormResult<Grammar> {
let macro_defs: HashMap<_, _> =
macro_defs.into_iter()
.map(|md| match md {
GrammarItem::Nonterminal(data) => (data.name, data),
GrammarItem::Nonterminal(ref data) => (data.name.clone(), data.clone()),
_ => unreachable!()
})
.collect();
@ -121,7 +121,7 @@ impl MacroExpander {
fn replace_symbol(&mut self, symbol: &mut Symbol) {
match symbol.kind {
SymbolKind::AmbiguousId(id) => {
SymbolKind::AmbiguousId(ref id) => {
panic!("ambiguous id `{}` encountered after name resolution", id)
}
SymbolKind::Macro(ref mut m) => {
@ -151,8 +151,8 @@ impl MacroExpander {
// only symbols we intend to expand fallthrough to here
let key = NonterminalString(intern(&symbol.canonical_form()));
let replacement = Symbol { span: symbol.span, kind: SymbolKind::Nonterminal(key) };
let key = NonterminalString(Atom::from(symbol.canonical_form()));
let replacement = Symbol { span: symbol.span, kind: SymbolKind::Nonterminal(key.clone()) };
let to_expand = mem::replace(symbol, replacement);
if self.expansion_set.insert(key) {
self.expansion_stack.push(to_expand);
@ -163,7 +163,7 @@ impl MacroExpander {
// Macro expansion
fn expand_macro_symbol(&mut self, span: Span, msym: MacroSymbol) -> NormResult<GrammarItem> {
let msym_name = NonterminalString(intern(&msym.canonical_form()));
let msym_name = NonterminalString(Atom::from(msym.canonical_form()));
let mdef = match self.macro_defs.get(&msym.name) {
Some(v) => v,
@ -228,18 +228,18 @@ impl MacroExpander {
TypeRef::Nominal { ref path, ref types } =>
TypeRef::Nominal { path: path.clone(),
types: self.macro_expand_type_refs(args, types) },
TypeRef::Lifetime(id) =>
TypeRef::Lifetime(id),
TypeRef::Lifetime(ref id) =>
TypeRef::Lifetime(id.clone()),
TypeRef::OfSymbol(ref sym) =>
TypeRef::OfSymbol(sym.clone()),
TypeRef::Ref { lifetime, mutable, ref referent } =>
TypeRef::Ref { lifetime: lifetime,
TypeRef::Ref { ref lifetime, mutable, ref referent } =>
TypeRef::Ref { lifetime: lifetime.clone(),
mutable: mutable,
referent: Box::new(self.macro_expand_type_ref(args, referent)) },
TypeRef::Id(id) => {
match args.get(&NonterminalString(id)) {
TypeRef::Id(ref id) => {
match args.get(&NonterminalString(id.clone())) {
Some(sym) => TypeRef::OfSymbol(sym.clone()),
None => TypeRef::Nominal { path: Path::from_id(id),
None => TypeRef::Nominal { path: Path::from_id(id.clone()),
types: vec![] },
}
}
@ -253,12 +253,12 @@ impl MacroExpander {
{
if let Some(ref c) = *opt_cond {
match args[&c.lhs] {
SymbolKind::Terminal(TerminalString::Literal(TerminalLiteral::Quoted(lhs))) => {
SymbolKind::Terminal(TerminalString::Literal(TerminalLiteral::Quoted(ref lhs))) => {
match c.op {
ConditionOp::Equals => Ok(lhs == c.rhs),
ConditionOp::NotEquals => Ok(lhs != c.rhs),
ConditionOp::Match => self.re_match(c.span, lhs, c.rhs),
ConditionOp::NotMatch => Ok(!try!(self.re_match(c.span, lhs, c.rhs))),
ConditionOp::Equals => Ok(lhs == &c.rhs),
ConditionOp::NotEquals => Ok(lhs != &c.rhs),
ConditionOp::Match => self.re_match(c.span, lhs, &c.rhs),
ConditionOp::NotMatch => Ok(!try!(self.re_match(c.span, lhs, &c.rhs))),
}
}
ref lhs => {
@ -273,14 +273,12 @@ impl MacroExpander {
}
}
fn re_match(&self, span: Span, lhs: InternedString, regex: InternedString) -> NormResult<bool> {
read(|interner| {
let re = match Regex::new(interner.data(regex)) {
Ok(re) => re,
Err(err) => return_err!(span, "invalid regular expression `{}`: {}", regex, err),
};
Ok(re.is_match(interner.data(lhs)))
})
fn re_match(&self, span: Span, lhs: &Atom, regex: &Atom) -> NormResult<bool> {
let re = match Regex::new(&regex) {
Ok(re) => re,
Err(err) => return_err!(span, "invalid regular expression `{}`: {}", regex, err),
};
Ok(re.is_match(&lhs))
}
fn macro_expand_symbols(&self,
@ -307,16 +305,16 @@ impl MacroExpander {
let kind = match symbol.kind {
SymbolKind::Expr(ref expr) =>
SymbolKind::Expr(self.macro_expand_expr_symbol(args, expr)),
SymbolKind::Terminal(id) =>
SymbolKind::Terminal(id),
SymbolKind::Nonterminal(id) =>
match args.get(&id) {
SymbolKind::Terminal(ref id) =>
SymbolKind::Terminal(id.clone()),
SymbolKind::Nonterminal(ref id) =>
match args.get(id) {
Some(sym) => sym.clone(),
None => SymbolKind::Nonterminal(id),
None => SymbolKind::Nonterminal(id.clone()),
},
SymbolKind::Macro(ref msym) =>
SymbolKind::Macro(MacroSymbol {
name: msym.name,
name: msym.name.clone(),
args: self.macro_expand_symbols(args, &msym.args),
}),
SymbolKind::Repeat(ref r) =>
@ -326,15 +324,15 @@ impl MacroExpander {
})),
SymbolKind::Choose(ref sym) =>
SymbolKind::Choose(Box::new(self.macro_expand_symbol(args, sym))),
SymbolKind::Name(id, ref sym) =>
SymbolKind::Name(id, 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::Lookahead =>
SymbolKind::Lookahead,
SymbolKind::Lookbehind =>
SymbolKind::Lookbehind,
SymbolKind::Error =>
SymbolKind::Error,
SymbolKind::AmbiguousId(id) =>
SymbolKind::AmbiguousId(ref id) =>
panic!("ambiguous id `{}` encountered after name resolution", id),
};
@ -345,11 +343,11 @@ impl MacroExpander {
// Expr expansion
fn expand_expr_symbol(&mut self, span: Span, expr: ExprSymbol) -> NormResult<GrammarItem> {
let name = NonterminalString(intern(&expr.canonical_form()));
let name = NonterminalString(Atom::from(expr.canonical_form()));
let ty_ref = match norm_util::analyze_expr(&expr) {
Symbols::Named(names) => {
let (_, 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",
@ -381,9 +379,9 @@ impl MacroExpander {
// Expr expansion
fn expand_repeat_symbol(&mut self, span: Span, repeat: RepeatSymbol) -> NormResult<GrammarItem> {
let name = NonterminalString(intern(&repeat.canonical_form()));
let v = intern("v");
let e = intern("e");
let name = NonterminalString(Atom::from(repeat.canonical_form()));
let v = Atom::from("v");
let e = Atom::from("e");
let base_symbol_ty = TypeRef::OfSymbol(repeat.symbol.kind.clone());
@ -439,7 +437,7 @@ impl MacroExpander {
Ok(GrammarItem::Nonterminal(NonterminalData {
visibility: Visibility::Priv,
span: span,
name: name,
name: name.clone(),
annotations: vec![],
args: vec![],
type_decl: Some(ty_ref),
@ -505,7 +503,7 @@ impl MacroExpander {
fn expand_lookaround_symbol(&mut self, span: Span, name: &str, action: ActionKind)
-> NormResult<GrammarItem> {
let name = NonterminalString(intern(name));
let name = NonterminalString(Atom::from(name));
Ok(GrammarItem::Nonterminal(NonterminalData {
visibility: Visibility::Priv,
span: span,
@ -537,6 +535,6 @@ fn action(s: &str) -> Option<ActionKind> {
fn inline(span: Span) -> Vec<Annotation> {
vec![Annotation {
id_span: span,
id: intern(INLINE),
id: Atom::from(INLINE),
}]
}

View File

@ -1,4 +1,4 @@
use intern::InternedString;
use string_cache::DefaultAtom as Atom;
use grammar::parse_tree::{ActionKind, Alternative, ExprSymbol, Symbol, SymbolKind};
#[derive(Debug)]
@ -9,7 +9,7 @@ pub enum AlternativeAction<'a> {
#[derive(Debug)]
pub enum Symbols<'a> {
Named(Vec<(usize, InternedString, &'a Symbol)>),
Named(Vec<(usize, Atom, &'a Symbol)>),
Anon(Vec<(usize, &'a Symbol)>),
}
@ -29,7 +29,7 @@ pub fn analyze_expr<'a>(expr: &'a ExprSymbol) -> Symbols<'a> {
.iter()
.enumerate()
.filter_map(|(idx, sym)| match sym.kind {
SymbolKind::Name(id, ref sub) => Some((idx, id, &**sub)),
SymbolKind::Name(ref id, ref sub) => Some((idx, id.clone(), &**sub)),
_ => None,
})
.collect();

View File

@ -6,7 +6,7 @@ use super::norm_util::{self, Symbols};
use grammar::consts::*;
use grammar::parse_tree::*;
use grammar::repr as r;
use intern::{intern, InternedString};
use string_cache::DefaultAtom as Atom;
use collections::{Multimap, set};
use util::Sep;
@ -43,10 +43,10 @@ struct Validator<'grammar> {
impl<'grammar> Validator<'grammar> {
fn validate(&self) -> NormResult<()> {
let allowed_names = vec![intern(LALR),
intern(TABLE_DRIVEN),
intern(RECURSIVE_ASCENT),
intern(TEST_ALL)];
let allowed_names = vec![Atom::from(LALR),
Atom::from(TABLE_DRIVEN),
Atom::from(RECURSIVE_ASCENT),
Atom::from(TEST_ALL)];
for annotation in &self.grammar.annotations {
if !allowed_names.contains(&annotation.id) {
return_err!(annotation.id_span,
@ -105,7 +105,7 @@ impl<'grammar> Validator<'grammar> {
}
}
let allowed_names = vec![intern(LOCATION), intern(ERROR)];
let allowed_names = vec![Atom::from(LOCATION), Atom::from(ERROR)];
let mut new_names = set();
for associated_type in &data.associated_types {
if !allowed_names.contains(&associated_type.type_name) {
@ -115,7 +115,7 @@ impl<'grammar> Validator<'grammar> {
try one of the following: {}",
associated_type.type_name,
Sep(", ", &allowed_names));
} else if !new_names.insert(associated_type.type_name) {
} else if !new_names.insert(associated_type.type_name.clone()) {
return_err!(
associated_type.type_span,
"associated type `{}` already specified",
@ -127,15 +127,15 @@ impl<'grammar> Validator<'grammar> {
if data.visibility.is_pub() && !data.args.is_empty() {
return_err!(data.span, "macros cannot be marked public");
}
let inline_annotation = intern(INLINE);
let known_annotations = vec![inline_annotation];
let inline_annotation = Atom::from(INLINE);
let known_annotations = vec![inline_annotation.clone()];
let mut found_annotations = set();
for annotation in &data.annotations {
if !known_annotations.contains(&annotation.id) {
return_err!(annotation.id_span,
"unrecognized annotation `{}`",
annotation.id);
} else if !found_annotations.insert(annotation.id) {
} else if !found_annotations.insert(annotation.id.clone()) {
return_err!(annotation.id_span,
"duplicate annotation `{}`",
annotation.id);
@ -209,10 +209,10 @@ impl<'grammar> Validator<'grammar> {
})
.collect();
let named: Multimap<InternedString, Vec<&Symbol>> =
let named: Multimap<Atom, Vec<&Symbol>> =
expr.symbols.iter()
.filter_map(|sym| match sym.kind {
SymbolKind::Name(nt, _) => Some((nt, sym)),
SymbolKind::Name(ref nt, _) => Some((nt.clone(), sym)),
_ => None,
})
.collect();
@ -275,7 +275,7 @@ impl<'grammar> Validator<'grammar> {
if let Some(extern_token) = self.extern_token {
if extern_token.enum_token.is_some() {
// otherwise, the Location type must be specified.
let loc = intern(LOCATION);
let loc = Atom::from(LOCATION);
if self.extern_token.unwrap().associated_type(loc).is_none() {
return_err!(
symbol.span,

View File

@ -4,7 +4,7 @@
use super::{NormResult, NormError};
use grammar::parse_tree::*;
use intern::{InternedString};
use string_cache::DefaultAtom as Atom;
use collections::{map, Map};
#[cfg(test)]
@ -21,7 +21,7 @@ fn resolve_in_place(grammar: &mut Grammar) -> NormResult<()> {
grammar.items
.iter()
.filter_map(|item| item.as_nonterminal())
.map(|nt| (nt.span, nt.name.0, Def::Nonterminal(nt.args.len())));
.map(|nt| (nt.span.clone(), nt.name.0.clone(), Def::Nonterminal(nt.args.len())));
let terminal_identifiers =
grammar.items
@ -31,7 +31,7 @@ fn resolve_in_place(grammar: &mut Grammar) -> NormResult<()> {
.flat_map(|enum_token| &enum_token.conversions)
.filter_map(|conversion| match conversion.from {
TerminalString::Literal(..) | TerminalString::Error => None,
TerminalString::Bare(id) => Some((conversion.span, id, Def::Terminal)),
TerminalString::Bare(ref id) => Some((conversion.span, id.clone(), Def::Terminal)),
});
// Extract all the bare identifiers that appear in the RHS of a `match` declaration.
@ -49,7 +49,7 @@ fn resolve_in_place(grammar: &mut Grammar) -> NormResult<()> {
.flat_map(|match_token| &match_token.contents)
.flat_map(|match_contents| &match_contents.items)
.filter_map(|item| match *item {
MatchItem::Mapped(_, TerminalString::Bare(id), _) => Some((item.span(), id, Def::Terminal)),
MatchItem::Mapped(_, TerminalString::Bare(ref id), _) => Some((item.span(), id.clone(), Def::Terminal)),
_ => None
});
@ -58,7 +58,7 @@ fn resolve_in_place(grammar: &mut Grammar) -> NormResult<()> {
let mut identifiers = map();
for (span, id, def) in all_identifiers {
if let Some(old_def) = identifiers.insert(id, def) {
if let Some(old_def) = identifiers.insert(id.clone(), def) {
let description = def.description();
let old_description = old_def.description();
if description == old_description {
@ -99,7 +99,7 @@ enum Def {
#[derive(Debug)]
struct ScopeChain<'scope> {
previous: Option<&'scope ScopeChain<'scope>>,
identifiers: Map<InternedString, Def>,
identifiers: Map<Atom, Def>,
}
impl Def {
@ -139,13 +139,13 @@ impl Validator {
fn validate_macro_args(&self,
span: Span,
args: &[NonterminalString])
-> NormResult<Map<InternedString, Def>> {
-> NormResult<Map<Atom, Def>> {
for (index, arg) in args.iter().enumerate() {
if args[..index].contains(&arg) {
return_err!(span, "multiple macro arguments declared with the name `{}`", arg);
}
}
Ok(args.iter().map(|&nt| (nt.0, Def::MacroArg)).collect())
Ok(args.iter().map(|nt| (nt.0.clone(), Def::MacroArg)).collect())
}
fn validate_alternative(&self,
@ -153,7 +153,7 @@ impl Validator {
alternative: &mut Alternative)
-> NormResult<()> {
if let Some(ref condition) = alternative.condition {
let def = try!(self.validate_id(scope, condition.span, condition.lhs.0));
let def = try!(self.validate_id(scope, condition.span.clone(), &condition.lhs.0));
match def {
Def::MacroArg => { /* OK */ }
_ => {
@ -189,16 +189,16 @@ impl Validator {
SymbolKind::Expr(ref mut expr) => {
try!(self.validate_expr(scope, expr));
}
SymbolKind::AmbiguousId(name) => {
try!(self.rewrite_ambiguous_id(scope, name, symbol));
SymbolKind::AmbiguousId(_) => {
try!(self.rewrite_ambiguous_id(scope, symbol));
}
SymbolKind::Terminal(_) => {
/* see postvalidate! */
}
SymbolKind::Nonterminal(id) => {
SymbolKind::Nonterminal(ref id) => {
// in normal operation, the parser never produces Nonterminal(_) entries,
// but during testing we do produce nonterminal entries
let def = try!(self.validate_id(scope, symbol.span, id.0));
let def = try!(self.validate_id(scope, symbol.span, &id.0));
match def {
Def::Nonterminal(0) |
Def::MacroArg => {
@ -213,7 +213,7 @@ impl Validator {
}
SymbolKind::Macro(ref mut msym) => {
debug_assert!(msym.args.len() > 0);
let def = try!(self.validate_id(scope, symbol.span, msym.name.0));
let def = try!(self.validate_id(scope, symbol.span, &msym.name.0));
match def {
Def::Nonterminal(0) |
Def::Terminal |
@ -250,10 +250,14 @@ impl Validator {
fn rewrite_ambiguous_id(&self,
scope: &ScopeChain,
id: InternedString,
symbol: &mut Symbol)
-> NormResult<()> {
symbol.kind = match try!(self.validate_id(scope, symbol.span, id)) {
let id = if let SymbolKind::AmbiguousId(ref name) = symbol.kind {
name.clone()
} else {
panic!("Should never happen.");
};
symbol.kind = match try!(self.validate_id(scope, symbol.span, &id)) {
Def::MacroArg |
Def::Nonterminal(0) => SymbolKind::Nonterminal(NonterminalString(id)),
Def::Terminal => SymbolKind::Terminal(TerminalString::Bare(id)),
@ -265,7 +269,7 @@ impl Validator {
fn validate_id(&self,
scope: &ScopeChain,
span: Span,
id: InternedString)
id: &Atom)
-> NormResult<Def> {
match scope.def(id) {
Some(def) => Ok(def),
@ -275,8 +279,8 @@ impl Validator {
}
impl<'scope> ScopeChain<'scope> {
fn def(&self, id: InternedString) -> Option<Def> {
self.identifiers.get(&id)
fn def(&self, id: &Atom) -> Option<Def> {
self.identifiers.get(id)
.cloned()
.or_else(|| self.previous.and_then(|s| s.def(id)))
}

View File

@ -7,7 +7,7 @@
use super::{NormResult, NormError};
use intern::{self, intern};
use string_cache::DefaultAtom as Atom;
use lexer::re;
use lexer::dfa::{self, DFAConstructionError, Precedence};
use lexer::nfa::NFAConstructionError::*;
@ -27,7 +27,7 @@ pub fn validate(mut grammar: Grammar) -> NormResult<Grammar> {
TokenMode::Extern {
conversions: enum_token.conversions
.iter()
.map(|conversion| conversion.from)
.map(|conversion| conversion.from.clone())
.collect()
}
} else {
@ -120,14 +120,14 @@ impl MatchBlock {
let precedence = &match_token.contents.len() - idx;
for item in &mc.items {
match *item {
MatchItem::Unmapped(sym, span) => {
MatchItem::Unmapped(ref sym, span) => {
match_block.add_match_entry(precedence,
sym,
TerminalString::Literal(sym),
sym.clone(),
TerminalString::Literal(sym.clone()),
span)?;
}
MatchItem::Mapped(sym, user, span) => {
match_block.add_match_entry(precedence, sym, user, span)?;
MatchItem::Mapped(ref sym, ref user, span) => {
match_block.add_match_entry(precedence, sym.clone(), user.clone(), span)?;
}
MatchItem::CatchAll(_) => {
match_block.catch_all = true;
@ -148,12 +148,12 @@ impl MatchBlock {
user_name: TerminalString,
span: Span)
-> NormResult<()> {
if let Some(_old_span) = self.spans.insert(sym, span) {
if let Some(_old_span) = self.spans.insert(sym.clone(), span) {
return_err!(span, "multiple match entries for `{}`", sym);
}
// NB: It's legal for multiple regex to produce same terminal.
self.match_user_names.insert(user_name);
self.match_user_names.insert(user_name.clone());
self.match_entries
.push(MatchEntry {
@ -167,7 +167,7 @@ impl MatchBlock {
fn add_literal_from_grammar(&mut self, sym: TerminalLiteral, span: Span) -> NormResult<()> {
// Already saw this literal, maybe in a match entry, maybe in the grammar.
if self.match_user_names
.contains(&TerminalString::Literal(sym)) {
.contains(&TerminalString::Literal(sym.clone())) {
return Ok(());
}
@ -178,13 +178,13 @@ impl MatchBlock {
}
self.match_user_names
.insert(TerminalString::Literal(sym));
.insert(TerminalString::Literal(sym.clone()));
self.match_entries
.push(MatchEntry {
precedence: sym.base_precedence(),
match_literal: sym,
user_name: TerminalString::Literal(sym),
match_literal: sym.clone(),
user_name: TerminalString::Literal(sym.clone()),
});
self.spans.insert(sym, span);
@ -229,7 +229,7 @@ impl<'grammar> Validator<'grammar> {
SymbolKind::Expr(ref expr) => {
try!(self.validate_expr(expr));
}
SymbolKind::Terminal(term) => {
SymbolKind::Terminal(ref term) => {
try!(self.validate_terminal(symbol.span, term));
}
SymbolKind::Nonterminal(_) => {}
@ -241,7 +241,7 @@ impl<'grammar> Validator<'grammar> {
try!(self.validate_symbol(sym));
}
SymbolKind::Lookahead | SymbolKind::Lookbehind | SymbolKind::Error => {}
SymbolKind::AmbiguousId(id) => {
SymbolKind::AmbiguousId(ref id) => {
panic!("ambiguous id `{}` encountered after name resolution", id)
}
SymbolKind::Macro(..) => {
@ -252,12 +252,12 @@ impl<'grammar> Validator<'grammar> {
Ok(())
}
fn validate_terminal(&mut self, span: Span, term: TerminalString) -> NormResult<()> {
fn validate_terminal(&mut self, span: Span, term: &TerminalString) -> NormResult<()> {
match self.mode {
// If there is an extern token definition, validate that
// this terminal has a defined conversion.
TokenMode::Extern { ref conversions } => {
if !conversions.contains(&term) {
if !conversions.contains(term) {
return_err!(span,
"terminal `{}` does not have a pattern defined for it",
term);
@ -267,15 +267,15 @@ impl<'grammar> Validator<'grammar> {
// If there is no extern token definition, then collect
// the terminal literals ("class", r"[a-z]+") into a set.
TokenMode::Internal { ref mut match_block } => {
match term {
match *term {
TerminalString::Bare(_) => {
assert!(match_block.match_user_names.contains(&term),
assert!(match_block.match_user_names.contains(term),
"bare terminal without match entry: {}",
term)
}
TerminalString::Literal(l) => {
match_block.add_literal_from_grammar(l, span)?
TerminalString::Literal(ref l) => {
match_block.add_literal_from_grammar(l.clone(), span)?
}
// Error is a builtin terminal that always exists
@ -306,15 +306,15 @@ fn construct(grammar: &mut Grammar, match_block: MatchBlock) -> NormResult<()> {
// one of precedences, that are parallel with `literals`.
let mut regexs = Vec::with_capacity(match_entries.len());
let mut precedences = Vec::with_capacity(match_entries.len());
try!(intern::read(|interner| {
try!({
for match_entry in &match_entries {
precedences.push(Precedence(match_entry.precedence));
match match_entry.match_literal {
TerminalLiteral::Quoted(s) => {
regexs.push(re::parse_literal(interner.data(s)));
TerminalLiteral::Quoted(ref s) => {
regexs.push(re::parse_literal(&s));
}
TerminalLiteral::Regex(s) => {
match re::parse_regex(interner.data(s)) {
TerminalLiteral::Regex(ref s) => {
match re::parse_regex(&s) {
Ok(regex) => regexs.push(regex),
Err(error) => {
let literal_span = spans[&match_entry.match_literal];
@ -328,7 +328,7 @@ fn construct(grammar: &mut Grammar, match_block: MatchBlock) -> NormResult<()> {
}
}
Ok(())
}));
});
let dfa = match dfa::build_dfa(&regexs, &precedences) {
Ok(dfa) => dfa,
@ -341,16 +341,16 @@ fn construct(grammar: &mut Grammar, match_block: MatchBlock) -> NormResult<()> {
TextBoundary => r#"text boundaries (`^` or `$`)"#,
ByteRegex => r#"byte-based matches"#,
};
let literal = match_entries[index.index()].match_literal;
return_err!(spans[&literal],
let literal = &match_entries[index.index()].match_literal;
return_err!(spans[literal],
"{} are not supported in regular expressions",
feature)
}
Err(DFAConstructionError::Ambiguity { match0, match1 }) => {
let literal0 = match_entries[match0.index()].match_literal;
let literal1 = match_entries[match1.index()].match_literal;
let literal0 = &match_entries[match0.index()].match_literal;
let literal1 = &match_entries[match1.index()].match_literal;
// FIXME(#88) -- it'd be nice to give an example here
return_err!(spans[&literal0],
return_err!(spans[literal0],
"ambiguity detected between the terminal `{}` and the terminal `{}`",
literal0,
literal1)
@ -366,10 +366,10 @@ fn construct(grammar: &mut Grammar, match_block: MatchBlock) -> NormResult<()> {
// we need to inject a `'input` lifetime and `input: &'input str` parameter as well:
let input_lifetime = intern(INPUT_LIFETIME);
let input_lifetime = Atom::from(INPUT_LIFETIME);
for parameter in &grammar.type_parameters {
match *parameter {
TypeParameter::Lifetime(i) if i == input_lifetime => {
TypeParameter::Lifetime(ref i) if *i == input_lifetime => {
return_err!(grammar.span,
"since there is no external token enum specified, \
the `'input` lifetime is implicit and cannot be declared");
@ -378,7 +378,7 @@ fn construct(grammar: &mut Grammar, match_block: MatchBlock) -> NormResult<()> {
}
}
let input_parameter = intern(INPUT_PARAMETER);
let input_parameter = Atom::from(INPUT_PARAMETER);
for parameter in &grammar.parameters {
if parameter.name == input_parameter {
return_err!(grammar.span,
@ -389,14 +389,14 @@ fn construct(grammar: &mut Grammar, match_block: MatchBlock) -> NormResult<()> {
grammar
.type_parameters
.insert(0, TypeParameter::Lifetime(input_lifetime));
.insert(0, TypeParameter::Lifetime(input_lifetime.clone()));
let parameter = Parameter {
name: input_parameter,
ty: TypeRef::Ref {
lifetime: Some(input_lifetime),
mutable: false,
referent: Box::new(TypeRef::Id(intern("str"))),
referent: Box::new(TypeRef::Id(Atom::from("str"))),
},
};
grammar.parameters.push(parameter);

View File

@ -28,8 +28,8 @@ fn check_intern_token(grammar: &str,
let actual_user_name =
interpret::interpret(&intern_token.dfa, input)
.map(|(index, text)| {
let user_name = intern_token.match_entries[index.index()].user_name;
(user_name, text)
let user_name = &intern_token.match_entries[index.index()].user_name;
(user_name.clone(), text)
});
let actual_user_name = format!("{:?}", actual_user_name);
if expected_user_name != actual_user_name {

View File

@ -12,7 +12,7 @@ use grammar::parse_tree::{ActionKind, Alternative,
TypeParameter,
TypeRef};
use grammar::repr::{NominalTypeRepr, Types, TypeRepr};
use intern::{intern, InternedString};
use string_cache::DefaultAtom as Atom;
#[cfg(test)]
mod test;
@ -26,7 +26,7 @@ struct TypeInferencer<'grammar> {
stack: Vec<NonterminalString>,
nonterminals: HashMap<NonterminalString, NT<'grammar>>,
types: Types,
type_parameters: HashSet<InternedString>,
type_parameters: HashSet<Atom>,
}
#[derive(Copy, Clone)]
@ -46,7 +46,7 @@ impl<'grammar> TypeInferencer<'grammar> {
.filter_map(|item| item.as_nonterminal())
.map(|data| {
assert!(!data.is_macro_def()); // normalized away by now
(data.name, NT::new(data))
(data.name.clone(), NT::new(data))
})
.collect();
@ -54,7 +54,7 @@ impl<'grammar> TypeInferencer<'grammar> {
.iter()
.filter_map(|p| match *p {
TypeParameter::Lifetime(_) => None,
TypeParameter::Id(ty) => Some(ty),
TypeParameter::Id(ref ty) => Some(ty.clone()),
})
.collect();
@ -70,7 +70,7 @@ impl<'grammar> TypeInferencer<'grammar> {
// Determine error type (if any).
let error_type =
opt_extern_token.and_then(|extern_token| {
extern_token.associated_type(intern(ERROR))
extern_token.associated_type(Atom::from(ERROR))
.map(|tr| tr.type_ref.type_repr())
});
@ -81,7 +81,7 @@ impl<'grammar> TypeInferencer<'grammar> {
TypeRepr::usize();
let input_str = // &'input str
TypeRepr::Ref {
lifetime: Some(intern(INPUT_LIFETIME)),
lifetime: Some(Atom::from(INPUT_LIFETIME)),
mutable: false,
referent: Box::new(TypeRepr::str())
};
@ -89,21 +89,21 @@ impl<'grammar> TypeInferencer<'grammar> {
TypeRepr::Nominal(NominalTypeRepr {
path: Path {
absolute: false,
ids: vec![intern("Token")],
ids: vec![Atom::from("Token")],
},
types: vec![TypeRepr::Lifetime(intern(INPUT_LIFETIME))]
types: vec![TypeRepr::Lifetime(Atom::from(INPUT_LIFETIME))]
});
let mut types = Types::new(&grammar.prefix, Some(loc_type), error_type, enum_type);
for match_entry in &intern_token.match_entries {
types.add_term_type(match_entry.user_name, input_str.clone());
types.add_term_type(match_entry.user_name.clone(), input_str.clone());
}
types
} else {
let extern_token = opt_extern_token.unwrap();
let loc_type = extern_token.associated_type(intern(LOCATION))
let loc_type = extern_token.associated_type(Atom::from(LOCATION))
.map(|tr| tr.type_ref.type_repr());
let enum_type = extern_token.enum_token
.as_ref()
@ -128,7 +128,7 @@ impl<'grammar> TypeInferencer<'grammar> {
conversion.to.for_each_binding(&mut |ty| tys.push(ty.type_repr()));
if tys.is_empty() { continue; }
let ty = maybe_tuple(tys);
types.add_term_type(conversion.from, ty);
types.add_term_type(conversion.from.clone(), ty);
}
types
@ -138,18 +138,18 @@ impl<'grammar> TypeInferencer<'grammar> {
fn infer_types(mut self) -> NormResult<Types> {
let ids: Vec<NonterminalString> =
self.nonterminals.iter()
.map(|(&id, _)| id)
.map(|(id, _)| id.clone())
.collect();
for id in ids {
try!(self.nonterminal_type(id));
debug_assert!(self.types.lookup_nonterminal_type(id).is_some());
try!(self.nonterminal_type(&id));
debug_assert!(self.types.lookup_nonterminal_type(&id).is_some());
}
Ok(self.types)
}
fn nonterminal_type(&mut self, id: NonterminalString) -> NormResult<TypeRepr> {
fn nonterminal_type(&mut self, id: &NonterminalString) -> NormResult<TypeRepr> {
if let Some(repr) = self.types.lookup_nonterminal_type(id) {
return Ok(repr.clone());
}
@ -207,16 +207,16 @@ impl<'grammar> TypeInferencer<'grammar> {
Ok(alternative_types.pop().unwrap())
}));
self.types.add_type(id, ty.clone());
self.types.add_type(id.clone(), ty.clone());
Ok(ty)
}
fn push<F,R>(&mut self, id: NonterminalString, f: F) -> NormResult<R>
fn push<F,R>(&mut self, id: &NonterminalString, f: F) -> NormResult<R>
where F: FnOnce(&mut TypeInferencer) -> NormResult<R>
{
self.stack.push(id);
self.stack.push(id.clone());
let r = f(self);
assert_eq!(self.stack.pop().unwrap(), id);
assert_eq!(self.stack.pop().unwrap(), *id);
r
}
@ -231,8 +231,8 @@ impl<'grammar> TypeInferencer<'grammar> {
TypeRef::Nominal { ref path, ref types } => {
if path.ids.len() == 2 && self.type_parameters.contains(&path.ids[0]) {
return Ok(TypeRepr::Associated {
type_parameter: path.ids[0],
id: path.ids[1],
type_parameter: path.ids[0].clone(),
id: path.ids[1].clone(),
});
}
@ -242,15 +242,15 @@ impl<'grammar> TypeInferencer<'grammar> {
Ok(TypeRepr::Nominal(NominalTypeRepr { path: path.clone(),
types: types }))
}
TypeRef::Lifetime(id) => {
Ok(TypeRepr::Lifetime(id))
TypeRef::Lifetime(ref id) => {
Ok(TypeRepr::Lifetime(id.clone()))
}
TypeRef::Id(id) => {
Ok(TypeRepr::Nominal(NominalTypeRepr { path: Path::from_id(id),
TypeRef::Id(ref id) => {
Ok(TypeRepr::Nominal(NominalTypeRepr { path: Path::from_id(id.clone()),
types: vec![] }))
}
TypeRef::Ref { lifetime, mutable, ref referent } => {
Ok(TypeRepr::Ref { lifetime: lifetime,
TypeRef::Ref { ref lifetime, mutable, ref referent } => {
Ok(TypeRepr::Ref { lifetime: lifetime.clone(),
mutable: mutable,
referent: Box::new(try!(self.type_ref(referent))) })
}
@ -291,8 +291,8 @@ impl<'grammar> TypeInferencer<'grammar> {
fn symbol_type(&mut self, symbol: &SymbolKind) -> NormResult<TypeRepr> {
match *symbol {
SymbolKind::Terminal(id) => Ok(self.types.terminal_type(id).clone()),
SymbolKind::Nonterminal(id) => self.nonterminal_type(id),
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::Error => Ok(self.types.parse_error_type().clone()),

View File

@ -1,4 +1,4 @@
use intern::intern;
use string_cache::DefaultAtom as Atom;
use parser;
use normalize::macro_expand::expand_macros;
use normalize::token_check;
@ -20,10 +20,10 @@ fn compare(g1: &str, expected: Vec<(&'static str, &'static str)>) {
println!("types table: {:?}", types);
for (nt_id, nt_type) in expected {
let id = NonterminalString(intern(nt_id));
let id = NonterminalString(Atom::from(nt_id));
let ty = type_repr(nt_type);
println!("expected type of {:?} is {:?}", id, ty);
assert_eq!(types.nonterminal_type(id), &ty);
assert_eq!(types.nonterminal_type(&id), &ty);
}
}

View File

@ -1,4 +1,4 @@
use intern::{intern, InternedString};
use string_cache::DefaultAtom as Atom;
use grammar::parse_tree::*;
use grammar::pattern::*;
use std::iter::once;
@ -45,7 +45,7 @@ GrammarWhereClause: WhereClause<TypeRef> = {
WhereClause::Type { forall: f, ty: ty, bounds: bounds }
};
ForAll: Vec<InternedString> =
ForAll: Vec<Atom> =
"for" "<" <Comma<Lifetime>> ">";
TypeBounds: Vec<TypeBound<TypeRef>> =
@ -120,7 +120,7 @@ Annotation: Annotation =
NonterminalName: (NonterminalString, Vec<NonterminalString>) = {
<MacroId> "<" <Comma<NotMacroId>> ">",
<n:NotMacroId> => (n, vec![]),
<"Escape"> => (NonterminalString(intern(<>)), vec![]),
<"Escape"> => (NonterminalString(Atom::from(<>)), vec![]),
};
Alternatives: Vec<Alternative> = {
@ -204,7 +204,7 @@ SymbolKind1: SymbolKind = {
SymbolKind::Terminal(<>),
"Id" =>
SymbolKind::AmbiguousId(intern(<>)),
SymbolKind::AmbiguousId(Atom::from(<>)),
Escape =>
SymbolKind::Nonterminal(NonterminalString(<>)),
@ -349,7 +349,7 @@ PatternKind: PatternKind<TypeRef> = {
PatternKind::Tuple(<>),
<c:"CharLiteral"> =>
PatternKind::CharLiteral(intern(c)),
PatternKind::CharLiteral(Atom::from(c)),
<Path> =>
PatternKind::Path(<>),
@ -363,25 +363,25 @@ FieldPattern: FieldPattern<TypeRef> =
};
MacroId: NonterminalString =
<i:"MacroId"> => NonterminalString(intern(i));
<i:"MacroId"> => NonterminalString(Atom::from(i));
NotMacroId: NonterminalString =
<i:"Id"> => NonterminalString(intern(i));
<i:"Id"> => NonterminalString(Atom::from(i));
Id: InternedString = {
<i:"Id"> => intern(i),
<i:"MacroId"> => intern(i),
Id: Atom = {
<i:"Id"> => Atom::from(i),
<i:"MacroId"> => Atom::from(i),
};
Escape: InternedString =
<i:"Escape"> => intern(i);
Escape: Atom =
<i:"Escape"> => Atom::from(i);
Lifetime: InternedString =
<i:"Lifetime"> => intern(i);
Lifetime: Atom =
<i:"Lifetime"> => Atom::from(i);
Terminal: TerminalString = {
QuotedTerminal,
<i:"Id"> => TerminalString::Bare(intern(i)),
<i:"Id"> => TerminalString::Bare(Atom::from(i)),
};
QuotedTerminal: TerminalString = {
@ -393,11 +393,11 @@ QuotedLiteral: TerminalLiteral = {
<s:RegexLiteral> => TerminalLiteral::Regex(s),
};
StringLiteral: InternedString =
<s:"StringLiteral"> => intern(s);
StringLiteral: Atom =
<s:"StringLiteral"> => Atom::from(s);
RegexLiteral: InternedString =
<s:"RegexLiteral"> => intern(s);
RegexLiteral: Atom =
<s:"RegexLiteral"> => Atom::from(s);
Comma<E>: Vec<E> =
<v0:(<E> ",")*> <e1:E?> =>