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>),
|
2015-07-25 16:12:42 -07:00
|
|
|
IfStatement(Box<AST>, Box<AST>, Option<Box<AST>>),
|
2015-07-29 00:52:17 -07:00
|
|
|
WhileStatement(Box<AST>, Box<AST>),
|
|
|
|
DoNothing
|
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-25 15:57:04 -07:00
|
|
|
fn statements(tokens: &mut Tokens) -> ParseResult {
|
2015-07-24 02:05:15 -07:00
|
|
|
|
|
|
|
let mut statements = Vec::new();
|
|
|
|
|
2015-07-25 16:55:58 -07:00
|
|
|
let initial_statement = match statement(tokens) {
|
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => ast
|
|
|
|
};
|
|
|
|
|
|
|
|
statements.push(initial_statement);
|
|
|
|
|
|
|
|
loop {
|
|
|
|
let lookahead = tokens.peek().map(|i| i.clone());
|
|
|
|
match lookahead {
|
|
|
|
Some(&Separator) => {
|
|
|
|
tokens.next();
|
|
|
|
match statement(tokens) {
|
|
|
|
ParseResult::Ok(ast_next) => {
|
2015-07-24 02:05:15 -07:00
|
|
|
statements.push(ast_next);
|
2015-07-25 16:55:58 -07:00
|
|
|
},
|
|
|
|
err@ParseResult::Err(_) => return err
|
|
|
|
};
|
|
|
|
},
|
|
|
|
_ => break
|
2015-07-24 02:05:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ParseResult::Ok(AST::Statements(statements));
|
2015-07-22 03:45:42 -07:00
|
|
|
}
|
|
|
|
|
2015-07-25 15:57:04 -07:00
|
|
|
fn statement(tokens: &mut Tokens) -> ParseResult {
|
|
|
|
match tokens.peek().map(|i| i.clone()) {
|
|
|
|
Some(&Keyword(Kw::Let)) => let_expression(tokens),
|
|
|
|
_ => expression(tokens)
|
2015-07-24 04:15:28 -07:00
|
|
|
}
|
2015-07-24 02:05:15 -07:00
|
|
|
}
|
2015-07-22 03:45:42 -07:00
|
|
|
|
2015-07-25 15:57:04 -07:00
|
|
|
fn let_expression(tokens: &mut Tokens) -> ParseResult {
|
|
|
|
expect!(Keyword(Kw::Let), tokens);
|
|
|
|
if let Some(&Identifier(ref name)) = tokens.next() {
|
|
|
|
if let Some(&Identifier(ref s)) = tokens.next() {
|
2015-07-22 03:28:26 -07:00
|
|
|
if s == "=" {
|
2015-07-26 02:38:31 -07:00
|
|
|
if let ParseResult::Ok(expr) = expression(tokens) {
|
2015-07-24 02:23:18 -07:00
|
|
|
return ParseResult::Ok(
|
|
|
|
AST::Binding(name.clone(),
|
2015-07-25 17:43:44 -07:00
|
|
|
Box::new(expr)));
|
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-25 15:57:04 -07:00
|
|
|
fn expression(tokens: &mut Tokens) -> ParseResult {
|
|
|
|
let lookahead = tokens.peek().map(|i| i.clone());
|
2015-07-24 17:59:24 -07:00
|
|
|
match lookahead {
|
|
|
|
Some(&Keyword(Kw::If)) => {
|
2015-07-25 15:57:04 -07:00
|
|
|
if_expression(tokens)
|
2015-07-24 17:59:24 -07:00
|
|
|
},
|
2015-07-25 16:12:42 -07:00
|
|
|
Some(&Keyword(Kw::While)) => {
|
|
|
|
while_expression(tokens)
|
|
|
|
},
|
2015-07-26 01:54:55 -07:00
|
|
|
Some(&LParen) => {
|
|
|
|
tokens.next();
|
|
|
|
let expr = expression(tokens);
|
|
|
|
expect!(RParen, tokens);
|
|
|
|
expr
|
|
|
|
},
|
2015-07-26 14:59:01 -07:00
|
|
|
_ => binop_expression(tokens)
|
2015-07-24 17:59:24 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-25 15:57:04 -07:00
|
|
|
fn if_expression(tokens: &mut Tokens) -> ParseResult {
|
2015-07-24 17:59:24 -07:00
|
|
|
|
2015-07-25 15:57:04 -07:00
|
|
|
expect!(Keyword(Kw::If), tokens);
|
|
|
|
let if_clause = match expression(tokens) {
|
2015-07-25 15:22:07 -07:00
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => ast
|
|
|
|
};
|
|
|
|
|
2015-07-25 15:57:04 -07:00
|
|
|
expect!(Keyword(Kw::Then), tokens);
|
2015-07-25 15:22:07 -07:00
|
|
|
|
2015-07-25 15:57:04 -07:00
|
|
|
let then_clause = match expression(tokens) {
|
2015-07-25 15:22:07 -07:00
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => ast
|
|
|
|
};
|
|
|
|
|
2015-07-25 15:57:04 -07:00
|
|
|
let else_clause = match tokens.peek().map(|i| i.clone()) {
|
2015-07-25 15:34:59 -07:00
|
|
|
Some(&Keyword(Kw::Else)) => {
|
2015-07-25 15:57:04 -07:00
|
|
|
tokens.next();
|
|
|
|
match expression(tokens) {
|
2015-07-25 15:34:59 -07:00
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => Some(ast)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
_ => None
|
|
|
|
};
|
|
|
|
|
2015-07-25 15:57:04 -07:00
|
|
|
expect!(Keyword(Kw::End), tokens);
|
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-25 16:12:42 -07:00
|
|
|
fn while_expression(tokens: &mut Tokens) -> ParseResult {
|
|
|
|
expect!(Keyword(Kw::While), tokens);
|
|
|
|
let while_expression = match expression(tokens) {
|
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => ast
|
|
|
|
};
|
|
|
|
|
|
|
|
expect!(Separator, tokens);
|
|
|
|
let statements = match statements(tokens) {
|
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => ast
|
|
|
|
};
|
|
|
|
|
|
|
|
expect!(Keyword(Kw::End), tokens);
|
|
|
|
|
|
|
|
ParseResult::Ok(AST::WhileStatement(
|
|
|
|
Box::new(while_expression),
|
|
|
|
Box::new(statements),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2015-07-26 14:59:01 -07:00
|
|
|
fn binop_expression(tokens: &mut Tokens) -> ParseResult {
|
|
|
|
let lhs = match simple_expression(tokens) {
|
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => ast
|
|
|
|
};
|
|
|
|
|
|
|
|
binop_rhs(0, lhs, tokens)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn binop_rhs(precedence: i32, lhs: AST, tokens: &mut Tokens) -> ParseResult {
|
|
|
|
|
|
|
|
let lookahead_precedence = tokens.peek().and_then(|tok| get_binop_precedence(tok));
|
|
|
|
|
|
|
|
let output = match lookahead_precedence {
|
|
|
|
None => lhs,
|
|
|
|
Some(next) => {
|
|
|
|
if next < precedence {
|
|
|
|
lhs
|
|
|
|
} else {
|
|
|
|
let binop = match tokens.next() {
|
|
|
|
Some(&Identifier(ref s)) => AST::Name(s.clone()),
|
|
|
|
_ => return ParseResult::Err("Bad binop parse".to_string())
|
|
|
|
};
|
|
|
|
let preliminary_rhs = match simple_expression(tokens) {
|
|
|
|
err@ParseResult::Err(_) => return err,
|
|
|
|
ParseResult::Ok(ast) => ast
|
|
|
|
};
|
|
|
|
|
|
|
|
let after_rhs_precedence = tokens.peek().and_then(|tok| get_binop_precedence(tok));
|
|
|
|
let true_rhs = match after_rhs_precedence {
|
|
|
|
Some(arp) if arp >= next => {
|
|
|
|
match binop_rhs(precedence+1, preliminary_rhs, tokens) {
|
|
|
|
ParseResult::Ok(ast) => ast,
|
|
|
|
err@ParseResult::Err(_) => return err
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_ => preliminary_rhs
|
|
|
|
};
|
|
|
|
|
|
|
|
AST::BinOp(
|
|
|
|
Box::new(binop),
|
|
|
|
Box::new(lhs),
|
|
|
|
Box::new(true_rhs)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ParseResult::Ok(output)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_binop_precedence(token: &Token) -> Option<i32> {
|
|
|
|
let identifier_str = match token {
|
|
|
|
&Identifier(ref s) => s,
|
|
|
|
_ => return None
|
|
|
|
};
|
|
|
|
let precedence = match &identifier_str[..] {
|
|
|
|
"+" => 20,
|
|
|
|
"-" => 20,
|
|
|
|
"*" => 40,
|
|
|
|
"/" => 40,
|
|
|
|
_ => -1
|
|
|
|
};
|
|
|
|
|
|
|
|
Some(precedence)
|
|
|
|
}
|
|
|
|
|
2015-07-25 17:43:44 -07:00
|
|
|
fn simple_expression(tokens: &mut Tokens) -> ParseResult {
|
2015-07-25 15:57:04 -07:00
|
|
|
let next = tokens.next();
|
2015-07-24 02:23:18 -07:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
2015-07-25 17:43:44 -07:00
|
|
|
return ParseResult::Err("Bad parse in simple_expression()".to_string());
|
2015-07-24 02:23:18 -07:00
|
|
|
}
|