mirror of
https://github.com/fluencelabs/lalrpop
synced 2025-04-25 03:02:15 +00:00
parent
50fb8a5d74
commit
1a487a0ae6
@ -1,6 +1,6 @@
|
||||
language: rust
|
||||
rust:
|
||||
- 1.18.0
|
||||
- 1.20.0
|
||||
- beta
|
||||
- nightly
|
||||
script:
|
||||
|
@ -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
|
||||
|
@ -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(),
|
||||
}
|
||||
})
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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: {:?}",
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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?
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 ®ex_strings {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>>
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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))),*]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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, "{{");
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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())
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
}));
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
|
@ -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)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 => {
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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(®ex) {
|
||||
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),
|
||||
}]
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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)))
|
||||
}
|
||||
|
@ -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(®exs, &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);
|
||||
|
@ -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 {
|
||||
|
@ -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()),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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?> =>
|
||||
|
Loading…
x
Reference in New Issue
Block a user