feat: parse arrays
This commit is contained in:
parent
72bd8c50c9
commit
fa4d79dbe4
@ -22,6 +22,7 @@
|
||||
## v0.1.2
|
||||
|
||||
- [x] Parse conditionals
|
||||
- [x] Parse arrays
|
||||
|
||||
|
||||
## v0.1.1
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,12 @@ pub enum TokenType {
|
||||
FUN,
|
||||
IF,
|
||||
ELSE,
|
||||
FOR,
|
||||
IN,
|
||||
WHILE,
|
||||
LOOP,
|
||||
MATCH,
|
||||
CASE,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug, Clone, PartialEq)]
|
||||
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,6 +193,7 @@ impl SemanticCheck for Expression<'_> {
|
||||
// After all these checks, we are ok
|
||||
Ok(())
|
||||
}
|
||||
Expression::Array(_) => unimplemented!("check for array"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ impl Typed for Expression<'_> {
|
||||
),
|
||||
}));
|
||||
}
|
||||
Expression::Array(_) => unimplemented!("get type of array"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
67
src/syntax/parsers/expression/array.rs
Normal file
67
src/syntax/parsers/expression/array.rs
Normal 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))
|
||||
}
|
||||
}
|
@ -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>;
|
||||
|
@ -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)),
|
||||
|
Loading…
Reference in New Issue
Block a user