From b4629af6b8c6c1b108612836616d70ad9aa89dbe Mon Sep 17 00:00:00 2001 From: GUstavo Date: Wed, 2 Jul 2025 12:00:39 -0300 Subject: [PATCH 1/6] =?UTF-8?q?adi=C3=A7=C3=A3o=20do=20parser,=20adi=C3=A7?= =?UTF-8?q?=C3=A3o=20na=20ast=20e=20keywords?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ir/ast.rs | 4 ++++ src/parser/keywords.rs | 1 + src/parser/parser_stmt.rs | 42 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/ir/ast.rs b/src/ir/ast.rs index ba580a1..9e83fe8 100644 --- a/src/ir/ast.rs +++ b/src/ir/ast.rs @@ -119,6 +119,10 @@ pub enum Statement { ValDeclaration(Name, Box), Assignment(Name, Box), IfThenElse(Box, Box, Option>), + IfChain { + branches: Vec<(Box, Box)>, + else_branch: Option>, + }, While(Box, Box), For(Name, Box, Box), Block(Vec), diff --git a/src/parser/keywords.rs b/src/parser/keywords.rs index 5d528d8..1d9d878 100644 --- a/src/parser/keywords.rs +++ b/src/parser/keywords.rs @@ -2,6 +2,7 @@ pub const KEYWORDS: &[&str] = &[ "if", "in", "else", + "elif", "def", "while", "for", diff --git a/src/parser/parser_stmt.rs b/src/parser/parser_stmt.rs index bdcebdb..b262fcb 100644 --- a/src/parser/parser_stmt.rs +++ b/src/parser/parser_stmt.rs @@ -99,6 +99,44 @@ fn parse_if_else_statement(input: &str) -> IResult<&str, Statement> { )(input) } +pub fn parse_if_chain_statement(input: &str) -> IResult<&str, Statement> { + let (input, _) = keyword(IF_KEYWORD)(input)?; + let (input, cond_if) = preceded(multispace1, parse_expression)(input)?; + let (input, block_if) = parse_block(input)?; + + let mut branches = vec![(Box::new(cond_if), Box::new(block_if))]; + let mut current_input = input; + + loop { + let result = tuple(( + multispace0, + keyword(ELIF_KEYWORD), + preceded(multispace1, parse_expression), + parse_block, + ))(current_input); + + match result { + Ok((next_input, (_, _, cond_elif, block_elif))) => { + branches.push((Box::new(cond_elif), Box::new(block_elif))); + current_input = next_input; + } + Err(_) => break, + } + } + let (input, else_branch) = opt(preceded( + tuple((multispace0, keyword(ELSE_KEYWORD))), + parse_block, + ))(current_input)?; + + Ok(( + input, + Statement::IfChain { + branches, + else_branch: else_branch.map(Box::new), + }, + )) +} + fn parse_while_statement(input: &str) -> IResult<&str, Statement> { map( tuple(( @@ -155,7 +193,7 @@ fn parse_function_definition_statement(input: &str) -> IResult<&str, Statement> keyword(DEF_KEYWORD), preceded(multispace1, identifier), delimited( - char::<&str, Error<&str>>(LEFT_PAREN), + char:// Tenta parsear um else opcional:<&str, Error<&str>>(LEFT_PAREN), separated_list0( tuple(( multispace0, @@ -170,7 +208,7 @@ fn parse_function_definition_statement(input: &str) -> IResult<&str, Statement> preceded(multispace0, parse_type), parse_block, )), - |(_, name, args, _, t, block)| { + |(_, name, ar// Tenta parsear um else opcionalgs, _, t, block)| { Statement::FuncDef(Function { name: name.to_string(), kind: t, From 4f179e0178d414048f6108e8099c0a55524b571d Mon Sep 17 00:00:00 2001 From: jm-236 Date: Wed, 2 Jul 2025 15:36:12 -0300 Subject: [PATCH 2/6] =?UTF-8?q?test:=20implementa=C3=A7=C3=A3o=20dos=20tes?= =?UTF-8?q?tes=20da=20fun=C3=A7=C3=A3o=20parse=5Fif=5Fchain=20e=20corre?= =?UTF-8?q?=C3=A7=C3=A3o=20de=20erros.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ir/ast.rs | 4 +- src/parser/parser_common.rs | 15 +++-- src/parser/parser_stmt.rs | 123 ++++++++++++++++++++++++++++++------ 3 files changed, 114 insertions(+), 28 deletions(-) diff --git a/src/ir/ast.rs b/src/ir/ast.rs index 9e83fe8..fc67aab 100644 --- a/src/ir/ast.rs +++ b/src/ir/ast.rs @@ -120,8 +120,8 @@ pub enum Statement { Assignment(Name, Box), IfThenElse(Box, Box, Option>), IfChain { - branches: Vec<(Box, Box)>, - else_branch: Option>, + branches: Vec<(Box, Box)>, + else_branch: Option>, }, While(Box, Box), For(Name, Box, Box), diff --git a/src/parser/parser_common.rs b/src/parser/parser_common.rs index 065a742..4b4b44b 100644 --- a/src/parser/parser_common.rs +++ b/src/parser/parser_common.rs @@ -1,7 +1,7 @@ use nom::{ branch::alt, bytes::complete::tag, - character::complete::{alpha1, multispace0}, + character::complete::{alpha1, multispace0, alphanumeric1}, combinator::{not, peek, recognize}, multi::many0, sequence::{delimited, terminated}, @@ -28,6 +28,7 @@ pub const END_KEYWORD: &str = "end"; // Statement keyword constants pub const IF_KEYWORD: &str = "if"; +pub const ELIF_KEYWORD: &str = "elif"; pub const ELSE_KEYWORD: &str = "else"; pub const WHILE_KEYWORD: &str = "while"; pub const FOR_KEYWORD: &str = "for"; @@ -67,11 +68,15 @@ pub fn separator<'a>(sep: &'static str) -> impl FnMut(&'a str) -> IResult<&'a st } /// Parses a reserved keyword (e.g., "if") surrounded by optional spaces -/// Fails if followed by an identifier character +/// A implementação da função keyword foi alterada para que seja garantida que a keyword seja uma palavra completa e seja separada por um espaço pub fn keyword<'a>(kw: &'static str) -> impl FnMut(&'a str) -> IResult<&'a str, &'a str> { - terminated( - delimited(multispace0, tag(kw), multispace0), - not(peek(identifier_start_or_continue)), + delimited( + multispace0, + terminated( + tag(kw), + peek(not(alphanumeric1)), + ), + multispace0, ) } diff --git a/src/parser/parser_stmt.rs b/src/parser/parser_stmt.rs index b262fcb..ab2c57a 100644 --- a/src/parser/parser_stmt.rs +++ b/src/parser/parser_stmt.rs @@ -13,7 +13,7 @@ use crate::ir::ast::{FormalArgument, Function, Statement}; use crate::parser::parser_common::{ identifier, keyword, ASSERT_KEYWORD, COLON_CHAR, COMMA_CHAR, DEF_KEYWORD, ELSE_KEYWORD, END_KEYWORD, EQUALS_CHAR, FOR_KEYWORD, FUNCTION_ARROW, IF_KEYWORD, IN_KEYWORD, LEFT_PAREN, - RIGHT_PAREN, SEMICOLON_CHAR, VAL_KEYWORD, VAR_KEYWORD, WHILE_KEYWORD, + RIGHT_PAREN, SEMICOLON_CHAR, VAL_KEYWORD, VAR_KEYWORD, WHILE_KEYWORD, ELIF_KEYWORD }; use crate::parser::parser_expr::parse_expression; use crate::parser::parser_type::parse_type; @@ -100,34 +100,25 @@ fn parse_if_else_statement(input: &str) -> IResult<&str, Statement> { } pub fn parse_if_chain_statement(input: &str) -> IResult<&str, Statement> { - let (input, _) = keyword(IF_KEYWORD)(input)?; - let (input, cond_if) = preceded(multispace1, parse_expression)(input)?; - let (input, block_if) = parse_block(input)?; - + + let (input_after_if, _) = keyword(IF_KEYWORD)(input)?; + let (input_after_expr, cond_if) = parse_expression(input_after_if)?; + let (input_after_block, block_if) = parse_block(input_after_expr)?; + let mut branches = vec![(Box::new(cond_if), Box::new(block_if))]; - let mut current_input = input; + let mut current_input = input_after_block; loop { - let result = tuple(( - multispace0, - keyword(ELIF_KEYWORD), - preceded(multispace1, parse_expression), - parse_block, - ))(current_input); - + let result = tuple((keyword(ELIF_KEYWORD), parse_expression, parse_block))(current_input); match result { - Ok((next_input, (_, _, cond_elif, block_elif))) => { + Ok((next_input, (_, cond_elif, block_elif))) => { branches.push((Box::new(cond_elif), Box::new(block_elif))); current_input = next_input; } Err(_) => break, } } - let (input, else_branch) = opt(preceded( - tuple((multispace0, keyword(ELSE_KEYWORD))), - parse_block, - ))(current_input)?; - + let (input, else_branch) = opt(preceded(keyword(ELSE_KEYWORD), parse_block))(current_input)?; Ok(( input, Statement::IfChain { @@ -193,7 +184,8 @@ fn parse_function_definition_statement(input: &str) -> IResult<&str, Statement> keyword(DEF_KEYWORD), preceded(multispace1, identifier), delimited( - char:// Tenta parsear um else opcional:<&str, Error<&str>>(LEFT_PAREN), + // Corrigido: Removido o comentário que quebrava a sintaxe + char::<&str, Error<&str>>(LEFT_PAREN), separated_list0( tuple(( multispace0, @@ -208,7 +200,8 @@ fn parse_function_definition_statement(input: &str) -> IResult<&str, Statement> preceded(multispace0, parse_type), parse_block, )), - |(_, name, ar// Tenta parsear um else opcionalgs, _, t, block)| { + // Corrigido: O nome da variável 'args' agora está correto + |(_, name, args, _, t, block)| { Statement::FuncDef(Function { name: name.to_string(), kind: t, @@ -381,4 +374,92 @@ mod tests { let parsed = parse_formal_argument(input).unwrap().1; assert_eq!(parsed, expected); } + + #[test] + fn test_parse_if_chain_statement() { + + // Cenário 1: Apenas um "if", sem "elif" ou "else". + let input_if_only = "if True: x = 1; end"; + let expected_if_only = Statement::IfChain { + branches: vec![( + Box::new(Expression::CTrue), + Box::new(Statement::Block(vec![Statement::Assignment( + "x".to_string(), + Box::new(Expression::CInt(1)), + )])), + )], + else_branch: None, + }; + let (_, parsed_if_only) = parse_if_chain_statement(input_if_only).unwrap(); + assert_eq!(parsed_if_only, expected_if_only); + + // Cenário 2: Um "if" com "else", mas sem "elif". + let input_if_else = "if False: x = 1; end else: y = 2; end"; + let expected_if_else = Statement::IfChain { + branches: vec![( + Box::new(Expression::CFalse), + Box::new(Statement::Block(vec![Statement::Assignment( + "x".to_string(), + Box::new(Expression::CInt(1)), + )])), + )], + else_branch: Some(Box::new(Statement::Block(vec![Statement::Assignment( + "y".to_string(), + Box::new(Expression::CInt(2)), + )]))), + }; + let (_, parsed_if_else) = parse_if_chain_statement(input_if_else).unwrap(); + assert_eq!(parsed_if_else, expected_if_else); + + // Cenário 3: "if", um "elif", e um "else". + let input_if_elif_else = "if a: x = 1; end elif b: y = 2; end else: z = 3; end"; + let expected_if_elif_else = Statement::IfChain { + branches: vec![ + ( + Box::new(Expression::Var("a".to_string())), + Box::new(Statement::Block(vec![Statement::Assignment( + "x".to_string(), + Box::new(Expression::CInt(1)), + )])), + ), + ( + Box::new(Expression::Var("b".to_string())), + Box::new(Statement::Block(vec![Statement::Assignment( + "y".to_string(), + Box::new(Expression::CInt(2)), + )])), + ), + ], + else_branch: Some(Box::new(Statement::Block(vec![Statement::Assignment( + "z".to_string(), + Box::new(Expression::CInt(3)), + )]))), + }; + let (_, parsed_if_elif_else) = parse_if_chain_statement(input_if_elif_else).unwrap(); + assert_eq!(parsed_if_elif_else, expected_if_elif_else); + + // Cenário 4: "if" com múltiplos "elif" e sem "else". + let input_multi_elif = "if a: x=1; end elif b: y=2; end elif c: z=3; end"; + let expected_multi_elif = Statement::IfChain { + branches: vec![ + ( + Box::new(Expression::Var("a".to_string())), + Box::new(Statement::Block(vec![Statement::Assignment("x".to_string(), Box::new(Expression::CInt(1)))])), + ), + ( + Box::new(Expression::Var("b".to_string())), + Box::new(Statement::Block(vec![Statement::Assignment("y".to_string(), Box::new(Expression::CInt(2)))])), + ), + ( + Box::new(Expression::Var("c".to_string())), + Box::new(Statement::Block(vec![Statement::Assignment("z".to_string(), Box::new(Expression::CInt(3)))])), + ), + ], + else_branch: None, + }; + let (_, parsed_multi_elif) = parse_if_chain_statement(input_multi_elif).unwrap(); + assert_eq!(parsed_multi_elif, expected_multi_elif); + } } + + From 1ee453a0a6ce28b20c906da54e4a8b44c0565a4c Mon Sep 17 00:00:00 2001 From: jm-236 Date: Fri, 4 Jul 2025 23:08:42 -0300 Subject: [PATCH 3/6] loop for implementation --- src/interpreter/statement_execute.rs | 54 +++++++++++++++++ src/ir/ast.rs | 1 + src/type_checker/statement_type_checker.rs | 67 +++++++++++++--------- 3 files changed, 96 insertions(+), 26 deletions(-) diff --git a/src/interpreter/statement_execute.rs b/src/interpreter/statement_execute.rs index 2c9e44f..71fd1c0 100644 --- a/src/interpreter/statement_execute.rs +++ b/src/interpreter/statement_execute.rs @@ -75,6 +75,60 @@ pub fn execute( } } + Statement::For(var, expr, stmt) => { + let coll = eval(*expr, &new_env)?; + + match coll { + // Lista de valores + Expression::ListValue(items) => { + new_env.push(); + for item in items { + new_env.map_variable(var.clone(), true, item); + new_env = execute(*stmt.clone(), &new_env)?; + } + new_env.pop(); + Ok(new_env) + } + + // String - itera sobre caracteres + Expression::CString(s) => { + new_env.push(); + for ch in s.chars() { + let char_value = Expression::CString(ch.to_string()); + new_env.map_variable(var.clone(), true, char_value); + new_env = execute(*stmt.clone(), &new_env)?; + } + new_env.pop(); + Ok(new_env) + } + + // Tupla (assumindo que você tem Expression::Tuple) + Expression::Tuple(items) => { + new_env.push(); + for item in items { + new_env.map_variable(var.clone(), true, item); + new_env = execute(*stmt.clone(), &new_env)?; + } + new_env.pop(); + Ok(new_env) + } + + // Constructor (já existia) + Expression::Constructor(_, items) => { + new_env.push(); + for item_expr in items { + let item_value = *item_expr.clone(); + new_env.map_variable(var.clone(), true, item_value); + new_env = execute(*stmt.clone(), &new_env)?; + } + new_env.pop(); + Ok(new_env) + } + + _ => Err((format!("Cannot iterate over {:?}", coll), None)), + } + } + Statement::Sequence(s1, s2) => { new_env = execute(*s1, &new_env)?; execute(*s2, &new_env) diff --git a/src/ir/ast.rs b/src/ir/ast.rs index ba580a1..cba61f0 100644 --- a/src/ir/ast.rs +++ b/src/ir/ast.rs @@ -134,4 +134,5 @@ pub enum Statement { FuncDef(Function), Return(Box), TypeDeclaration(Name, Vec), + Tuple(Vec) } \ No newline at end of file diff --git a/src/type_checker/statement_type_checker.rs b/src/type_checker/statement_type_checker.rs index 5c6835e..40546e4 100644 --- a/src/type_checker/statement_type_checker.rs +++ b/src/type_checker/statement_type_checker.rs @@ -141,6 +141,28 @@ fn check_while_stmt( Ok(new_env) } +// Função auxiliar para determinar o tipo do elemento iterável +fn get_iterable_element_type(expr_type: &Type) -> Result { + match expr_type { + Type::TList(base_type) => Ok((**base_type).clone()), + Type::TString => Ok(Type::TString), // Caracteres como strings + Type::TTuple(types) => { + if types.is_empty() { + return Err("[Type Error] Cannot iterate over empty tuple type".to_string()); + } + + // Verificar se todos os tipos são iguais (tupla homogênea) + let first_type = &types[0]; + if types.iter().all(|t| t == first_type) { + Ok(first_type.clone()) + } else { + Err("[Type Error] Can only iterate over homogeneous tuples (all elements same type)".to_string()) + } + } + _ => Err(format!("[Type Error] Type {:?} is not iterable", expr_type)) + } +} + fn check_for_stmt( var: Name, expr: Box, @@ -148,33 +170,26 @@ fn check_for_stmt( env: &Environment, ) -> Result, ErrorMessage> { let mut new_env = env.clone(); - let _var_type = env.lookup(&var); + + // Avaliar o tipo da expressão iterável let expr_type = check_expr(*expr, &new_env)?; - match expr_type { - Type::TList(base_type) => { - if let Some((_, t)) = env.lookup(&var) { - if t == *base_type || *base_type == Type::TAny { - new_env = check_stmt(*stmt, &new_env)?; - return Ok(new_env); - } else { - return Err(format!( - "[TypeError] Type mismatch between {:?} and {:?}", - t, base_type - )); - } - } else { - new_env.map_variable(var.clone(), false, *base_type); - new_env = check_stmt(*stmt, &new_env)?; - return Ok(new_env); - } - } - _ => { - return Err(format!( - "[TypeError] Expecting a List type, but found a {:?}", - expr_type - )) - } - } + + // Determinar o tipo do elemento + let element_type = get_iterable_element_type(&expr_type)?; + + // Criar novo escopo para o loop + new_env.push(); + + // Mapear a variável iteradora no novo escopo + new_env.map_variable(var.clone(), false, element_type); + + // Verificar o corpo do loop no novo escopo + new_env = check_stmt(*stmt, &new_env)?; + + // Remover o escopo do loop + new_env.pop(); + + Ok(new_env) } fn check_func_def_stmt( From 91899b6916b1763f9cde2b14ce992387033760d7 Mon Sep 17 00:00:00 2001 From: Inaskii Date: Tue, 8 Jul 2025 22:35:01 -0300 Subject: [PATCH 4/6] tuple for tests --- tests/parser_tests.rs | 108 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/tests/parser_tests.rs b/tests/parser_tests.rs index 937e3c2..e634540 100644 --- a/tests/parser_tests.rs +++ b/tests/parser_tests.rs @@ -109,6 +109,45 @@ mod expression_tests { assert_eq!(rest, ""); assert_eq!(result, expected); } + + #[test] + fn test_tuple_literals() { + let cases = vec![ + ( + "(1, 2, 3)", + Expression::Tuple(vec![ + Expression::CInt(1), + Expression::CInt(2), + Expression::CInt(3), + ]), + ), + ( + "(\"hello\", True)", + Expression::Tuple(vec![ + Expression::CString("hello".to_string()), + Expression::CTrue, + ]), + ), + ("()", Expression::Tuple(vec![])), + ( + "(42,)", + Expression::Tuple(vec![Expression::CInt(42)]), + ), + ( + "((1, 2), (3, 4))", + Expression::Tuple(vec![ + Expression::Tuple(vec![Expression::CInt(1), Expression::CInt(2)]), + Expression::Tuple(vec![Expression::CInt(3), Expression::CInt(4)]), + ]), + ), + ]; + + for (input, expected) in cases { + let (rest, result) = parse_expression(input).unwrap(); + assert_eq!(rest, ""); + assert_eq!(result, expected); + } + } } // Statement Tests @@ -204,6 +243,75 @@ mod statement_tests { assert_eq!(result, expected); } + #[test] + fn test_for_over_tuple() { + let cases = vec![ + ( + "for x in (1, 2, 3): x = x + 1; end", + Statement::For( + "x".to_string(), + Box::new(Expression::Tuple(vec![ + Expression::CInt(1), + Expression::CInt(2), + Expression::CInt(3), + ])), + Box::new(Statement::Block(vec![Statement::Assignment( + "x".to_string(), + Box::new(Expression::Add( + Box::new(Expression::Var("x".to_string())), + Box::new(Expression::CInt(1)), + )), + )])), + ), + ), + ( + "for item in (\"a\", \"b\"): val x = item; end", + Statement::For( + "item".to_string(), + Box::new(Expression::Tuple(vec![ + Expression::CString("a".to_string()), + Expression::CString("b".to_string()), + ])), + Box::new(Statement::Block(vec![Statement::ValDeclaration( + "x".to_string(), + Box::new(Expression::Var("item".to_string())), + )])), + ), + ), + ( + "for x in (): val y = 1; end", + Statement::For( + "x".to_string(), + Box::new(Expression::Tuple(vec![])), + Box::new(Statement::Block(vec![Statement::ValDeclaration( + "y".to_string(), + Box::new(Expression::CInt(1)), + )])), + ), + ), + ( + "for t in ((1,2), (3,4)): val x = t; end", + Statement::For( + "t".to_string(), + Box::new(Expression::Tuple(vec![ + Expression::Tuple(vec![Expression::CInt(1), Expression::CInt(2)]), + Expression::Tuple(vec![Expression::CInt(3), Expression::CInt(4)]), + ])), + Box::new(Statement::Block(vec![Statement::ValDeclaration( + "x".to_string(), + Box::new(Expression::Var("t".to_string())), + )])), + ), + ), + ]; + + for (input, expected) in cases { + let (rest, result) = parse_statement(input).unwrap(); + assert_eq!(rest, ""); + assert_eq!(result, expected); + } + } + #[test] #[ignore] fn test_function_definitions() { From 9f6c30f71671a7102b87c7b5670c86b7e96f7897 Mon Sep 17 00:00:00 2001 From: jm-236 Date: Thu, 10 Jul 2025 12:35:37 -0300 Subject: [PATCH 5/6] feat: Adiciona parser if_chain ao parser_stmt --- src/parser/parser_stmt.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/parser/parser_stmt.rs b/src/parser/parser_stmt.rs index ab2c57a..5870d7f 100644 --- a/src/parser/parser_stmt.rs +++ b/src/parser/parser_stmt.rs @@ -23,6 +23,7 @@ pub fn parse_statement(input: &str) -> IResult<&str, Statement> { parse_var_declaration_statement, parse_val_declaration_statement, parse_assignment_statement, + parse_if_chain_statement, parse_if_else_statement, parse_while_statement, parse_for_statement, From 1dff39f2afc7bf14c1bb086891ad977c7c18042a Mon Sep 17 00:00:00 2001 From: RafaelLopes23 Date: Wed, 27 Aug 2025 16:34:13 -0300 Subject: [PATCH 6/6] chore(fmt): apply rustfmt after merging PR #52 --- src/parser/parser_stmt.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/parser/parser_stmt.rs b/src/parser/parser_stmt.rs index 43c90da..7723beb 100644 --- a/src/parser/parser_stmt.rs +++ b/src/parser/parser_stmt.rs @@ -13,9 +13,9 @@ use crate::ir::ast::Type; use crate::ir::ast::{FormalArgument, Function, Statement}; use crate::parser::parser_common::{ identifier, keyword, ASSERTEQ_KEYWORD, ASSERTFALSE_KEYWORD, ASSERTNEQ_KEYWORD, - ASSERTTRUE_KEYWORD, ASSERT_KEYWORD, COLON_CHAR, COMMA_CHAR, DEF_KEYWORD, ELSE_KEYWORD, - END_KEYWORD, EQUALS_CHAR, FOR_KEYWORD, FUNCTION_ARROW, IF_KEYWORD, IN_KEYWORD, LEFT_PAREN, - RIGHT_PAREN, SEMICOLON_CHAR, VAL_KEYWORD, VAR_KEYWORD, WHILE_KEYWORD, ELIF_KEYWORD + ASSERTTRUE_KEYWORD, ASSERT_KEYWORD, COLON_CHAR, COMMA_CHAR, DEF_KEYWORD, ELIF_KEYWORD, + ELSE_KEYWORD, END_KEYWORD, EQUALS_CHAR, FOR_KEYWORD, FUNCTION_ARROW, IF_KEYWORD, IN_KEYWORD, + LEFT_PAREN, RIGHT_PAREN, SEMICOLON_CHAR, VAL_KEYWORD, VAR_KEYWORD, WHILE_KEYWORD, }; use crate::parser::parser_expr::parse_expression; use crate::parser::parser_type::parse_type; @@ -108,11 +108,10 @@ fn parse_if_else_statement(input: &str) -> IResult<&str, Statement> { } pub fn parse_if_chain_statement(input: &str) -> IResult<&str, Statement> { - let (input_after_if, _) = keyword(IF_KEYWORD)(input)?; let (input_after_expr, cond_if) = parse_expression(input_after_if)?; let (input_after_block, block_if) = parse_block(input_after_expr)?; - + let mut branches = vec![(Box::new(cond_if), Box::new(block_if))]; let mut current_input = input_after_block; @@ -509,7 +508,6 @@ mod tests { #[test] fn test_parse_if_chain_statement() { - // Cenário 1: Apenas um "if", sem "elif" ou "else". let input_if_only = "if True: x = 1; end"; let expected_if_only = Statement::IfChain { @@ -569,22 +567,31 @@ mod tests { }; let (_, parsed_if_elif_else) = parse_if_chain_statement(input_if_elif_else).unwrap(); assert_eq!(parsed_if_elif_else, expected_if_elif_else); - + // Cenário 4: "if" com múltiplos "elif" e sem "else". let input_multi_elif = "if a: x=1; end elif b: y=2; end elif c: z=3; end"; let expected_multi_elif = Statement::IfChain { branches: vec![ ( Box::new(Expression::Var("a".to_string())), - Box::new(Statement::Block(vec![Statement::Assignment("x".to_string(), Box::new(Expression::CInt(1)))])), + Box::new(Statement::Block(vec![Statement::Assignment( + "x".to_string(), + Box::new(Expression::CInt(1)), + )])), ), ( Box::new(Expression::Var("b".to_string())), - Box::new(Statement::Block(vec![Statement::Assignment("y".to_string(), Box::new(Expression::CInt(2)))])), + Box::new(Statement::Block(vec![Statement::Assignment( + "y".to_string(), + Box::new(Expression::CInt(2)), + )])), ), ( Box::new(Expression::Var("c".to_string())), - Box::new(Statement::Block(vec![Statement::Assignment("z".to_string(), Box::new(Expression::CInt(3)))])), + Box::new(Statement::Block(vec![Statement::Assignment( + "z".to_string(), + Box::new(Expression::CInt(3)), + )])), ), ], else_branch: None, @@ -867,5 +874,3 @@ mod tests { } } } - -