diff options
| author | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-12-01 02:25:32 +0300 |
|---|---|---|
| committer | Vadim Petrochenkov <vadim.petrochenkov@gmail.com> | 2019-12-02 21:56:34 +0300 |
| commit | a81804b4d5f222f94758139b504aa2570528f9f1 (patch) | |
| tree | 74b1326371f305dfe4e1ca85a559623740266ed6 /src/librustc_parse/parser | |
| parent | fdc0011561c6365c596dfd8fa1ef388162bc89c7 (diff) | |
syntax: Introduce a struct `MacArgs` for macro arguments
Diffstat (limited to 'src/librustc_parse/parser')
| -rw-r--r-- | src/librustc_parse/parser/attr.rs | 2 | ||||
| -rw-r--r-- | src/librustc_parse/parser/expr.rs | 5 | ||||
| -rw-r--r-- | src/librustc_parse/parser/item.rs | 22 | ||||
| -rw-r--r-- | src/librustc_parse/parser/mod.rs | 64 | ||||
| -rw-r--r-- | src/librustc_parse/parser/pat.rs | 5 | ||||
| -rw-r--r-- | src/librustc_parse/parser/stmt.rs | 12 | ||||
| -rw-r--r-- | src/librustc_parse/parser/ty.rs | 5 |
7 files changed, 66 insertions, 49 deletions
diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs index 524b551e54c..a0f535a4b95 100644 --- a/src/librustc_parse/parser/attr.rs +++ b/src/librustc_parse/parser/attr.rs @@ -244,7 +244,7 @@ impl<'a> Parser<'a> { Ok(attrs) } - fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> { + pub(super) fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> { let lit = self.parse_lit()?; debug!("checking if {:?} is unusuffixed", lit); diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 43c740f7f93..a6629aef1ee 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -922,12 +922,11 @@ impl<'a> Parser<'a> { // `!`, as an operator, is prefix, so we know this isn't that. if self.eat(&token::Not) { // MACRO INVOCATION expression - let (delim, tts) = self.expect_delimited_token_tree()?; + let args = self.parse_mac_args()?; hi = self.prev_span; ex = ExprKind::Mac(Mac { path, - tts, - delim, + args, span: lo.to(hi), prior_type_ascription: self.last_type_ascription, }); diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index a0669a2a174..9bf5ae3cc5a 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -8,7 +8,7 @@ use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, Us use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit}; use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField}; -use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param}; +use syntax::ast::{Mac, Block, BindingMode, FnDecl, FnSig, SelfKind, Param}; use syntax::print::pprust; use syntax::ptr::P; use syntax::ThinVec; @@ -437,16 +437,15 @@ impl<'a> Parser<'a> { // Item macro let path = self.parse_path(PathStyle::Mod)?; self.expect(&token::Not)?; - let (delim, tts) = self.expect_delimited_token_tree()?; - if delim != MacDelimiter::Brace && !self.eat(&token::Semi) { + let args = self.parse_mac_args()?; + if args.need_semicolon() && !self.eat(&token::Semi) { self.report_invalid_macro_expansion_item(); } let hi = self.prev_span; let mac = Mac { path, - tts, - delim, + args, span: mac_lo.to(hi), prior_type_ascription: self.last_type_ascription, }; @@ -518,15 +517,14 @@ impl<'a> Parser<'a> { *at_end = true; // eat a matched-delimiter token tree: - let (delim, tts) = self.expect_delimited_token_tree()?; - if delim != MacDelimiter::Brace { + let args = self.parse_mac_args()?; + if args.need_semicolon() { self.expect_semi()?; } Ok(Some(Mac { path, - tts, - delim, + args, span: lo.to(self.prev_span), prior_type_ascription: self.last_type_ascription, })) @@ -1660,12 +1658,12 @@ impl<'a> Parser<'a> { self.bump(); let ident = self.parse_ident()?; - let (delim, tokens) = self.expect_delimited_token_tree()?; - if delim != MacDelimiter::Brace && !self.eat(&token::Semi) { + let args = self.parse_mac_args()?; + if args.need_semicolon() && !self.eat(&token::Semi) { self.report_invalid_macro_expansion_item(); } - (ident, ast::MacroDef { tokens, legacy: true }) + (ident, ast::MacroDef { tokens: args.inner_tokens(), legacy: true }) } else { return Ok(None); }; diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index ea7673767d0..77bbf8bb941 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -16,7 +16,7 @@ use crate::lexer::UnmatchedBrace; use syntax::ast::{ self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit, - IsAsync, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety, + IsAsync, MacArgs, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety, }; use syntax::print::pprust; @@ -1010,27 +1010,49 @@ impl<'a> Parser<'a> { } } - fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, TokenStream)> { - let delim = match self.token.kind { - token::OpenDelim(delim) => delim, - _ => { - let msg = "expected open delimiter"; - let mut err = self.fatal(msg); - err.span_label(self.token.span, msg); - return Err(err) + fn parse_mac_args(&mut self) -> PResult<'a, P<MacArgs>> { + self.parse_mac_args_common(true) + } + + #[allow(dead_code)] + fn parse_attr_args(&mut self) -> PResult<'a, P<MacArgs>> { + self.parse_mac_args_common(false) + } + + fn parse_mac_args_common(&mut self, delimited_only: bool) -> PResult<'a, P<MacArgs>> { + Ok(P(if self.check(&token::OpenDelim(DelimToken::Paren)) || + self.check(&token::OpenDelim(DelimToken::Bracket)) || + self.check(&token::OpenDelim(DelimToken::Brace)) { + match self.parse_token_tree() { + TokenTree::Delimited(dspan, delim, tokens) => + MacArgs::Delimited(dspan, MacDelimiter::from_token(delim), tokens), + _ => unreachable!(), } - }; - let tts = match self.parse_token_tree() { - TokenTree::Delimited(_, _, tts) => tts, - _ => unreachable!(), - }; - let delim = match delim { - token::Paren => MacDelimiter::Parenthesis, - token::Bracket => MacDelimiter::Bracket, - token::Brace => MacDelimiter::Brace, - token::NoDelim => self.bug("unexpected no delimiter"), - }; - Ok((delim, tts.into())) + } else if !delimited_only { + if self.eat(&token::Eq) { + let eq_span = self.prev_span; + let mut is_interpolated_expr = false; + if let token::Interpolated(nt) = &self.token.kind { + if let token::NtExpr(..) = **nt { + is_interpolated_expr = true; + } + } + let token_tree = if is_interpolated_expr { + // We need to accept arbitrary interpolated expressions to continue + // supporting things like `doc = $expr` that work on stable. + // Non-literal interpolated expressions are rejected after expansion. + self.parse_token_tree() + } else { + self.parse_unsuffixed_lit()?.token_tree() + }; + + MacArgs::Eq(eq_span, token_tree.into()) + } else { + MacArgs::Empty + } + } else { + return self.unexpected(); + })) } fn parse_or_use_outer_attributes( diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index b068a4f16a5..c16b5f5574a 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -595,11 +595,10 @@ impl<'a> Parser<'a> { /// Parse macro invocation fn parse_pat_mac_invoc(&mut self, lo: Span, path: Path) -> PResult<'a, PatKind> { self.bump(); - let (delim, tts) = self.expect_delimited_token_tree()?; + let args = self.parse_mac_args()?; let mac = Mac { path, - tts, - delim, + args, span: lo.to(self.prev_span), prior_type_ascription: self.last_type_ascription, }; diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index a5f20691d07..68c85ad8abf 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -10,7 +10,7 @@ use syntax::ThinVec; use syntax::ptr::P; use syntax::ast; use syntax::ast::{DUMMY_NODE_ID, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind}; -use syntax::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac, MacDelimiter}; +use syntax::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac}; use syntax::util::classify; use syntax::token; use syntax::source_map::{respan, Span}; @@ -93,10 +93,11 @@ impl<'a> Parser<'a> { })); } - let (delim, tts) = self.expect_delimited_token_tree()?; + let args = self.parse_mac_args()?; + let delim = args.delim(); let hi = self.prev_span; - let style = if delim == MacDelimiter::Brace { + let style = if delim == token::Brace { MacStmtStyle::Braces } else { MacStmtStyle::NoBraces @@ -104,12 +105,11 @@ impl<'a> Parser<'a> { let mac = Mac { path, - tts, - delim, + args, span: lo.to(hi), prior_type_ascription: self.last_type_ascription, }; - let kind = if delim == MacDelimiter::Brace || + let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof { StmtKind::Mac(P((mac, style, attrs.into()))) } diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 8e6bc29be52..802bef525db 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -177,11 +177,10 @@ impl<'a> Parser<'a> { let path = self.parse_path(PathStyle::Type)?; if self.eat(&token::Not) { // Macro invocation in type position - let (delim, tts) = self.expect_delimited_token_tree()?; + let args = self.parse_mac_args()?; let mac = Mac { path, - tts, - delim, + args, span: lo.to(self.prev_span), prior_type_ascription: self.last_type_ascription, }; |
