Compare commits
No commits in common. "712936e4d6cd8712ca642c361ae4dd635598202f" and "b4e5caa0f00559891125b97fedb0379dd7c2c62c" have entirely different histories.
712936e4d6
...
b4e5caa0f0
41
CHANGELOG.md
41
CHANGELOG.md
@ -2,28 +2,21 @@
|
|||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- [ ] Implement functions as first class citizens
|
- Implement functions as first class citizens
|
||||||
- [ ] Parse __more__ binary operators
|
- Parse __more__ binary operators
|
||||||
- [ ] Parse more complex bindings
|
- Parse more complex bindings
|
||||||
- [ ] Namespace identifiers in the symbol table
|
- Namespace identifiers in the symbol table
|
||||||
- [ ] Stdlib
|
- Stdlib
|
||||||
- [ ] Document code
|
- Document code
|
||||||
- [ ] Watch mode
|
- Watch mode
|
||||||
- [ ] Simple language server
|
- Simple language server
|
||||||
- [ ] Decide how to handle comments in the syntax (?)(should comments mean something like in rust?)
|
- 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
|
- Abstract the parsing of datatypes, such that in the future generics can be implemented in a single place
|
||||||
- [ ] Begin work on the code formatter
|
- Begin work on the code formatter
|
||||||
- [ ] Remove all panic! and todo!
|
- Remove all panic! and todo!
|
||||||
- [ ] Change REPL to execute code only after `;;` is found
|
- Change REPL to execute code only after `;;` is found
|
||||||
- [ ] Forward the code generated by the REPL to the PHP repl
|
- Forward the code generated by the REPL to the PHP repl
|
||||||
- [ ] Test assignment parsing
|
- Test assignment parsing
|
||||||
|
|
||||||
|
|
||||||
## v0.1.4
|
|
||||||
|
|
||||||
- [ ] Parse obj/map/dict syntax
|
|
||||||
- [ ] Parse tuple syntax
|
|
||||||
- [ ] Parse class instantiation syntax
|
|
||||||
|
|
||||||
|
|
||||||
## v0.1.3
|
## v0.1.3
|
||||||
@ -32,9 +25,9 @@
|
|||||||
- [ ] Generate php code from current AST
|
- [ ] Generate php code from current AST
|
||||||
- [x] Test correct operator precedence
|
- [x] Test correct operator precedence
|
||||||
- [x] Parse assignments
|
- [x] Parse assignments
|
||||||
- [x] Parse dot `.` operator
|
- [ ] Parse dot `.` operator
|
||||||
- [ ] Parse logic operators `&& ||`
|
- [ ] Parse logic operators `&& ||`
|
||||||
- [x] Parse Array access `arr[pos]`
|
- [ ] Parse Array access `arr[pos]`
|
||||||
- [ ] Parse namespace operator `::`
|
- [ ] Parse namespace operator `::`
|
||||||
- [ ] Implement subtyping for numbers
|
- [ ] Implement subtyping for numbers
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ pub const COMPILER_TODO: u32 = 20;
|
|||||||
pub const SEMANTIC_MISMATCHED_TYPES: u32 = 21;
|
pub const SEMANTIC_MISMATCHED_TYPES: u32 = 21;
|
||||||
pub const SEMANTIC_DUPLICATED_REFERENCE: u32 = 22;
|
pub const SEMANTIC_DUPLICATED_REFERENCE: u32 = 22;
|
||||||
pub const SEMANTIC_MISMATCHED_ARGUMENT_COUNT: u32 = 23;
|
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
|
/// Reads the error codes from the error code list
|
||||||
pub fn error_code_to_string() -> String {
|
pub fn error_code_to_string() -> String {
|
||||||
|
@ -45,7 +45,6 @@ impl<'a> PHPTransformable<'a> for Expression<'_> {
|
|||||||
PExpresssion::BinaryOp(Box::new(left_value), Box::new(right_value), &op.value)
|
PExpresssion::BinaryOp(Box::new(left_value), Box::new(right_value), &op.value)
|
||||||
}
|
}
|
||||||
Expression::Array(_) => unimplemented!("transform array into php"),
|
Expression::Array(_) => unimplemented!("transform array into php"),
|
||||||
Expression::ArrayAcccess(_) => unimplemented!("transform array access into php"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,7 +262,6 @@ impl SemanticCheck for Expression<'_> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Expression::ArrayAcccess(_array_access) => unimplemented!("typecheck array access"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,6 @@ impl Typed for Expression<'_> {
|
|||||||
let first_type = arr.exps[0].get_type(scope)?;
|
let first_type = arr.exps[0].get_type(scope)?;
|
||||||
Ok(Type::Generic("Array".into(), vec![first_type]))
|
Ok(Type::Generic("Array".into(), vec![first_type]))
|
||||||
}
|
}
|
||||||
Expression::ArrayAcccess(_array_access) => unimplemented!("typecheck array access"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,6 @@ pub enum 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>),
|
Array(Array<'a>),
|
||||||
ArrayAcccess(ArrayAccess<'a>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -133,13 +132,6 @@ pub struct Array<'a> {
|
|||||||
pub end: usize,
|
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<'_> {
|
impl Positionable for Expression<'_> {
|
||||||
/// Returns the absolute start and end position
|
/// Returns the absolute start and end position
|
||||||
/// of this expression
|
/// of this expression
|
||||||
@ -166,10 +158,6 @@ impl Positionable for Expression<'_> {
|
|||||||
end,
|
end,
|
||||||
exps: _,
|
exps: _,
|
||||||
}) => (*start, *end),
|
}) => (*start, *end),
|
||||||
Expression::ArrayAcccess(a) => {
|
|
||||||
let (start, _) = a.left_expr.get_position();
|
|
||||||
(start, a.end_pos)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
syntax::{ast::Expression, ParsingError, ParsingResult},
|
syntax::{ast::Expression, ParsingError, ParsingResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::utils::parse_many;
|
use super::utils::try_binary_op;
|
||||||
|
|
||||||
/// Parses a factor expression.
|
/// Parses a factor expression.
|
||||||
///
|
///
|
||||||
@ -16,7 +16,33 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
|||||||
_ => return Err(ParsingError::Unmatched),
|
_ => return Err(ParsingError::Unmatched),
|
||||||
};
|
};
|
||||||
|
|
||||||
parse_many(tokens, next_pos, term, 0, &vec![">", ">=", "<", "<="])
|
parse_many(tokens, next_pos, term, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_many<'a>(
|
||||||
|
tokens: &'a Vec<Token>,
|
||||||
|
pos: usize,
|
||||||
|
prev_expr: Expression<'a>,
|
||||||
|
indentation_level: u32,
|
||||||
|
) -> ParsingResult<'a, Expression<'a>> {
|
||||||
|
// comparison = term, ((">" | ">=" | "<" | "<="), term)*;
|
||||||
|
try_binary_op(
|
||||||
|
tokens,
|
||||||
|
pos,
|
||||||
|
prev_expr,
|
||||||
|
vec![">", ">=", "<", "<="],
|
||||||
|
indentation_level,
|
||||||
|
|tokens, next_pos, prev_expr, token, indent_count: u32| match super::term::try_parse(
|
||||||
|
tokens, next_pos,
|
||||||
|
) {
|
||||||
|
Ok((expr, next_pos)) => {
|
||||||
|
let expr = Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
|
||||||
|
|
||||||
|
parse_many(tokens, next_pos, expr, indentation_level + indent_count)
|
||||||
|
}
|
||||||
|
_ => return Err(ParsingError::Unmatched),
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
lexic::token::Token,
|
|
||||||
syntax::{ast::Expression, ParsingError, ParsingResult},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::utils::parse_many;
|
|
||||||
|
|
||||||
/// Parses a dot access
|
|
||||||
///
|
|
||||||
/// ```ebnf
|
|
||||||
/// dot_access = unary, (("."), unary)*;
|
|
||||||
/// ```
|
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
|
||||||
let (unary, next_pos) = match super::unary::try_parse(tokens, pos) {
|
|
||||||
Ok((expr, next_pos)) => (expr, next_pos),
|
|
||||||
_ => return Err(ParsingError::Unmatched),
|
|
||||||
};
|
|
||||||
|
|
||||||
parse_many(tokens, next_pos, unary, 0, &vec![".", "?.", "!."])
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||||||
syntax::{ast::Expression, ParsingError, ParsingResult},
|
syntax::{ast::Expression, ParsingError, ParsingResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::utils::parse_many;
|
use super::utils::try_binary_op;
|
||||||
|
|
||||||
/// Parses a factor expression.
|
/// Parses a factor expression.
|
||||||
///
|
///
|
||||||
@ -16,7 +16,33 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
|||||||
_ => return Err(ParsingError::Unmatched),
|
_ => return Err(ParsingError::Unmatched),
|
||||||
};
|
};
|
||||||
|
|
||||||
parse_many(tokens, next_pos, comparison, 0, &vec!["==", "!="])
|
parse_many(tokens, next_pos, comparison, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_many<'a>(
|
||||||
|
tokens: &'a Vec<Token>,
|
||||||
|
pos: usize,
|
||||||
|
prev_expr: Expression<'a>,
|
||||||
|
indentation_level: u32,
|
||||||
|
) -> ParsingResult<'a, Expression<'a>> {
|
||||||
|
// equality = comparison, (("==" | "!="), comparison )*;
|
||||||
|
try_binary_op(
|
||||||
|
tokens,
|
||||||
|
pos,
|
||||||
|
prev_expr,
|
||||||
|
vec!["==", "!="],
|
||||||
|
indentation_level,
|
||||||
|
|tokens, next_pos, prev_expr, token, indent_count: u32| match super::comparison::try_parse(
|
||||||
|
tokens, next_pos,
|
||||||
|
) {
|
||||||
|
Ok((expr, next_pos)) => {
|
||||||
|
let expr = Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
|
||||||
|
|
||||||
|
parse_many(tokens, next_pos, expr, indentation_level + indent_count)
|
||||||
|
}
|
||||||
|
_ => return Err(ParsingError::Unmatched),
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,22 +1,50 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
lexic::token::Token,
|
lexic::token::Token,
|
||||||
syntax::{ast::Expression, ParsingError, ParsingResult},
|
syntax::{
|
||||||
|
ast::Expression, parsers::expression::utils::try_binary_op, ParsingError, ParsingResult,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::utils::parse_many;
|
|
||||||
|
|
||||||
/// Parses a factor expression.
|
/// Parses a factor expression.
|
||||||
///
|
///
|
||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// factor = dot_access, (("/" | "*" | "%"), dot_access)*;
|
/// factor = unary, (("/" | "*" | "%"), unary)*;
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
||||||
let (unary, next_pos) = match super::dot_access::try_parse(tokens, pos) {
|
let (unary, next_pos) = match super::unary::try_parse(tokens, pos) {
|
||||||
Ok((expr, next_pos)) => (expr, next_pos),
|
Ok((expr, next_pos)) => (expr, next_pos),
|
||||||
_ => return Err(ParsingError::Unmatched),
|
_ => return Err(ParsingError::Unmatched),
|
||||||
};
|
};
|
||||||
|
|
||||||
parse_many(tokens, next_pos, unary, 0, &vec!["/", "*", "%"])
|
parse_many(tokens, next_pos, unary, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_many<'a>(
|
||||||
|
tokens: &'a Vec<Token>,
|
||||||
|
pos: usize,
|
||||||
|
prev_expr: Expression<'a>,
|
||||||
|
indentation_level: u32,
|
||||||
|
) -> ParsingResult<'a, Expression<'a>> {
|
||||||
|
// (("/" | "*" | "%"), unary)*
|
||||||
|
try_binary_op(
|
||||||
|
tokens,
|
||||||
|
pos,
|
||||||
|
prev_expr,
|
||||||
|
vec!["/", "*", "%"],
|
||||||
|
indentation_level,
|
||||||
|
|tokens, next_pos, prev_expr, token, indent_count: u32| {
|
||||||
|
// match next
|
||||||
|
match super::unary::try_parse(tokens, next_pos) {
|
||||||
|
Ok((expr, next_pos)) => {
|
||||||
|
let expr =
|
||||||
|
Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
|
||||||
|
|
||||||
|
parse_many(tokens, next_pos, expr, indentation_level + indent_count)
|
||||||
|
}
|
||||||
|
_ => return Err(ParsingError::Unmatched),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
error_handling::{error_messages::SYNTAX_INVALID_ARRAY_ACCESS, ErrorContainer, ErrorLabel},
|
lexic::token::Token,
|
||||||
lexic::token::{Token, TokenType},
|
|
||||||
syntax::{
|
syntax::{
|
||||||
ast::{functions::FunctionCall, ArrayAccess, Expression},
|
ast::{functions::FunctionCall, Expression},
|
||||||
functions::arguments_list,
|
functions::arguments_list,
|
||||||
parseable::Parseable,
|
|
||||||
utils::parse_token_type,
|
|
||||||
ParsingError, ParsingResult,
|
ParsingError, ParsingResult,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -14,7 +11,6 @@ use crate::{
|
|||||||
///
|
///
|
||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// function call expr = primary, "(", (arguments list)?, ")"
|
/// function call expr = primary, "(", (arguments list)?, ")"
|
||||||
/// | primary, "[", expressions, "]"
|
|
||||||
/// | primary;
|
/// | primary;
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
||||||
@ -23,90 +19,21 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
|||||||
_ => return Err(ParsingError::Unmatched),
|
_ => return Err(ParsingError::Unmatched),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Attempt to parse a function call
|
|
||||||
// Parse arguments list
|
// Parse arguments list
|
||||||
match arguments_list::try_parse(tokens, next_pos) {
|
let (arguments, next_pos) = match arguments_list::try_parse(tokens, next_pos) {
|
||||||
Ok((arguments, next_pos)) => {
|
Ok((args, next)) => (args, next),
|
||||||
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)),
|
Err(ParsingError::Err(err)) => return Err(ParsingError::Err(err)),
|
||||||
_ => {}
|
_ => {
|
||||||
};
|
return Ok((primary_expr, next_pos));
|
||||||
|
|
||||||
// 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)),
|
|
||||||
_ => {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the parsed primary
|
let fun_call = FunctionCall {
|
||||||
return Ok((primary_expr, next_pos));
|
function: Box::new(primary_expr),
|
||||||
}
|
arguments: Box::new(arguments),
|
||||||
|
|
||||||
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
|
Ok((Expression::FunctionCall(fun_call), next_pos))
|
||||||
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)]
|
#[cfg(test)]
|
||||||
|
@ -3,7 +3,6 @@ use crate::{lexic::token::Token, syntax::parseable::Parseable};
|
|||||||
|
|
||||||
mod array;
|
mod array;
|
||||||
mod comparison;
|
mod comparison;
|
||||||
mod dot_access;
|
|
||||||
mod equality;
|
mod equality;
|
||||||
mod factor;
|
mod factor;
|
||||||
pub mod function_call_expr;
|
pub mod function_call_expr;
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
|
use crate::syntax::parsers::expression::utils::try_binary_op;
|
||||||
use crate::{
|
use crate::{
|
||||||
lexic::token::Token,
|
lexic::token::Token,
|
||||||
syntax::{ast::Expression, ParsingError, ParsingResult},
|
syntax::{ast::Expression, ParsingError, ParsingResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::utils::parse_many;
|
|
||||||
|
|
||||||
/// Parses a factor expression.
|
/// Parses a factor expression.
|
||||||
///
|
///
|
||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
@ -16,7 +15,36 @@ pub fn try_parse(tokens: &Vec<Token>, pos: usize) -> ParsingResult<Expression> {
|
|||||||
_ => return Err(ParsingError::Unmatched),
|
_ => return Err(ParsingError::Unmatched),
|
||||||
};
|
};
|
||||||
|
|
||||||
parse_many(tokens, next_pos, factor, 0, &vec!["-", "+", "++"])
|
parse_many(tokens, next_pos, factor, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_many<'a>(
|
||||||
|
tokens: &'a Vec<Token>,
|
||||||
|
pos: usize,
|
||||||
|
prev_expr: Expression<'a>,
|
||||||
|
indentation_level: u32,
|
||||||
|
) -> ParsingResult<'a, Expression<'a>> {
|
||||||
|
// term = factor, (("-" | "+" | "++"), factor)*;
|
||||||
|
|
||||||
|
try_binary_op(
|
||||||
|
tokens,
|
||||||
|
pos,
|
||||||
|
prev_expr,
|
||||||
|
vec!["+", "-", "++"],
|
||||||
|
indentation_level,
|
||||||
|
|tokens, pos, prev_expr, token, indent_count: u32| {
|
||||||
|
// Parse the next factor
|
||||||
|
match super::factor::try_parse(tokens, pos) {
|
||||||
|
Ok((expr, next_pos)) => {
|
||||||
|
let expr =
|
||||||
|
Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
|
||||||
|
|
||||||
|
parse_many(tokens, next_pos, expr, indentation_level + indent_count)
|
||||||
|
}
|
||||||
|
_ => return Err(ParsingError::Unmatched),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::lexic::token::Token;
|
use crate::lexic::token::Token;
|
||||||
use crate::lexic::token::TokenType::{NewLine, DEDENT, INDENT};
|
use crate::lexic::token::TokenType::{NewLine, DEDENT, INDENT};
|
||||||
use crate::syntax::ast::Expression;
|
use crate::syntax::ast::Expression;
|
||||||
use crate::syntax::parseable::{ParsingError, ParsingResult};
|
use crate::syntax::parseable::ParsingResult;
|
||||||
|
|
||||||
/// Parses a binary operator, handles indentation and runs a function on it.
|
/// Parses a binary operator, handles indentation and runs a function on it.
|
||||||
///
|
///
|
||||||
@ -15,7 +15,7 @@ pub fn try_binary_op<'a, F>(
|
|||||||
tokens: &'a Vec<Token>,
|
tokens: &'a Vec<Token>,
|
||||||
original_pos: usize,
|
original_pos: usize,
|
||||||
prev_expr: Expression<'a>,
|
prev_expr: Expression<'a>,
|
||||||
operators: &Vec<&str>,
|
operators: Vec<&str>,
|
||||||
indentation_level: u32,
|
indentation_level: u32,
|
||||||
fun: F,
|
fun: F,
|
||||||
) -> ParsingResult<'a, Expression<'a>>
|
) -> ParsingResult<'a, Expression<'a>>
|
||||||
@ -87,36 +87,3 @@ where
|
|||||||
|
|
||||||
Ok((new_expr, next_pos))
|
Ok((new_expr, next_pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_many<'a>(
|
|
||||||
tokens: &'a Vec<Token>,
|
|
||||||
pos: usize,
|
|
||||||
prev_expr: Expression<'a>,
|
|
||||||
indentation_level: u32,
|
|
||||||
operators: &Vec<&str>,
|
|
||||||
) -> ParsingResult<'a, Expression<'a>> {
|
|
||||||
// comparison = term, ((">" | ">=" | "<" | "<="), term)*;
|
|
||||||
try_binary_op(
|
|
||||||
tokens,
|
|
||||||
pos,
|
|
||||||
prev_expr,
|
|
||||||
operators,
|
|
||||||
indentation_level,
|
|
||||||
|tokens, next_pos, prev_expr, token, indent_count: u32| match super::term::try_parse(
|
|
||||||
tokens, next_pos,
|
|
||||||
) {
|
|
||||||
Ok((expr, next_pos)) => {
|
|
||||||
let expr = Expression::BinaryOperator(Box::new(prev_expr), Box::new(expr), &token);
|
|
||||||
|
|
||||||
parse_many(
|
|
||||||
tokens,
|
|
||||||
next_pos,
|
|
||||||
expr,
|
|
||||||
indentation_level + indent_count,
|
|
||||||
operators,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => return Err(ParsingError::Unmatched),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user