Merge pull request #293 from ahmedcharles/pubrestricted

Add support for pub(restricted).
This commit is contained in:
Niko Matsakis 2018-01-31 05:47:33 -05:00 committed by GitHub
commit 50fb8a5d74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 73 additions and 32 deletions

View File

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

View File

@ -15,7 +15,7 @@ extern {
} }
} }
pub Expr = { pub(crate) Expr = {
<l:Expr> "-" <r:Factor> => l - r, <l:Expr> "-" <r:Factor> => l - r,
<l:Expr> "+" <r:Factor> => l + r, <l:Expr> "+" <r:Factor> => l + r,
Factor, Factor,

View File

@ -396,7 +396,8 @@ fn emit_recursive_ascent(session: &Session, grammar: &r::Grammar, report_file :
} }
rust!(rust, rust!(rust,
"pub use self::{}parse{}::parse_{};", "{}use self::{}parse{}::parse_{};",
grammar.nonterminals[&user_nt].visibility,
grammar.prefix, grammar.prefix,
start_nt, start_nt,
user_nt); user_nt);

View File

@ -342,10 +342,24 @@ pub struct Parameter {
pub ty: TypeRef, pub ty: TypeRef,
} }
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Visibility {
Pub(Option<Path>),
Priv,
}
impl Visibility {
pub fn is_pub(&self) -> bool {
match *self {
Visibility::Pub(_) => true,
Visibility::Priv => false,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct NonterminalData { pub struct NonterminalData {
// a "public" nonterminal is one that we will use as a start symbol pub visibility: Visibility,
pub public: bool,
pub name: NonterminalString, pub name: NonterminalString,
pub annotations: Vec<Annotation>, pub annotations: Vec<Annotation>,
pub span: Span, 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<T: Display> Display for WhereClause<T> { impl<T: Display> Display for WhereClause<T> {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
match *self { match *self {

View File

@ -17,7 +17,11 @@ pub use grammar::parse_tree::{Annotation,
NonterminalString, NonterminalString,
Path, Path,
Span, Span,
TerminalLiteral, TerminalString, TypeParameter, WhereClause}; TerminalLiteral,
TerminalString,
TypeParameter,
Visibility,
WhereClause};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Grammar { pub struct Grammar {
@ -75,6 +79,7 @@ pub struct TerminalSet {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct NonterminalData { pub struct NonterminalData {
pub name: NonterminalString, pub name: NonterminalString,
pub visibility: Visibility,
pub span: Span, pub span: Span,
pub annotations: Vec<Annotation>, pub annotations: Vec<Annotation>,
pub productions: Vec<Production>, pub productions: Vec<Production>,

View File

@ -135,6 +135,7 @@ impl<'codegen, 'grammar, W: Write, C> CodeGenerator<'codegen, 'grammar, W, C> {
rust!(self.out, "#[allow(dead_code)]"); rust!(self.out, "#[allow(dead_code)]");
try!(self.out.write_pub_fn_header(self.grammar, try!(self.out.write_pub_fn_header(self.grammar,
&self.grammar.nonterminals[&self.start_symbol].visibility,
format!("parse_{}", self.user_start_symbol), format!("parse_{}", self.user_start_symbol),
type_parameters, type_parameters,
parameters, parameters,

View File

@ -3,6 +3,7 @@
use collections::{Map, Set}; use collections::{Map, Set};
use grammar::parse_tree::WhereClause; use grammar::parse_tree::WhereClause;
use grammar::repr::*; use grammar::repr::*;
use intern::intern;
use lr1::core::*; use lr1::core::*;
use lr1::lookahead::Token; use lr1::lookahead::Token;
use rust::RustWrite; use rust::RustWrite;
@ -749,6 +750,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TableDrive
format!("_: {}", self.phantom_data_type())]; format!("_: {}", self.phantom_data_type())];
try!(self.out.write_pub_fn_header(self.grammar, try!(self.out.write_pub_fn_header(self.grammar,
&Visibility::Pub(Some(Path::from_id(intern("crate")))),
format!("{}reduce", self.prefix), format!("{}reduce", self.prefix),
vec![], vec![],
parameters, parameters,

View File

@ -54,11 +54,12 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TestAll> {
this.states, this.states,
"super::super::super", "super::super::super",
this.out)); this.out));
rust!(this.out, let pub_use = format!("{}use self::{}parse{}::parse_{};",
"pub use self::{}parse{}::parse_{};", this.grammar.nonterminals[&this.user_start_symbol].visibility,
this.prefix, this.prefix,
this.start_symbol, this.start_symbol,
this.user_start_symbol); this.user_start_symbol);
rust!(this.out, "{}", pub_use);
rust!(this.out, "}}"); rust!(this.out, "}}");
rust!(this.out, "mod {}parse_table {{", this.prefix); rust!(this.out, "mod {}parse_table {{", this.prefix);
@ -68,11 +69,7 @@ impl<'ascent, 'grammar, W: Write> CodeGenerator<'ascent, 'grammar, W, TestAll> {
this.states, this.states,
"super::super::super", "super::super::super",
this.out)); this.out));
rust!(this.out, rust!(this.out, "{}", pub_use);
"pub use self::{}parse{}::parse_{};",
this.prefix,
this.start_symbol,
this.user_start_symbol);
rust!(this.out, "}}"); rust!(this.out, "}}");
Ok(()) Ok(())

View File

@ -137,6 +137,7 @@ impl<'s> LowerState<'s> {
self.nonterminals.insert(nt_name, self.nonterminals.insert(nt_name,
r::NonterminalData { r::NonterminalData {
name: nt_name, name: nt_name,
visibility: nt.visibility.clone(),
annotations: nt.annotations, annotations: nt.annotations,
span: nt.span, span: nt.span,
productions: productions, productions: productions,
@ -215,7 +216,7 @@ impl<'s> LowerState<'s> {
grammar.items grammar.items
.iter() .iter()
.filter_map(|item| item.as_nonterminal()) .filter_map(|item| item.as_nonterminal())
.filter(|nt| nt.public) .filter(|nt| nt.visibility.is_pub())
.map(|nt| { .map(|nt| {
// create a synthetic symbol `__Foo` for each public symbol `Foo` // create a synthetic symbol `__Foo` for each public symbol `Foo`
// with a rule like: // with a rule like:
@ -241,6 +242,7 @@ impl<'s> LowerState<'s> {
self.nonterminals.insert(fake_name, self.nonterminals.insert(fake_name,
r::NonterminalData { r::NonterminalData {
name: fake_name, name: fake_name,
visibility: nt.visibility.clone(),
annotations: vec![], annotations: vec![],
span: nt.span, span: nt.span,
productions: vec![production], productions: vec![production],

View File

@ -10,7 +10,8 @@ use grammar::parse_tree::{ActionKind, Alternative, Annotation,
Path, Path,
RepeatOp, RepeatSymbol, RepeatOp, RepeatSymbol,
Span, Symbol, SymbolKind, Span, Symbol, SymbolKind,
TerminalLiteral, TerminalString, TypeRef}; TerminalLiteral, TerminalString, TypeRef,
Visibility};
use normalize::resolve; use normalize::resolve;
use normalize::{NormResult, NormError}; use normalize::{NormResult, NormError};
use normalize::norm_util::{self, Symbols}; use normalize::norm_util::{self, Symbols};
@ -198,7 +199,7 @@ impl MacroExpander {
} }
Ok(GrammarItem::Nonterminal(NonterminalData { Ok(GrammarItem::Nonterminal(NonterminalData {
public: mdef.public, visibility: mdef.visibility.clone(),
span: span, span: span,
name: msym_name, name: msym_name,
annotations: mdef.annotations.clone(), annotations: mdef.annotations.clone(),
@ -363,7 +364,7 @@ impl MacroExpander {
}; };
Ok(GrammarItem::Nonterminal(NonterminalData { Ok(GrammarItem::Nonterminal(NonterminalData {
public: false, visibility: Visibility::Priv,
span: span, span: span,
name: name, name: name,
annotations: inline(span), annotations: inline(span),
@ -397,7 +398,7 @@ impl MacroExpander {
}); });
Ok(GrammarItem::Nonterminal(NonterminalData { Ok(GrammarItem::Nonterminal(NonterminalData {
public: false, visibility: Visibility::Priv,
span: span, span: span,
name: name, name: name,
annotations: inline(span), annotations: inline(span),
@ -436,7 +437,7 @@ impl MacroExpander {
let ty_ref = TypeRef::Nominal { path: path, types: vec![base_symbol_ty] }; let ty_ref = TypeRef::Nominal { path: path, types: vec![base_symbol_ty] };
Ok(GrammarItem::Nonterminal(NonterminalData { Ok(GrammarItem::Nonterminal(NonterminalData {
public: false, visibility: Visibility::Priv,
span: span, span: span,
name: name, name: name,
annotations: vec![], annotations: vec![],
@ -475,7 +476,7 @@ impl MacroExpander {
let ty_ref = TypeRef::Nominal { path: path, types: vec![base_symbol_ty] }; let ty_ref = TypeRef::Nominal { path: path, types: vec![base_symbol_ty] };
Ok(GrammarItem::Nonterminal(NonterminalData { Ok(GrammarItem::Nonterminal(NonterminalData {
public: false, visibility: Visibility::Priv,
span: span, span: span,
name: name, name: name,
annotations: inline(span), annotations: inline(span),
@ -506,7 +507,7 @@ impl MacroExpander {
-> NormResult<GrammarItem> { -> NormResult<GrammarItem> {
let name = NonterminalString(intern(name)); let name = NonterminalString(intern(name));
Ok(GrammarItem::Nonterminal(NonterminalData { Ok(GrammarItem::Nonterminal(NonterminalData {
public: false, visibility: Visibility::Priv,
span: span, span: span,
name: name, name: name,
annotations: inline(span), annotations: inline(span),

View File

@ -124,7 +124,7 @@ impl<'grammar> Validator<'grammar> {
} }
} }
GrammarItem::Nonterminal(ref data) => { 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"); return_err!(data.span, "macros cannot be marked public");
} }
let inline_annotation = intern(INLINE); let inline_annotation = intern(INLINE);
@ -139,7 +139,7 @@ impl<'grammar> Validator<'grammar> {
return_err!(annotation.id_span, return_err!(annotation.id_span,
"duplicate annotation `{}`", "duplicate annotation `{}`",
annotation.id); 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, return_err!(annotation.id_span,
"public items cannot be marked #[inline]"); "public items cannot be marked #[inline]");
} }

View File

@ -93,11 +93,17 @@ GrammarItem: GrammarItem = {
Use: GrammarItem = Use: GrammarItem =
<u:"use"> ";" => GrammarItem::Use(strip(u).to_string()); <u:"use"> ";" => GrammarItem::Use(strip(u).to_string());
Visibility: Visibility = {
"pub" "(" <p:Path> ")" => Visibility::Pub(Some(p)),
"pub" => Visibility::Pub(None),
() => Visibility::Priv,
};
Nonterminal: GrammarItem = Nonterminal: GrammarItem =
<annotations:Annotation*> <annotations:Annotation*>
<p:"pub"?> <lo:@L> <n:NonterminalName> <hi:@R> <v:Visibility> <lo:@L> <n:NonterminalName> <hi:@R>
<t:(":" <TypeRef>)?> "=" <a:Alternatives> => { <t:(":" <TypeRef>)?> "=" <a:Alternatives> => {
GrammarItem::Nonterminal(NonterminalData { public: p.is_some(), GrammarItem::Nonterminal(NonterminalData { visibility: v,
span: Span(lo, hi), span: Span(lo, hi),
name: n.0, name: n.0,
annotations: annotations, annotations: annotations,

View File

@ -2,6 +2,7 @@
//! which then gets serialized. //! which then gets serialized.
use grammar::repr::Grammar; use grammar::repr::Grammar;
use grammar::parse_tree::Visibility;
use tls::Tls; use tls::Tls;
use std::fmt; use std::fmt;
use std::io::{self, Write}; use std::io::{self, Write};
@ -106,6 +107,7 @@ impl<W:Write> RustWrite<W> {
pub fn write_pub_fn_header(&mut self, pub fn write_pub_fn_header(&mut self,
grammar: &Grammar, grammar: &Grammar,
visibility: &Visibility,
name: String, name: String,
type_parameters: Vec<String>, type_parameters: Vec<String>,
parameters: Vec<String>, parameters: Vec<String>,
@ -113,7 +115,7 @@ impl<W:Write> RustWrite<W> {
where_clauses: Vec<String>) where_clauses: Vec<String>)
-> io::Result<()> -> 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) parameters, return_type, where_clauses)
} }
@ -126,13 +128,13 @@ impl<W:Write> RustWrite<W> {
where_clauses: Vec<String>) where_clauses: Vec<String>)
-> io::Result<()> -> 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) parameters, return_type, where_clauses)
} }
fn write_fn_header_helper(&mut self, fn write_fn_header_helper(&mut self,
grammar: &Grammar, grammar: &Grammar,
qualifiers: &str, visibility: &Visibility,
name: String, name: String,
type_parameters: Vec<String>, type_parameters: Vec<String>,
parameters: Vec<String>, parameters: Vec<String>,
@ -140,7 +142,7 @@ impl<W:Write> RustWrite<W> {
where_clauses: Vec<String>) where_clauses: Vec<String>)
-> io::Result<()> -> io::Result<()>
{ {
rust!(self, "{}fn {}<", qualifiers, name); rust!(self, "{}fn {}<", visibility, name);
for type_parameter in &grammar.type_parameters { for type_parameter in &grammar.type_parameters {
rust!(self, "{0:1$}{2},", "", TAB, type_parameter); rust!(self, "{0:1$}{2},", "", TAB, type_parameter);