extern crate lalrpop_util; extern crate colored; extern crate regex; mod parser; mod ast; use colored::*; use lalrpop_util::ParseError; use regex::Regex; pub use ast::*; pub use parser::{ parse_file, parse_model, parse_package, parse_block, parse_connector, parse_record, }; pub fn strip_comments(raw: &str) -> String { // TODO: shouldn't recompile regex on every function call // Match on comments: // (?m) sets multi-line mode let comment_re = Regex::new(r"(?m)(//.*)$").unwrap(); comment_re.replace_all(&raw, "") } fn pp_segment(raw: &str, start: usize, end: usize) -> String { let mut line_start = 0; let mut num = 0; let mut ret = String::new(); for line in raw.lines() { num += 1; let line_end = line_start + line.len(); if (line_start <= start) && (start < line_end) { ret += &format!(" {}\n{:>3} {} {}{}{}\n {} {}{}\n", "|".blue().bold(), num.to_string().blue().bold(), "|".blue().bold(), raw[line_start..start].normal(), raw[start..end].red().bold(), if end < line_end { raw[end..line_end].normal() } else { "".normal() }, "|".blue().bold(), std::iter::repeat(" ").take(start - line_start).collect::(), std::iter::repeat("^").take(end - start).collect::().red().bold()); } line_start += line.len() + 1; if line_start > end { break }; } ret } pub fn pp_parseerror(raw: &str, pe: ParseError) -> String { match pe { ParseError::InvalidToken{location} => { format!("{} invalid token starting at:\n{}", "parse error:".red().bold(), pp_segment(raw, location, location+1)) }, ParseError::UnrecognizedToken{token: Some((start, (_, tok), end)), expected} => { format!("{} unrecognized token '{}'{}:\n{}", "parse error:".red().bold(), tok, if expected.len() > 0 { format!(" (expected one of {:?})", expected) } else { format!("") }, pp_segment(raw, start, end)) }, ParseError::UnrecognizedToken{token: None, expected} => { format!("{} premature end-of-file{}", "parse error:".red().bold(), if expected.len() > 0 { format!(" (expected one of {:?})", expected) } else { format!("") }) }, ParseError::ExtraToken{token: (start, (_, tok), end)} => { format!("{} unexpected extra token '{}':\n{}", "parse error:".red().bold(), tok, pp_segment(raw, start, end)) }, _ => { format!("{} {:?}", "parse error:".red().bold(), pe) }, } }