Skip to content

Commit e33f604

Browse files
Merge pull request #64 from RafaelLopes23/pr-52-resolvido
Integração do PR #52: if-elif-else + correção de keyword
2 parents fd0917a + 1dff39f commit e33f604

File tree

4 files changed

+142
-7
lines changed

4 files changed

+142
-7
lines changed

src/ir/ast.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ pub enum Statement {
130130
ValDeclaration(Name, Box<Expression>),
131131
Assignment(Name, Box<Expression>),
132132
IfThenElse(Box<Expression>, Box<Statement>, Option<Box<Statement>>),
133+
IfChain {
134+
branches: Vec<(Box<Expression>, Box<Statement>)>,
135+
else_branch: Option<Box<Statement>>,
136+
},
133137
While(Box<Expression>, Box<Statement>),
134138
For(Name, Box<Expression>, Box<Statement>),
135139
Block(Vec<Statement>),

src/parser/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pub const KEYWORDS: &[&str] = &[
22
"if",
33
"in",
44
"else",
5+
"elif",
56
"def",
67
"while",
78
"for",

src/parser/parser_common.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub const END_KEYWORD: &str = "end";
2828

2929
// Statement keyword constants
3030
pub const IF_KEYWORD: &str = "if";
31+
pub const ELIF_KEYWORD: &str = "elif";
3132
pub const ELSE_KEYWORD: &str = "else";
3233
pub const WHILE_KEYWORD: &str = "while";
3334
pub const FOR_KEYWORD: &str = "for";
@@ -72,11 +73,16 @@ pub fn separator<'a>(sep: &'static str) -> impl FnMut(&'a str) -> IResult<&'a st
7273
}
7374

7475
/// Parses a reserved keyword (e.g., "if") surrounded by optional spaces
75-
/// Fails if followed by an identifier character
76+
/// 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
7677
pub fn keyword<'a>(kw: &'static str) -> impl FnMut(&'a str) -> IResult<&'a str, &'a str> {
77-
terminated(
78-
delimited(multispace0, tag(kw), multispace0),
79-
not(peek(identifier_start_or_continue)),
78+
delimited(
79+
multispace0,
80+
terminated(
81+
tag(kw),
82+
// Ensure the keyword is not followed by an identifier character (letter, digit, or underscore)
83+
peek(not(identifier_start_or_continue)),
84+
),
85+
multispace0,
8086
)
8187
}
8288

src/parser/parser_stmt.rs

Lines changed: 127 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ use crate::ir::ast::Type;
1313
use crate::ir::ast::{FormalArgument, Function, Statement};
1414
use crate::parser::parser_common::{
1515
identifier, keyword, ASSERTEQ_KEYWORD, ASSERTFALSE_KEYWORD, ASSERTNEQ_KEYWORD,
16-
ASSERTTRUE_KEYWORD, ASSERT_KEYWORD, COLON_CHAR, COMMA_CHAR, DEF_KEYWORD, ELSE_KEYWORD,
17-
END_KEYWORD, EQUALS_CHAR, FOR_KEYWORD, FUNCTION_ARROW, IF_KEYWORD, IN_KEYWORD, LEFT_PAREN,
18-
RIGHT_PAREN, SEMICOLON_CHAR, VAL_KEYWORD, VAR_KEYWORD, WHILE_KEYWORD,
16+
ASSERTTRUE_KEYWORD, ASSERT_KEYWORD, COLON_CHAR, COMMA_CHAR, DEF_KEYWORD, ELIF_KEYWORD,
17+
ELSE_KEYWORD, END_KEYWORD, EQUALS_CHAR, FOR_KEYWORD, FUNCTION_ARROW, IF_KEYWORD, IN_KEYWORD,
18+
LEFT_PAREN, RIGHT_PAREN, SEMICOLON_CHAR, VAL_KEYWORD, VAR_KEYWORD, WHILE_KEYWORD,
1919
};
2020
use crate::parser::parser_expr::parse_expression;
2121
use crate::parser::parser_type::parse_type;
@@ -25,6 +25,7 @@ pub fn parse_statement(input: &str) -> IResult<&str, Statement> {
2525
parse_var_declaration_statement,
2626
parse_val_declaration_statement,
2727
parse_assignment_statement,
28+
parse_if_chain_statement,
2829
parse_if_else_statement,
2930
parse_while_statement,
3031
parse_for_statement,
@@ -106,6 +107,34 @@ fn parse_if_else_statement(input: &str) -> IResult<&str, Statement> {
106107
)(input)
107108
}
108109

110+
pub fn parse_if_chain_statement(input: &str) -> IResult<&str, Statement> {
111+
let (input_after_if, _) = keyword(IF_KEYWORD)(input)?;
112+
let (input_after_expr, cond_if) = parse_expression(input_after_if)?;
113+
let (input_after_block, block_if) = parse_block(input_after_expr)?;
114+
115+
let mut branches = vec![(Box::new(cond_if), Box::new(block_if))];
116+
let mut current_input = input_after_block;
117+
118+
loop {
119+
let result = tuple((keyword(ELIF_KEYWORD), parse_expression, parse_block))(current_input);
120+
match result {
121+
Ok((next_input, (_, cond_elif, block_elif))) => {
122+
branches.push((Box::new(cond_elif), Box::new(block_elif)));
123+
current_input = next_input;
124+
}
125+
Err(_) => break,
126+
}
127+
}
128+
let (input, else_branch) = opt(preceded(keyword(ELSE_KEYWORD), parse_block))(current_input)?;
129+
Ok((
130+
input,
131+
Statement::IfChain {
132+
branches,
133+
else_branch: else_branch.map(Box::new),
134+
},
135+
))
136+
}
137+
109138
fn parse_while_statement(input: &str) -> IResult<&str, Statement> {
110139
map(
111140
tuple((
@@ -275,6 +304,7 @@ fn parse_function_definition_statement(input: &str) -> IResult<&str, Statement>
275304
keyword(DEF_KEYWORD),
276305
preceded(multispace1, identifier),
277306
delimited(
307+
// Corrigido: Removido o comentário que quebrava a sintaxe
278308
char::<&str, Error<&str>>(LEFT_PAREN),
279309
separated_list0(
280310
tuple((
@@ -290,6 +320,7 @@ fn parse_function_definition_statement(input: &str) -> IResult<&str, Statement>
290320
preceded(multispace0, parse_type),
291321
parse_block,
292322
)),
323+
// Corrigido: O nome da variável 'args' agora está correto
293324
|(_, name, args, _, t, block)| {
294325
Statement::FuncDef(Function {
295326
name: name.to_string(),
@@ -475,6 +506,99 @@ mod tests {
475506
assert_eq!(parsed, expected);
476507
}
477508

509+
#[test]
510+
fn test_parse_if_chain_statement() {
511+
// Cenário 1: Apenas um "if", sem "elif" ou "else".
512+
let input_if_only = "if True: x = 1; end";
513+
let expected_if_only = Statement::IfChain {
514+
branches: vec![(
515+
Box::new(Expression::CTrue),
516+
Box::new(Statement::Block(vec![Statement::Assignment(
517+
"x".to_string(),
518+
Box::new(Expression::CInt(1)),
519+
)])),
520+
)],
521+
else_branch: None,
522+
};
523+
let (_, parsed_if_only) = parse_if_chain_statement(input_if_only).unwrap();
524+
assert_eq!(parsed_if_only, expected_if_only);
525+
526+
// Cenário 2: Um "if" com "else", mas sem "elif".
527+
let input_if_else = "if False: x = 1; end else: y = 2; end";
528+
let expected_if_else = Statement::IfChain {
529+
branches: vec![(
530+
Box::new(Expression::CFalse),
531+
Box::new(Statement::Block(vec![Statement::Assignment(
532+
"x".to_string(),
533+
Box::new(Expression::CInt(1)),
534+
)])),
535+
)],
536+
else_branch: Some(Box::new(Statement::Block(vec![Statement::Assignment(
537+
"y".to_string(),
538+
Box::new(Expression::CInt(2)),
539+
)]))),
540+
};
541+
let (_, parsed_if_else) = parse_if_chain_statement(input_if_else).unwrap();
542+
assert_eq!(parsed_if_else, expected_if_else);
543+
544+
// Cenário 3: "if", um "elif", e um "else".
545+
let input_if_elif_else = "if a: x = 1; end elif b: y = 2; end else: z = 3; end";
546+
let expected_if_elif_else = Statement::IfChain {
547+
branches: vec![
548+
(
549+
Box::new(Expression::Var("a".to_string())),
550+
Box::new(Statement::Block(vec![Statement::Assignment(
551+
"x".to_string(),
552+
Box::new(Expression::CInt(1)),
553+
)])),
554+
),
555+
(
556+
Box::new(Expression::Var("b".to_string())),
557+
Box::new(Statement::Block(vec![Statement::Assignment(
558+
"y".to_string(),
559+
Box::new(Expression::CInt(2)),
560+
)])),
561+
),
562+
],
563+
else_branch: Some(Box::new(Statement::Block(vec![Statement::Assignment(
564+
"z".to_string(),
565+
Box::new(Expression::CInt(3)),
566+
)]))),
567+
};
568+
let (_, parsed_if_elif_else) = parse_if_chain_statement(input_if_elif_else).unwrap();
569+
assert_eq!(parsed_if_elif_else, expected_if_elif_else);
570+
571+
// Cenário 4: "if" com múltiplos "elif" e sem "else".
572+
let input_multi_elif = "if a: x=1; end elif b: y=2; end elif c: z=3; end";
573+
let expected_multi_elif = Statement::IfChain {
574+
branches: vec![
575+
(
576+
Box::new(Expression::Var("a".to_string())),
577+
Box::new(Statement::Block(vec![Statement::Assignment(
578+
"x".to_string(),
579+
Box::new(Expression::CInt(1)),
580+
)])),
581+
),
582+
(
583+
Box::new(Expression::Var("b".to_string())),
584+
Box::new(Statement::Block(vec![Statement::Assignment(
585+
"y".to_string(),
586+
Box::new(Expression::CInt(2)),
587+
)])),
588+
),
589+
(
590+
Box::new(Expression::Var("c".to_string())),
591+
Box::new(Statement::Block(vec![Statement::Assignment(
592+
"z".to_string(),
593+
Box::new(Expression::CInt(3)),
594+
)])),
595+
),
596+
],
597+
else_branch: None,
598+
};
599+
let (_, parsed_multi_elif) = parse_if_chain_statement(input_multi_elif).unwrap();
600+
assert_eq!(parsed_multi_elif, expected_multi_elif);
601+
}
478602
//TODO: Apresentar Parser de TestDef (Testes)
479603
mod testdef_tests {
480604
use super::*;

0 commit comments

Comments
 (0)