2015-07-22 03:12:01 -07:00
|
|
|
use std::slice::Iter;
|
2015-07-22 03:42:21 -07:00
|
|
|
use std::iter::Peekable;
|
2015-07-22 03:12:01 -07:00
|
|
|
|
2015-07-22 04:01:56 -07:00
|
|
|
use tokenizer::{Token, Kw};
|
2015-07-22 03:12:01 -07:00
|
|
|
use tokenizer::Token::*;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum AST {
|
|
|
|
Name(String),
|
|
|
|
LangString(String),
|
|
|
|
Number(f64),
|
|
|
|
BinOp(Box<AST>, Box<AST>, Box<AST>),
|
2015-07-24 02:05:15 -07:00
|
|
|
Binding(String, Box<AST>),
|
2015-07-24 17:59:24 -07:00
|
|
|
Statements(Vec<AST>),
|
|
|
|
IfStatement(Box<AST>, Box<AST>, Option<Box<AST>>)
|
2015-07-22 03:12:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub enum ParseResult {
|
|
|
|
Ok(AST),
|
|
|
|
Err(String)
|
|
|
|
}
|
|
|
|
|
2015-07-22 03:42:21 -07:00
|
|
|
type Tokens<'a> = Peekable<Iter<'a,Token>>;
|
2015-07-22 03:36:32 -07:00
|
|
|
|
2015-07-22 03:45:42 -07:00
|
|
|
/* expect calls .next() and thus advances the token list */
|
2015-07-22 03:28:26 -07:00
|
|
|
macro_rules! expect {
|
|
|
|
($tok:expr, $tokens:expr) => ( if !expect_token($tok, $tokens) {
|
|
|
|
return ParseResult::Err(format!("Expected {:?}", $tok));
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2015-07-22 03:36:32 -07:00
|
|
|
fn expect_token(tok: Token, tokens: &mut Tokens) -> bool {
|
2015-07-22 03:12:01 -07:00
|
|
|
if let Some(n) = tokens.next() {
|
|
|
|
let next = (*n).clone();
|
|
|
|
return match (tok, next) {
|
|
|
|
(EOF, EOF) => true,
|
|
|
|
(Separator, Separator) => true,
|
|
|
|
(LParen, LParen) => true,
|
|
|
|
(RParen, RParen) => true,
|
|
|
|
(Comma, Comma) => true,
|
|
|
|
(NumLiteral(_), NumLiteral(_)) => true,
|
|
|
|
(StrLiteral(_), StrLiteral(_)) => true,
|
|
|
|
(Identifier(ref i1), Identifier(ref i2)) => i1 == i2,
|
2015-07-22 04:01:56 -07:00
|
|
|
(Keyword(k1), Keyword(k2)) => k1 == k2,
|
2015-07-22 03:12:01 -07:00
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-22 03:45:42 -07:00
|
|
|
false
|
2015-07-22 03:12:01 -07:00
|
|
|
}
|
|
|
|
|
2015-07-22 03:45:42 -07:00
|
|
|
pub fn parse(input: Vec<Token>) -> ParseResult {
|
|
|
|
|
|
|
|
let mut tokens: Tokens = input.iter().peekable();
|
|
|
|
|
2015-07-24 02:08:55 -07:00
|
|
|
if let Some(&&EOF) = tokens.peek() {
|
|
|
|
return ParseResult::Ok(AST::Statements(vec!()));
|
|
|
|
}
|
|
|
|
|
2015-07-24 02:05:15 -07:00
|
|
|
match statements(&mut tokens) {
|
|
|
|
ok@ParseResult::Ok(_) => {
|
|
|
|
expect!(EOF, &mut tokens);
|
|
|
|
ok
|
|
|
|
},
|
|
|
|
err@ParseResult::Err(_) => err
|
2015-07-22 03:45:42 -07:00
|
|
|
}
|
2015-07-24 02:05:15 -07:00
|
|
|
}
|
2015-07-22 03:45:42 -07:00
|
|
|
|
2015-07-24 02:05:15 -07:00
|
|
|
fn statements(input: &mut Tokens) -> ParseResult {
|
|
|
|
|
|
|
|
let mut statements = Vec::new();
|
|
|
|
|
|
|
|
let initial_statement = statement(input);
|
|
|
|
match initial_statement {
|
|
|
|
ParseResult::Ok(ast) => {
|
|
|
|
statements.push(ast);
|
|
|
|
loop {
|
|
|
|
let lookahead = input.peek().map(|i| i.clone());
|
|
|
|
if let Some(&Separator) = lookahead {
|
|
|
|
input.next();
|
|
|
|
if let ParseResult::Ok(ast_next) = statement(input) {
|
|
|
|
statements.push(ast_next);
|
|
|
|
} else {
|
|
|
|
return ParseResult::Err("bad thing happened".to_string());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
err@ParseResult::Err(_) => {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ParseResult::Ok(AST::Statements(statements));
|
2015-07-22 03:45:42 -07:00
|
|
|
}
|
|
|
|
|
2015-07-24 02:05:15 -07:00
|
|
|
fn statement(input: &mut Tokens) -> ParseResult {
|
2015-07-24 04:15:28 -07:00
|
|
|
match input.peek().map(|i| i.clone()) {
|
|
|
|
Some(&Keyword(Kw::Let)) => let_expression(input),
|
|
|
|
_ => expression(input)
|
|
|
|
}
|
2015-07-24 02:05:15 -07:00
|
|
|
}
|
2015-07-22 03:45:42 -07:00
|
|
|
|
2015-07-22 03:36:32 -07:00
|
|
|
fn let_expression(input: &mut Tokens) -> ParseResult {
|
2015-07-22 04:01:56 -07:00
|
|
|
expect!(Keyword(Kw::Let), input);
|
2015-07-22 03:28:26 -07:00
|
|
|
if let Some(&Identifier(ref name)) = input.next() {
|
|
|
|
if let Some(&Identifier(ref s)) = input.next() {
|
|
|
|
if s == "=" {
|
2015-07-24 02:23:18 -07:00
|
|
|
if let ParseResult::Ok(rhs) = rhs(input) {
|
|
|
|
return ParseResult::Ok(
|
|
|
|
AST::Binding(name.clone(),
|
|
|
|
Box::new(rhs)));
|
2015-07-22 03:12:01 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-24 02:05:15 -07:00
|
|
|
return ParseResult::Err("Bad parse in let_expression()".to_string());
|
2015-07-22 03:12:01 -07:00
|
|
|
}
|
2015-07-24 02:23:18 -07:00
|
|
|
|
2015-07-24 04:15:28 -07:00
|
|
|
fn expression(input: &mut Tokens) -> ParseResult {
|
2015-07-24 17:59:24 -07:00
|
|
|
let lookahead = input.peek().map(|i| i.clone());
|
|
|
|
match lookahead {
|
|
|
|
Some(&Keyword(Kw::If)) => {
|
2015-07-25 15:22:07 -07:00
|
|
|
if_expression(input)
|
2015-07-24 17:59:24 -07:00
|
|
|
},
|
2015-07-25 15:22:07 -07:00
|
|
|
_ => rhs(input)
|
2015-07-24 17:59:24 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn if_expression(input: &mut Tokens) -> ParseResult {
|
|
|
|
|
2015-07-25 15:22:07 -07:00
|
|
|
expect!(Keyword(Kw::If), input);
|
|
|
|
let if_clause = match expression(input) {
|
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => ast
|
|
|
|
};
|
|
|
|
|
|
|
|
expect!(Keyword(Kw::Then), input);
|
|
|
|
|
|
|
|
let then_clause = match expression(input) {
|
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => ast
|
|
|
|
};
|
|
|
|
|
2015-07-25 15:34:59 -07:00
|
|
|
let else_clause = match input.peek().map(|i| i.clone()) {
|
|
|
|
Some(&Keyword(Kw::Else)) => {
|
|
|
|
input.next();
|
|
|
|
match expression(input) {
|
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => Some(ast)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => None
|
|
|
|
};
|
|
|
|
|
2015-07-25 15:22:07 -07:00
|
|
|
expect!(Keyword(Kw::End), input);
|
2015-07-24 17:59:24 -07:00
|
|
|
|
2015-07-25 15:22:07 -07:00
|
|
|
ParseResult::Ok( AST::IfStatement(
|
|
|
|
Box::new(if_clause),
|
|
|
|
Box::new(then_clause),
|
2015-07-25 15:34:59 -07:00
|
|
|
else_clause.map(|ast| Box::new(ast))
|
|
|
|
))
|
2015-07-24 04:15:28 -07:00
|
|
|
}
|
|
|
|
|
2015-07-24 02:23:18 -07:00
|
|
|
fn rhs(input: &mut Tokens) -> ParseResult {
|
|
|
|
let next = input.next();
|
|
|
|
if let Some(&Identifier(ref value)) = next {
|
|
|
|
return ParseResult::Ok(AST::Name(value.clone()));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(&StrLiteral(ref value)) = next {
|
|
|
|
return ParseResult::Ok(AST::LangString(value.clone()));
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(&NumLiteral(n)) = next {
|
|
|
|
return ParseResult::Ok(AST::Number(n));
|
|
|
|
}
|
|
|
|
|
|
|
|
return ParseResult::Err("Bad parse in rhs()".to_string());
|
|
|
|
}
|