Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse 61131-3 Classes #225

Merged
merged 32 commits into from
Aug 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a64e4d9
take care of PResult in expression parser
ulmer-a Jul 22, 2021
5abc8c0
take care of PResult in control parser
ulmer-a Jul 23, 2021
e7bfd95
get rid of PResult from parser
ulmer-a Jul 26, 2021
eb8471c
get rid of ~200 unwrap()s
ulmer-a Jul 26, 2021
e31f54f
Add expect_token! macro to avoid duplicated code
ulmer-a Jul 26, 2021
c9b45c5
add tests for expect_token!() usages
ulmer-a Jul 26, 2021
0075e0e
reintroduce Results to the expression parser
ulmer-a Aug 2, 2021
79b1cbe
Revert "reintroduce Results to the expression parser"
ulmer-a Aug 3, 2021
de7fcf9
finalize expression_parser, remove misleading fn parse_primary_expres…
ulmer-a Aug 3, 2021
4da0088
merge upstream/master
ulmer-a Aug 3, 2021
275c1ae
add CLASS END_CLASS tokens
ulmer-a Aug 2, 2021
2029cc5
parse class VAR..END_VAR section
ulmer-a Aug 2, 2021
9585183
start parsing class declaration
ulmer-a Aug 3, 2021
b28ffa5
start parsing method declaration
ulmer-a Aug 3, 2021
ba9b175
add basic class declaration parsing
ulmer-a Aug 4, 2021
4dbfcaf
parse classes and methods into AST
ulmer-a Aug 4, 2021
cd3988b
add method parse tests
ulmer-a Aug 4, 2021
451796a
add more class parse tests
ulmer-a Aug 4, 2021
9d77996
add parse error tests for classes
ulmer-a Aug 5, 2021
43312ca
parse variable blocks in class declaration
ulmer-a Aug 5, 2021
cb80dd6
add varblock parsing tests
ulmer-a Aug 5, 2021
d21af5e
Merge branch 'master' into classes
ulmer-a Aug 5, 2021
b294873
implement variable block parsing in methods
ulmer-a Aug 6, 2021
6a58354
add tests for method variable blocks
ulmer-a Aug 6, 2021
f7ec99d
Merge upstream/master into classes
ulmer-a Aug 6, 2021
86f4f4d
integrate ClassPou into Pou
ulmer-a Aug 10, 2021
056a34a
break up long test into multiple lines
ulmer-a Aug 10, 2021
b7ad401
allow function blocks to have methods
ulmer-a Aug 10, 2021
306c2ef
add tests for methods in function blocks
ulmer-a Aug 10, 2021
3c168ee
add index tests for methods
ulmer-a Aug 11, 2021
677438f
fix coverage
ulmer-a Aug 11, 2021
7e44d5a
Merge branch 'master' into classes
ulmer-a Aug 11, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ pub struct Pou {
pub pou_type: PouType,
pub return_type: Option<DataTypeDeclaration>,
pub location: SourceRange,
pub poly_mode: Option<PolymorphismMode>,
}

#[derive(Debug, PartialEq)]
pub enum PolymorphismMode {
None,
Abstract,
Final,
}

impl Debug for Pou {
Expand All @@ -46,6 +54,8 @@ pub struct Implementation {
pub pou_type: PouType,
pub statements: Vec<Statement>,
pub location: SourceRange,
pub overriding: bool,
pub access: Option<AccessModifier>,
}

#[derive(Debug, Copy, PartialEq, Clone)]
Expand All @@ -54,12 +64,22 @@ pub enum LinkageType {
External,
}

#[derive(Debug, PartialEq)]
pub enum AccessModifier {
Private,
Public,
Protected, // default
Internal,
}

#[derive(Debug, Copy, PartialEq, Clone)]
pub enum PouType {
Program,
Function,
FunctionBlock,
Action,
Class,
Method,
}

#[derive(Debug, PartialEq)]
Expand Down Expand Up @@ -99,6 +119,7 @@ impl Default for CompilationUnit {
#[derive(Debug, Copy, PartialEq, Clone)]
pub enum VariableBlockType {
Local,
Temp,
ulmer-a marked this conversation as resolved.
Show resolved Hide resolved
Input,
Output,
Global,
Expand All @@ -107,6 +128,9 @@ pub enum VariableBlockType {

#[derive(PartialEq)]
pub struct VariableBlock {
pub access: AccessModifier,
pub constant: bool,
pub retain: bool,
pub variables: Vec<Variable>,
pub variable_block_type: VariableBlockType,
}
Expand Down
1 change: 1 addition & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl VariableIndexEntry {
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum VariableType {
Local,
Temp,
Input,
Output,
InOut,
Expand Down
70 changes: 70 additions & 0 deletions src/index/tests/index_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,70 @@ fn actions_are_indexed() {
}
}

#[test]
fn fb_methods_are_indexed() {
let index = index!(
r#"
FUNCTION_BLOCK myFuncBlock
METHOD foo
VAR x : SINT; END_VAR
END_METHOD
END_FUNCTION_BLOCK
"#
);

let foo_impl = index.find_implementation("myFuncBlock.foo").unwrap();
assert_eq!("myFuncBlock.foo", foo_impl.call_name);
assert_eq!("myFuncBlock", foo_impl.type_name);
let info = index
.get_type("myFuncBlock.foo")
.unwrap()
.get_type_information();
if let crate::typesystem::DataTypeInformation::Struct {
name,
member_names,
varargs: _,
} = info
{
assert_eq!("myFuncBlock.foo_interface", name);
ulmer-a marked this conversation as resolved.
Show resolved Hide resolved
assert_eq!(&vec!["x"], member_names);
} else {
panic!("Wrong variant : {:#?}", info);
}
}

#[test]
fn class_methods_are_indexed() {
let index = index!(
r#"
CLASS myClass
METHOD foo
VAR y : DINT; END_VAR
END_METHOD
END_CLASS
"#
);

let foo_impl = index.find_implementation("myClass.foo").unwrap();
assert_eq!("myClass.foo", foo_impl.call_name);
assert_eq!("myClass", foo_impl.type_name);
let info = index
.get_type("myClass.foo")
.unwrap()
.get_type_information();
if let crate::typesystem::DataTypeInformation::Struct {
name,
member_names,
varargs: _,
} = info
{
assert_eq!("myClass.foo_interface", name);
ulmer-a marked this conversation as resolved.
Show resolved Hide resolved
assert_eq!(&vec!["y"], member_names);
} else {
panic!("Wrong variant : {:#?}", info);
}
}

#[test]
fn function_is_indexed() {
let index = index!(
Expand Down Expand Up @@ -190,11 +254,17 @@ fn pous_are_indexed() {
END_PROGRAM
FUNCTION myFunction : INT
END_FUNCTION
FUNCTION_BLOCK myFunctionBlock : INT
END_FUNCTION_BLOCK
CLASS myClass
END_CLASS
"#
);

index.find_type("myFunction").unwrap();
index.find_type("myProgram").unwrap();
index.find_type("myFunctionBlock").unwrap();
index.find_type("myClass").unwrap();
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions src/index/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ fn visit_global_var_block(index: &mut Index, block: &VariableBlock) {
fn get_variable_type_from_block(block: &VariableBlock) -> VariableType {
match block.variable_block_type {
VariableBlockType::Local => VariableType::Local,
VariableBlockType::Temp => VariableType::Temp,
VariableBlockType::Input => VariableType::Input,
VariableBlockType::Output => VariableType::Output,
VariableBlockType::Global => VariableType::Global,
Expand Down
4 changes: 3 additions & 1 deletion src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ impl<'a> ParseSession<'a> {
| Token::KeywordEndActions
| Token::KeywordEndIf
| Token::KeywordEndFor
| Token::KeywordEndRepeat => {
| Token::KeywordEndRepeat
| Token::KeywordEndMethod
| Token::KeywordEndClass => {
if !self.slice().to_string().contains('_') {
self.accept_diagnostic(Diagnostic::ImprovementSuggestion {
message: format!(
Expand Down
47 changes: 47 additions & 0 deletions src/lexer/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ pub enum Token {
#[token("PROGRAM")]
KeywordProgram,

#[token("CLASS")]
KeywordClass,

#[token("END_CLASS")]
#[token("ENDCLASS")]
KeywordEndClass,

#[token("VAR_INPUT")]
#[token("VARINPUT")]
KeywordVarInput,
Expand All @@ -26,6 +33,46 @@ pub enum Token {
#[token("VAR")]
KeywordVar,

#[token("ABSTRACT")]
KeywordAbstract,

#[token("FINAL")]
KeywordFinal,

#[token("METHOD")]
KeywordMethod,

#[token("CONSTANT")]
KeywordConstant,

#[token("RETAIN")]
KeywordRetain,

#[token("NON_RETAIN")]
KeywordNonRetain,

#[token("VAR_TEMP")]
KeywordVarTemp,

#[token("END_METHOD")]
#[token("ENDMETHOD")]
KeywordEndMethod,

#[token("PUBLIC")]
KeywordAccessPublic,

#[token("PRIVATE")]
KeywordAccessPrivate,

#[token("INTERNAL")]
KeywordAccessInternal,

#[token("PROTECTED")]
KeywordAccessProtected,

#[token("OVERRIDE")]
KeywordOverride,

#[token("VAR_GLOBAL")]
#[token("VARGLOBAL")]
KeywordVarGlobal,
Expand Down
Loading