Improve parser error reporting.
This commit is contained in:
parent
0db3bfb8bc
commit
d25c4d5624
|
@ -1,6 +1,7 @@
|
||||||
#![feature(proc_macro_hygiene)]
|
#![feature(proc_macro_hygiene)]
|
||||||
#![feature(proc_macro_quote)]
|
#![feature(proc_macro_quote)]
|
||||||
#![feature(proc_macro_span)]
|
#![feature(proc_macro_span)]
|
||||||
|
#![feature(proc_macro_diagnostic)]
|
||||||
|
|
||||||
extern crate pom;
|
extern crate pom;
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
@ -18,7 +19,10 @@ pub fn html(input: TokenStream) -> TokenStream {
|
||||||
let input: Vec<TokenTree> = input.into_iter().collect();
|
let input: Vec<TokenTree> = input.into_iter().collect();
|
||||||
let result = html::expand_html(&input);
|
let result = html::expand_html(&input);
|
||||||
match result {
|
match result {
|
||||||
Err(error) => panic!(parser::parse_error(&input, &error)),
|
Err(error) => {
|
||||||
|
parser::parse_error(&input, &error).emit();
|
||||||
|
panic!("macro expansion produced errors; see above.")
|
||||||
|
}
|
||||||
Ok(ts) => ts,
|
Ok(ts) => ts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +32,10 @@ pub fn declare_element(input: TokenStream) -> TokenStream {
|
||||||
let input: Vec<TokenTree> = input.into_iter().collect();
|
let input: Vec<TokenTree> = input.into_iter().collect();
|
||||||
let result = declare::expand_declare(&input);
|
let result = declare::expand_declare(&input);
|
||||||
match result {
|
match result {
|
||||||
Err(error) => panic!(parser::parse_error(&input, &error)),
|
Err(error) => {
|
||||||
|
parser::parse_error(&input, &error).emit();
|
||||||
|
panic!("macro expansion produced errors; see above.")
|
||||||
|
}
|
||||||
Ok(ts) => ts,
|
Ok(ts) => ts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use pom::combinator::*;
|
use pom::combinator::*;
|
||||||
use pom::{Error, Parser};
|
use pom::{Error, Parser};
|
||||||
use proc_macro::{Delimiter, Group, Ident, Literal, Punct, TokenStream, TokenTree};
|
use proc_macro::{
|
||||||
|
Delimiter, Diagnostic, Group, Ident, Level, Literal, Punct, TokenStream, TokenTree,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn unit<'a, I: 'a, A: Clone>(value: A) -> Combinator<impl Parser<'a, I, Output = A>> {
|
pub fn unit<'a, I: 'a, A: Clone>(value: A) -> Combinator<impl Parser<'a, I, Output = A>> {
|
||||||
comb(move |_, start| Ok((value.clone(), start)))
|
comb(move |_, start| Ok((value.clone(), start)))
|
||||||
|
@ -102,7 +104,7 @@ pub fn html_ident<'a>() -> Combinator<impl Parser<'a, TokenTree, Output = Ident>
|
||||||
let next = punct('-') * ident();
|
let next = punct('-') * ident();
|
||||||
(start * next.repeat(0..)).collect().map(|stream| {
|
(start * next.repeat(0..)).collect().map(|stream| {
|
||||||
let (span, name) = stream
|
let (span, name) = stream
|
||||||
.into_iter()
|
.iter()
|
||||||
.fold((None, String::new()), |(span, name), token| {
|
.fold((None, String::new()), |(span, name), token| {
|
||||||
(
|
(
|
||||||
match span {
|
match span {
|
||||||
|
@ -120,39 +122,39 @@ pub fn html_ident<'a>() -> Combinator<impl Parser<'a, TokenTree, Output = Ident>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_location(input: &[TokenTree], position: usize) -> String {
|
/// Turn a parser error into a proc_macro diagnostic.
|
||||||
format!("{:?}", input[position].span())
|
pub fn parse_error(input: &[TokenTree], error: &pom::Error) -> Diagnostic {
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_error(input: &[TokenTree], error: &pom::Error) -> String {
|
|
||||||
match error {
|
match error {
|
||||||
pom::Error::Incomplete => "Incomplete token stream".to_string(),
|
pom::Error::Incomplete => Diagnostic::new(Level::Error, "unexpected end of macro!"),
|
||||||
pom::Error::Mismatch { message, position } => {
|
pom::Error::Mismatch { message, position } => {
|
||||||
format!("{}: {}", error_location(input, *position), message)
|
Diagnostic::spanned(input[*position].span(), Level::Error, message.as_str())
|
||||||
}
|
}
|
||||||
pom::Error::Conversion { message, position } => {
|
pom::Error::Conversion { message, position } => {
|
||||||
format!("{}: {}", error_location(input, *position), message)
|
Diagnostic::spanned(input[*position].span(), Level::Error, message.as_str())
|
||||||
}
|
}
|
||||||
pom::Error::Expect {
|
pom::Error::Expect {
|
||||||
message,
|
message,
|
||||||
position,
|
position,
|
||||||
inner,
|
inner,
|
||||||
} => format!(
|
} => {
|
||||||
"{}: {}\n{}",
|
let mut diag =
|
||||||
error_location(input, *position),
|
Diagnostic::spanned(input[*position].span(), Level::Error, message.as_str());
|
||||||
message,
|
let child = parse_error(input, &inner);
|
||||||
parse_error(input, &inner)
|
diag.span_error(child.spans(), child.message())
|
||||||
),
|
}
|
||||||
pom::Error::Custom {
|
pom::Error::Custom {
|
||||||
message,
|
message,
|
||||||
position,
|
position,
|
||||||
inner,
|
inner,
|
||||||
} => {
|
} => {
|
||||||
let mut out = format!("{}: {}", error_location(input, *position), message);
|
let mut diag =
|
||||||
if let Some(error) = inner {
|
Diagnostic::spanned(input[*position].span(), Level::Error, message.as_str());
|
||||||
out += &format!("\n{}", parse_error(input, error));
|
if let Some(inner) = inner {
|
||||||
|
let child = parse_error(input, &inner);
|
||||||
|
diag.span_error(child.spans(), child.message())
|
||||||
|
} else {
|
||||||
|
diag
|
||||||
}
|
}
|
||||||
out
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue