From 1f7ee2e3fa8a280a50fe0e4333e41ce1f33455b3 Mon Sep 17 00:00:00 2001 From: Michael <78988079+mhasel@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:31:49 +0100 Subject: [PATCH] fix: parse IMPLEMENTS keyword after EXTENDS (#1391) --- src/parser.rs | 2 +- src/parser/tests/class_parser_tests.rs | 63 ++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/parser.rs b/src/parser.rs index 9fb6f82921..48a0fe32d6 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -274,11 +274,11 @@ fn parse_pou( parse_identifier(lexer).unwrap_or_else(|| ("".to_string(), SourceLocation::undefined())); // parse POU name let generics = parse_generics(lexer); - let interfaces = parse_interface_declarations(lexer); with_scope(lexer, name.clone(), |lexer| { // TODO: Parse USING directives let super_class = parse_super_class(lexer); + let interfaces = parse_interface_declarations(lexer); // parse an optional return type // classes do not have a return type (check in validator) diff --git a/src/parser/tests/class_parser_tests.rs b/src/parser/tests/class_parser_tests.rs index c0008baa86..9ec2535c73 100644 --- a/src/parser/tests/class_parser_tests.rs +++ b/src/parser/tests/class_parser_tests.rs @@ -513,3 +513,66 @@ fn method_variable_blocks_can_be_parsed() { let with_initializer = variables.iter().filter(|it| it.initializer.is_some()); assert_eq!(with_initializer.count(), 4); } + +#[test] +fn fb_extends_can_be_parsed() { + let src = r#" + FUNCTION_BLOCK MyFb + END_FUNCTION_BLOCK + + FUNCTION_BLOCK MyFb2 EXTENDS MyFb + END_FUNCTION_BLOCK + "#; + let unit = parse(src).0; + + assert_eq!(&unit.units[1].super_class.clone().unwrap(), "MyFb"); +} +#[test] +fn class_with_extends_and_implements_can_be_parsed() { + let src = r#" + INTERFACE MyInterface + END_INTERFACE + + CLASS MyClass IMPLEMENTS MyInterface + END_CLASS + + CLASS MyClass2 EXTENDS MyClass IMPLEMENTS MyInterface + END_CLASS + "#; + let unit = parse(src).0; + let class1 = &unit.units[0]; + assert_eq!(class1.kind, PouType::Class); + assert_eq!(class1.name, "MyClass"); + assert_eq!(class1.interfaces[0].name, "MyInterface"); + let class2 = &unit.units[1]; + assert_eq!(class2.kind, PouType::Class); + assert_eq!(class2.name, "MyClass2"); + assert_eq!(class2.super_class.as_ref().unwrap(), "MyClass"); + assert_eq!(class2.interfaces[0].name, "MyInterface"); +} + +#[test] +fn function_block_with_extends_and_implements_can_be_parsed() { + let src = r#" + INTERFACE MyInterface + END_INTERFACE + + FUNCTION_BLOCK MyFb IMPLEMENTS MyInterface + END_FUNCTION_BLOCK + + FUNCTION_BLOCK MyFb2 EXTENDS MyFb IMPLEMENTS MyInterface + END_FUNCTION_BLOCK + "#; + let unit = parse(src).0; + + let fb1 = &unit.units[0]; + assert_eq!(fb1.kind, PouType::FunctionBlock); + assert_eq!(fb1.name, "MyFb"); + assert_eq!(fb1.interfaces[0].name, "MyInterface"); + + let fb2 = &unit.units[1]; + assert_eq!(fb2.kind, PouType::FunctionBlock); + assert_eq!(fb2.name, "MyFb2"); + assert_eq!(fb2.super_class.as_ref().unwrap(), "MyFb"); + assert_eq!(fb2.interfaces[0].name, "MyInterface"); +}