extern crate libc; extern crate ruby_sys; #[macro_use] extern crate lazy_static; #[macro_use] mod rb; use rb::{CallbackPtr, Value, RB_NIL}; mod atom; mod quotes; mod lisp { include!(concat!(env!("OUT_DIR"), "/lisp.rs")); } fn parse_native(rself: Value) -> Value { let code = rbstr2str!(&rb::ivar_get(&rself, "@code")); let filename_rbstr = rb::ivar_get(&rself, "@filename"); let filename = rbstr2str!(&filename_rbstr); let newlines: Vec = code.match_indices("\n").map(|(i, _s)| i).collect(); rb::gc_disable(); match lisp::program(&code, &filename, &newlines) { Ok(ast) => { rb::gc_enable(); ast }, Err(err) => { raise_syntax_error(err, filename_rbstr); RB_NIL } } } fn raise_syntax_error(err: lisp::ParseError, filename_rbstr: Value) { let c_parser = rb::const_get("Parser", &RB_NIL); let c_parse_error = rb::const_get("ParseError", &c_parser); let line = int2rbnum!(err.line); let column = int2rbnum!(err.column); let mut expected = rb::ary_new(); for token in err.expected { expected = rb::ary_push(expected, rb::str_new(token)); } let error = rb::class_new_instance(&c_parse_error, vec![filename_rbstr, line, column, expected]); rb::gc_enable(); rb::raise_instance(&error); } #[no_mangle] pub extern fn init_parser() { let c_parser = rb::const_get("Parser", &RB_NIL); rb::define_method(&c_parser, "parse_native", parse_native as CallbackPtr, 0); }