diff --git a/src/parser.rs b/src/parser.rs index 3f4c1db..c3e16a0 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,3 +1,24 @@ +use std::cell::RefCell; +use std::rc::Rc; +use nom::branch::alt; +use nom::combinator::map; +use nom::IResult; +use nom::multi::many1; +use crate::parser::grammar_parser::{function_declaration_parser, value_declaration_parser}; +use crate::parser::syntax_tree::SyntaxNode; +use crate::tokenizer::LexicalTokenSpan; + mod syntax_tree; mod grammar_parser; +pub fn compiler_unit_parser(cursor: LexicalTokenSpan) -> IResult>> { + map( + many1(alt(( + value_declaration_parser, + function_declaration_parser + ))), + |blocks| { + SyntaxNode::block(&blocks) + } + )(cursor) +} \ No newline at end of file diff --git a/src/parser/grammar_parser.rs b/src/parser/grammar_parser.rs index c3ef659..fb8a090 100644 --- a/src/parser/grammar_parser.rs +++ b/src/parser/grammar_parser.rs @@ -1,8 +1,8 @@ -use crate::parser::syntax_tree::{BinaryNodeType, SyntaxNode, UnaryNodeType}; +use crate::parser::syntax_tree::{BasicTypes, BinaryNodeType, InitializerNode, SyntaxNode, UnaryNodeType}; use crate::tokenizer::{LexicalTokenSpan, LexicalTokenType}; use nom::branch::alt; use nom::combinator::{map, opt}; -use nom::multi::{many0, separated_list0}; +use nom::multi::{many0, separated_list0, separated_list1}; use nom::sequence::tuple; use nom::IResult; use std::cell::RefCell; @@ -510,6 +510,7 @@ fn block_parser(cursor: LexicalTokenSpan) -> IResult IResult IResult>> { + alt(( + map( + tuple(( + lexical!(Delimiter("{")), + separated_list0(lexical!(Delimiter(",")), value_initializer_parser), + lexical!(Delimiter("}")) + )), + |(_, initializers, _)| { + InitializerNode::array(initializers) + }, + ), + map( + expression_parser, + |expression| { + InitializerNode::single(expression) + }, + ) + ))(cursor) +} + +type ValueDefinitionParseType<'a> = (Rc>, Vec<(LexicalTokenSpan<'a>, Rc>, LexicalTokenSpan<'a>)>); + +type InitializedValueDefinitionParseType<'a> = (Rc>, Vec<(LexicalTokenSpan<'a>, Rc>, + LexicalTokenSpan<'a>)>, LexicalTokenSpan<'a>, Rc>); +fn value_definition_parser(cursor: LexicalTokenSpan) -> IResult>> { + alt(( + map( + tuple(( + identifier_parser, + many0( + tuple(( + lexical!(Delimiter("[")), + expression_parser, + lexical!(Delimiter("]")) + )) + ), + lexical!(Operator("=")), + value_initializer_parser + )), + |(identifier, indexers, _, initializer): InitializedValueDefinitionParseType| { + SyntaxNode::initialized_value_definition( + &identifier, + indexers.iter().map(|p| &p.1), + &initializer, + ) + }, + ), + map(tuple(( + identifier_parser, + many0(tuple(( + lexical!(Delimiter("[")), + expression_parser, + lexical!(Delimiter("]")) + ))) + )), + |(identifier, indexers): ValueDefinitionParseType| { + SyntaxNode::value_definition( + &identifier, + indexers.iter().map(|p| &p.1), + ) + }, + ) + ))(cursor) +} + +fn basic_type_parser(cursor: LexicalTokenSpan) -> IResult { + alt(( + map( + lexical!(Keyword("void")), + |_| { + BasicTypes::Void + }, + ), + map( + lexical!(Keyword("int")), + |_| { + BasicTypes::Integer + }, + ), + map( + lexical!(Keyword("float")), + |_| { + BasicTypes::Float + }, + ) + ))(cursor) +} + +pub fn value_declaration_parser(cursor: LexicalTokenSpan) -> IResult>> { + alt(( + map( + tuple(( + lexical!(Keyword("const")), + basic_type_parser, + separated_list1(lexical!(Delimiter(",")), value_definition_parser), + lexical!(Delimiter(";")) + )), + |(_, basic_type, definitions, _)| { + SyntaxNode::value_declaration( + true, + basic_type, + &definitions, + ) + }, + ), + map( + tuple(( + basic_type_parser, + separated_list1(lexical!(Delimiter(",")), value_definition_parser), + lexical!(Delimiter(";")) + )), + |(basic_type, definitions, _)| { + SyntaxNode::value_declaration( + false, + basic_type, + &definitions, + ) + }, + ) + ))(cursor) +} + +type FunctionParameterParseResult<'a> = (BasicTypes, + Rc>, + Option<(LexicalTokenSpan<'a>, + LexicalTokenSpan<'a>, + Vec<(LexicalTokenSpan<'a>, Rc>, LexicalTokenSpan<'a>)>)>); +fn function_parameter_parser(cursor: LexicalTokenSpan) -> IResult>> { + map( + tuple(( + basic_type_parser, + identifier_parser, + opt(tuple(( + lexical!(Delimiter("[")), + lexical!(Delimiter("]")), + many0(tuple(( + lexical!(Delimiter("[")), + expression_parser, + lexical!(Delimiter("]")), + ))) + ))) + )), + |(basic_type, identifier, indexers): FunctionParameterParseResult| { + let parameters = if let Some(indexers) = indexers { + let mut result = vec![SyntaxNode::unit()]; + + for indexer in indexers.2 { + result.push(Rc::clone(&indexer.1)); + } + + result + } else { + vec![] + }; + + SyntaxNode::function_parameter(basic_type, &identifier, ¶meters) + }, + )(cursor) +} + + +pub fn function_declaration_parser(cursor: LexicalTokenSpan) -> IResult>> { + map( + tuple(( + basic_type_parser, + identifier_parser, + lexical!(Delimiter("(")), + separated_list0(lexical!(Delimiter(",")), function_parameter_parser), + lexical!(Delimiter(")")), + block_parser + )), + |(basic_type, identifier, _, parameters, _, block)| { + SyntaxNode::function_declaration( + basic_type, + &identifier, + ¶meters, + &block, + ) + }, + )(cursor) +} + #[cfg(test)] mod test { use super::*; @@ -801,7 +985,7 @@ mod test { &SyntaxNode::assign_statement(&SyntaxNode::identifier("i".to_owned()), &SyntaxNode::const_integer(1)), ); - + validate_syntax_node("if (i == 1) i = 2; else i = 1;", &node.borrow().node_type, if_statement_parser); validate_syntax_node("if (i == 1) i = 2; else i = 1;", &node.borrow().node_type, statement_parser); @@ -810,13 +994,13 @@ mod test { &SyntaxNode::identifier("i".to_owned()), &SyntaxNode::const_integer(1)), &SyntaxNode::assign_statement(&SyntaxNode::identifier("i".to_owned()), &SyntaxNode::const_integer(2)), - &SyntaxNode::unit() + &SyntaxNode::unit(), ); validate_syntax_node("if (i == 1) i = 2;", &node.borrow().node_type, if_statement_parser); validate_syntax_node("if (i == 1) i = 2;", &node.borrow().node_type, statement_parser); } - + #[test] fn multiplx_if_statement_test() { let node = SyntaxNode::if_statement( @@ -824,33 +1008,33 @@ mod test { &SyntaxNode::identifier("i".to_owned()), &SyntaxNode::const_integer(1)), &SyntaxNode::if_statement( &SyntaxNode::binary_node(BinaryNodeType::Equal, - &SyntaxNode::identifier("i".to_owned()), &SyntaxNode::const_integer(2)), + &SyntaxNode::identifier("i".to_owned()), &SyntaxNode::const_integer(2)), &SyntaxNode::assign_statement(&SyntaxNode::identifier("i".to_owned()), &SyntaxNode::const_integer(2)), &SyntaxNode::assign_statement(&SyntaxNode::identifier("i".to_owned()), - &SyntaxNode::const_integer(1)) + &SyntaxNode::const_integer(1)), ), - &SyntaxNode::unit() + &SyntaxNode::unit(), ); validate_syntax_node("if (i == 1) if (i == 2) i = 2; else i = 1;", &node.borrow().node_type, if_statement_parser); validate_syntax_node("if (i == 1) if (i == 2) i = 2; else i = 1;", &node.borrow().node_type, statement_parser); } - + #[test] fn while_statement_test() { let node = SyntaxNode::while_statement( &SyntaxNode::binary_node(BinaryNodeType::NotEqual, - &SyntaxNode::identifier("i".to_owned()), - &SyntaxNode::const_integer(10)), + &SyntaxNode::identifier("i".to_owned()), + &SyntaxNode::const_integer(10)), &SyntaxNode::assign_statement( &SyntaxNode::identifier("i".to_owned()), &SyntaxNode::binary_node(BinaryNodeType::Add, - &SyntaxNode::identifier("i".to_owned()), - &SyntaxNode::const_integer(1)) - ) + &SyntaxNode::identifier("i".to_owned()), + &SyntaxNode::const_integer(1)), + ), ); - + validate_syntax_node("while (i != 10 ) i = i + 1;", &node.borrow().node_type, while_statement_parser); validate_syntax_node("while (i != 10 ) i = i + 1;", &node.borrow().node_type, statement_parser); } @@ -870,23 +1054,152 @@ mod test { validate_syntax_node("continue;", &node.borrow().node_type, continue_statement_parser); validate_syntax_node("continue;", &node.borrow().node_type, statement_parser); } - + #[test] fn return_statement_test() { let node = SyntaxNode::return_statement( &SyntaxNode::binary_node(BinaryNodeType::Add, - &SyntaxNode::const_integer(1), - &SyntaxNode::const_integer(1)) + &SyntaxNode::const_integer(1), + &SyntaxNode::const_integer(1)) ); - + validate_syntax_node("return 1 + 1;", &node.borrow().node_type, return_statement_parser); validate_syntax_node("return 1 + 1;", &node.borrow().node_type, statement_parser); - + let node = SyntaxNode::return_statement( &SyntaxNode::unit() ); - + validate_syntax_node("return;", &node.borrow().node_type, return_statement_parser); validate_syntax_node("return;", &node.borrow().node_type, statement_parser); } + + #[test] + fn value_initializer_test() { + let initializer = InitializerNode::single(SyntaxNode::const_integer(1)); + let (_, tokens) = lexical_parser("1").unwrap(); + let (_, node) = value_initializer_parser((&tokens).into()).unwrap(); + assert_eq!(initializer, node); + + let initializer = InitializerNode::array(vec![InitializerNode::single(SyntaxNode::const_integer(1)), + InitializerNode::single(SyntaxNode::const_integer(2))]); + let (_, tokens) = lexical_parser("{1, 2}").unwrap(); + let (_, node) = value_initializer_parser((&tokens).into()).unwrap(); + assert_eq!(initializer, node); + } + + #[test] + fn value_definition_test() { + let node = SyntaxNode::initialized_value_definition( + &SyntaxNode::identifier("i".to_owned()), + vec![], + &InitializerNode::single(SyntaxNode::const_integer(1)), + ); + validate_syntax_node("i = 1", &node.borrow().node_type, value_definition_parser); + + let node = SyntaxNode::value_definition( + &SyntaxNode::identifier("array".to_owned()), + vec![ + SyntaxNode::const_integer(100), + SyntaxNode::const_integer(10) + ].iter(), + ); + validate_syntax_node("array[100][10]", &node.borrow().node_type, value_definition_parser); + + let node = SyntaxNode::initialized_value_definition( + &SyntaxNode::identifier("test".to_owned()), + vec![ + SyntaxNode::const_integer(3) + ].iter(), + &InitializerNode::array(vec![ + InitializerNode::single(SyntaxNode::const_integer(1)), + InitializerNode::single(SyntaxNode::const_integer(2)), + InitializerNode::single(SyntaxNode::const_integer(3)), + ]), + ); + validate_syntax_node("test[3] = {1,2,3}", &node.borrow().node_type, value_definition_parser); + } + + #[test] + fn value_declaration_test() { + let node1 = SyntaxNode::initialized_value_definition( + &SyntaxNode::identifier("i".to_owned()), + vec![], + &InitializerNode::single(SyntaxNode::const_integer(1)), + ); + let node2 = SyntaxNode::value_definition( + &SyntaxNode::identifier("array".to_owned()), + vec![ + SyntaxNode::const_integer(100), + SyntaxNode::const_integer(10) + ].iter(), + ); + let node = SyntaxNode::value_declaration( + false, + BasicTypes::Integer, + &vec![node1, node2], + ); + validate_syntax_node("int i = 1, array[100][10];", &node.borrow().node_type, value_declaration_parser); + + + let node = SyntaxNode::initialized_value_definition( + &SyntaxNode::identifier("test".to_owned()), + vec![ + SyntaxNode::const_integer(3) + ].iter(), + &InitializerNode::array(vec![ + InitializerNode::single(SyntaxNode::const_float(1f32)), + InitializerNode::single(SyntaxNode::const_float(2f32)), + InitializerNode::single(SyntaxNode::const_float(3f32)), + ]), + ); + let node = SyntaxNode::value_declaration( + true, + BasicTypes::Float, + &vec![node], + ); + validate_syntax_node("const float test[3] = {1.0,2.0,3.0};", &node.borrow().node_type, value_declaration_parser); + } + + #[test] + fn function_parameter_test() { + let node = SyntaxNode::function_parameter(BasicTypes::Integer, + &SyntaxNode::identifier("a".to_owned()), &vec![]); + validate_syntax_node("int a", &node.borrow().node_type, function_parameter_parser); + + let node = SyntaxNode::function_parameter(BasicTypes::Float, + &SyntaxNode::identifier("array".to_owned()), &vec![SyntaxNode::unit()]); + validate_syntax_node("float array[]", &node.borrow().node_type, function_parameter_parser); + + let node = SyntaxNode::function_parameter(BasicTypes::Integer, + &SyntaxNode::identifier("array".to_owned()), + &vec![SyntaxNode::unit(), SyntaxNode::const_integer(10)]); + validate_syntax_node("int array[][10]", &node.borrow().node_type, function_parameter_parser); + } + + #[test] + fn function_declaration_test() { + let node = SyntaxNode::function_declaration( + BasicTypes::Void, + &SyntaxNode::identifier("test".to_owned()), + &vec![], + &SyntaxNode::block(&vec![ + SyntaxNode::assign_statement(&SyntaxNode::identifier("a".to_owned()), &SyntaxNode::const_integer(1)) + ]), + ); + validate_syntax_node("void test()\ + {\ + a = 1;\ + }", &node.borrow().node_type, function_declaration_parser); + + let node = SyntaxNode::function_declaration( + BasicTypes::Integer, + &SyntaxNode::identifier("empty".to_owned()), + &vec![ + SyntaxNode::function_parameter(BasicTypes::Integer, &SyntaxNode::identifier("a".to_owned()), &vec![]) + ], + &SyntaxNode::block(&vec![]) + ); + validate_syntax_node("int empty(int a) {}", &node.borrow().node_type, function_declaration_parser); + } } \ No newline at end of file diff --git a/src/parser/syntax_tree.rs b/src/parser/syntax_tree.rs index e3bbff4..c8bbda2 100644 --- a/src/parser/syntax_tree.rs +++ b/src/parser/syntax_tree.rs @@ -1,6 +1,6 @@ use std::cell::RefCell; use std::rc::Rc; -use nom::IResult; +use crate::parser::syntax_tree::SyntaxNodeType::FunctionParameter; /// 单元表达式类型 #[derive(Debug, PartialEq)] @@ -50,13 +50,6 @@ pub struct FunctionCallNode { pub arguments: Vec>>, } -#[derive(Debug, PartialEq)] -pub enum BasicTypes { - Void, - Integer, - Float, -} - #[derive(Debug, PartialEq)] pub struct IfStatementNode { pub condition: Rc>, @@ -76,6 +69,58 @@ pub struct AssignStatmentNode { pub expression: Rc>, } +#[derive(Debug, PartialEq)] +pub enum BasicTypes { + Void, + Integer, + Float, +} + +#[derive(Debug, PartialEq)] +pub enum InitializerNode { + Single(Rc>), + Array(Vec>>), +} + +impl InitializerNode { + pub fn single(node: Rc>) -> Rc> { + Rc::new(RefCell::new(Self::Single(node))) + } + + pub fn array(nodes: Vec>>) -> Rc> { + Rc::new(RefCell::new(Self::Array(nodes))) + } +} + +#[derive(Debug, PartialEq)] +pub struct ValueDefinitionNode { + pub identifier: Rc>, + pub indexers: Vec>>, + pub initialzier: Option>>, +} + +#[derive(Debug, PartialEq)] +pub struct ValueDeclarationNode { + pub is_constant: bool, + pub value_type: BasicTypes, + pub definitions: Vec>>, +} + +#[derive(Debug, PartialEq)] +pub struct FunctionParameterNode { + pub parameter_type: BasicTypes, + pub identifier: Rc>, + pub indexers: Vec>>, +} + +#[derive(Debug, PartialEq)] +pub struct FunctionDeclarationNode { + pub function_type: BasicTypes, + pub identifier: Rc>, + pub parameters: Vec>>, + pub block: Rc>, +} + /// 语法分析树节点类型 #[derive(Debug, PartialEq)] pub enum SyntaxNodeType { @@ -96,7 +141,10 @@ pub enum SyntaxNodeType { ExpressionStatement(Rc>), ReturnStatement(Rc>), Block(Vec>>), - BasicTypeNode(BasicTypes), + ValueDefinition(ValueDefinitionNode), + ValueDeclaration(ValueDeclarationNode), + FunctionParameter(FunctionParameterNode), + FunctionDeclaration(FunctionDeclarationNode), } /// 语法分析器节点 @@ -180,7 +228,7 @@ impl SyntaxNode { node_type: SyntaxNodeType::ReturnStatement(Rc::clone(expression)) })) } - + pub fn unit() -> Rc> { Rc::new(RefCell::new(Self { node_type: SyntaxNodeType::Unit @@ -192,39 +240,101 @@ impl SyntaxNode { node_type: SyntaxNodeType::BreakNode })) } - + pub fn continue_statement() -> Rc> { Rc::new(RefCell::new(Self { node_type: SyntaxNodeType::ContinueNode })) } - - pub fn if_statement(condition: &Rc>, - if_statement: &Rc>, + + pub fn if_statement(condition: &Rc>, + if_statement: &Rc>, else_statement: &Rc>) -> Rc> { Rc::new(RefCell::new(Self { node_type: SyntaxNodeType::IfStatement(IfStatementNode { condition: Rc::clone(condition), if_statement: Rc::clone(if_statement), - else_statement: Rc::clone(else_statement) + else_statement: Rc::clone(else_statement), }) })) } - + pub fn while_statement(condition: &Rc>, statement: &Rc>) -> Rc> { Rc::new(RefCell::new(Self { node_type: SyntaxNodeType::WhileStatement(WhileStatmentNode { condition: Rc::clone(condition), - statement: Rc::clone(statement) + statement: Rc::clone(statement), }) })) } - + pub fn block(statements: &Vec>>) -> Rc> { Rc::new(RefCell::new(Self { node_type: SyntaxNodeType::Block(statements.iter().map(|x| Rc::clone(x)).collect()) })) } - - + + pub fn value_definition<'a, T>(identifier: &Rc>, indexers: T) -> Rc> + where + T: IntoIterator>>, + { + Rc::new(RefCell::new(Self { + node_type: SyntaxNodeType::ValueDefinition(ValueDefinitionNode { + identifier: Rc::clone(identifier), + indexers: indexers.into_iter().map(|x| Rc::clone(x)).collect(), + initialzier: None, + }) + })) + } + + pub fn initialized_value_definition<'a, T>(identifier: &Rc>, + indexers: T, + initializer: &Rc>) -> Rc> + where + T: IntoIterator>>, + { + Rc::new(RefCell::new(Self { + node_type: SyntaxNodeType::ValueDefinition(ValueDefinitionNode { + identifier: Rc::clone(identifier), + indexers: indexers.into_iter().map(|x| Rc::clone(x)).collect(), + initialzier: Some(Rc::clone(initializer)), + }) + })) + } + + pub fn value_declaration(is_constant: bool, value_type: BasicTypes, definitions: &Vec>>) -> Rc> { + Rc::new(RefCell::new(Self { + node_type: SyntaxNodeType::ValueDeclaration(ValueDeclarationNode { + is_constant, + value_type, + definitions: definitions.iter().map(|x| Rc::clone(x)).collect(), + }) + })) + } + + pub fn function_parameter(parameter_type: BasicTypes, + identifier: &Rc>, + indexers: &Vec>>) -> Rc> { + Rc::new(RefCell::new(Self { + node_type: FunctionParameter(FunctionParameterNode { + parameter_type, + identifier: Rc::clone(identifier), + indexers: indexers.iter().map(|x| Rc::clone(x)).collect(), + }) + })) + } + + pub fn function_declaration(function_type: BasicTypes, + identifier: &Rc>, + parameters: &Vec>>, + block: &Rc>) -> Rc> { + Rc::new(RefCell::new(Self { + node_type: SyntaxNodeType::FunctionDeclaration(FunctionDeclarationNode { + function_type, + identifier: Rc::clone(identifier), + parameters: parameters.iter().map(|x| Rc::clone(x)).collect(), + block: Rc::clone(block), + }) + })) + } } \ No newline at end of file diff --git a/tests/grammar_tests.rs b/tests/grammar_tests.rs new file mode 100644 index 0000000..e9161d5 --- /dev/null +++ b/tests/grammar_tests.rs @@ -0,0 +1,419 @@ +use nom::InputLength; +use rustic_sysy::parser::compiler_unit_parser; +use rustic_sysy::tokenizer::lexical_parser; + +fn parse_grammar(input: &'static str) { + let (_, tokens) = lexical_parser(input).unwrap(); + let (remaining, node) = compiler_unit_parser((&tokens).into()).unwrap(); + dbg!(node); + + assert_eq!(0, remaining.input_len()); +} + +#[test] +fn main_test() { + parse_grammar(r"int main(){ + return 3; +}"); +} + +#[test] +fn value_definition_test() { + parse_grammar(r"//test domain of global var define and local define +int a = 3; +int b = 5; + +int main(){ + int a = 5; + return a + b; +}"); + + parse_grammar(r"//test local var define +int main(){ + int a, b0, _c; + a = 1; + b0 = 2; + _c = 3; + return b0 + _c; +}"); + + parse_grammar(r"//test const gloal var define +const int a = 10, b = 5; + +int main(){ + return b; +}"); + + parse_grammar(r"//test const local var define +int main(){ + const int a = 10, b = 5; + return b; +}"); +} + +#[test] +fn array_definition_test() { + parse_grammar(r"int a[10][10]; +int main(){ + return 0; +}"); + + parse_grammar(r"//test array define +int main(){ + int a[4][2] = {}; + int b[4][2] = {1, 2, 3, 4, 5, 6, 7, 8}; + int c[4][2] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}}; + int d[4][2] = {1, 2, {3}, {5}, 7 , 8}; + int e[4][2] = {{d[2][1], c[2][1]}, {3, 4}, {5, 6}, {7, 8}}; + return e[3][1] + e[0][0] + e[0][1] + a[2][0]; +}"); + + parse_grammar(r"int main(){ + const int a[4][2] = {{1, 2}, {3, 4}, {}, 7}; + const int N = 3; + int b[4][2] = {}; + int c[4][2] = {1, 2, 3, 4, 5, 6, 7, 8}; + int d[N + 1][2] = {1, 2, {3}, {5}, a[3][0], 8}; + int e[4][2][1] = {{d[2][1], {c[2][1]}}, {3, 4}, {5, 6}, {7, 8}}; + return e[3][1][0] + e[0][0][0] + e[0][1][0] + d[3][0]; +}"); +} + +#[test] +fn operator_priority_test() { + parse_grammar(r"//test the priority of add and mul +int main(){ + int a, b, c, d; + a = 10; + b = 4; + c = 2; + d = 2; + return c + a * b - d; +}"); + + parse_grammar(r"//test the priority of add and mul +int main(){ + int a, b, c, d; + a = 10; + b = 4; + c = 2; + d = 2; + return (c + a) * (b - d); +}"); + + parse_grammar(r"//test the priority of unary operator and binary operator +int main(){ + int a, b; + a = 10; + b = 30; + return a - -5 + b + -5; +}"); +} + +#[test] +fn statement_test() { + parse_grammar(r"int k; +const int n = 10; +int main () { + int i = 0; + k = 1; + while (i <= n - 1) { + i = i + 1; + k + 1; + k = k + k; + } + putint(k); + return k; +}"); + + parse_grammar(r"// test if-else-if +int ifElseIf() { + int a; + a = 5; + int b; + b = 10; + if(a == 6 || b == 0xb) { + return a; + } + else { + if (b == 10 && a == 1) + a = 25; + else if (b == 10 && a == -5) + a = a + 15; + else + a = -+a; + } + + return a; +} + +int main(){ + putint(ifElseIf()); + return 0; +}"); + + parse_grammar(r"// test if-if-else +int ififElse() { + int a; + a = 5; + int b; + b = 10; + if(a == 5) + if (b == 10) + a = 25; + else + a = a + 15; + + return (a); +} + +int main(){ + return (ififElse()); +}"); + + parse_grammar(r"// test if-{if-else} +int if_ifElse_() { + int a; + a = 5; + int b; + b = 10; + if(a == 5){ + if (b == 10) + a = 25; + else + a = a + 15; + } + return (a); +} + +int main(){ + return (if_ifElse_()); +}"); + + parse_grammar(r"// test while-if +int whileIf() { + int a; + a = 0; + int b; + b = 0; + while (a < 100) { + if (a == 5) { + b = 25; + } + else if (a == 10) { + b = 42; + } + else { + b = a * 2; + } + a = a + 1; + } + return (b); +} + + +int main(){ + return (whileIf()); +}"); + + parse_grammar(r"int deepWhileBr(int a, int b) { + int c; + c = a + b; + while (c < 75) { + int d; + d = 42; + if (c < 100) { + c = c + d; + if (c > 99) { + int e; + e = d * 2; + if (1 == 1) { + c = e * 2; + } + } + } + } + return (c); +} + +int main() { + int p; + p = 2; + return deepWhileBr(p, p); +}"); +} + +#[test] +fn dijkstra_test() { + parse_grammar(r"const int INF = 65535; +int e[16][16]; +int book[16]; +int dis[16]; +int n, m; +int v1, v2, w; + +void Dijkstra() +{ + int i, j; + + i = 1; + while (i <= n) { + dis[i] = e[1][i]; + book[i] = 0; + i = i + 1; + } + book[1] = 1; + + i = 1; + while (i <= n - 1) { + int min_num = INF; + int min_index = 0; + int k = 1; + while (k <= n) { + if (min_num > dis[k] && book[k] == 0) { + min_num = dis[k]; + min_index = k; + } + k = k + 1; + } + book[min_index] = 1; + int j = 1; + while (j <= n) { + if (e[min_index][j] < INF) { + if (dis[j] > dis[min_index] + e[min_index][j]) { + dis[j] = dis[min_index] + e[min_index][j]; + } + } + j = j + 1; + } + i = i + 1; + } +} + +int main() +{ + int i; + n = getint(); + m = getint(); + + i = 1; + while (i <= n) { + int j = 1; + while (j <= n) { + if (i == j) + e[i][j] = 0; + else + e[i][j] = INF; + j = j + 1; + } + i = i + 1; + } + + i = 1; + while (i <= m) { + int u = getint(), v = getint(); + e[u][v] = getint(); + i = i + 1; + } + + Dijkstra(); + + i = 1; + while (i <= n) { + putint(dis[i]); + putch(32); + i = i + 1; + } + putch(10); + return 0; +}"); +} + +#[test] +fn sort_test() { + parse_grammar(r"int n; +int bubblesort(int arr[]) +{ + int i; + int j; + i =0; + while(i < n-1){ + // Last i elements are already in place + j = 0; + while(j < n-i-1){ + if (arr[j] > arr[j+1]) { + // swap(&arr[j], &arr[j+1]); + int tmp; + tmp = arr[j+1]; + arr[j+1] = arr[j]; + arr[j] = tmp; + } + j = j + 1; + } + i = i + 1; + } + return 0; +} + +int main(){ + n = 10; + int a[10]; + a[0]=4;a[1]=3;a[2]=9;a[3]=2;a[4]=0; + a[5]=1;a[6]=6;a[7]=5;a[8]=7;a[9]=8; + int i; + i = bubblesort(a); + while (i < n) { + int tmp; + tmp = a[i]; + putint(tmp); + tmp = 10; + putch(tmp); + i = i + 1; + } + return 0; +}"); + + parse_grammar(r"int n; +int insertsort(int a[]) +{ + int i; + i = 1; + while(i-1&&temp