Show location of error in parse error

This commit is contained in:
greg 2019-01-07 01:52:31 -08:00
parent a0f4abb9a3
commit fa295aab28

View File

@ -90,7 +90,8 @@ impl Schala {
} }
//TODO rejigger the signature of these methods so you don't awkwardly have the input in the middle //TODO rejigger the signature of these methods so you don't awkwardly have the input in the middle
fn load_source<'a>(_handle: &mut Schala, input: &'a str, comp: Option<&mut UnfinishedComputation>) -> Result<&'a str, String> { fn load_source<'a>(handle: &mut Schala, input: &'a str, _comp: Option<&mut UnfinishedComputation>) -> Result<&'a str, String> {
handle.source_reference.load_new_source(input);
Ok(input) Ok(input)
} }
@ -131,13 +132,25 @@ fn parsing(handle: &mut Schala, input: Vec<tokenizing::Token>, comp: Option<&mut
Some(ref x) => println!("Bad parsing debug option: {}", x), Some(ref x) => println!("Bad parsing debug option: {}", x),
}; };
}); });
ast.map_err(|error: parsing::ParseError| { ast.map_err(|err| format_parse_error(err, handle))
let location_frag = match error.token { }
Some(tok) => format!(" at line: {} column: {}", tok.offset.0, tok.offset.1),
None => "".into() fn format_parse_error(error: parsing::ParseError, handle: &mut Schala) -> String {
}; //TODO make token no longer be Optoinal
format!("'{}'{}", error.msg, location_frag) if let Some(tok) = error.token {
}) let line = tok.offset.0;
let ch = tok.offset.1;
let line_from_program = handle.source_reference.get_line(line);
let location_pointer = format!("{}^", " ".repeat(ch));
format!(r#"
{}
|
| {}
| {}
"#, error.msg, line_from_program, location_pointer)
} else {
format!("{}", error.msg)
}
} }
fn symbol_table(handle: &mut Schala, input: ast::AST, comp: Option<&mut UnfinishedComputation>) -> Result<ast::AST, String> { fn symbol_table(handle: &mut Schala, input: ast::AST, comp: Option<&mut UnfinishedComputation>) -> Result<ast::AST, String> {
@ -183,15 +196,20 @@ fn eval(handle: &mut Schala, input: reduced_ast::ReducedAST, comp: Option<&mut U
} }
struct SourceReference { struct SourceReference {
lines: Option<Vec<String>>
} }
impl SourceReference { impl SourceReference {
fn new() -> SourceReference { fn new() -> SourceReference {
SourceReference { } SourceReference { lines: None }
} }
fn load_new_source(&mut self, source: String) { fn load_new_source(&mut self, source: &str) {
//TODO this is a lot of heap allocations - maybe there's a way to make it more efficient?
self.lines = Some(source.lines().map(|s| s.to_string()).collect());
}
fn get_line(&self, line: usize) -> String {
self.lines.as_ref().and_then(|x| x.get(line).map(|s| s.to_string())).unwrap_or(format!("NO LINE FOUND"))
} }
} }