feat: parse arrays

master
Araozu 2024-08-27 18:34:30 -05:00
parent 72bd8c50c9
commit fa4d79dbe4
10 changed files with 113 additions and 2 deletions

View File

@ -22,6 +22,7 @@
## v0.1.2
- [x] Parse conditionals
- [x] Parse arrays
## v0.1.1

View File

@ -9,6 +9,12 @@ fn str_is_keyword(s: &String) -> Option<TokenType> {
"fun" => Some(TokenType::FUN),
"if" => Some(TokenType::IF),
"else" => Some(TokenType::ELSE),
"for" => Some(TokenType::FOR),
"in" => Some(TokenType::IN),
"while" => Some(TokenType::WHILE),
"loop" => Some(TokenType::LOOP),
"match" => Some(TokenType::MATCH),
"case" => Some(TokenType::CASE),
_ => None,
}
}

View File

@ -26,6 +26,12 @@ pub enum TokenType {
FUN,
IF,
ELSE,
FOR,
IN,
WHILE,
LOOP,
MATCH,
CASE,
}
#[derive(Serialize, Debug, Clone, PartialEq)]

View File

@ -37,6 +37,7 @@ impl<'a> PHPTransformable<'a> for Expression<'_> {
}
Expression::UnaryOperator(_, _) => unimplemented!("transform unary op into php"),
Expression::BinaryOperator(_, _, _) => unimplemented!("transform binary op into php"),
Expression::Array(_) => unimplemented!("transform array into php"),
}
}
}

View File

@ -193,6 +193,7 @@ impl SemanticCheck for Expression<'_> {
// After all these checks, we are ok
Ok(())
}
Expression::Array(_) => unimplemented!("check for array"),
}
}
}

View File

@ -122,6 +122,7 @@ impl Typed for Expression<'_> {
),
}));
}
Expression::Array(_) => unimplemented!("get type of array"),
}
}
}

View File

@ -92,6 +92,16 @@ pub enum Expression<'a> {
UnaryOperator(&'a Token, Box<Expression<'a>>),
/// left expression, right expression, operator
BinaryOperator(Box<Expression<'a>>, Box<Expression<'a>>, &'a Token),
Array(Array<'a>),
}
#[derive(Debug)]
pub struct Array<'a> {
pub exps: Vec<Expression<'a>>,
/// The position of the open bracket [
pub start: usize,
/// The position of the closed bracket ]
pub end: usize,
}
impl Positionable for Expression<'_> {
@ -115,6 +125,9 @@ impl Positionable for Expression<'_> {
let (_, end) = right_expr.get_position();
(start, end)
}
Expression::Array(Array {start, end, exps: _}) => {
(*start, *end)
}
}
}
}

View File

@ -0,0 +1,67 @@
use crate::{
lexic::token::{Token, TokenType},
syntax::{
ast::{Array, Expression},
parseable::{Parseable, ParsingError, ParsingResult},
utils::parse_token_type,
},
};
impl<'a> Parseable<'a> for Array<'a> {
type Item = Array<'a>;
fn try_parse(tokens: &'a Vec<Token>, current_pos: usize) -> ParsingResult<'a, Self::Item> {
// parse open bracket
let (open_bracket, next) =
match parse_token_type(tokens, current_pos, TokenType::LeftBracket) {
Ok(t) => t,
Err(_) => return Err(ParsingError::Unmatched),
};
// parse expressions
let mut exps = Vec::new();
let mut current_pos = next;
let tokens_len = tokens.len();
while current_pos < tokens_len {
// parse expression
let (exp, after_exp) = match Expression::try_parse(tokens, current_pos) {
Ok(t) => t,
Err(ParsingError::Mismatch(_)) => break,
Err(ParsingError::Unmatched) => break,
// If an error is found parsing an exp, bubble up
Err(e) => return Err(e),
};
// add exp to vec
exps.push(exp);
// parse comma
let (_, after_comma) = match parse_token_type(tokens, after_exp, TokenType::Comma) {
Ok(t) => t,
// If a comma is not found then the expressions are over
Err(_) => {
current_pos = after_exp;
break;
}
};
// update position tracker
current_pos = after_comma;
}
// parse closed bracket
let (closed_bracket, next) =
match parse_token_type(tokens, current_pos, TokenType::RightBracket) {
Ok(t) => t,
Err(e) => return Err(e),
};
// return
let arr = Array {
exps,
start: open_bracket.position,
end: closed_bracket.position,
};
Ok((arr, next))
}
}

View File

@ -9,6 +9,7 @@ mod primary;
mod term;
mod unary;
mod utils;
mod array;
impl<'a> Parseable<'a> for Expression<'a> {
type Item = Expression<'a>;

View File

@ -1,16 +1,30 @@
use crate::{
lexic::token::{Token, TokenType},
syntax::{
ast::Expression, parseable::Parseable, utils::Tokenizer, ParsingError, ParsingResult,
ast::{Array, Expression}, parseable::Parseable, utils::Tokenizer, ParsingError, ParsingResult,
},
};
/// This grammar may not be up to date. Refer to the spec for the latest grammar.
///
/// ```ebnf
/// primary = number | string | boolean | identifier | ("(", expression, ")");
/// primary = array
/// | number
/// | string
/// | boolean
/// | identifier
/// | ("(", expression, ")");
/// ```
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
// array
match Array::try_parse(tokens, pos) {
Ok((exp, next)) => {
return Ok((Expression::Array(exp), next))
},
Err(ParsingError::Err(e)) => return Err(ParsingError::Err(e)),
Err(_) => {},
}
match tokens.get_significant(pos) {
Some((token, token_pos)) => match token.token_type {
TokenType::Int => Ok((Expression::Int(&token), token_pos + 1)),