如何在过程宏中提供有用的编译器错误?
How do I provide helpful compiler errors in a procedural macro?
我正在使用 proc_macro
和 syn
设计自定义 HTML 语法分析器。样本:
#[derive(Debug)]
struct BlockElement {
stag: Ident,
child: Vec<Element>,
ctag: Ident
}
impl Synom for BlockElement {
named!(parse -> Self, do_parse!(
punct!(<) >>
stag: syn!(Ident) >>
punct!(>) >>
child: syn!(ElementList) >>
punct!(<) >>
punct!(/) >>
ctag: syn!(Ident) >>
punct!(>) >>
(BlockElement { stag, child: child.inner, ctag })
));
}
虽然我知道如何在解析后使用 Span
给出错误,但我无法弄清楚在解析过程中该怎么做。它只是出错 failed to parse anything
。如何查明解析失败的位置并给出适当的错误?
通过升级您的宏以使用 Syn 0.15 或更高版本,您无需额外的努力即可获得有用的解析错误消息。
extern crate proc_macro;
use self::proc_macro::TokenStream;
use syn::parse::{Parse, ParseStream, Result};
use syn::{parse_macro_input, Ident, Token};
// FIXME
type Element = Ident;
struct ElementList {
inner: Vec<Element>,
}
impl Parse for ElementList {
fn parse(input: ParseStream) -> Result<Self> {
let mut list = Vec::new();
while let Some(element) = input.parse()? {
list.push(element);
}
Ok(ElementList { inner: list })
}
}
struct BlockElement {
stag: Ident,
child: Vec<Element>,
ctag: Ident
}
impl Parse for BlockElement {
fn parse(input: ParseStream) -> Result<Self> {
input.parse::<Token![<]>()?;
let stag: Ident = input.parse()?;
input.parse::<Token![>]>()?;
let child: ElementList = input.parse()?;
input.parse::<Token![<]>()?;
input.parse::<Token![/]>()?;
let ctag: Ident = input.parse()?;
input.parse::<Token![>]>()?;
Ok(BlockElement { stag, child: child.inner, ctag })
}
}
#[proc_macro]
pub fn html_syntax(input: TokenStream) -> TokenStream {
let _input = parse_macro_input!(input as BlockElement);
// TODO
TokenStream::new()
}
这是输入解析错误的示例。此类错误将指示输入未能解析的位置以及宏在该位置期望的标记。
fn main() {
html_syntax!(<em>syn quote proc_macro2<em>);
}
error: expected `/`
--> src/main.rs
|
| html_syntax!(<em>syn quote proc_macro2<em>);
| ^^
我正在使用 proc_macro
和 syn
设计自定义 HTML 语法分析器。样本:
#[derive(Debug)]
struct BlockElement {
stag: Ident,
child: Vec<Element>,
ctag: Ident
}
impl Synom for BlockElement {
named!(parse -> Self, do_parse!(
punct!(<) >>
stag: syn!(Ident) >>
punct!(>) >>
child: syn!(ElementList) >>
punct!(<) >>
punct!(/) >>
ctag: syn!(Ident) >>
punct!(>) >>
(BlockElement { stag, child: child.inner, ctag })
));
}
虽然我知道如何在解析后使用 Span
给出错误,但我无法弄清楚在解析过程中该怎么做。它只是出错 failed to parse anything
。如何查明解析失败的位置并给出适当的错误?
通过升级您的宏以使用 Syn 0.15 或更高版本,您无需额外的努力即可获得有用的解析错误消息。
extern crate proc_macro;
use self::proc_macro::TokenStream;
use syn::parse::{Parse, ParseStream, Result};
use syn::{parse_macro_input, Ident, Token};
// FIXME
type Element = Ident;
struct ElementList {
inner: Vec<Element>,
}
impl Parse for ElementList {
fn parse(input: ParseStream) -> Result<Self> {
let mut list = Vec::new();
while let Some(element) = input.parse()? {
list.push(element);
}
Ok(ElementList { inner: list })
}
}
struct BlockElement {
stag: Ident,
child: Vec<Element>,
ctag: Ident
}
impl Parse for BlockElement {
fn parse(input: ParseStream) -> Result<Self> {
input.parse::<Token![<]>()?;
let stag: Ident = input.parse()?;
input.parse::<Token![>]>()?;
let child: ElementList = input.parse()?;
input.parse::<Token![<]>()?;
input.parse::<Token![/]>()?;
let ctag: Ident = input.parse()?;
input.parse::<Token![>]>()?;
Ok(BlockElement { stag, child: child.inner, ctag })
}
}
#[proc_macro]
pub fn html_syntax(input: TokenStream) -> TokenStream {
let _input = parse_macro_input!(input as BlockElement);
// TODO
TokenStream::new()
}
这是输入解析错误的示例。此类错误将指示输入未能解析的位置以及宏在该位置期望的标记。
fn main() {
html_syntax!(<em>syn quote proc_macro2<em>);
}
error: expected `/`
--> src/main.rs
|
| html_syntax!(<em>syn quote proc_macro2<em>);
| ^^