Skip to content

Commit d28a465

Browse files
committed
Adicionar parser para funções de teste
Este commit adiciona a função parse_test_function_definition_statement, que realiza o parser de TestDef em r-python, bem como testes para garantir que o parser funcione corretamente. Este commit também altera a função parse_function_definition_statement, para rejeitar funções cujo identificador se inicia com "test", também possuindo um teste para realizar esta checagem. Observações: - Parser de Declaração de Funções comuns está quebrado, isso dado a função keyword, que está consumindo o espaço após de KEYWORD_DEF e assumindo que def é uma palavra maior, quebrando parsers que utilizam a keyword def.
1 parent 3135447 commit d28a465

1 file changed

Lines changed: 131 additions & 7 deletions

File tree

src/parser/parser_stmt.rs

Lines changed: 131 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use nom::{
22
branch::alt,
33
bytes::complete::tag,
44
character::complete::{char, multispace0, multispace1},
5-
combinator::{map, opt},
6-
error::Error,
5+
combinator::{map, opt, map_res},
6+
error::{Error, ErrorKind},
77
multi::separated_list0,
88
sequence::{delimited, preceded, tuple},
99
IResult,
@@ -17,6 +17,7 @@ use crate::parser::parser_common::{
1717
};
1818
use crate::parser::parser_expr::parse_expression;
1919
use crate::parser::parser_type::parse_type;
20+
use crate::ir::ast::Type; // TODO: Check if needed
2021

2122
pub fn parse_statement(input: &str) -> IResult<&str, Statement> {
2223
alt((
@@ -27,6 +28,7 @@ pub fn parse_statement(input: &str) -> IResult<&str, Statement> {
2728
parse_while_statement,
2829
parse_for_statement,
2930
parse_assert_statement,
31+
parse_test_function_definition_statement, // FIXME: Being Implemented
3032
parse_function_definition_statement,
3133
))(input)
3234
}
@@ -150,7 +152,7 @@ fn parse_assert_statement(input: &str) -> IResult<&str, Statement> {
150152
}
151153

152154
fn parse_function_definition_statement(input: &str) -> IResult<&str, Statement> {
153-
map(
155+
map_res(
154156
tuple((
155157
keyword(DEF_KEYWORD),
156158
preceded(multispace1, identifier),
@@ -171,12 +173,59 @@ fn parse_function_definition_statement(input: &str) -> IResult<&str, Statement>
171173
parse_block,
172174
)),
173175
|(_, name, args, _, t, block)| {
174-
Statement::FuncDef(Function {
176+
if name.starts_with("test") {
177+
// Força falha aqui para evitar aceitar funções test_ no parser geral
178+
Err(nom::Err::Error(Error::new(name, ErrorKind::Tag)))
179+
} else {
180+
Ok(Statement::FuncDef(Function {
181+
name: name.to_string(),
182+
kind: t,
183+
params: args,
184+
body: Some(Box::new(block)),
185+
}))
186+
}
187+
},
188+
)(input)
189+
}
190+
191+
192+
// TODO: Fazer testes para essa função de parser
193+
fn parse_test_function_definition_statement(input: &str) -> IResult<&str, Statement> {
194+
map_res(
195+
tuple((
196+
//keyword(DEF_KEYWORD),
197+
tag("def"),
198+
preceded(multispace1, identifier),
199+
//identifier,
200+
delimited(
201+
char::<&str, Error<&str>>(LEFT_PAREN),
202+
multispace0, // Permite `()` com espaços, mas sem argumentos
203+
char::<&str, Error<&str>>(RIGHT_PAREN),
204+
),
205+
opt(preceded(
206+
preceded(multispace0, tag("->")),
207+
preceded(multispace0, parse_type),
208+
)),
209+
parse_block,
210+
)),
211+
|(_, name, _,opt_ret_type, block)| {
212+
if !name.starts_with("test") {
213+
return Err(nom::Err::Error(Error::new(name, ErrorKind::Tag)));
214+
}
215+
216+
// Se tiver tipo declarado, só aceita Bool
217+
if let Some(ret_type) = opt_ret_type {
218+
if ret_type != Type::TBool {
219+
return Err(nom::Err::Error(Error::new(name, ErrorKind::Tag)));
220+
}
221+
}
222+
223+
Ok(Statement::TestDef(Function {
175224
name: name.to_string(),
176-
kind: t,
177-
params: args,
225+
kind: Type::TBool, // Sempre bool (mesmo se não declarou)
226+
params: Vec::new(), // Nenhum argumento
178227
body: Some(Box::new(block)),
179-
})
228+
}))
180229
},
181230
)(input)
182231
}
@@ -343,4 +392,79 @@ mod tests {
343392
let parsed = parse_formal_argument(input).unwrap().1;
344393
assert_eq!(parsed, expected);
345394
}
395+
396+
#[test]
397+
fn test_parse_test_function_definition_statement_valid() {
398+
let input = "def test_example(): x = 1; end";
399+
let expected = Statement::TestDef(Function {
400+
name: "test_example".to_string(),
401+
kind: Type::TBool,
402+
params: vec![],
403+
body: Some(Box::new(Statement::Block(vec![
404+
Statement::Assignment("x".to_string(), Box::new(Expression::CInt(1))),
405+
]))),
406+
});
407+
let parsed = parse_test_function_definition_statement(input).unwrap().1;
408+
assert_eq!(parsed, expected);
409+
}
410+
411+
#[test]
412+
fn test_parse_test_function_definition_statement_with_spaces() {
413+
let input = "def test_spaces( ): x = 2; end";
414+
let expected = Statement::TestDef(Function {
415+
name: "test_spaces".to_string(),
416+
kind: Type::TBool,
417+
params: vec![],
418+
body: Some(Box::new(Statement::Block(vec![
419+
Statement::Assignment("x".to_string(), Box::new(Expression::CInt(2))),
420+
]))),
421+
});
422+
let parsed = parse_test_function_definition_statement(input).unwrap().1;
423+
assert_eq!(parsed, expected);
424+
}
425+
426+
#[test]
427+
fn test_parse_test_function_definition_statement_args() {
428+
let input = "def test_with_args(x: Int, y: Int): x = y; end";
429+
430+
// O parser deve falhar, pois funções de teste não podem ter argumentos.
431+
let parsed = parse_test_function_definition_statement(input);
432+
433+
assert!(parsed.is_err(), "Funções de teste com argumentos devem ser rejeitadas");
434+
}
435+
436+
#[test]
437+
fn test_parse_test_function_definition_statement_invalid_return_type() {
438+
let input = "def test_with_invalid_return() -> Int: x = 2; end";
439+
440+
// O parser deve falhar, pois funções de teste não podem ter argumentos.
441+
let parsed = parse_test_function_definition_statement(input);
442+
443+
assert!(parsed.is_err(), "Funções de teste não devem especificar tipo de retorno");
444+
}
445+
446+
#[test]
447+
fn test_parse_test_function_definition_statement_valid_return_type() {
448+
let input = "def test_with_valid_return() -> Boolean: x = 2; end";
449+
let expected = Statement::TestDef(Function {
450+
name: "test_with_valid_return".to_string(),
451+
kind: Type::TBool,
452+
params: vec![],
453+
body: Some(Box::new(Statement::Block(vec![
454+
Statement::Assignment("x".to_string(), Box::new(Expression::CInt(2))),
455+
]))),
456+
});
457+
let parsed = parse_test_function_definition_statement(input).unwrap().1;
458+
assert_eq!(parsed, expected);
459+
}
460+
#[test]
461+
#[ignore]
462+
fn test_parse_function_definition_statement_reject_test_function() {
463+
let input = "def test_function_rejected() -> Int: x = 2; end";
464+
465+
let parsed = parse_function_definition_statement(input);
466+
assert!(parsed.is_err(), "Funções comuns não devem iniciar com 'test'");
467+
}
468+
469+
346470
}

0 commit comments

Comments
 (0)