Implement display and string support resolves #10
This commit is contained in:
@@ -20,6 +20,10 @@ pub fn get_global_environment<'a>() -> Env<'a> {
|
||||
(make_symbol("-"), Datum::Procedure(primitives::sub)),
|
||||
(make_symbol("="), Datum::Procedure(primitives::eq)),
|
||||
(make_symbol("<"), Datum::Procedure(primitives::lt)),
|
||||
(
|
||||
make_symbol("display"),
|
||||
Datum::Procedure(primitives::display),
|
||||
),
|
||||
],
|
||||
outer: None,
|
||||
}
|
||||
|
||||
@@ -83,6 +83,10 @@ fn interpret_define(args: &Vec<Datum>, env: &mut Env) -> Datum {
|
||||
}
|
||||
}
|
||||
|
||||
fn interpret_cond(_vec: &Vec<Datum>, _env: &mut Env) -> Datum {
|
||||
Datum::Unspecified
|
||||
}
|
||||
|
||||
fn interpret_begin(vec: &Vec<Datum>, env: &mut Env) -> Datum {
|
||||
let mut r = Datum::Unspecified;
|
||||
for i in 1..vec.len() {
|
||||
@@ -127,16 +131,17 @@ pub fn interpret(exp: &Datum, env: &mut Env) -> Datum {
|
||||
match exp {
|
||||
Boolean(_) => exp.clone(),
|
||||
Number(_) => exp.clone(),
|
||||
Unspecified => Unspecified,
|
||||
String(_) => exp.clone(),
|
||||
Symbol(_) => environment::lookup_variable_value(exp, env),
|
||||
List(v) if has_tag(v, "if") => interpret_if(v, env),
|
||||
List(v) if has_tag(v, "set!") => interpret_set(v, env),
|
||||
List(v) if has_tag(v, "define") => interpret_define(v, env),
|
||||
List(v) if has_tag(v, "cond") => panic!("cond-not-supported"),
|
||||
List(v) if has_tag(v, "cond") => interpret_cond(v, env),
|
||||
List(v) if has_tag(v, "let") => panic!("let-not-supported"),
|
||||
List(v) if has_tag(v, "begin") => interpret_begin(v, env),
|
||||
List(v) if has_tag(v, "quote") => v[1].clone(),
|
||||
List(v) => interpret_application(v, env),
|
||||
Unspecified => Unspecified,
|
||||
_ => panic!("unknown-expression {:?}", exp),
|
||||
}
|
||||
}
|
||||
|
||||
36
src/lexer.rs
36
src/lexer.rs
@@ -3,6 +3,7 @@ pub enum Token {
|
||||
Identifier(String),
|
||||
Boolean(bool),
|
||||
Number(i64),
|
||||
String(String),
|
||||
LeftRoundBracket,
|
||||
RightRoundBracket,
|
||||
Quote,
|
||||
@@ -33,6 +34,8 @@ fn scan(code: &str, mut ix: usize, mut tokens: Tokens) -> Tokens {
|
||||
return scan_boolean(code, ix, tokens);
|
||||
} else if c == ';' {
|
||||
return scan_comment(code, ix, tokens);
|
||||
} else if c == '"' {
|
||||
return scan_string(code, ix, tokens);
|
||||
} else if c.is_ascii_digit() {
|
||||
return scan_number(code, ix, tokens);
|
||||
} else if c.is_ascii_alphabetic() || SPECIAL_INITIAL.contains(&c) {
|
||||
@@ -95,6 +98,39 @@ fn scan_comment(code: &str, mut ix: usize, tokens: Tokens) -> Tokens {
|
||||
scan(code, ix, tokens)
|
||||
}
|
||||
|
||||
fn scan_string(code: &str, mut ix: usize, mut tokens: Tokens) -> Tokens {
|
||||
let mut s = String::new();
|
||||
let mut chars = code[ix..].chars();
|
||||
let c = chars.next().unwrap();
|
||||
assert!(c == '"');
|
||||
|
||||
ix += 1;
|
||||
while let Some(c) = chars.next() {
|
||||
ix += 1;
|
||||
if c == '"' {
|
||||
break;
|
||||
} else if c == '\\' {
|
||||
ix += 1;
|
||||
if let Some(next_c) = chars.next() {
|
||||
let escaped_c = match next_c {
|
||||
'n' => '\n',
|
||||
'"' => '"',
|
||||
'\\' => '\\',
|
||||
_ => panic!("SCAN-STRING -- cannot escape {}", next_c),
|
||||
};
|
||||
s.push(escaped_c);
|
||||
} else {
|
||||
panic!("SCAN-STRING -- found escape at eof")
|
||||
}
|
||||
} else {
|
||||
s.push(c);
|
||||
}
|
||||
}
|
||||
let token = Token::String(s);
|
||||
tokens.push(token);
|
||||
scan(code, ix, tokens)
|
||||
}
|
||||
|
||||
fn scan_number(code: &str, mut ix: usize, mut tokens: Tokens) -> Tokens {
|
||||
let start_ix = ix;
|
||||
let mut chars = code[ix..].chars();
|
||||
|
||||
@@ -6,6 +6,7 @@ use std::cmp::Ordering;
|
||||
pub enum Datum {
|
||||
Boolean(bool),
|
||||
Number(i64),
|
||||
String(String),
|
||||
Symbol(String),
|
||||
List(Vec<Datum>),
|
||||
Procedure(fn(Vec<Datum>) -> Datum),
|
||||
@@ -52,6 +53,7 @@ fn parse_datum(tokens: &Tokens, ix: usize) -> (Datum, usize) {
|
||||
Token::Identifier(s) => (Datum::Symbol(s.to_string()), ix + 1),
|
||||
Token::Boolean(b) => (Datum::Boolean(*b), ix + 1),
|
||||
Token::Number(n) => (Datum::Number(*n), ix + 1),
|
||||
Token::String(s) => (Datum::String(s.to_string()), ix + 1),
|
||||
Token::Quote => parse_quote(tokens, ix + 1),
|
||||
Token::LeftRoundBracket => parse_list(tokens, ix + 1),
|
||||
_ => panic!("Unexpected token {:?}", tokens[ix]),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
use crate::parser::Datum;
|
||||
use crate::parser::Datum::*;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::mem;
|
||||
|
||||
pub fn add(mut args: Vec<Datum>) -> Datum {
|
||||
@@ -84,3 +86,17 @@ pub fn lt(args: Vec<Datum>) -> Datum {
|
||||
Boolean(true)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display(args: Vec<Datum>) -> Datum {
|
||||
for i in 1..args.len() {
|
||||
match &args[i] {
|
||||
Boolean(b) => print!("{}", b),
|
||||
Number(n) => print!("{}", n),
|
||||
String(s) => print!("{}", s),
|
||||
List(v) => print!("{:?}", v),
|
||||
_ => panic!("DISPLAY -- cannot-print {:?}", args[1]),
|
||||
};
|
||||
}
|
||||
io::stdout().flush().ok().expect("Could not flush stdout");
|
||||
Unspecified
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user