如何在过程宏中提供有用的编译器错误信息?

9
我正在使用proc_macrosyn设计自定义的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 的错误。如何准确定位解析失败的位置并给出适当的错误提示?


我不太确定你的主要关注点是什么,不过trace_macros!log_syntax!或许可以帮到你? - hellow
我的主要关注点是,这个宏的用户将不得不自己查找自定义语法中的任何错误。我希望解析器能够显示出错误发生的位置。 - pepsighan
1个回答

4
通过将您的宏升级到使用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>);
  |                                            ^^

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接