2017-11-26 21:17:17 -08:00
|
|
|
use itertools::Itertools;
|
|
|
|
use schala_lib::{ProgrammingLanguageInterface, EvalOptions, ReplOutput};
|
2017-11-29 01:45:29 -08:00
|
|
|
use std::iter::Peekable;
|
|
|
|
use std::str::Chars;
|
2017-11-26 21:17:17 -08:00
|
|
|
|
|
|
|
pub struct Rukka { }
|
|
|
|
|
|
|
|
impl Rukka {
|
|
|
|
pub fn new() -> Rukka { Rukka { } }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ProgrammingLanguageInterface for Rukka {
|
|
|
|
fn get_language_name(&self) -> String {
|
|
|
|
"Rukka".to_string()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_source_file_suffix(&self) -> String {
|
|
|
|
format!("rukka")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn evaluate_in_repl(&mut self, input: &str, _eval_options: &EvalOptions) -> ReplOutput {
|
|
|
|
let mut output = ReplOutput::default();
|
2017-11-29 01:45:29 -08:00
|
|
|
match parse(input).and_then(|x| eval(x)) {
|
|
|
|
Ok(s) => output.add_output(s),
|
|
|
|
Err(e) => output.add_output(format!("Error: {}", e))
|
|
|
|
};
|
2017-11-26 21:17:17 -08:00
|
|
|
output
|
|
|
|
}
|
|
|
|
}
|
2017-11-27 00:57:26 -08:00
|
|
|
|
2017-11-28 03:37:16 -08:00
|
|
|
fn eval(ast: Sexp) -> Result<String, String> {
|
2017-11-29 02:08:30 -08:00
|
|
|
Ok(format!("{:?}", ast))
|
2017-11-28 03:37:16 -08:00
|
|
|
}
|
|
|
|
|
2017-11-29 01:45:29 -08:00
|
|
|
fn parse(input: &str) -> Result<Sexp, String> {
|
|
|
|
let mut iter: Peekable<Chars> = input.chars().peekable();
|
2017-11-29 02:08:30 -08:00
|
|
|
let output = read_sexp(&mut iter);
|
|
|
|
match iter.next() {
|
|
|
|
None => output,
|
|
|
|
Some(c) => Err(format!("Expected end of input, got {}", c)),
|
|
|
|
}
|
2017-11-28 03:37:16 -08:00
|
|
|
}
|
2017-11-27 00:57:26 -08:00
|
|
|
|
2017-11-30 22:37:49 -08:00
|
|
|
#[derive(Debug)]
|
|
|
|
enum Token {
|
|
|
|
LParen,
|
|
|
|
RParen,
|
|
|
|
Symbol(String)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tokenize(input: &mut Peekable<Chars>) -> Vec<Token> {
|
|
|
|
let mut tokens = Vec::new();
|
|
|
|
loop {
|
|
|
|
match input.peek().map(|x| *x) {
|
|
|
|
None => break,
|
|
|
|
Some('(') => tokens.push(LParen),
|
|
|
|
Some(')') => tokens.push(RParen),
|
|
|
|
Some(c) if c.is_whitespace() => { tokens.next(); continue },
|
|
|
|
Some(c) => {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-29 02:08:30 -08:00
|
|
|
fn read_sexp(input: &mut Peekable<Chars>) -> Result<Sexp, String> {
|
2017-11-29 01:45:29 -08:00
|
|
|
if input.next() != Some('(') {
|
|
|
|
return Err(format!("Expected '('"));
|
2017-11-28 03:37:16 -08:00
|
|
|
}
|
2017-11-29 02:08:30 -08:00
|
|
|
let mut v = Vec::new();
|
|
|
|
loop {
|
|
|
|
let c = input.peek().map(|x| *x);
|
|
|
|
match c {
|
|
|
|
Some(')') | None => break,
|
|
|
|
Some('(') => v.push(read_sexp(input)?),
|
|
|
|
Some(c) if c.is_whitespace() => { input.next(); continue; },
|
|
|
|
Some(c) => v.push(read_sym(input)?)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if input.next() != Some(')') {
|
|
|
|
return Err(format!("Expected ')'"));
|
|
|
|
}
|
|
|
|
Ok(Sexp::List(v))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_sym(input: &mut Peekable<Chars>) -> Result<Sexp, String> {
|
|
|
|
let mut sym = String::new();
|
|
|
|
loop {
|
|
|
|
sym.push(input.next().unwrap());
|
|
|
|
match input.peek().map(|x| *x) {
|
|
|
|
Some('(') | Some(')') | None => break,
|
|
|
|
Some(c) if c.is_whitespace() => break,
|
|
|
|
_ => continue,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(Sexp::Atom(AtomT::Symbol(sym)))
|
2017-11-28 03:37:16 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
enum Sexp {
|
|
|
|
Atom(AtomT),
|
|
|
|
List(Vec<Sexp>),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
enum AtomT {
|
|
|
|
Symbol(String),
|
2017-11-29 02:08:30 -08:00
|
|
|
//Number(u64),
|
2017-11-27 00:57:26 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct List<'a> {
|
|
|
|
next: Option<&'a List<'a>>,
|
2017-11-28 03:37:16 -08:00
|
|
|
data: usize
|
2017-11-27 00:57:26 -08:00
|
|
|
}
|
2017-11-28 03:37:16 -08:00
|
|
|
|