Skip to main content

anillo/
main.rs

1//! The Anillo Compiler
2//!
3//! The Anillo compiler serves as the currently (Work In Progress) reference implementation
4//! of the Anillo Language.
5
6use std::{collections::VecDeque, error::Error};
7
8use argparse::{ArgumentParser, Store, StoreTrue};
9
10mod error;
11mod lexer;
12mod parser;
13mod token;
14
15use parser::Parser;
16use token::TokenInfo;
17
18/// The main just parses command line args and drives the lexer, parser, and AST
19/// validator.
20///
21/// # Arguments
22/// * **_input_**
23///   Single positional argument that dictates the .ani Anillo file to parse
24/// * **_--verbose_**
25///   Enables in-progress printing of the AST as it is being built as
26///   well as other useful information as the compiler runs (such as
27///   the initial token buffer produced by the lexer)
28/// * **_-h_** or **_--help_**
29///   Prints command line help
30fn main() -> Result<(), Box<dyn Error>> {
31    let mut input_file = std::path::PathBuf::new();
32    let mut verbose: bool = false;
33
34    {
35        let mut arg_parser: ArgumentParser = ArgumentParser::new();
36        arg_parser.set_description("Parse your Anillo file");
37        arg_parser
38            .refer(&mut input_file)
39            .add_argument("input", Store, "anillo file to parse")
40            .required();
41        arg_parser.refer(&mut verbose).add_option(
42            &["--verbose"],
43            StoreTrue,
44            "Print in progress Lexer, parser, and AST state",
45        );
46
47        arg_parser.parse_args_or_exit();
48    }
49
50    if let Some(ext) = input_file.extension()
51        && let Some(ext_str) = ext.to_str()
52        && ext_str == "ani"
53    {
54        println!("Parsing input: {}", input_file.display());
55    } else {
56        eprintln!(
57            "Not an anillo file ending in '.ani': {}",
58            input_file.display()
59        );
60        return Err(Box::new(std::io::Error::new(
61            std::io::ErrorKind::NotFound,
62            "Not an anillo file ending in '.ani'",
63        )));
64    }
65
66    let mut lexer = lexer::Lexer::new(&input_file)?;
67    let tokens: VecDeque<TokenInfo> = lexer.tokenize()?;
68    let mut parser = Parser::new(tokens);
69
70    if verbose {
71        println!(
72            "********************************************************************************"
73        );
74        println!("Starting token buffer:");
75        dbg!(&parser);
76        println!(
77            "********************************************************************************"
78        );
79    }
80
81    let ast = parser.run(verbose)?;
82
83    if verbose {
84        println!(
85            "********************************************************************************"
86        );
87        println!("Final AST:");
88        dbg!(&ast);
89        println!(
90            "********************************************************************************"
91        );
92    }
93
94    ast.verify()?;
95    println!("{} passed verification!", input_file.display());
96
97    Ok(())
98}