Punctuated parsing
diff --git a/src/data.rs b/src/data.rs
index 9c77254..b87eaf1 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -196,9 +196,9 @@
ident: input.parse()?,
fields: {
if input.peek(token::Brace) {
- Fields::Named(input.parse_synom(FieldsNamed::parse)?)
+ Fields::Named(input.parse()?)
} else if input.peek(token::Paren) {
- Fields::Unnamed(input.parse_synom(FieldsUnnamed::parse)?)
+ Fields::Unnamed(input.parse()?)
} else {
Fields::Unit
}
@@ -214,62 +214,46 @@
}
}
- impl Synom for FieldsNamed {
- named!(parse -> Self, map!(
- braces!(call!(Punctuated::parse_terminated_with, Field::parse_named)),
- |(brace, fields)| FieldsNamed {
- brace_token: brace,
- named: fields,
- }
- ));
-
- fn description() -> Option<&'static str> {
- Some("named fields in a struct or struct variant")
+ impl Parse for FieldsNamed {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(FieldsNamed {
+ brace_token: braced!(content in input),
+ named: content.parse_terminated(Field::parse_named)?,
+ })
}
}
- impl Synom for FieldsUnnamed {
- named!(parse -> Self, map!(
- parens!(call!(Punctuated::parse_terminated_with, Field::parse_unnamed)),
- |(paren, fields)| FieldsUnnamed {
- paren_token: paren,
- unnamed: fields,
- }
- ));
-
- fn description() -> Option<&'static str> {
- Some("unnamed fields in a tuple struct or tuple variant")
+ impl Parse for FieldsUnnamed {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let content;
+ Ok(FieldsUnnamed {
+ paren_token: parenthesized!(content in input),
+ unnamed: content.parse_terminated(Field::parse_unnamed)?,
+ })
}
}
impl Field {
- named!(pub parse_named -> Self, do_parse!(
- attrs: many0!(Attribute::old_parse_outer) >>
- vis: syn!(Visibility) >>
- id: syn!(Ident) >>
- colon: punct!(:) >>
- ty: syn!(Type) >>
- (Field {
- ident: Some(id),
- vis: vis,
- attrs: attrs,
- ty: ty,
- colon_token: Some(colon),
+ fn parse_named(input: ParseStream) -> Result<Self> {
+ Ok(Field {
+ attrs: input.call(Attribute::parse_outer)?,
+ vis: input.parse()?,
+ ident: Some(input.parse()?),
+ colon_token: Some(input.parse()?),
+ ty: input.parse_synom(Type::parse)?,
})
- ));
+ }
- named!(pub parse_unnamed -> Self, do_parse!(
- attrs: many0!(Attribute::old_parse_outer) >>
- vis: syn!(Visibility) >>
- ty: syn!(Type) >>
- (Field {
+ fn parse_unnamed(input: ParseStream) -> Result<Self> {
+ Ok(Field {
+ attrs: input.call(Attribute::parse_outer)?,
+ vis: input.parse()?,
ident: None,
colon_token: None,
- vis: vis,
- attrs: attrs,
- ty: ty,
+ ty: input.parse_synom(Type::parse)?,
})
- ));
+ }
}
impl Parse for Visibility {
diff --git a/src/parse.rs b/src/parse.rs
index cfc0817..aa3043d 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -11,6 +11,7 @@
use buffer::Cursor;
use error;
+use punctuated::Punctuated;
use synom::PResult;
pub use error::{Error, Result};
@@ -123,6 +124,13 @@
self.lookahead1().peek(token)
}
+ pub fn parse_terminated<T, P: Parse>(
+ &self,
+ parser: fn(ParseStream) -> Result<T>,
+ ) -> Result<Punctuated<T, P>> {
+ Punctuated::parse_terminated2(self, parser)
+ }
+
pub fn fork(&self) -> Self {
self.clone()
}
diff --git a/src/punctuated.rs b/src/punctuated.rs
index b4a0b3f..171e549 100644
--- a/src/punctuated.rs
+++ b/src/punctuated.rs
@@ -40,6 +40,8 @@
#[cfg(feature = "parsing")]
use buffer::Cursor;
#[cfg(feature = "parsing")]
+use parse::{Parse, ParseStream, Result};
+#[cfg(feature = "parsing")]
use parse_error;
#[cfg(feature = "parsing")]
use synom::{PResult, Synom};
@@ -773,6 +775,34 @@
}
}
+#[cfg(feature = "parsing")]
+impl<T, P> Punctuated<T, P>
+where
+ P: Parse,
+{
+ pub fn parse_terminated2(
+ input: ParseStream,
+ parser: fn(ParseStream) -> Result<T>,
+ ) -> Result<Self> {
+ let mut res = Punctuated::new();
+
+ loop {
+ if input.is_empty() {
+ break;
+ }
+ let value = parser(input)?;
+ res.push_value(value);
+ if input.is_empty() {
+ break;
+ }
+ let punct = input.parse()?;
+ res.push_punct(punct);
+ }
+
+ Ok(res)
+ }
+}
+
#[cfg(feature = "printing")]
mod printing {
use super::*;