mirror of
https://gitee.com/openharmony/third_party_rust_syn
synced 2024-11-27 09:50:41 +00:00
Unify the error modules
This commit is contained in:
parent
456c982ee2
commit
ad4b247cf0
130
src/error.rs
130
src/error.rs
@ -6,9 +6,98 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use buffer::Cursor;
|
||||
use std::error::Error;
|
||||
use std;
|
||||
use std::fmt::{self, Display};
|
||||
use std::iter::FromIterator;
|
||||
|
||||
use proc_macro2::{
|
||||
Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
|
||||
};
|
||||
|
||||
use buffer::Cursor;
|
||||
|
||||
/// The result of a Syn parser.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Error returned when a Syn parser cannot parse the input tokens.
|
||||
///
|
||||
/// Refer to the [module documentation] for details about parsing in Syn.
|
||||
///
|
||||
/// [module documentation]: index.html
|
||||
///
|
||||
/// *This type is available if Syn is built with the `"parsing"` feature.*
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
span: Span,
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn new<T: Display>(span: Span, message: T) -> Self {
|
||||
Error {
|
||||
span: span,
|
||||
message: message.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the error as an invocation of [`compile_error!`].
|
||||
///
|
||||
/// The [`parse_macro_input!`] macro provides a convenient way to invoke
|
||||
/// this method correctly in a procedural macro.
|
||||
///
|
||||
/// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
|
||||
/// [`parse_macro_input!`]: ../macro.parse_macro_input.html
|
||||
pub fn into_compile_error(self) -> TokenStream {
|
||||
// compile_error!($message)
|
||||
TokenStream::from_iter(vec![
|
||||
TokenTree::Ident(Ident::new("compile_error", self.span)),
|
||||
TokenTree::Punct({
|
||||
let mut punct = Punct::new('!', Spacing::Alone);
|
||||
punct.set_span(self.span);
|
||||
punct
|
||||
}),
|
||||
TokenTree::Group({
|
||||
let mut group = Group::new(Delimiter::Brace, {
|
||||
TokenStream::from_iter(vec![TokenTree::Literal({
|
||||
let mut string = Literal::string(&self.message);
|
||||
string.set_span(self.span);
|
||||
string
|
||||
})])
|
||||
});
|
||||
group.set_span(self.span);
|
||||
group
|
||||
}),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
|
||||
if cursor.eof() {
|
||||
Error::new(scope, format!("unexpected end of input, {}", message))
|
||||
} else {
|
||||
Error::new(cursor.span(), message)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(&self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
"parse error"
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LexError> for Error {
|
||||
fn from(err: LexError) -> Self {
|
||||
Error::new(Span::call_site(), format!("{:?}", err))
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of a `Synom` parser.
|
||||
///
|
||||
@ -17,44 +106,11 @@ use std::fmt::{self, Display};
|
||||
/// [module documentation]: index.html
|
||||
///
|
||||
/// *This type is available if Syn is built with the `"parsing"` feature.*
|
||||
pub type PResult<'a, O> = Result<(O, Cursor<'a>), ParseError>;
|
||||
pub type PResult<'a, O> = std::result::Result<(O, Cursor<'a>), Error>;
|
||||
|
||||
/// An error with a default error message.
|
||||
///
|
||||
/// NOTE: We should provide better error messages in the future.
|
||||
pub fn parse_error<'a, O>() -> PResult<'a, O> {
|
||||
Err(ParseError(None))
|
||||
}
|
||||
|
||||
/// Error returned when a `Synom` parser cannot parse the input tokens.
|
||||
///
|
||||
/// Refer to the [module documentation] for details about parsing in Syn.
|
||||
///
|
||||
/// [module documentation]: index.html
|
||||
///
|
||||
/// *This type is available if Syn is built with the `"parsing"` feature.*
|
||||
#[derive(Debug)]
|
||||
pub struct ParseError(Option<String>);
|
||||
|
||||
impl Error for ParseError {
|
||||
fn description(&self) -> &str {
|
||||
match self.0 {
|
||||
Some(ref desc) => desc,
|
||||
None => "failed to parse",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for ParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
Display::fmt(self.description(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ParseError {
|
||||
// For syn use only. Not public API.
|
||||
#[doc(hidden)]
|
||||
pub fn new<T: Into<String>>(msg: T) -> Self {
|
||||
ParseError(Some(msg.into()))
|
||||
}
|
||||
Err(Error::new(Span::call_site(), "parse error"))
|
||||
}
|
||||
|
18
src/lib.rs
18
src/lib.rs
@ -582,11 +582,13 @@ mod span;
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
use synom::{Parser, Synom};
|
||||
#[cfg(feature = "parsing")]
|
||||
use proc_macro2::Span;
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
mod error;
|
||||
pub mod error;
|
||||
#[cfg(feature = "parsing")]
|
||||
use error::ParseError;
|
||||
use error::Error;
|
||||
|
||||
// Not public API.
|
||||
#[cfg(feature = "parsing")]
|
||||
@ -645,7 +647,7 @@ pub use error::parse_error;
|
||||
feature = "parsing",
|
||||
feature = "proc-macro"
|
||||
))]
|
||||
pub fn parse<T>(tokens: proc_macro::TokenStream) -> Result<T, ParseError>
|
||||
pub fn parse<T>(tokens: proc_macro::TokenStream) -> Result<T, Error>
|
||||
where
|
||||
T: Synom,
|
||||
{
|
||||
@ -665,13 +667,13 @@ where
|
||||
///
|
||||
/// *This function is available if Syn is built with the `"parsing"` feature.*
|
||||
#[cfg(feature = "parsing")]
|
||||
pub fn parse2<T>(tokens: proc_macro2::TokenStream) -> Result<T, ParseError>
|
||||
pub fn parse2<T>(tokens: proc_macro2::TokenStream) -> Result<T, Error>
|
||||
where
|
||||
T: Synom,
|
||||
{
|
||||
let parser = T::parse;
|
||||
parser.parse2(tokens).map_err(|err| match T::description() {
|
||||
Some(s) => ParseError::new(format!("failed to parse {}: {}", s, err)),
|
||||
Some(s) => Error::new(Span::call_site(), format!("failed to parse {}: {}", s, err)),
|
||||
None => err,
|
||||
})
|
||||
}
|
||||
@ -705,10 +707,10 @@ where
|
||||
/// # fn main() { run().unwrap() }
|
||||
/// ```
|
||||
#[cfg(feature = "parsing")]
|
||||
pub fn parse_str<T: Synom>(s: &str) -> Result<T, ParseError> {
|
||||
pub fn parse_str<T: Synom>(s: &str) -> Result<T, Error> {
|
||||
match s.parse() {
|
||||
Ok(tts) => parse2(tts),
|
||||
Err(_) => Err(ParseError::new("error while lexing input string")),
|
||||
Err(_) => Err(Error::new(Span::call_site(), "error while lexing input string")),
|
||||
}
|
||||
}
|
||||
|
||||
@ -753,7 +755,7 @@ pub fn parse_str<T: Synom>(s: &str) -> Result<T, ParseError> {
|
||||
/// # fn main() { run().unwrap() }
|
||||
/// ```
|
||||
#[cfg(all(feature = "parsing", feature = "full"))]
|
||||
pub fn parse_file(mut content: &str) -> Result<File, ParseError> {
|
||||
pub fn parse_file(mut content: &str) -> Result<File, Error> {
|
||||
// Strip the BOM if it is present
|
||||
const BOM: &'static str = "\u{feff}";
|
||||
if content.starts_with(BOM) {
|
||||
|
@ -15,7 +15,7 @@ use proc_macro2::Ident;
|
||||
#[cfg(feature = "parsing")]
|
||||
use proc_macro2::TokenStream;
|
||||
#[cfg(feature = "parsing")]
|
||||
use {ParseError, Synom};
|
||||
use {Error, Synom};
|
||||
|
||||
use proc_macro2::TokenTree;
|
||||
|
||||
@ -122,12 +122,12 @@ impl LitStr {
|
||||
///
|
||||
/// All spans in the syntax tree will point to the span of this `LitStr`.
|
||||
#[cfg(feature = "parsing")]
|
||||
pub fn parse<T: Synom>(&self) -> Result<T, ParseError> {
|
||||
pub fn parse<T: Synom>(&self) -> Result<T, Error> {
|
||||
use proc_macro2::Group;
|
||||
|
||||
// Parse string literal into a token stream with every span equal to the
|
||||
// original literal's span.
|
||||
fn spanned_tokens(s: &LitStr) -> Result<TokenStream, ParseError> {
|
||||
fn spanned_tokens(s: &LitStr) -> Result<TokenStream, Error> {
|
||||
let stream = ::parse_str(&s.value())?;
|
||||
Ok(respan_token_stream(stream, s.span()))
|
||||
}
|
||||
|
@ -1,86 +0,0 @@
|
||||
use std;
|
||||
use std::fmt::{self, Display};
|
||||
use std::iter::FromIterator;
|
||||
|
||||
use proc_macro2::{
|
||||
Delimiter, Group, Ident, LexError, Literal, Punct, Spacing, Span, TokenStream, TokenTree,
|
||||
};
|
||||
|
||||
use buffer::Cursor;
|
||||
|
||||
/// The result of a Syn parser.
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Error returned when a Syn parser cannot parse the input tokens.
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
span: Span,
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn new<T: Display>(span: Span, message: T) -> Self {
|
||||
Error {
|
||||
span: span,
|
||||
message: message.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Render the error as an invocation of [`compile_error!`].
|
||||
///
|
||||
/// The [`parse_macro_input!`] macro provides a convenient way to invoke
|
||||
/// this method correctly in a procedural macro.
|
||||
///
|
||||
/// [`compile_error!`]: https://doc.rust-lang.org/std/macro.compile_error.html
|
||||
/// [`parse_macro_input!`]: ../macro.parse_macro_input.html
|
||||
pub fn into_compile_error(self) -> TokenStream {
|
||||
// compile_error!($message)
|
||||
TokenStream::from_iter(vec![
|
||||
TokenTree::Ident(Ident::new("compile_error", self.span)),
|
||||
TokenTree::Punct({
|
||||
let mut punct = Punct::new('!', Spacing::Alone);
|
||||
punct.set_span(self.span);
|
||||
punct
|
||||
}),
|
||||
TokenTree::Group({
|
||||
let mut group = Group::new(Delimiter::Brace, {
|
||||
TokenStream::from_iter(vec![TokenTree::Literal({
|
||||
let mut string = Literal::string(&self.message);
|
||||
string.set_span(self.span);
|
||||
string
|
||||
})])
|
||||
});
|
||||
group.set_span(self.span);
|
||||
group
|
||||
}),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
// Not public API.
|
||||
#[doc(hidden)]
|
||||
pub fn new_at<T: Display>(scope: Span, cursor: Cursor, message: T) -> Error {
|
||||
if cursor.eof() {
|
||||
Error::new(scope, format!("unexpected end of input, {}", message))
|
||||
} else {
|
||||
Error::new(cursor.span(), message)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(&self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
"parse error"
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LexError> for Error {
|
||||
fn from(err: LexError) -> Self {
|
||||
Error::new(Span::call_site(), format!("{:?}", err))
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
use proc_macro2::Delimiter;
|
||||
|
||||
use super::parse::{ParseBuffer, Result};
|
||||
use error::Result;
|
||||
use super::parse::ParseBuffer;
|
||||
use token;
|
||||
|
||||
pub struct Braces<'a> {
|
||||
|
@ -1,11 +1,10 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use buffer::Cursor;
|
||||
use proc_macro2::Span;
|
||||
|
||||
use buffer::Cursor;
|
||||
use error::{self, Error};
|
||||
use span::IntoSpans;
|
||||
use super::error;
|
||||
use super::parse::Error;
|
||||
use token::Token;
|
||||
|
||||
/// Support for checking the next token in a stream to decide how to parse.
|
||||
|
@ -7,8 +7,6 @@ pub mod lookahead;
|
||||
#[macro_use]
|
||||
mod group;
|
||||
|
||||
mod error;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use buffer::TokenBuffer;
|
||||
@ -16,7 +14,8 @@ use buffer::TokenBuffer;
|
||||
use proc_macro;
|
||||
use proc_macro2::{self, Span};
|
||||
|
||||
use self::parse::{Parse, ParseBuffer, Result};
|
||||
use error::Result;
|
||||
use self::parse::{Parse, ParseBuffer};
|
||||
|
||||
/// Parse tokens of source code into the chosen syntax tree node.
|
||||
#[cfg(feature = "proc-macro")]
|
||||
|
@ -7,11 +7,9 @@ use std::mem;
|
||||
use std::ops::Deref;
|
||||
|
||||
use buffer::Cursor;
|
||||
use error::{self, Error, Result};
|
||||
use proc_macro2::{Ident, Span};
|
||||
|
||||
use super::error;
|
||||
|
||||
pub use super::error::{Error, Result};
|
||||
pub use super::lookahead::{Lookahead1, Peek};
|
||||
|
||||
/// Parsing interface implemented by all types that can be parsed in a default
|
||||
|
26
src/synom.rs
26
src/synom.rs
@ -13,11 +13,11 @@
|
||||
//! cheaply copyable cursor over a range of tokens in a token stream, and
|
||||
//! `PResult` is a result that packages together a parsed syntax tree node `T`
|
||||
//! with a stream of remaining unparsed tokens after `T` represented as another
|
||||
//! `Cursor`, or a [`ParseError`] if parsing failed.
|
||||
//! `Cursor`, or an [`Error`] if parsing failed.
|
||||
//!
|
||||
//! [`Cursor`]: ../buffer/index.html
|
||||
//! [`PResult<T>`]: type.PResult.html
|
||||
//! [`ParseError`]: struct.ParseError.html
|
||||
//! [`Error`]: struct.Error.html
|
||||
//!
|
||||
//! This `Cursor`- and `PResult`-based interface is convenient for parser
|
||||
//! combinators and parser implementations, but not necessarily when you just
|
||||
@ -39,7 +39,7 @@
|
||||
//! ```
|
||||
//! use syn::Type;
|
||||
//!
|
||||
//! # fn run_parser() -> Result<(), syn::synom::ParseError> {
|
||||
//! # fn run_parser() -> Result<(), syn::synom::Error> {
|
||||
//! let t: Type = syn::parse_str("std::collections::HashMap<String, Value>")?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
@ -90,7 +90,7 @@
|
||||
//! use syn::punctuated::Punctuated;
|
||||
//! use syn::{PathSegment, Expr, Attribute};
|
||||
//!
|
||||
//! # fn run_parsers() -> Result<(), syn::synom::ParseError> {
|
||||
//! # fn run_parsers() -> Result<(), syn::synom::Error> {
|
||||
//! # let tokens = TokenStream::new().into();
|
||||
//! // Parse a nonempty sequence of path segments separated by `::` punctuation
|
||||
//! // with no trailing punctuation.
|
||||
@ -158,7 +158,7 @@ use proc_macro;
|
||||
use proc_macro2::{Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};
|
||||
|
||||
use error::parse_error;
|
||||
pub use error::{PResult, ParseError};
|
||||
pub use error::{PResult, Error};
|
||||
|
||||
use buffer::{Cursor, TokenBuffer};
|
||||
use next;
|
||||
@ -213,7 +213,7 @@ impl<T> Synom for T where T: next::parse::Parse {
|
||||
let state = next::parse::ParseBuffer::new(Span::call_site(), input);
|
||||
match <T as next::parse::Parse>::parse(&state) {
|
||||
Ok(node) => Ok((node, state.cursor())),
|
||||
Err(err) => Err(ParseError::new(err.to_string())),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -295,7 +295,7 @@ pub trait Parser: Sized {
|
||||
type Output;
|
||||
|
||||
/// Parse a proc-macro2 token stream into the chosen syntax tree node.
|
||||
fn parse2(self, tokens: TokenStream) -> Result<Self::Output, ParseError>;
|
||||
fn parse2(self, tokens: TokenStream) -> Result<Self::Output, Error>;
|
||||
|
||||
/// Parse tokens of source code into the chosen syntax tree node.
|
||||
///
|
||||
@ -305,7 +305,7 @@ pub trait Parser: Sized {
|
||||
not(all(target_arch = "wasm32", target_os = "unknown")),
|
||||
feature = "proc-macro"
|
||||
))]
|
||||
fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output, ParseError> {
|
||||
fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output, Error> {
|
||||
self.parse2(tokens.into())
|
||||
}
|
||||
|
||||
@ -315,10 +315,10 @@ pub trait Parser: Sized {
|
||||
///
|
||||
/// Every span in the resulting syntax tree will be set to resolve at the
|
||||
/// macro call site.
|
||||
fn parse_str(self, s: &str) -> Result<Self::Output, ParseError> {
|
||||
fn parse_str(self, s: &str) -> Result<Self::Output, Error> {
|
||||
match s.parse() {
|
||||
Ok(tts) => self.parse2(tts),
|
||||
Err(_) => Err(ParseError::new("error while lexing input string")),
|
||||
Err(_) => Err(Error::new(Span::call_site(), "error while lexing input string")),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -329,16 +329,16 @@ where
|
||||
{
|
||||
type Output = T;
|
||||
|
||||
fn parse2(self, tokens: TokenStream) -> Result<T, ParseError> {
|
||||
fn parse2(self, tokens: TokenStream) -> Result<T, Error> {
|
||||
let buf = TokenBuffer::new2(tokens);
|
||||
let (t, rest) = self(buf.begin())?;
|
||||
if rest.eof() {
|
||||
Ok(t)
|
||||
} else if rest == buf.begin() {
|
||||
// parsed nothing
|
||||
Err(ParseError::new("failed to parse anything"))
|
||||
Err(Error::new(Span::call_site(), "failed to parse anything"))
|
||||
} else {
|
||||
Err(ParseError::new("failed to parse all tokens"))
|
||||
Err(Error::new(Span::call_site(), "failed to parse all tokens"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,10 +113,12 @@ use proc_macro2::Spacing;
|
||||
#[cfg(feature = "printing")]
|
||||
use quote::{ToTokens, TokenStreamExt};
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
use error::Result;
|
||||
#[cfg(feature = "parsing")]
|
||||
use next::lookahead;
|
||||
#[cfg(feature = "parsing")]
|
||||
use next::parse::{Lookahead1, Parse, ParseStream, Result};
|
||||
use next::parse::{Lookahead1, Parse, ParseStream};
|
||||
use span::IntoSpans;
|
||||
|
||||
/// Marker trait for types that represent single tokens.
|
||||
@ -772,7 +774,8 @@ mod parsing {
|
||||
use proc_macro2::{Delimiter, Spacing, Span};
|
||||
|
||||
use buffer::Cursor;
|
||||
use next::parse::{Error, ParseStream, Result};
|
||||
use error::{Error, Result};
|
||||
use next::parse::ParseStream;
|
||||
use parse_error;
|
||||
use span::FromSpans;
|
||||
use synom::PResult;
|
||||
|
@ -11,9 +11,9 @@ extern crate syn;
|
||||
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use std::str::FromStr;
|
||||
use syn::synom::ParseError;
|
||||
use syn::error::Error;
|
||||
|
||||
fn parse(s: &str) -> Result<Ident, ParseError> {
|
||||
fn parse(s: &str) -> Result<Ident, Error> {
|
||||
syn::parse2(TokenStream::from_str(s).unwrap())
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ fn run_test<T: Into<Meta>>(input: &str, expected: T) {
|
||||
assert!(rest.eof());
|
||||
e
|
||||
}
|
||||
Err(err) => panic!(err),
|
||||
Err(err) => panic!(err.to_string()),
|
||||
};
|
||||
assert_eq!(expected.into(), attr.interpret_meta().unwrap());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user