85 lines
2.7 KiB
Rust
85 lines
2.7 KiB
Rust
use codespan_reporting::files::SimpleFiles;
|
|
use codespan_reporting::term;
|
|
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
|
|
use deimos::ast::build::build_ast;
|
|
use deimos::name_analysis::analyze_names;
|
|
use deimos::name_analysis::symbol_table::SymbolTable;
|
|
use deimos::parser::{DeimosParser, Rule};
|
|
use deimos::std_core::add_std_core_symbols;
|
|
use pest::Parser;
|
|
use std::collections::HashMap;
|
|
use std::fmt::{Debug, Display, Formatter};
|
|
use std::path::PathBuf;
|
|
use deimos::ast::node::CompilationUnit;
|
|
|
|
struct ParseErrors {
|
|
errors: Vec<pest::error::Error<Rule>>,
|
|
}
|
|
|
|
impl Debug for ParseErrors {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
Display::fmt(self, f)
|
|
}
|
|
}
|
|
|
|
impl Display for ParseErrors {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
writeln!(f, "There were errors during parsing.")?;
|
|
for parse_error in &self.errors {
|
|
writeln!(f, "{}", parse_error)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for ParseErrors {}
|
|
|
|
pub fn name_analysis(paths: &[PathBuf]) -> Result<Vec<CompilationUnit>, Box<dyn std::error::Error>> {
|
|
let mut paths_and_sources: HashMap<String, String> = HashMap::new();
|
|
for path in paths {
|
|
let src = std::fs::read_to_string(path).unwrap();
|
|
paths_and_sources.insert(path.display().to_string(), src);
|
|
}
|
|
|
|
let mut compilation_units = vec![];
|
|
let mut files: SimpleFiles<&str, &str> = SimpleFiles::new();
|
|
let mut parse_errors = vec![];
|
|
|
|
for (path, source) in &paths_and_sources {
|
|
let parse_result = DeimosParser::parse(Rule::CompilationUnit, source);
|
|
match parse_result {
|
|
Ok(mut pairs) => {
|
|
let file_id = files.add(path, source);
|
|
let compilation_unit = build_ast(file_id, &mut pairs);
|
|
compilation_units.push(compilation_unit);
|
|
}
|
|
Err(error) => {
|
|
parse_errors.push(error);
|
|
}
|
|
}
|
|
}
|
|
|
|
if !parse_errors.is_empty() {
|
|
return Err(Box::new(ParseErrors {
|
|
errors: parse_errors,
|
|
}));
|
|
}
|
|
|
|
let mut symbol_table = SymbolTable::new();
|
|
add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols.");
|
|
|
|
let diagnostics = analyze_names(&mut compilation_units, &files, &mut symbol_table);
|
|
if diagnostics.is_empty() {
|
|
println!("Name analysis complete.");
|
|
println!("{}", symbol_table);
|
|
} else {
|
|
let writer = StandardStream::stderr(ColorChoice::Always);
|
|
let config = term::Config::default();
|
|
for diagnostic in diagnostics {
|
|
term::emit(&mut writer.lock(), &config, &files, &diagnostic)?;
|
|
}
|
|
}
|
|
|
|
Ok(compilation_units)
|
|
}
|