retrobasic 0.1.0

A BASIC emulator with easy access to a libary of classic games
use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

extern crate clap;
use clap::{App, Arg, SubCommand};

extern crate dimsum;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate rand;
extern crate serde;
extern crate serde_json;

extern crate futures;
extern crate hyper;
#[macro_use]
extern crate serde_derive;
extern crate tokio_core;

mod ast;
mod error;
mod fetcher;
mod interpreter;
mod lexer;
mod parser;
mod tokenid;

use fetcher::Fetcher;
use interpreter::Interpreter;
use lexer::Lexer;
use parser::Parser;

fn main() {
    env_logger::init();

    let matches = App::new("retrobasic")
        .version("0.1")
        .author("Salim Alam")
        .about("BASIC interpreter")
        .subcommand(SubCommand::with_name("list").about("List of known classic BASIC programs"))
        .subcommand(
            SubCommand::with_name("play")
                .about("Play a known classic BASIC program")
                .arg(
                    Arg::with_name("NAME")
                        .short("n")
                        .help("Name of classic BASIC programs")
                        .required(true)
                        .index(1),
                ),
        )
        .subcommand(
            SubCommand::with_name("run")
                .about("Run a BASIC program from a specified file")
                .arg(
                    Arg::with_name("FILENAME")
                        .short("f")
                        .help("File path of BASIC program")
                        .required(true)
                        .index(1),
                ),
        )
        .get_matches();

    if let Some(_matches) = matches.subcommand_matches("list") {
        let fetcher = Fetcher::new();
        println!("{}", fetcher);
        std::process::exit(0);
    }

    let prog = if let Some(matches) = matches.subcommand_matches("play") {
        let name = matches.value_of("NAME").unwrap();
        let fetcher = Fetcher::new();
        match fetcher.fetch(name) {
            Some(b) => b,
            None => {
                println!("Program '{}' not found!", name);
                std::process::exit(1);
            }
        }
    } else if let Some(matches) = matches.subcommand_matches("run") {
        let filename = matches.value_of("FILENAME").unwrap();
        let path = Path::new(&filename);
        let mut file = match File::open(&path) {
            Err(why) => {
                println!("Couldn't open {}: {}", filename, why.description());
                std::process::exit(1);
            }
            Ok(file) => file,
        };

        let mut b = String::new();
        match file.read_to_string(&mut b) {
            Err(why) => {
                println!("couldn't read {}: {}", filename, why.description());
                std::process::exit(1);
            }
            Ok(_) => {}
        };
        b
    } else {
        println!("How about a nice game of Chess?");
        std::process::exit(1);
    };

    let lexer = Lexer::new(prog);
    let ast = match Parser::new(lexer).parse() {
        Ok(ast) => ast,
        Err(e) => {
            println!("{}", e);
            std::process::exit(1);
        }
    };

    let mut interpreter = Interpreter::new();
    match interpreter.run(&ast) {
        Ok(_) => (),
        Err(e) => {
            println!("{}", e);
            std::process::exit(1);
        }
    };
}