2022-03-06 09:04:48 -06:00
|
|
|
use std::fs;
|
|
|
|
|
|
|
|
use clap::Parser as ArgParser;
|
2022-03-06 09:50:23 -06:00
|
|
|
use ariadne::{Report, ReportKind, Label, Source, Color, Fmt};
|
2022-03-06 09:04:48 -06:00
|
|
|
use lexer::lex;
|
|
|
|
use parser::parse;
|
|
|
|
|
|
|
|
pub mod args;
|
|
|
|
use args::{Args, Options};
|
|
|
|
|
|
|
|
pub mod util;
|
|
|
|
use crate::util::log;
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let args = Args::parse();
|
|
|
|
match args.options {
|
|
|
|
Options::Compile {
|
|
|
|
input: file_name,
|
|
|
|
ast: _print_ast,
|
|
|
|
} => {
|
|
|
|
// Get file contents.
|
|
|
|
let src = fs::read_to_string(&file_name).expect("Failed to read file");
|
|
|
|
|
|
|
|
// Lex the file.
|
|
|
|
let (tokens, lex_error) = lex(src.clone());
|
2022-03-06 09:50:23 -06:00
|
|
|
let (ast, parse_error) = parse(tokens.unwrap(), src.chars().count());
|
2022-03-06 09:04:48 -06:00
|
|
|
|
2022-03-06 09:50:23 -06:00
|
|
|
lex_error.into_iter()
|
|
|
|
.map(|e| e.map(|e| e.to_string()))
|
|
|
|
.chain(parse_error.into_iter().map(|e| e.map(|tok| tok.to_string())))
|
|
|
|
.for_each(|e| {
|
|
|
|
let report = Report::build(ReportKind::Error, (), e.span().start);
|
2022-03-06 09:04:48 -06:00
|
|
|
|
2022-03-06 09:50:23 -06:00
|
|
|
let report = match e.reason() {
|
|
|
|
chumsky::error::SimpleReason::Unclosed { span, delimiter } => report
|
|
|
|
.with_message(format!(
|
|
|
|
"Unclosed delimiter {}",
|
|
|
|
delimiter.fg(Color::Yellow)
|
|
|
|
))
|
|
|
|
.with_label(
|
|
|
|
Label::new(span.clone())
|
|
|
|
.with_message(format!(
|
|
|
|
"Expected closing delimiter {}",
|
|
|
|
delimiter.fg(Color::Yellow)
|
|
|
|
))
|
|
|
|
.with_color(Color::Yellow)
|
|
|
|
)
|
|
|
|
.with_label(
|
|
|
|
Label::new(e.span())
|
|
|
|
.with_message(format!(
|
|
|
|
"Must be closed before this {}",
|
|
|
|
e.found()
|
|
|
|
.unwrap_or(&"end of file".to_string())
|
|
|
|
.fg(Color::Red)
|
|
|
|
))
|
|
|
|
.with_color(Color::Red)
|
|
|
|
),
|
|
|
|
|
|
|
|
chumsky::error::SimpleReason::Unexpected => report
|
|
|
|
.with_message(format!(
|
|
|
|
"{}, expected {}",
|
|
|
|
|
2022-03-06 11:20:18 -06:00
|
|
|
if e.found().is_some() { "Unexpected token in input" }
|
2022-03-06 09:50:23 -06:00
|
|
|
else { "Unexpected end of input" },
|
|
|
|
|
|
|
|
if e.expected().len() == 0 { "something else".to_string().fg(Color::Green) }
|
|
|
|
else {
|
|
|
|
e.expected()
|
|
|
|
.map(|expected| match expected {
|
|
|
|
Some(expected) => expected.to_string(),
|
|
|
|
None => "end of input".to_string()
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.join(", ")
|
|
|
|
.fg(Color::Green)
|
|
|
|
}
|
|
|
|
))
|
|
|
|
.with_label(
|
|
|
|
Label::new(e.span())
|
|
|
|
.with_message(format!(
|
|
|
|
"Unexpected token {}",
|
|
|
|
e.found()
|
|
|
|
.unwrap_or(&"EOF".to_string())
|
|
|
|
.fg(Color::Red)
|
|
|
|
))
|
|
|
|
.with_color(Color::Red)
|
2022-03-06 11:20:18 -06:00
|
|
|
)
|
|
|
|
.with_help(
|
|
|
|
"You might have forgotten to end a previous line with semicolon"
|
2022-03-06 09:50:23 -06:00
|
|
|
),
|
|
|
|
_ => {
|
|
|
|
println!("{:?}", e);
|
|
|
|
todo!();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
report.finish().print(Source::from(&src)).unwrap();
|
|
|
|
});
|
|
|
|
|
|
|
|
match ast {
|
|
|
|
Some(ast) => {
|
2022-03-06 09:04:48 -06:00
|
|
|
println!("{:#?}", ast);
|
2022-03-06 09:50:23 -06:00
|
|
|
},
|
|
|
|
None => {
|
|
|
|
log(2, "Failed to parse.");
|
2022-03-06 09:04:48 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|