From 08eb97cf38bdaca2ec58755a8b5ae325a6f38ec3 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Thu, 7 Apr 2022 20:48:38 +0200 Subject: [PATCH] Support constructor func calls, more integration tests --- Cargo.toml | 2 +- src/integration_tests/add_function.rs | 5 +- src/integration_tests/build.rs | 4 +- .../class_with_many_statements.rs | 77 +++++++++++++++++++ .../empty_class_declaration.rs | 4 +- src/integration_tests/enum_definition.rs | 4 +- src/integration_tests/mod.rs | 1 + .../multiple_inheritance_class.rs | 4 +- .../test_cases/add_function/parsed_tree.json | 1 + .../class_with_many_statements/script.ses | 21 +++++ src/parsing/parser/mod.rs | 28 +++++-- src/parsing/parser/parsed_statement.rs | 1 + 12 files changed, 135 insertions(+), 17 deletions(-) create mode 100644 src/integration_tests/class_with_many_statements.rs create mode 100644 src/integration_tests/test_cases/class_with_many_statements/script.ses diff --git a/Cargo.toml b/Cargo.toml index 28f1f18..7249fd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,4 +24,4 @@ debug = true opt-level = 3 [profile.dev] -opt-level = 1 \ No newline at end of file +opt-level = 0 \ No newline at end of file diff --git a/src/integration_tests/add_function.rs b/src/integration_tests/add_function.rs index 84feaae..bdeaf99 100644 --- a/src/integration_tests/add_function.rs +++ b/src/integration_tests/add_function.rs @@ -20,7 +20,7 @@ fn integration_add_function() { return a + b; }"; let lexed_tokens = lex(script, &mut panic_on_error); - println!("{}", serde_json::to_string(&lexed_tokens).unwrap()); + println!("Lexed tokens JSON: {}", serde_json::to_string(&lexed_tokens).unwrap()); let expected_tokens: Vec = serde_json::from_str(r#"[ { @@ -254,7 +254,7 @@ fn integration_add_function() { assert_eq!(lexed_tokens, expected_tokens); let parsed_tree = parse(lexed_tokens, &mut panic_on_error); - println!("{}", serde_json::to_string(&parsed_tree).unwrap()); + println!("Parsed Tree JSON: {}", serde_json::to_string(&parsed_tree).unwrap()); let expected_tree: Box = serde_json::from_str(r#"{ "Script": { @@ -264,6 +264,7 @@ fn integration_add_function() { "modifiers": 0, "field_mod": null, "is_destructor": false, + "is_constructor": false, "returns_reference": false, "return_type": { "Type": { diff --git a/src/integration_tests/build.rs b/src/integration_tests/build.rs index 65932d2..196d1c3 100644 --- a/src/integration_tests/build.rs +++ b/src/integration_tests/build.rs @@ -68,7 +68,7 @@ fn panic_on_error(msg: Message, _: Span) {{ fn integration_{name}() {{ let script = "{script}"; let lexed_tokens = lex(script, &mut panic_on_error); - println!("{{}}", serde_json::to_string(&lexed_tokens).unwrap()); + println!("Lexed tokens JSON: {{}}", serde_json::to_string(&lexed_tokens).unwrap()); "#, name = test_name, script = script.as_str() @@ -94,7 +94,7 @@ fn integration_{name}() {{ testfile, r##" let parsed_tree = parse(lexed_tokens, &mut panic_on_error); - println!("{{}}", serde_json::to_string(&parsed_tree).unwrap()); + println!("Parsed Tree JSON: {{}}", serde_json::to_string(&parsed_tree).unwrap()); "## ) .unwrap(); diff --git a/src/integration_tests/class_with_many_statements.rs b/src/integration_tests/class_with_many_statements.rs new file mode 100644 index 0000000..4f8b683 --- /dev/null +++ b/src/integration_tests/class_with_many_statements.rs @@ -0,0 +1,77 @@ +//////////////////////////// +// Automatically Generated// +//////////////////////////// +use crate::logger::messages::Message; +use crate::parsing::lexer::lex; +use crate::parsing::lexer::lex_tokens::LexToken; +use crate::parsing::parser::parse; +use crate::parsing::parser::parsed_statement::ParsedStatement; +use crate::span::Span; + +fn ignore_error(_msg: Message, _: Span) { +} + +fn panic_on_error(msg: Message, _: Span) { + std::panic::panic_any(msg.stringify()); +} +#[test] +fn integration_class_with_many_statements() { + let script = "final shared class Foobar { + int _a; + int _b; + + Foobar(int a, int b) { + _a = a; + _b = b; + } + + int GetA(){ + return _a; + } + + int Add() { + return _a + _b; + } + + class Inner { + int a; + } +}"; + let lexed_tokens = lex(script, &mut panic_on_error); + println!("Lexed tokens JSON: {}", serde_json::to_string(&lexed_tokens).unwrap()); + + let parsed_tree = parse(lexed_tokens, &mut panic_on_error); + println!("Parsed Tree JSON: {}", serde_json::to_string(&parsed_tree).unwrap()); +} +// A substring of a script should never panic, even though it might be completely invalid. +#[test] +fn integration_class_with_many_statements_substring() { + let mut script = "final shared class Foobar { + int _a; + int _b; + + Foobar(int a, int b) { + _a = a; + _b = b; + } + + int GetA(){ + return _a; + } + + int Add() { + return _a + _b; + } + + class Inner { + int a; + } +}".to_string(); + for _ in 0..script.len() { + script.pop(); + let lexed_tokens = lex(script.as_str(), &mut ignore_error); + let _parsed_tree = parse(lexed_tokens, &mut ignore_error); + } + +} + \ No newline at end of file diff --git a/src/integration_tests/empty_class_declaration.rs b/src/integration_tests/empty_class_declaration.rs index 5fe8482..93af9e8 100644 --- a/src/integration_tests/empty_class_declaration.rs +++ b/src/integration_tests/empty_class_declaration.rs @@ -18,7 +18,7 @@ fn panic_on_error(msg: Message, _: Span) { fn integration_empty_class_declaration() { let script = "class Foo {}"; let lexed_tokens = lex(script, &mut panic_on_error); - println!("{}", serde_json::to_string(&lexed_tokens).unwrap()); + println!("Lexed tokens JSON: {}", serde_json::to_string(&lexed_tokens).unwrap()); let expected_tokens: Vec = serde_json::from_str(r#"[ { @@ -76,7 +76,7 @@ fn integration_empty_class_declaration() { assert_eq!(lexed_tokens, expected_tokens); let parsed_tree = parse(lexed_tokens, &mut panic_on_error); - println!("{}", serde_json::to_string(&parsed_tree).unwrap()); + println!("Parsed Tree JSON: {}", serde_json::to_string(&parsed_tree).unwrap()); let expected_tree: Box = serde_json::from_str(r#"{ "Script": { diff --git a/src/integration_tests/enum_definition.rs b/src/integration_tests/enum_definition.rs index 8340c2c..9a2178b 100644 --- a/src/integration_tests/enum_definition.rs +++ b/src/integration_tests/enum_definition.rs @@ -24,7 +24,7 @@ fn integration_enum_definition() { e }"; let lexed_tokens = lex(script, &mut panic_on_error); - println!("{}", serde_json::to_string(&lexed_tokens).unwrap()); + println!("Lexed tokens JSON: {}", serde_json::to_string(&lexed_tokens).unwrap()); let expected_tokens: Vec = serde_json::from_str(r#"[ { @@ -395,7 +395,7 @@ fn integration_enum_definition() { assert_eq!(lexed_tokens, expected_tokens); let parsed_tree = parse(lexed_tokens, &mut panic_on_error); - println!("{}", serde_json::to_string(&parsed_tree).unwrap()); + println!("Parsed Tree JSON: {}", serde_json::to_string(&parsed_tree).unwrap()); let expected_tree: Box = serde_json::from_str(r#"{ "Script": { diff --git a/src/integration_tests/mod.rs b/src/integration_tests/mod.rs index 1693cd0..91f9dd1 100644 --- a/src/integration_tests/mod.rs +++ b/src/integration_tests/mod.rs @@ -3,4 +3,5 @@ ////////////////////////////mod enum_definition; mod multiple_inheritance_class; mod empty_class_declaration; +mod class_with_many_statements; mod add_function; diff --git a/src/integration_tests/multiple_inheritance_class.rs b/src/integration_tests/multiple_inheritance_class.rs index 7736991..ffc9dcb 100644 --- a/src/integration_tests/multiple_inheritance_class.rs +++ b/src/integration_tests/multiple_inheritance_class.rs @@ -18,7 +18,7 @@ fn panic_on_error(msg: Message, _: Span) { fn integration_multiple_inheritance_class() { let script = "class Foo : Zom, Aar, Bar {}"; let lexed_tokens = lex(script, &mut panic_on_error); - println!("{}", serde_json::to_string(&lexed_tokens).unwrap()); + println!("Lexed tokens JSON: {}", serde_json::to_string(&lexed_tokens).unwrap()); let expected_tokens: Vec = serde_json::from_str(r#"[ { @@ -152,7 +152,7 @@ fn integration_multiple_inheritance_class() { assert_eq!(lexed_tokens, expected_tokens); let parsed_tree = parse(lexed_tokens, &mut panic_on_error); - println!("{}", serde_json::to_string(&parsed_tree).unwrap()); + println!("Parsed Tree JSON: {}", serde_json::to_string(&parsed_tree).unwrap()); let expected_tree: Box = serde_json::from_str(r#"{ "Script": { diff --git a/src/integration_tests/test_cases/add_function/parsed_tree.json b/src/integration_tests/test_cases/add_function/parsed_tree.json index d673b37..dc6ed93 100644 --- a/src/integration_tests/test_cases/add_function/parsed_tree.json +++ b/src/integration_tests/test_cases/add_function/parsed_tree.json @@ -6,6 +6,7 @@ "modifiers": 0, "field_mod": null, "is_destructor": false, + "is_constructor": false, "returns_reference": false, "return_type": { "Type": { diff --git a/src/integration_tests/test_cases/class_with_many_statements/script.ses b/src/integration_tests/test_cases/class_with_many_statements/script.ses new file mode 100644 index 0000000..d3ce62e --- /dev/null +++ b/src/integration_tests/test_cases/class_with_many_statements/script.ses @@ -0,0 +1,21 @@ +final shared class Foobar { + int _a; + int _b; + + Foobar(int a, int b) { + _a = a; + _b = b; + } + + int GetA(){ + return _a; + } + + int Add() { + return _a + _b; + } + + class Inner { + int a; + } +} \ No newline at end of file diff --git a/src/parsing/parser/mod.rs b/src/parsing/parser/mod.rs index b3f8888..bb56c1a 100644 --- a/src/parsing/parser/mod.rs +++ b/src/parsing/parser/mod.rs @@ -736,8 +736,20 @@ fn parse_func( returns_reference = true; reader.next(); } + return_type.as_ref()?; } - let name = parse_identifier(&mut reader, log, true); + let mut name = parse_identifier(&mut reader, log, true); + + let mut is_constructor = false; + if name.is_none() && return_type.is_some() { + if let ParsedStatement::Type { datatype, .. } = return_type.as_ref().unwrap().as_ref() { + if let ParsedStatement::DataTypeIdentifier { identifier } = datatype.as_ref() { + name = Some(identifier.to_string()); + is_constructor = true; + } + } + } + name.as_ref()?; let param_list = parse_paramlist(&mut reader, log); param_list.as_ref()?; @@ -759,6 +771,7 @@ fn parse_func( modifiers, field_mod, is_destructor, + is_constructor, returns_reference, return_type, name: name.unwrap(), @@ -773,6 +786,7 @@ fn parse_virtprop( outer_reader: &mut ParseReader, log: &mut dyn FnMut(Message, Span), ) -> Option> { + // virtprop ::= ['private' | 'protected'] type ['&'] identifier '{' {('get' | 'set') ['const'] funcattr (statblock | ';')} '}'; let mut reader = outer_reader.create_inner(); let mut field_mod: Option = None; match reader.peek().token_type { @@ -794,7 +808,7 @@ fn parse_virtprop( reader.next(); is_handle = true; } - let identifier = parse_identifier(&mut reader, log, false); + let identifier = parse_identifier(&mut reader, log, true); identifier.as_ref()?; let next = reader.next(); if next.token_type != TokenType::OpenCurlyBracket { @@ -1015,7 +1029,7 @@ fn parse_var( } property_type.as_ref()?; - let identifier = parse_identifier(&mut reader, log, false); + let identifier = parse_identifier(&mut reader, log, true); identifier.as_ref()?; let mut assignment: Option> = None; @@ -1402,7 +1416,6 @@ fn parse_exprterm( }) } - println!("{:?}", real_value); outer_reader.set_from_inner(&reader); Some(real_value) } @@ -1567,7 +1580,7 @@ fn parse_exprvalue( fn parse_lambda( reader: &mut ParseReader, - log: &mut dyn FnMut(Message, Span), + _log: &mut dyn FnMut(Message, Span), ) -> Option> { // lambda ::= 'function' '(' [[type typemod] identifier {',' [type typemod] identifier}] ')' statblock; if reader.peek().token_type != TokenType::FunctionKeyword { @@ -1783,7 +1796,10 @@ fn parse_assign( ternary.as_ref()?; if let Some(assign_op) = parse_assignop(reader, log) { let assign = parse_assign(reader, log); - // FIXME: deal with None assign. + if assign.is_none() { + // FIXME: Logging + return Some(Box::new(ParsedStatement::Invalid)); + } return Some(Box::new(ParsedStatement::Assignment { left: ternary.unwrap(), operator: assign_op, diff --git a/src/parsing/parser/parsed_statement.rs b/src/parsing/parser/parsed_statement.rs index 6595114..3067622 100644 --- a/src/parsing/parser/parsed_statement.rs +++ b/src/parsing/parser/parsed_statement.rs @@ -216,6 +216,7 @@ pub enum ParsedStatement { modifiers: BitFlags, field_mod: Option, is_destructor: bool, + is_constructor: bool, returns_reference: bool, return_type: Option>, name: String,