Skip to content

mo-xiaoming/clang-rs-binding

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Baby Steps With LibClang ("idiomatic" rust version)

CI codecov

Inspired by Bastian Rieck's wonderful blogs, Baby Steps With LibClang: Walking an Abstract Syntax Tree and Baby Steps With LibClang: Counting Function Extents

Two blog's corresponding rust code

A Simple Demo

For a C++ file traverse_ast.cpp like

template <typename T>
bool f(T x) {
  return x % 2;
}

To get output like

FunctionTemplate (f)
TemplateTypeParameter (T)
ParmDecl (x)
TypeRef (T)
CompoundStmt ()
ReturnStmt ()
BinaryOperator ()
DeclRefExpr (x)
IntegerLiteral ()

You can use something like

use std::path::Path;
use clang_rs_binding::index::{Cursor, Payload, ChildVisitResult};

fn visitor(cursor: &Cursor, _parent: &Cursor, payload: Payload) -> i32 {
    if cursor.is_from_main_file() {
        return ChildVisitResult::CONTINUE;
    }
    let cursor_kind_spelling = cursor.kind_spelling();
    let cursor_spelling = cursor.spelling();
    println!("{} ({})", cursor_kind_spelling, cursor_spelling);
    cursor.visit_children(visitor, payload);
    ChildVisitResult::CONTINUE
}

fn generate_ast<P: AsRef<Path>>(filename: P) -> impl AsRef<Path> {
    let ast_filename = Path::new("traverse_ast.ast");
    std::process::Command::new("clang++")
        .arg("-emit-ast").arg(filename.as_ref()).status().unwrap();
    ast_filename
}

fn main() {
    let traverse_ast_dir = Path::new("tests/artifacts/traverse_ast");
    let ast_filename = generate_ast(traverse_ast_dir.join("traverse_ast.cpp"));

    clang_rs_binding::clang::Clang::default()
        .create_index_with_display_diagnostics()
        .create_translation_unit(&ast_filename)
        .create_cursor()
        .visit_children(visitor, std::ptr::null());
}

About

"idiomatic" libclang rust binding

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages