feat: parse arrays
This commit is contained in:
parent
72bd8c50c9
commit
fa4d79dbe4
@ -22,6 +22,7 @@
|
|||||||
## v0.1.2
|
## v0.1.2
|
||||||
|
|
||||||
- [x] Parse conditionals
|
- [x] Parse conditionals
|
||||||
|
- [x] Parse arrays
|
||||||
|
|
||||||
|
|
||||||
## v0.1.1
|
## v0.1.1
|
||||||
|
@ -9,6 +9,12 @@ fn str_is_keyword(s: &String) -> Option<TokenType> {
|
|||||||
"fun" => Some(TokenType::FUN),
|
"fun" => Some(TokenType::FUN),
|
||||||
"if" => Some(TokenType::IF),
|
"if" => Some(TokenType::IF),
|
||||||
"else" => Some(TokenType::ELSE),
|
"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,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,12 @@ pub enum TokenType {
|
|||||||
FUN,
|
FUN,
|
||||||
IF,
|
IF,
|
||||||
ELSE,
|
ELSE,
|
||||||
|
FOR,
|
||||||
|
IN,
|
||||||
|
WHILE,
|
||||||
|
LOOP,
|
||||||
|
MATCH,
|
||||||
|
CASE,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Debug, Clone, PartialEq)]
|
||||||
|
@ -37,6 +37,7 @@ impl<'a> PHPTransformable<'a> for Expression<'_> {
|
|||||||
}
|
}
|
||||||
Expression::UnaryOperator(_, _) => unimplemented!("transform unary op into php"),
|
Expression::UnaryOperator(_, _) => unimplemented!("transform unary op into php"),
|
||||||
Expression::BinaryOperator(_, _, _) => unimplemented!("transform binary 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
|
// After all these checks, we are ok
|
||||||
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>>),
|
UnaryOperator(&'a Token, Box<Expression<'a>>),
|
||||||
/// left expression, right expression, operator
|
/// left expression, right expression, operator
|
||||||
BinaryOperator(Box<Expression<'a>>, Box<Expression<'a>>, &'a Token),
|
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<'_> {
|
impl Positionable for Expression<'_> {
|
||||||
@ -115,6 +125,9 @@ impl Positionable for Expression<'_> {
|
|||||||
let (_, end) = right_expr.get_position();
|
let (_, end) = right_expr.get_position();
|
||||||
(start, end)
|
(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 term;
|
||||||
mod unary;
|
mod unary;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod array;
|
||||||
|
|
||||||
impl<'a> Parseable<'a> for Expression<'a> {
|
impl<'a> Parseable<'a> for Expression<'a> {
|
||||||
type Item = Expression<'a>;
|
type Item = Expression<'a>;
|
||||||
|
@ -1,16 +1,30 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
lexic::token::{Token, TokenType},
|
lexic::token::{Token, TokenType},
|
||||||
syntax::{
|
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.
|
/// This grammar may not be up to date. Refer to the spec for the latest grammar.
|
||||||
///
|
///
|
||||||
/// ```ebnf
|
/// ```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> {
|
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) {
|
match tokens.get_significant(pos) {
|
||||||
Some((token, token_pos)) => match token.token_type {
|
Some((token, token_pos)) => match token.token_type {
|
||||||
TokenType::Int => Ok((Expression::Int(&token), token_pos + 1)),
|
TokenType::Int => Ok((Expression::Int(&token), token_pos + 1)),
|
||||||
|
Loading…
Reference in New Issue
Block a user