diff --git a/.travis.yml b/.travis.yml index ba96027..c91db40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: rust rust: - - 1.16.0 + - 1.18.0 - beta - nightly script: diff --git a/lalrpop-test/src/expr.lalrpop b/lalrpop-test/src/expr.lalrpop index bdecb0f..c804976 100644 --- a/lalrpop-test/src/expr.lalrpop +++ b/lalrpop-test/src/expr.lalrpop @@ -15,7 +15,7 @@ extern { } } -pub Expr = { +pub(crate) Expr = { "-" => l - r, "+" => l + r, Factor, diff --git a/lalrpop/src/build/mod.rs b/lalrpop/src/build/mod.rs index 195317a..57f0a82 100644 --- a/lalrpop/src/build/mod.rs +++ b/lalrpop/src/build/mod.rs @@ -396,7 +396,8 @@ fn emit_recursive_ascent(session: &Session, grammar: &r::Grammar, report_file : } rust!(rust, - "pub use self::{}parse{}::parse_{};", + "{}use self::{}parse{}::parse_{};", + grammar.nonterminals[&user_nt].visibility, grammar.prefix, start_nt, user_nt); diff --git a/lalrpop/src/grammar/parse_tree.rs b/lalrpop/src/grammar/parse_tree.rs index f6604e1..81c2a02 100644 --- a/lalrpop/src/grammar/parse_tree.rs +++ b/lalrpop/src/grammar/parse_tree.rs @@ -342,10 +342,24 @@ pub struct Parameter { pub ty: TypeRef, } +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Visibility { + Pub(Option), + Priv, +} + +impl Visibility { + pub fn is_pub(&self) -> bool { + match *self { + Visibility::Pub(_) => true, + Visibility::Priv => false, + } + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct NonterminalData { - // a "public" nonterminal is one that we will use as a start symbol - pub public: bool, + pub visibility: Visibility, pub name: NonterminalString, pub annotations: Vec, pub span: Span, @@ -646,6 +660,16 @@ impl Symbol { } } +impl Display for Visibility { + fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { + match *self { + Visibility::Pub(Some(ref path)) => write!(fmt, "pub({}) ", path), + Visibility::Pub(None) => write!(fmt, "pub "), + Visibility::Priv => Ok(()), + } + } +} + impl Display for WhereClause { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { match *self { diff --git a/lalrpop/src/grammar/repr.rs b/lalrpop/src/grammar/repr.rs index ca4cb44..43af9fd 100644 --- a/lalrpop/src/grammar/repr.rs +++ b/lalrpop/src/grammar/repr.rs @@ -17,7 +17,11 @@ pub use grammar::parse_tree::{Annotation, NonterminalString, Path, Span, - TerminalLiteral, TerminalString, TypeParameter, WhereClause}; + TerminalLiteral, + TerminalString, + TypeParameter, + Visibility, + WhereClause}; #[derive(Clone, Debug)] pub struct Grammar { @@ -75,6 +79,7 @@ pub struct TerminalSet { #[derive(Clone, Debug)] pub struct NonterminalData { pub name: NonterminalString, + pub visibility: Visibility, pub span: Span, pub annotations: Vec, pub productions: Vec, diff --git a/lalrpop/src/lr1/codegen/base.rs b/lalrpop/src/lr1/codegen/base.rs index ee9faa4..adc8b2f 100644 --- a/lalrpop/src/lr1/codegen/base.rs +++ b/lalrpop/src/lr1/codegen/base.rs @@ -135,6 +135,7 @@ impl<'codegen, 'grammar, W: Write, C> CodeGenerator<'codegen, 'grammar, W, C> { rust!(self.out, "#[allow(dead_code)]"); try!(self.out.write_pub_fn_header(self.grammar, + &self.grammar.nonterminals[&self.start_symbol].visibility, format!("parse_{}", self.user_start_symbol), type_parameters, parameters, diff --git a/lalrpop/src/lr1/codegen/parse_table.rs b/lalrpop/src/lr1/codegen/parse_table.rs index c1be06f..a0fbfd1 100644 --- a/lalrpop/src/lr1/codegen/parse_table.rs +++ b/lalrpop/src/lr1/codegen/parse_table.rs @@ -3,6 +3,7 @@ use collections::{Map, Set}; use grammar::parse_tree::WhereClause; use grammar::repr::*; +use intern::intern; use lr1::core::*; use lr1::lookahead::Token; use rust::RustWrite; @@ -749,6 +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")))), format!("{}reduce", self.prefix), vec![], parameters, diff --git a/lalrpop/src/lr1/codegen/test_all.rs b/lalrpop/src/lr1/codegen/test_all.rs index 14de318..7817b29 100644 --- a/lalrpop/src/lr1/codegen/test_all.rs +++ b/lalrpop/src/lr1/codegen/test_all.rs @@ -54,11 +54,12 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TestAll> { this.states, "super::super::super", this.out)); - rust!(this.out, - "pub use self::{}parse{}::parse_{};", - this.prefix, - this.start_symbol, - this.user_start_symbol); + let pub_use = format!("{}use self::{}parse{}::parse_{};", + this.grammar.nonterminals[&this.user_start_symbol].visibility, + this.prefix, + this.start_symbol, + this.user_start_symbol); + rust!(this.out, "{}", pub_use); rust!(this.out, "}}"); rust!(this.out, "mod {}parse_table {{", this.prefix); @@ -68,11 +69,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TestAll> { this.states, "super::super::super", this.out)); - rust!(this.out, - "pub use self::{}parse{}::parse_{};", - this.prefix, - this.start_symbol, - this.user_start_symbol); + rust!(this.out, "{}", pub_use); rust!(this.out, "}}"); Ok(()) diff --git a/lalrpop/src/normalize/lower/mod.rs b/lalrpop/src/normalize/lower/mod.rs index 102de58..a6f4991 100644 --- a/lalrpop/src/normalize/lower/mod.rs +++ b/lalrpop/src/normalize/lower/mod.rs @@ -137,6 +137,7 @@ impl<'s> LowerState<'s> { self.nonterminals.insert(nt_name, r::NonterminalData { name: nt_name, + visibility: nt.visibility.clone(), annotations: nt.annotations, span: nt.span, productions: productions, @@ -215,7 +216,7 @@ impl<'s> LowerState<'s> { grammar.items .iter() .filter_map(|item| item.as_nonterminal()) - .filter(|nt| nt.public) + .filter(|nt| nt.visibility.is_pub()) .map(|nt| { // create a synthetic symbol `__Foo` for each public symbol `Foo` // with a rule like: @@ -241,6 +242,7 @@ impl<'s> LowerState<'s> { self.nonterminals.insert(fake_name, r::NonterminalData { name: fake_name, + visibility: nt.visibility.clone(), annotations: vec![], span: nt.span, productions: vec![production], diff --git a/lalrpop/src/normalize/macro_expand/mod.rs b/lalrpop/src/normalize/macro_expand/mod.rs index 30f2e28..744f00c 100644 --- a/lalrpop/src/normalize/macro_expand/mod.rs +++ b/lalrpop/src/normalize/macro_expand/mod.rs @@ -10,7 +10,8 @@ use grammar::parse_tree::{ActionKind, Alternative, Annotation, Path, RepeatOp, RepeatSymbol, Span, Symbol, SymbolKind, - TerminalLiteral, TerminalString, TypeRef}; + TerminalLiteral, TerminalString, TypeRef, + Visibility}; use normalize::resolve; use normalize::{NormResult, NormError}; use normalize::norm_util::{self, Symbols}; @@ -198,7 +199,7 @@ impl MacroExpander { } Ok(GrammarItem::Nonterminal(NonterminalData { - public: mdef.public, + visibility: mdef.visibility.clone(), span: span, name: msym_name, annotations: mdef.annotations.clone(), @@ -363,7 +364,7 @@ impl MacroExpander { }; Ok(GrammarItem::Nonterminal(NonterminalData { - public: false, + visibility: Visibility::Priv, span: span, name: name, annotations: inline(span), @@ -397,7 +398,7 @@ impl MacroExpander { }); Ok(GrammarItem::Nonterminal(NonterminalData { - public: false, + visibility: Visibility::Priv, span: span, name: name, annotations: inline(span), @@ -436,7 +437,7 @@ impl MacroExpander { let ty_ref = TypeRef::Nominal { path: path, types: vec![base_symbol_ty] }; Ok(GrammarItem::Nonterminal(NonterminalData { - public: false, + visibility: Visibility::Priv, span: span, name: name, annotations: vec![], @@ -475,7 +476,7 @@ impl MacroExpander { let ty_ref = TypeRef::Nominal { path: path, types: vec![base_symbol_ty] }; Ok(GrammarItem::Nonterminal(NonterminalData { - public: false, + visibility: Visibility::Priv, span: span, name: name, annotations: inline(span), @@ -506,7 +507,7 @@ impl MacroExpander { -> NormResult { let name = NonterminalString(intern(name)); Ok(GrammarItem::Nonterminal(NonterminalData { - public: false, + visibility: Visibility::Priv, span: span, name: name, annotations: inline(span), diff --git a/lalrpop/src/normalize/prevalidate/mod.rs b/lalrpop/src/normalize/prevalidate/mod.rs index bc703c5..45c1844 100644 --- a/lalrpop/src/normalize/prevalidate/mod.rs +++ b/lalrpop/src/normalize/prevalidate/mod.rs @@ -124,7 +124,7 @@ impl<'grammar> Validator<'grammar> { } } GrammarItem::Nonterminal(ref data) => { - if data.public && !data.args.is_empty() { + if data.visibility.is_pub() && !data.args.is_empty() { return_err!(data.span, "macros cannot be marked public"); } let inline_annotation = intern(INLINE); @@ -139,7 +139,7 @@ impl<'grammar> Validator<'grammar> { return_err!(annotation.id_span, "duplicate annotation `{}`", annotation.id); - } else if annotation.id == inline_annotation && data.public { + } else if annotation.id == inline_annotation && data.visibility.is_pub() { return_err!(annotation.id_span, "public items cannot be marked #[inline]"); } diff --git a/lalrpop/src/parser/lrgrammar.lalrpop b/lalrpop/src/parser/lrgrammar.lalrpop index 070569e..0dfdb39 100644 --- a/lalrpop/src/parser/lrgrammar.lalrpop +++ b/lalrpop/src/parser/lrgrammar.lalrpop @@ -93,11 +93,17 @@ GrammarItem: GrammarItem = { Use: GrammarItem = ";" => GrammarItem::Use(strip(u).to_string()); +Visibility: Visibility = { + "pub" "(" ")" => Visibility::Pub(Some(p)), + "pub" => Visibility::Pub(None), + () => Visibility::Priv, +}; + Nonterminal: GrammarItem = - + )?> "=" => { - GrammarItem::Nonterminal(NonterminalData { public: p.is_some(), + GrammarItem::Nonterminal(NonterminalData { visibility: v, span: Span(lo, hi), name: n.0, annotations: annotations, diff --git a/lalrpop/src/rust/mod.rs b/lalrpop/src/rust/mod.rs index ab69e57..0d2aa88 100644 --- a/lalrpop/src/rust/mod.rs +++ b/lalrpop/src/rust/mod.rs @@ -2,6 +2,7 @@ //! which then gets serialized. use grammar::repr::Grammar; +use grammar::parse_tree::Visibility; use tls::Tls; use std::fmt; use std::io::{self, Write}; @@ -106,6 +107,7 @@ impl RustWrite { pub fn write_pub_fn_header(&mut self, grammar: &Grammar, + visibility: &Visibility, name: String, type_parameters: Vec, parameters: Vec, @@ -113,7 +115,7 @@ impl RustWrite { where_clauses: Vec) -> io::Result<()> { - self.write_fn_header_helper(grammar, "pub ", name, type_parameters, + self.write_fn_header_helper(grammar, visibility, name, type_parameters, parameters, return_type, where_clauses) } @@ -126,13 +128,13 @@ impl RustWrite { where_clauses: Vec) -> io::Result<()> { - self.write_fn_header_helper(grammar, "", name, type_parameters, + self.write_fn_header_helper(grammar, &Visibility::Priv, name, type_parameters, parameters, return_type, where_clauses) } fn write_fn_header_helper(&mut self, grammar: &Grammar, - qualifiers: &str, + visibility: &Visibility, name: String, type_parameters: Vec, parameters: Vec, @@ -140,7 +142,7 @@ impl RustWrite { where_clauses: Vec) -> io::Result<()> { - rust!(self, "{}fn {}<", qualifiers, name); + rust!(self, "{}fn {}<", visibility, name); for type_parameter in &grammar.type_parameters { rust!(self, "{0:1$}{2},", "", TAB, type_parameter);