diff --git a/src/syntax/expression.rs b/src/syntax/expression.rs index f3539e4..b28bc0d 100644 --- a/src/syntax/expression.rs +++ b/src/syntax/expression.rs @@ -1,10 +1,18 @@ -use crate::token::Token; - +use crate::token::{Token, TokenType}; use super::types::Expression; pub fn try_parse(tokens: &Vec, pos: usize) -> Option { - None + tokens + .get(pos) + .and_then(|token| { + match token.token_type { + TokenType::Number => { + Some(Expression::Number(&token.value)) + } + _ => None + } + }) } diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index c412f75..cfc3d0f 100755 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -1,10 +1,13 @@ use super::token::Token; mod expression; +mod val_binding; mod types; +use types::ModuleAST; + /// Constructs the Misti AST from a vector of tokens -pub fn construct_ast(_tokens: Vec) -> Result { +pub fn construct_ast<'a>(_tokens: Vec) -> Result, String> { Err(String::from("NOT IMPLEMENTED")) } diff --git a/src/syntax/types.rs b/src/syntax/types.rs index 197e7bf..5662bb5 100644 --- a/src/syntax/types.rs +++ b/src/syntax/types.rs @@ -1,17 +1,17 @@ -pub struct ModuleAST { - bindings: Vec, +pub struct ModuleAST<'a> { + bindings: Vec>, } -pub enum Binding { - Val(ValBinding), +pub enum Binding<'a> { + Val(ValBinding<'a>), } -pub struct ValBinding { - identifier: String, - expression: Expression, +pub struct ValBinding<'a> { + pub identifier: &'a String, + pub expression: Expression<'a>, } -pub enum Expression { - Number(String), +pub enum Expression<'a> { + Number(&'a String), } diff --git a/src/syntax/val_binding.rs b/src/syntax/val_binding.rs new file mode 100644 index 0000000..b614c41 --- /dev/null +++ b/src/syntax/val_binding.rs @@ -0,0 +1,92 @@ +use crate::token::{Token, TokenType}; +use super::types::{Binding, ValBinding}; +use super::expression; + +// Should return a 3 state value: +// - Success: binding parsed successfully +// - NotFound: the first token (var | val) was not found, so the parser should try other options +// - Error: token (var | val) was found, but then other expected tokens were not found +pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> Option { + let val_token = try_token_type(tokens, pos, TokenType::VAL)?; + + let identifier = try_token_type(tokens, pos + 1, TokenType::Identifier); + if identifier.is_none() { return None } + let identifier = identifier.unwrap(); + + let equal_operator = try_operator(tokens, pos + 2, String::from("=")); + if equal_operator.is_none() { return None } + let equal_operator = equal_operator.unwrap(); + + let expression = expression::try_parse(tokens, pos + 3); + if expression.is_none() { return None } + let expression = expression.unwrap(); + + let bind = ValBinding { + identifier: &identifier.value, + expression, + }; + + Some(Binding::Val(bind)) +} + +fn try_token_type(tokens: &Vec, pos: usize, token_type: TokenType) -> Option<&Token> { + tokens + .get(pos) + .and_then(|token| { + (token.token_type == token_type).then(|| token) + }) +} + +fn try_operator(tokens: &Vec, pos: usize, operator: String) -> Option<&Token> { + tokens + .get(pos) + .and_then(|token| { + (token.token_type == TokenType::Operator && token.value == operator) + .then(|| token) + }) +} + + + +#[cfg(test)] +mod tests { + use super::*; + use crate::lexic::get_tokens; + + #[test] + fn should_parse_val_binding() { + let tokens = get_tokens(&String::from("val identifier = 20")).unwrap(); + let binding = try_parse(&tokens, 0).unwrap(); + + match binding { + Binding::Val(binding) => { + assert_eq!("identifier", binding.identifier); + } + } + } + + #[test] + fn should_parse_val() { + let tokens = get_tokens(&String::from("val")).unwrap(); + let token = try_token_type(&tokens, 0, TokenType::VAL).unwrap(); + + assert_eq!(TokenType::VAL, token.token_type); + assert_eq!("val", token.value); + } + + #[test] + fn should_parse_identifier() { + let tokens = get_tokens(&String::from("identifier")).unwrap(); + let token = try_token_type(&tokens, 0, TokenType::Identifier).unwrap(); + + assert_eq!("identifier", token.value); + } + + #[test] + fn should_parse_operator() { + let tokens = get_tokens(&String::from("=")).unwrap(); + let token = try_operator(&tokens, 0, String::from("=")).unwrap(); + + assert_eq!("=", token.value); + } +}