1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
#[macro_use] extern crate log; extern crate regex; use std::path::PathBuf; use std::fs::File; use std::io::Read; use regex::Regex; use std::io::Write; mod ast; mod context; mod error; mod evaluator; mod sass; mod optimizer; mod parser; mod token; mod tokenizer; use context::Context; use error::Result; use tokenizer::Tokenizer; use parser::Parser; use sass::output_style::SassOutputStyle; fn resolve_imports(inputpath: &PathBuf) -> Result<String> { let mut file = try!(File::open(&inputpath)); let mut sass = String::new(); try!(file.read_to_string(&mut sass)); let mut imports_resolved = String::new(); for line in sass.split("\n") { let re = Regex::new("@import \"([^\"]*)\";").unwrap(); match re.captures(line) { Some(caps) => { let imported = try!(resolve_imports(&inputpath.with_file_name(caps.at(1).unwrap()))); imports_resolved.push_str(&imported); }, None => { imports_resolved.push_str(line); }, } imports_resolved.push_str("\n"); } Ok(imports_resolved) } pub fn compile<W: Write>(input_filename: &str, output: &mut W, style: &str) -> Result<()> { let input_path = PathBuf::from(input_filename); let imports_resolved = try!(resolve_imports(&input_path)); let style: SassOutputStyle = try!(style.parse()); match style { SassOutputStyle::Tokens => { let mut tokenizer = Tokenizer::new(&imports_resolved); while let Some(token) = tokenizer.next() { try!(write!(output, "{:?}\n", token)) } }, SassOutputStyle::AST => { let mut parser = Parser::new(&imports_resolved); while let Some(ast_node) = parser.next() { try!(write!(output, "{:?}\n", ast_node)); } }, other_style => { let mut parser = Parser::new(&imports_resolved); let mut context = Context::new(); while let Some(Ok(ast_node)) = parser.next() { let evaluated = evaluator::evaluate(ast_node, &mut context); if let Some(root) = evaluated { let optimized = optimizer::optimize(root); for r in optimized { try!(r.stream(output, other_style)); } } } }, } Ok(()) }