symboscript-interpreter 0.17.1

SymboScript interpreter
use crate::parser::Parser;
use crate::Interpreter;

use rustyline::error::ReadlineError;
use rustyline::Result;

use rustyline::validate::{
    MatchingBracketValidator, ValidationContext, ValidationResult, Validator,
};
use rustyline::Editor;
use rustyline_derive::{Completer, Helper, Highlighter, Hinter};

#[derive(Completer, Helper, Highlighter, Hinter)]
struct InputValidator {
    brackets: MatchingBracketValidator,
}

impl Validator for InputValidator {
    fn validate(&self, ctx: &mut ValidationContext) -> Result<ValidationResult> {
        self.brackets.validate(ctx)
    }
}

pub fn start() -> Result<()> {
    let mut interpreter = Interpreter::new("repl//", "", true);

    interpreter.initialize();

    let mut k = 0;

    let h = InputValidator {
        brackets: MatchingBracketValidator::new(),
    };
    let mut rl = Editor::new()?;
    rl.set_helper(Some(h));

    println!("Symboscript v{} REPL.\n", env!("CARGO_PKG_VERSION"));
    loop {
        let readline = rl.readline("");

        match readline {
            Ok(mut line) => {
                k += 1;

                if line.trim() == "" {
                    continue;
                } else if !line.ends_with(";") && !line.ends_with("}") {
                    line += ";";
                }

                let curr_src = format!("repl/{k}/");
                let ast = Parser::new(&curr_src, &line).parse();

                interpreter.append_to_current_source(line);

                interpreter.eval_ast(ast);
            }

            Err(ReadlineError::Interrupted) => {
                println!("CTRL-C");
                break;
            }
            Err(ReadlineError::Eof) => {
                println!("CTRL-D");
                break;
            }

            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        }
    }

    Ok(())
}