feat: parse conditionals
This commit is contained in:
parent
6ff782a20e
commit
72bd8c50c9
@ -19,6 +19,10 @@
|
||||
- Begin work on the code formatter
|
||||
- Remove all panic! and todo!
|
||||
|
||||
## v0.1.2
|
||||
|
||||
- [x] Parse conditionals
|
||||
|
||||
|
||||
## v0.1.1
|
||||
|
||||
|
@ -7,6 +7,8 @@ fn str_is_keyword(s: &String) -> Option<TokenType> {
|
||||
"val" => Some(TokenType::VAL),
|
||||
"var" => Some(TokenType::VAR),
|
||||
"fun" => Some(TokenType::FUN),
|
||||
"if" => Some(TokenType::IF),
|
||||
"else" => Some(TokenType::ELSE),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ pub enum TokenType {
|
||||
VAR,
|
||||
EOF,
|
||||
FUN,
|
||||
IF,
|
||||
ELSE,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Clone, PartialEq)]
|
||||
|
@ -49,6 +49,7 @@ impl SemanticCheck for FunctionDeclaration<'_> {
|
||||
|
||||
return Err(MistiError::Semantic(error));
|
||||
}
|
||||
BlockMember::Stmt(Statement::Conditional(_)) => unimplemented!("check conditional"),
|
||||
BlockMember::Expr(e) => e.check_semantics(scope)?,
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ impl SemanticCheck for Statement<'_> {
|
||||
match self {
|
||||
Statement::Binding(b) => b.check_semantics(scope),
|
||||
Statement::FnDecl(f) => f.check_semantics(scope),
|
||||
Statement::Conditional(_) => unimplemented!("check conditional"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,24 @@ pub enum ModuleMembers<'a> {
|
||||
pub enum Statement<'a> {
|
||||
Binding(VariableBinding<'a>),
|
||||
FnDecl(FunctionDeclaration<'a>),
|
||||
// TODO: Implement conditionals as expressions
|
||||
Conditional(Conditional<'a>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Conditional<'a> {
|
||||
pub if_member: Condition<'a>,
|
||||
pub else_if_members: Vec<Condition<'a>>,
|
||||
pub else_block: Option<Block<'a>>
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Condition<'a> {
|
||||
pub condition: Expression<'a>,
|
||||
pub body: Block<'a>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FunctionDeclaration<'a> {
|
||||
pub identifier: &'a Token,
|
||||
|
181
src/syntax/parsers/conditional.rs
Normal file
181
src/syntax/parsers/conditional.rs
Normal file
@ -0,0 +1,181 @@
|
||||
use crate::{
|
||||
error_handling::SyntaxError,
|
||||
lexic::token::{Token, TokenType},
|
||||
syntax::{
|
||||
ast::{Block, Condition, Conditional, Expression, Positionable},
|
||||
parseable::{Parseable, ParsingError, ParsingResult},
|
||||
utils::parse_token_type,
|
||||
},
|
||||
};
|
||||
|
||||
impl<'a> Parseable<'a> for Conditional<'a> {
|
||||
type Item = Conditional<'a>;
|
||||
|
||||
fn try_parse(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<'a, Self::Item> {
|
||||
// if keyword
|
||||
let (if_token, next) = match parse_token_type(tokens, current_pos, TokenType::IF) {
|
||||
Ok(tuple) => tuple,
|
||||
_ => return Err(ParsingError::Unmatched),
|
||||
};
|
||||
|
||||
// if condition
|
||||
let (if_expression, next) = match Expression::try_parse(tokens, next) {
|
||||
Ok(tuple) => tuple,
|
||||
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||
Err(ParsingError::Mismatch(wrong_token)) => {
|
||||
return Err(ParsingError::Err(SyntaxError {
|
||||
reason: String::from("Expected an expression after the if token"),
|
||||
error_start: wrong_token.position,
|
||||
error_end: wrong_token.get_end_position(),
|
||||
}));
|
||||
}
|
||||
Err(ParsingError::Unmatched) => {
|
||||
return Err(ParsingError::Err(SyntaxError {
|
||||
reason: String::from("Expected an expression after the if token"),
|
||||
error_start: if_token.position,
|
||||
error_end: if_token.get_end_position(),
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
// if block
|
||||
let (if_block, next) = match Block::try_parse(tokens, next) {
|
||||
Ok(t) => t,
|
||||
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||
Err(ParsingError::Mismatch(wrong_token)) => {
|
||||
return Err(ParsingError::Err(SyntaxError {
|
||||
reason: String::from("Expected a block after the condition"),
|
||||
error_start: wrong_token.position,
|
||||
error_end: wrong_token.get_end_position(),
|
||||
}));
|
||||
}
|
||||
Err(ParsingError::Unmatched) => {
|
||||
let (error_start, error_end) = if_expression.get_position();
|
||||
return Err(ParsingError::Err(SyntaxError {
|
||||
reason: String::from("Expected a block after the condition"),
|
||||
error_start,
|
||||
error_end,
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
let mut else_if_members = Vec::<Condition>::new();
|
||||
let mut current_pos = next;
|
||||
let tokens_len = tokens.len();
|
||||
|
||||
// many else if
|
||||
while current_pos < tokens_len {
|
||||
// else token
|
||||
let (_, next) = match parse_token_type(tokens, current_pos, TokenType::ELSE) {
|
||||
Ok(tuple) => tuple,
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// if token
|
||||
let (if_token, next) = match parse_token_type(tokens, next, TokenType::IF) {
|
||||
Ok(tuple) => tuple,
|
||||
// This might be a else {}, not a else if {}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// condition
|
||||
let (condition, next) = match Expression::try_parse(tokens, next) {
|
||||
Ok(tuple) => tuple,
|
||||
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||
Err(ParsingError::Mismatch(wrong_token)) => {
|
||||
return Err(ParsingError::Err(SyntaxError {
|
||||
reason: String::from("Expected an expression after the if token"),
|
||||
error_start: wrong_token.position,
|
||||
error_end: wrong_token.get_end_position(),
|
||||
}));
|
||||
}
|
||||
Err(ParsingError::Unmatched) => {
|
||||
return Err(ParsingError::Err(SyntaxError {
|
||||
reason: String::from("Expected an expression after the if token"),
|
||||
error_start: if_token.position,
|
||||
error_end: if_token.get_end_position(),
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
// block
|
||||
let (block, next) = match Block::try_parse(tokens, next) {
|
||||
Ok(t) => t,
|
||||
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||
Err(ParsingError::Mismatch(wrong_token)) => {
|
||||
return Err(ParsingError::Err(SyntaxError {
|
||||
reason: String::from("Expected a block after the condition"),
|
||||
error_start: wrong_token.position,
|
||||
error_end: wrong_token.get_end_position(),
|
||||
}));
|
||||
}
|
||||
Err(ParsingError::Unmatched) => {
|
||||
let (error_start, error_end) = condition.get_position();
|
||||
return Err(ParsingError::Err(SyntaxError {
|
||||
reason: String::from("Expected a block after the condition"),
|
||||
error_start,
|
||||
error_end,
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
else_if_members.push(Condition {
|
||||
condition,
|
||||
body: block,
|
||||
});
|
||||
|
||||
current_pos = next;
|
||||
}
|
||||
|
||||
// else
|
||||
let (else_block, next) = {
|
||||
match parse_token_type(tokens, current_pos, TokenType::ELSE) {
|
||||
Ok((else_token, next)) => {
|
||||
// block
|
||||
let (block, next) = match Block::try_parse(tokens, next) {
|
||||
Ok(t) => t,
|
||||
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||
Err(ParsingError::Mismatch(wrong_token)) => {
|
||||
return Err(ParsingError::Err(SyntaxError {
|
||||
reason: String::from(
|
||||
"Expected a block after the else keyword",
|
||||
),
|
||||
error_start: wrong_token.position,
|
||||
error_end: wrong_token.get_end_position(),
|
||||
}));
|
||||
}
|
||||
Err(ParsingError::Unmatched) => {
|
||||
return Err(ParsingError::Err(SyntaxError {
|
||||
reason: String::from(
|
||||
"Expected a block after the else keyword",
|
||||
),
|
||||
error_start: else_token.position,
|
||||
error_end: else_token.get_end_position(),
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
(Some(block), next)
|
||||
}
|
||||
_ => (None, current_pos),
|
||||
}
|
||||
};
|
||||
|
||||
// return
|
||||
|
||||
let result = Conditional {
|
||||
if_member: Condition {
|
||||
condition: if_expression,
|
||||
body: if_block,
|
||||
},
|
||||
else_if_members,
|
||||
else_block,
|
||||
};
|
||||
|
||||
Ok((result, next))
|
||||
}
|
||||
}
|
@ -4,3 +4,4 @@ pub mod expression;
|
||||
pub mod function_declaration;
|
||||
pub mod module;
|
||||
pub mod statement;
|
||||
pub mod conditional;
|
||||
|
@ -1,15 +1,15 @@
|
||||
use crate::syntax::{
|
||||
ast::{var_binding::VariableBinding, FunctionDeclaration, Statement},
|
||||
parseable::{Parseable, ParsingError},
|
||||
use crate::{
|
||||
lexic::token::Token,
|
||||
syntax::{
|
||||
ast::{var_binding::VariableBinding, Conditional, FunctionDeclaration, Statement},
|
||||
parseable::{Parseable, ParsingError, ParsingResult},
|
||||
},
|
||||
};
|
||||
|
||||
impl<'a> Parseable<'a> for Statement<'a> {
|
||||
type Item = Statement<'a>;
|
||||
|
||||
fn try_parse(
|
||||
tokens: &'a Vec<crate::lexic::token::Token>,
|
||||
current_pos: usize,
|
||||
) -> crate::syntax::parseable::ParsingResult<'a, Self::Item> {
|
||||
fn try_parse(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<'a, Self::Item> {
|
||||
// Try to parse a variable binding
|
||||
match VariableBinding::try_parse(tokens, current_pos) {
|
||||
Ok((prod, next)) => {
|
||||
@ -34,6 +34,13 @@ impl<'a> Parseable<'a> for Statement<'a> {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Try to parse a conditional
|
||||
match Conditional::try_parse(tokens, current_pos) {
|
||||
Ok((prod, next)) => return Ok((Statement::Conditional(prod), next)),
|
||||
Err(ParsingError::Err(e)) => return Err(ParsingError::Err(e)),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Here nothing was parsed.
|
||||
Err(ParsingError::Unmatched)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user