Parsing 我自己如何使用Rust解析器(libsyntax)?

Parsing 我自己如何使用Rust解析器(libsyntax)?,parsing,rust,abstract-syntax-tree,Parsing,Rust,Abstract Syntax Tree,我想使用Rust解析器(libsyntax)解析Rust文件,并从中提取函数名等信息。我开始挖掘文档和代码,所以我的第一个目标是开发一个程序,在.rs文件中打印独立函数的所有函数名 程序应该在打印函数名之前展开所有宏,这样就不会遗漏通过宏声明的函数。这就是为什么我不能自己编写一些糟糕的小解析器来完成这项工作 我必须承认,我还不太擅长编程,所以我为这个问题中的任何愚蠢陈述提前道歉 如何理解它,我需要执行以下步骤: 通过 使用展开宏 使用a浏览AST并提取我需要的信息(例如通过) 下面是我的问题:

我想使用Rust解析器(libsyntax)解析Rust文件,并从中提取函数名等信息。我开始挖掘文档和代码,所以我的第一个目标是开发一个程序,在
.rs
文件中打印独立函数的所有函数名

程序应该在打印函数名之前展开所有宏,这样就不会遗漏通过宏声明的函数。这就是为什么我不能自己编写一些糟糕的小解析器来完成这项工作

我必须承认,我还不太擅长编程,所以我为这个问题中的任何愚蠢陈述提前道歉

如何理解它,我需要执行以下步骤:

  • 通过
  • 使用展开宏
  • 使用a浏览AST并提取我需要的信息(例如通过)
  • 下面是我的问题:

  • 如何使用宏扩展器
  • 如何与自定义访问者一起在扩展的AST中行走
  • 我的想法是使用一个语法分析器,而不是一个完全成熟的语法分析器。我正在调查这个选择


    如果有关系的话,我每晚使用的是rustc 0.13.0(f168c12c5 2014-10-25 20:57:10+0000)恐怕我不能直接回答你的问题;但我可以提出一个可能有用的替代方案

    如果您只需要AST,那么可以使用
    rustc-zASTJSON
    以JSON格式检索它。然后使用您喜欢的语言(Python很棒)处理输出

    您还可以使用
    rustc--pretty=(扩展的|正常的|类型)
    获得打印精美的源代码

    例如,给定以下
    hello.rs

    fn main() {
        println!("hello world");
    }
    
    我们得到:

    $ rustc -Z ast-json hello.rs
    {"module":{"inner":null,"view_items":[{"node":{"va... (etc.)
    
    如果您需要更多,那么lint插件将是最好的选择。正确处理宏扩展、模块系统和出现的任何其他问题都是非常重要的。使用lint插件,您可以立即检查AST的类型,而无需大惊小怪。Cargo也支持编译器插件,因此您的工具将很好地适合其他人的项目。

    您可以使用它来解析Rust,因此不需要使用不稳定的Rust

    下面是一个简单的例子:

    // Tested against syntex_syntax v0.33
    extern crate syntex_syntax as syntax;
    
    use std::rc::Rc;
    use syntax::codemap::{CodeMap};
    use syntax::errors::{Handler};
    use syntax::errors::emitter::{ColorConfig};
    use syntax::parse::{self, ParseSess};
    
    fn main() {
        let codemap = Rc::new(CodeMap::new());
        let tty_handler =
            Handler::with_tty_emitter(ColorConfig::Auto, None, true, false, codemap.clone());
        let parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone());
    
        let src = "fn foo(x: i64) { let y = x + 1; return y; }".to_owned();
    
        let result = parse::parse_crate_from_source_str(String::new(), src, Vec::new(), &parse_session);
        println!("parse result: {:?}", result);
    }
    
    这将打印整个AST:

    parse result: Ok(Crate { module: Mod { inner: Span { lo: BytePos(0), hi: BytePos(43), expn_id: ExpnId(4294967295) },
    items: [Item { ident: foo#0, attrs: [], id: 4294967295, node: Fn(FnDecl { inputs: [Arg { ty: type(i64), pat:
    pat(4294967295: x), id: 4294967295 }], output: Default(Span { lo: BytePos(15), hi: BytePos(15), expn_id: ExpnId(4294967295) }),
    variadic: false }, Normal, NotConst, Rust, Generics { lifetimes: [], ty_params: [], where_clause: WhereClause { id:
    4294967295, predicates: [] } }, Block { stmts: [stmt(4294967295: let y = x + 1;), stmt(4294967295: return y;)], expr:
    None, id: 4294967295, rules: Default, span: Span { lo: BytePos(15), hi: BytePos(43), expn_id: ExpnId(4294967295) } }),
    vis: Inherited, span: Span { lo: BytePos(0), hi: BytePos(43), expn_id: ExpnId(4294967295) } }] }, attrs: [], config: [],
    span: Span { lo: BytePos(0), hi: BytePos(42), expn_id: ExpnId(4294967295) }, exported_macros: [] })
    

    提取有趣的事实通常需要的不仅仅是“一个解析器”,请参阅我在“解析后的生活”(google或via bio page)上的文章。我认为syntex不会继续。非常感谢。我也觉得不使用不稳定的编译器内部是解决问题的方法!
    // Tested against syntex_syntax v0.33
    extern crate syntex_syntax as syntax;
    
    use std::rc::Rc;
    use syntax::codemap::{CodeMap};
    use syntax::errors::{Handler};
    use syntax::errors::emitter::{ColorConfig};
    use syntax::parse::{self, ParseSess};
    
    fn main() {
        let codemap = Rc::new(CodeMap::new());
        let tty_handler =
            Handler::with_tty_emitter(ColorConfig::Auto, None, true, false, codemap.clone());
        let parse_session = ParseSess::with_span_handler(tty_handler, codemap.clone());
    
        let src = "fn foo(x: i64) { let y = x + 1; return y; }".to_owned();
    
        let result = parse::parse_crate_from_source_str(String::new(), src, Vec::new(), &parse_session);
        println!("parse result: {:?}", result);
    }
    
    parse result: Ok(Crate { module: Mod { inner: Span { lo: BytePos(0), hi: BytePos(43), expn_id: ExpnId(4294967295) },
    items: [Item { ident: foo#0, attrs: [], id: 4294967295, node: Fn(FnDecl { inputs: [Arg { ty: type(i64), pat:
    pat(4294967295: x), id: 4294967295 }], output: Default(Span { lo: BytePos(15), hi: BytePos(15), expn_id: ExpnId(4294967295) }),
    variadic: false }, Normal, NotConst, Rust, Generics { lifetimes: [], ty_params: [], where_clause: WhereClause { id:
    4294967295, predicates: [] } }, Block { stmts: [stmt(4294967295: let y = x + 1;), stmt(4294967295: return y;)], expr:
    None, id: 4294967295, rules: Default, span: Span { lo: BytePos(15), hi: BytePos(43), expn_id: ExpnId(4294967295) } }),
    vis: Inherited, span: Span { lo: BytePos(0), hi: BytePos(43), expn_id: ExpnId(4294967295) } }] }, attrs: [], config: [],
    span: Span { lo: BytePos(0), hi: BytePos(42), expn_id: ExpnId(4294967295) }, exported_macros: [] })