refactor: parse indentation on comparison
This commit is contained in:
parent
be8c16ccf0
commit
fa14439507
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
- [x] Begin work on a formal grammar
|
- [x] Begin work on a formal grammar
|
||||||
- [x] Simplify/rewrite AST
|
- [x] Simplify/rewrite AST
|
||||||
|
- [ ] Properly parse expression indentation/dedentation
|
||||||
- [x] Define the top level constructs
|
- [x] Define the top level constructs
|
||||||
- [ ] Include the original tokens in the AST
|
- [ ] Include the original tokens in the AST
|
||||||
- [ ] Finish the workflow for a hello world
|
- [ ] Finish the workflow for a hello world
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
use crate::lexic::token::TokenType;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
handle_dedentation, handle_indentation,
|
||||||
lexic::token::Token,
|
lexic::token::Token,
|
||||||
syntax::{ast::Expression, ParsingError, ParsingResult},
|
syntax::{ast::Expression, ParsingError, ParsingResult},
|
||||||
};
|
};
|
||||||
@ -14,24 +16,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, term)
|
parse_many(tokens, next_pos, term, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_many<'a>(
|
fn parse_many<'a>(
|
||||||
tokens: &'a Vec<Token>,
|
tokens: &'a Vec<Token>,
|
||||||
pos: usize,
|
pos: usize,
|
||||||
prev_expr: Expression<'a>,
|
prev_expr: Expression<'a>,
|
||||||
|
indentation_level: u32,
|
||||||
) -> ParsingResult<'a, Expression<'a>> {
|
) -> ParsingResult<'a, Expression<'a>> {
|
||||||
// comparison = term, ((">" | ">=" | "<" | "<="), term)*;
|
// comparison = term, ((">" | ">=" | "<" | "<="), term)*;
|
||||||
|
|
||||||
match tokens.get(pos) {
|
let mut indent_count: u32 = 0;
|
||||||
|
let mut next_pos = pos;
|
||||||
|
|
||||||
|
// Handle possible indentation before binary operator
|
||||||
|
handle_indentation!(tokens, next_pos, indent_count, indentation_level);
|
||||||
|
|
||||||
|
let result = match tokens.get(next_pos) {
|
||||||
Some(token)
|
Some(token)
|
||||||
if token.value == "<"
|
if token.value == "<"
|
||||||
|| token.value == "<="
|
|| token.value == "<="
|
||||||
|| token.value == ">"
|
|| token.value == ">"
|
||||||
|| token.value == ">=" =>
|
|| token.value == ">=" =>
|
||||||
{
|
{
|
||||||
match super::term::try_parse(tokens, pos + 1) {
|
next_pos += 1;
|
||||||
|
|
||||||
|
// Handle possible indentation after binary operator
|
||||||
|
handle_indentation!(tokens, next_pos, indent_count, indentation_level);
|
||||||
|
|
||||||
|
match super::term::try_parse(tokens, next_pos) {
|
||||||
Ok((expr, next_pos)) => {
|
Ok((expr, next_pos)) => {
|
||||||
let expr = Expression::BinaryOperator(
|
let expr = Expression::BinaryOperator(
|
||||||
Box::new(prev_expr),
|
Box::new(prev_expr),
|
||||||
@ -39,13 +53,22 @@ fn parse_many<'a>(
|
|||||||
&token.value,
|
&token.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
parse_many(tokens, next_pos, expr)
|
parse_many(tokens, next_pos, expr, indentation_level + indent_count)
|
||||||
}
|
}
|
||||||
_ => Err(ParsingError::Unmatched),
|
_ => return Err(ParsingError::Unmatched),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Ok((prev_expr, pos)),
|
_ => return Ok((prev_expr, pos)),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
let (new_expr, mut next_pos) = match result {
|
||||||
|
Ok((e, n)) => (e, n),
|
||||||
|
_ => return result,
|
||||||
|
};
|
||||||
|
|
||||||
|
handle_dedentation!(tokens, next_pos, indent_count);
|
||||||
|
|
||||||
|
Ok((new_expr, next_pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -88,4 +111,80 @@ mod tests {
|
|||||||
_ => panic!("Expected an Unmatched error"),
|
_ => panic!("Expected an Unmatched error"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_parse_indented_1() {
|
||||||
|
let tokens = get_tokens(&String::from("a\n >= b")).unwrap();
|
||||||
|
let (result, next) = try_parse(&tokens, 0).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(tokens[5].token_type, TokenType::DEDENT);
|
||||||
|
assert_eq!(next, 6);
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Expression::BinaryOperator(_, _, op) => {
|
||||||
|
assert_eq!(op, ">=")
|
||||||
|
}
|
||||||
|
_ => panic!("Expected a binary operator"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_parse_indented_2() {
|
||||||
|
let tokens = get_tokens(&String::from("a\n <= b\n <= c")).unwrap();
|
||||||
|
let (result, next) = try_parse(&tokens, 0).unwrap();
|
||||||
|
assert_eq!(next, 11);
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Expression::BinaryOperator(_, _, op) => {
|
||||||
|
assert_eq!(op, "<=")
|
||||||
|
}
|
||||||
|
_ => panic!("Expected a binary operator"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_parse_indented_3() {
|
||||||
|
let tokens = get_tokens(&String::from("a\n <= b <= c")).unwrap();
|
||||||
|
let (result, next) = try_parse(&tokens, 0).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(tokens[7].token_type, TokenType::DEDENT);
|
||||||
|
assert_eq!(next, 8);
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Expression::BinaryOperator(_, _, op) => {
|
||||||
|
assert_eq!(op, "<=")
|
||||||
|
}
|
||||||
|
_ => panic!("Expected a binary operator"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_parse_indented_4() {
|
||||||
|
let tokens = get_tokens(&String::from("a\n <= b\n <= c")).unwrap();
|
||||||
|
let (result, next) = try_parse(&tokens, 0).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(next, 9);
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Expression::BinaryOperator(_, _, op) => {
|
||||||
|
assert_eq!(op, "<=")
|
||||||
|
}
|
||||||
|
_ => panic!("Expected a binary operator"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_parse_indented_5() {
|
||||||
|
let tokens = get_tokens(&String::from("a >=\n b")).unwrap();
|
||||||
|
let (result, next) = try_parse(&tokens, 0).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(next, 6);
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Expression::BinaryOperator(_, _, op) => {
|
||||||
|
assert_eq!(op, ">=")
|
||||||
|
}
|
||||||
|
_ => panic!("Expected a binary operator"),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
handle_dedentation, handle_indentation, lexic::token::{Token, TokenType}, syntax::{ast::Expression, ParsingError, ParsingResult}
|
handle_dedentation, handle_indentation,
|
||||||
|
lexic::token::{Token, TokenType},
|
||||||
|
syntax::{ast::Expression, ParsingError, ParsingResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parses a factor expression.
|
/// Parses a factor expression.
|
||||||
@ -33,7 +35,7 @@ fn parse_many<'a>(
|
|||||||
let result = match tokens.get(next_pos) {
|
let result = match tokens.get(next_pos) {
|
||||||
Some(token) if token.value == "==" || token.value == "!=" => {
|
Some(token) if token.value == "==" || token.value == "!=" => {
|
||||||
next_pos += 1;
|
next_pos += 1;
|
||||||
|
|
||||||
// Handle possible indentation after binary operator
|
// Handle possible indentation after binary operator
|
||||||
handle_indentation!(tokens, next_pos, indent_count, indentation_level);
|
handle_indentation!(tokens, next_pos, indent_count, indentation_level);
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ fn parse_many<'a>(
|
|||||||
}
|
}
|
||||||
_ => return Ok((prev_expr, pos)),
|
_ => return Ok((prev_expr, pos)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (new_expr, mut next_pos) = match result {
|
let (new_expr, mut next_pos) = match result {
|
||||||
Ok((e, n)) => (e, n),
|
Ok((e, n)) => (e, n),
|
||||||
_ => return result,
|
_ => return result,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
handle_dedentation, handle_indentation, lexic::token::{Token, TokenType}, syntax::{ast::Expression, ParsingError, ParsingResult}
|
handle_dedentation, handle_indentation,
|
||||||
|
lexic::token::{Token, TokenType},
|
||||||
|
syntax::{ast::Expression, ParsingError, ParsingResult},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parses a factor expression.
|
/// Parses a factor expression.
|
||||||
|
Loading…
Reference in New Issue
Block a user