use std::slice::Iter; use std::iter::Peekable; use tokenizer::{Token}; use tokenizer::Token::*; #[derive(Debug)] pub enum AST { Name(String), LangString(String), Number(f64), BinOp(Box, Box, Box), Binding(String, Box) } pub enum ParseResult { Ok(AST), Err(String) } type Tokens<'a> = Peekable>; /* expect calls .next() and thus advances the token list */ macro_rules! expect { ($tok:expr, $tokens:expr) => ( if !expect_token($tok, $tokens) { return ParseResult::Err(format!("Expected {:?}", $tok)); }) } fn expect_token(tok: Token, tokens: &mut Tokens) -> bool { 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, _ => false } } false } pub fn parse(input: Vec) -> ParseResult { let mut tokens: Tokens = input.iter().peekable(); if let ParseResult::Ok(ast) = let_expression(&mut tokens) { expect!(EOF, &mut tokens); return ParseResult::Ok(ast); } return ParseResult::Err("Bad parse".to_string()); } fn let_expression(input: &mut Tokens) -> ParseResult { expect!(Identifier("let".to_string()), input); if let Some(&Identifier(ref name)) = input.next() { if let Some(&Identifier(ref s)) = input.next() { if s == "=" { let next = input.next(); if let Some(&Identifier(ref value)) = next { let ast = AST::Binding(name.clone(), Box::new(AST::Name(value.clone()))); return ParseResult::Ok(ast); } if let Some(&StrLiteral(ref value)) = next { let ast = AST::Binding(name.clone(), Box::new(AST::LangString(value.clone()))); return ParseResult::Ok(ast); } if let Some(&NumLiteral(n)) = next { let ast = AST::Binding(name.clone(), Box::new(AST::Number(n))); return ParseResult::Ok(ast); } } } } return ParseResult::Err("Bad parse".to_string()); }