feat: parse array access in an expression
This commit is contained in:
parent
ff533c5ae7
commit
712936e4d6
41
CHANGELOG.md
41
CHANGELOG.md
@ -2,21 +2,28 @@
|
||||
|
||||
## TODO
|
||||
|
||||
- Implement functions as first class citizens
|
||||
- Parse __more__ binary operators
|
||||
- Parse more complex bindings
|
||||
- Namespace identifiers in the symbol table
|
||||
- Stdlib
|
||||
- Document code
|
||||
- Watch mode
|
||||
- Simple language server
|
||||
- Decide how to handle comments in the syntax (?)(should comments mean something like in rust?)
|
||||
- Abstract the parsing of datatypes, such that in the future generics can be implemented in a single place
|
||||
- Begin work on the code formatter
|
||||
- Remove all panic! and todo!
|
||||
- Change REPL to execute code only after `;;` is found
|
||||
- Forward the code generated by the REPL to the PHP repl
|
||||
- Test assignment parsing
|
||||
- [ ] Implement functions as first class citizens
|
||||
- [ ] Parse __more__ binary operators
|
||||
- [ ] Parse more complex bindings
|
||||
- [ ] Namespace identifiers in the symbol table
|
||||
- [ ] Stdlib
|
||||
- [ ] Document code
|
||||
- [ ] Watch mode
|
||||
- [ ] Simple language server
|
||||
- [ ] Decide how to handle comments in the syntax (?)(should comments mean something like in rust?)
|
||||
- [ ] Abstract the parsing of datatypes, such that in the future generics can be implemented in a single place
|
||||
- [ ] Begin work on the code formatter
|
||||
- [ ] Remove all panic! and todo!
|
||||
- [ ] Change REPL to execute code only after `;;` is found
|
||||
- [ ] Forward the code generated by the REPL to the PHP repl
|
||||
- [ ] Test assignment parsing
|
||||
|
||||
|
||||
## v0.1.4
|
||||
|
||||
- [ ] Parse obj/map/dict syntax
|
||||
- [ ] Parse tuple syntax
|
||||
- [ ] Parse class instantiation syntax
|
||||
|
||||
|
||||
## v0.1.3
|
||||
@ -25,9 +32,9 @@
|
||||
- [ ] Generate php code from current AST
|
||||
- [x] Test correct operator precedence
|
||||
- [x] Parse assignments
|
||||
- [ ] Parse dot `.` operator
|
||||
- [x] Parse dot `.` operator
|
||||
- [ ] Parse logic operators `&& ||`
|
||||
- [ ] Parse Array access `arr[pos]`
|
||||
- [x] Parse Array access `arr[pos]`
|
||||
- [ ] Parse namespace operator `::`
|
||||
- [ ] Implement subtyping for numbers
|
||||
|
||||
|
@ -24,6 +24,7 @@ pub const COMPILER_TODO: u32 = 20;
|
||||
pub const SEMANTIC_MISMATCHED_TYPES: u32 = 21;
|
||||
pub const SEMANTIC_DUPLICATED_REFERENCE: u32 = 22;
|
||||
pub const SEMANTIC_MISMATCHED_ARGUMENT_COUNT: u32 = 23;
|
||||
pub const SYNTAX_INVALID_ARRAY_ACCESS: u32 = 24;
|
||||
|
||||
/// Reads the error codes from the error code list
|
||||
pub fn error_code_to_string() -> String {
|
||||
|
@ -45,6 +45,7 @@ impl<'a> PHPTransformable<'a> for Expression<'_> {
|
||||
PExpresssion::BinaryOp(Box::new(left_value), Box::new(right_value), &op.value)
|
||||
}
|
||||
Expression::Array(_) => unimplemented!("transform array into php"),
|
||||
Expression::ArrayAcccess(_) => unimplemented!("transform array access into php"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,6 +262,7 @@ impl SemanticCheck for Expression<'_> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Expression::ArrayAcccess(_array_access) => unimplemented!("typecheck array access"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,6 +219,7 @@ impl Typed for Expression<'_> {
|
||||
let first_type = arr.exps[0].get_type(scope)?;
|
||||
Ok(Type::Generic("Array".into(), vec![first_type]))
|
||||
}
|
||||
Expression::ArrayAcccess(_array_access) => unimplemented!("typecheck array access"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,6 +121,7 @@ pub enum Expression<'a> {
|
||||
/// left expression, right expression, operator
|
||||
BinaryOperator(Box<Expression<'a>>, Box<Expression<'a>>, &'a Token),
|
||||
Array(Array<'a>),
|
||||
ArrayAcccess(ArrayAccess<'a>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -132,6 +133,13 @@ pub struct Array<'a> {
|
||||
pub end: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ArrayAccess<'a> {
|
||||
pub left_expr: Box<Expression<'a>>,
|
||||
pub idx_expr: Box<Expression<'a>>,
|
||||
pub end_pos: usize,
|
||||
}
|
||||
|
||||
impl Positionable for Expression<'_> {
|
||||
/// Returns the absolute start and end position
|
||||
/// of this expression
|
||||
@ -158,6 +166,10 @@ impl Positionable for Expression<'_> {
|
||||
end,
|
||||
exps: _,
|
||||
}) => (*start, *end),
|
||||
Expression::ArrayAcccess(a) => {
|
||||
let (start, _) = a.left_expr.get_position();
|
||||
(start, a.end_pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
use crate::{
|
||||
lexic::token::Token,
|
||||
error_handling::{error_messages::SYNTAX_INVALID_ARRAY_ACCESS, ErrorContainer, ErrorLabel},
|
||||
lexic::token::{Token, TokenType},
|
||||
syntax::{
|
||||
ast::{functions::FunctionCall, Expression},
|
||||
ast::{functions::FunctionCall, ArrayAccess, Expression},
|
||||
functions::arguments_list,
|
||||
parseable::Parseable,
|
||||
utils::parse_token_type,
|
||||
ParsingError, ParsingResult,
|
||||
},
|
||||
};
|
||||
@ -11,6 +14,7 @@ use crate::{
|
||||
///
|
||||
/// ```ebnf
|
||||
/// function call expr = primary, "(", (arguments list)?, ")"
|
||||
/// | primary, "[", expressions, "]"
|
||||
/// | primary;
|
||||
/// ```
|
||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
||||
@ -19,21 +23,90 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
||||
_ => return Err(ParsingError::Unmatched),
|
||||
};
|
||||
|
||||
// Attempt to parse a function call
|
||||
// Parse arguments list
|
||||
let (arguments, next_pos) = match arguments_list::try_parse(tokens, next_pos) {
|
||||
Ok((args, next)) => (args, next),
|
||||
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||
_ => {
|
||||
return Ok((primary_expr, next_pos));
|
||||
match arguments_list::try_parse(tokens, next_pos) {
|
||||
Ok((arguments, next_pos)) => {
|
||||
let fun_call = FunctionCall {
|
||||
function: Box::new(primary_expr),
|
||||
arguments: Box::new(arguments),
|
||||
};
|
||||
|
||||
return Ok((Expression::FunctionCall(fun_call), next_pos));
|
||||
}
|
||||
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
let fun_call = FunctionCall {
|
||||
function: Box::new(primary_expr),
|
||||
arguments: Box::new(arguments),
|
||||
// Attempt to parse an array access
|
||||
match try_parse_array_access(tokens, next_pos) {
|
||||
Ok(((array_idx, end_pos), next_pos)) => {
|
||||
let fun_call = ArrayAccess {
|
||||
left_expr: Box::new(primary_expr),
|
||||
idx_expr: Box::new(array_idx),
|
||||
end_pos,
|
||||
};
|
||||
|
||||
return Ok((Expression::ArrayAcccess(fun_call), next_pos));
|
||||
}
|
||||
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
Ok((Expression::FunctionCall(fun_call), next_pos))
|
||||
// Return the parsed primary
|
||||
return Ok((primary_expr, next_pos));
|
||||
}
|
||||
|
||||
pub fn try_parse_array_access(
|
||||
tokens: &Vec<Token>,
|
||||
pos: usize,
|
||||
) -> ParsingResult<(Expression, usize)> {
|
||||
let (_token, next_pos) = parse_token_type(&tokens, pos, TokenType::LeftBracket)?;
|
||||
|
||||
// parse an expression
|
||||
let (exp, next_pos) = match Expression::try_parse(tokens, next_pos) {
|
||||
Ok(t) => t,
|
||||
Err(ParsingError::Mismatch(e)) => {
|
||||
let label = ErrorLabel {
|
||||
message: String::from("Expected an expression for this array access"),
|
||||
start: e.position,
|
||||
end: e.get_end_position(),
|
||||
};
|
||||
let econtainer = ErrorContainer {
|
||||
error_code: SYNTAX_INVALID_ARRAY_ACCESS,
|
||||
error_offset: e.position,
|
||||
labels: vec![label],
|
||||
note: None,
|
||||
help: None,
|
||||
};
|
||||
return Err(ParsingError::Err(econtainer));
|
||||
}
|
||||
Err(ParsingError::Unmatched) => {
|
||||
//
|
||||
let label = ErrorLabel {
|
||||
message: String::from("Expected an expression for this array access"),
|
||||
start: pos,
|
||||
end: pos + 1,
|
||||
};
|
||||
let econtainer = ErrorContainer {
|
||||
error_code: SYNTAX_INVALID_ARRAY_ACCESS,
|
||||
error_offset: pos,
|
||||
labels: vec![label],
|
||||
note: None,
|
||||
help: None,
|
||||
};
|
||||
return Err(ParsingError::Err(econtainer));
|
||||
}
|
||||
Err(ParsingError::Err(e)) => return Err(ParsingError::Err(e)),
|
||||
};
|
||||
|
||||
// parse the closing bracket
|
||||
let (closed_bracket, next) = match parse_token_type(tokens, next_pos, TokenType::RightBracket) {
|
||||
Ok(t) => t,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
return Ok(((exp, closed_bracket.get_end_position()), next));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
Loading…
Reference in New Issue
Block a user