Add parsing for simple declarations
This commit is contained in:
parent
e080945d37
commit
7d99920a71
@ -1,10 +1,18 @@
|
|||||||
use crate::token::Token;
|
use crate::token::{Token, TokenType};
|
||||||
|
|
||||||
use super::types::Expression;
|
use super::types::Expression;
|
||||||
|
|
||||||
|
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> Option<Expression> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> Option<Expression> {
|
||||||
None
|
tokens
|
||||||
|
.get(pos)
|
||||||
|
.and_then(|token| {
|
||||||
|
match token.token_type {
|
||||||
|
TokenType::Number => {
|
||||||
|
Some(Expression::Number(&token.value))
|
||||||
|
}
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
use super::token::Token;
|
use super::token::Token;
|
||||||
|
|
||||||
mod expression;
|
mod expression;
|
||||||
|
mod val_binding;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
|
use types::ModuleAST;
|
||||||
|
|
||||||
/// Constructs the Misti AST from a vector of tokens
|
/// Constructs the Misti AST from a vector of tokens
|
||||||
pub fn construct_ast(_tokens: Vec<Token>) -> Result<types::ModuleAST, String> {
|
pub fn construct_ast<'a>(_tokens: Vec<Token>) -> Result<ModuleAST<'a>, String> {
|
||||||
Err(String::from("NOT IMPLEMENTED"))
|
Err(String::from("NOT IMPLEMENTED"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
|
|
||||||
pub struct ModuleAST {
|
pub struct ModuleAST<'a> {
|
||||||
bindings: Vec<Binding>,
|
bindings: Vec<Binding<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Binding {
|
pub enum Binding<'a> {
|
||||||
Val(ValBinding),
|
Val(ValBinding<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ValBinding {
|
pub struct ValBinding<'a> {
|
||||||
identifier: String,
|
pub identifier: &'a String,
|
||||||
expression: Expression,
|
pub expression: Expression<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Expression {
|
pub enum Expression<'a> {
|
||||||
Number(String),
|
Number(&'a String),
|
||||||
}
|
}
|
||||||
|
92
src/syntax/val_binding.rs
Normal file
92
src/syntax/val_binding.rs
Normal file
@ -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<Token>, pos: usize) -> Option<Binding> {
|
||||||
|
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<Token>, 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<Token>, 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user