diff --git a/src/error/error.rs b/src/error/error.rs index 4f7811b..a54ed2d 100644 --- a/src/error/error.rs +++ b/src/error/error.rs @@ -80,7 +80,8 @@ impl Error { | ParseError::UndefinedVariable(loc) | ParseError::UnusedVariable(loc) | ParseError::NotMatchReturnType(loc) - | ParseError::UnexpectedUnderScoreOperator(loc) => loc.clone(), + | ParseError::UnexpectedUnderScoreOperator(loc) + | ParseError::NotMatchTypeAnotherOneOfStatement(loc) => loc.clone(), ParseError::Eof => Loc::new(input.len() as u8, input.len() as u8 + 1), }; (e, loc) diff --git a/src/fmt/fmt.rs b/src/fmt/fmt.rs index 4b9b3a7..4ee2073 100644 --- a/src/fmt/fmt.rs +++ b/src/fmt/fmt.rs @@ -111,6 +111,12 @@ impl fmt::Display for ParseError { "{}: Expected under socre as void return, but used as operator.", loc ), + ParseError::NotMatchTypeAnotherOneOfStatement(loc) => write!( + f, + "{}: Expected match return type of each statement but not match.", + loc + ), + ParseError::Eof => write!(f, "Expected token, but not detected."), } } diff --git a/src/node/node.rs b/src/node/node.rs index 7a3f050..d0df3d4 100644 --- a/src/node/node.rs +++ b/src/node/node.rs @@ -188,4 +188,28 @@ impl NodeSt { _ => unimplemented!(), } } + + pub fn isi(self) -> bool { + match self.c.value { + NodeKind::Num(_) + | NodeKind::Add + | NodeKind::Sub + | NodeKind::Mul + | NodeKind::Div + | NodeKind::E + | NodeKind::NE + | NodeKind::L + | NodeKind::LE + | NodeKind::G + | NodeKind::GE + | NodeKind::NewAssignG + | NodeKind::NewAssignL + | NodeKind::NewAssign + | NodeKind::Assign + | NodeKind::Ident(_) + | NodeKind::GVar(_) + | NodeKind::LVar(_) => true, + _ => false, + } + } } diff --git a/src/node_arr/node_arr.rs b/src/node_arr/node_arr.rs index 468571e..3118c4e 100644 --- a/src/node_arr/node_arr.rs +++ b/src/node_arr/node_arr.rs @@ -154,27 +154,19 @@ impl NodeArr { it: &mut TokenIter, ev: Vec>, ) -> Result<(Self, Vec), ParseError> { - let mut a = Self::new(); - a.set_env(ev); - expect_token( TokenKind::LBrace, ParseError::NotOpenedStmt(it.p.peek().unwrap().to_owned().to_owned()), it, )?; - while it.peek_value() != TokenKind::RBrace { - match NodeSt::parser(it)? { - n => match n.c.value { - _ => { - a.set_imm_env(); - let n = beta(&mut n.to_owned(), &mut a); - a.node_st_vec.push(n.to_owned()); - } - }, - } - } - it.p.next().unwrap(); + let (a, _) = Self::stp(it, ev)?; + + expect_token( + TokenKind::RBrace, + ParseError::NotOpenedStmt(it.p.peek().unwrap().to_owned().to_owned()), + it, + )?; Ok((a, vec![])) } @@ -352,8 +344,7 @@ impl NodeArr { let mut c = beta(&mut n.to_owned().cond.unwrap(), &mut a); c = c.simplified(); - let if_stmts_a = - Self::parse_statement(it, a.imm_env_v.to_owned())?.0; + let if_stmts = Self::parse_statement(it, a.imm_env_v.to_owned())?.0; let mut _else_if_stmts: NodeArr = NodeArr::new(); match it.p.peek().unwrap().value { @@ -365,6 +356,15 @@ impl NodeArr { _ => (), }; + let if_stmts_isi = NodeSt::isi(if_stmts.ret_node_st); + let else_if_stmts_isi = NodeSt::isi(_else_if_stmts.ret_node_st); + + if if_stmts_isi != else_if_stmts_isi { + return Err(ParseError::NotMatchTypeAnotherOneOfStatement( + it.p.peek().unwrap().loc.to_owned(), + )); + } + match c.c.value { NodeKind::Num(num) => { if num == 0 { @@ -377,8 +377,7 @@ impl NodeArr { } } - a.node_st_vec - .append(&mut if_stmts_a.node_st_vec.to_owned()); + a.node_st_vec.append(&mut if_stmts.node_st_vec.to_owned()); } _ => { a.set_imm_env(); diff --git a/src/parser/error.rs b/src/parser/error.rs index e1ecd4e..63b22da 100644 --- a/src/parser/error.rs +++ b/src/parser/error.rs @@ -22,6 +22,7 @@ pub enum ParseError { UnusedVariable(Loc), NotMatchReturnType(Loc), UnexpectedUnderScoreOperator(Loc), + NotMatchTypeAnotherOneOfStatement(Loc), // UnexpectedToken(Token), // NotExpression(Token), // UnclosedOpenParen(Token), diff --git a/src/tests/parser/tests.rs b/src/tests/parser/tests.rs index dd73a44..7fab279 100644 --- a/src/tests/parser/tests.rs +++ b/src/tests/parser/tests.rs @@ -269,3 +269,64 @@ fn unexpected_under_score_operator_test() { }; assert!(n) } + +#[test] +fn type_match_another_one_of_statement_1_test() { + let mut t = Token::tokenize("fn { int i = 9; if (i) { i; _ } else { 3*4; _ } _ }").unwrap(); + let mut it = TokenIter::new(&mut t); + let n = match NodeArr::w_parser(&mut it, vec![]) { + Ok(_) => true, + Err(_) => false, + }; + assert!(n) +} + +// #[test] +// fn type_match_another_one_of_statement_2_test() { +// let mut t = Token::tokenize("fn { int i = 9; if (i) { i; 0; } else { 3*4; _ } _ }").unwrap(); +// let mut it = TokenIter::new(&mut t); +// let n = match NodeArr::w_parser(&mut it, vec![]) { +// Ok(_) => true, +// Err(_) => false +// }; +// assert!(n) +// } + +#[test] +fn type_match_another_one_of_statement_3_test() { + let mut t = Token::tokenize("fn { int i = 9; if (i) { i; 0 } else { 3*4; 3 } _ }").unwrap(); + let mut it = TokenIter::new(&mut t); + let n = match NodeArr::w_parser(&mut it, vec![]) { + Ok(_) => true, + Err(_) => false, + }; + assert!(n) +} + +#[test] +fn type_not_match_another_one_of_statement_1_test() { + let mut t = Token::tokenize("fn { int i = 9; if (i) { i; _ } else { 3*4; 2; } _ }").unwrap(); + let mut it = TokenIter::new(&mut t); + let n = match NodeArr::w_parser(&mut it, vec![]) { + Ok(_) => false, + Err(e) => match e { + ParseError::NotMatchTypeAnotherOneOfStatement(_) => true, + _ => false, + }, + }; + assert!(n) +} + +// #[test] +// fn type_not_match_another_one_of_statement_2_test() { +// let mut t = Token::tokenize("fn { int i = 9; if (i) { i; 0 } else { 3*4; 2; } _ }").unwrap(); +// let mut it = TokenIter::new(&mut t); +// let n = match NodeArr::w_parser(&mut it, vec![]) { +// Ok(_) => false, +// Err(e) => match e { +// ParseError::NotMatchTypeAnotherOneOfStatement(_) => true, +// _ => false, +// }, +// }; +// assert!(n) +// } diff --git a/test.sh b/test.sh index 2da7bff..54c47ca 100644 --- a/test.sh +++ b/test.sh @@ -158,7 +158,8 @@ assert_llvm 34 'fn int { int _u = 8; int a = 2; 4+2*a*_u-2 }' assert_llvm 1 'fn int { int i = 1; if (i) { 0 } else { 0 } i }' assert_llvm 0 'fn { if (2 == 3) { 1; 2; } else { 3; 4; } _ }' assert_llvm 0 'fn { int i = 9; if (i) { 1; 2; } else { 3*4; 5; } _ }' -assert_llvm 0 'fn { int i = 9; if (i) { i; 2; } else { 3*4; 5; } _ }' +assert_llvm 0 'fn { int i = 9; if (i) { i; 2 } else { 3*4; 5 } _ }' +assert_llvm 0 'fn { int i = 9; if (i) { i; _ } else { 3*4; _ } _ }' echo "------------------------------" echo "All llvm test passed!\n"