klauer / blark

Beckhoff TwinCAT ST (IEC 61131-3) code parsing in Python using Lark (Earley)
https://klauer.github.io/blark/
GNU General Public License v2.0
42 stars 5 forks source link

Add Support for Multi-Line Object Oriented Function-Block Usage #54

Closed engineerjoe440 closed 1 year ago

engineerjoe440 commented 1 year ago

Ok, so admittedly this is a new one to me. I had someone send me a snippet of 61131, and I was playing with it in blark and ran into a nice-big-ol'-error. Thought I'd report it, since it does seem worth supporting.

Problem

Apparently, given the right constraints, it's possible to "chain" method calls in 61131 (e.g., object.call1().call2()) and it's legal to have that "chaining" extend across line-separation. In other words, the following logic is "legal:"

object.call1()
      .call2();

The problem is that white-space between call1() and call2(). blark does not like it. :frowning:

Here's a sample of what the error might look like (through the lens of a pytest run)

E           lark.exceptions.UnexpectedCharacters: No terminal matches '.' in the current parser context, at line 9 col 4
E           
E              .DoSomethingElse(input_1:=5)
E              ^
E           Expected one of: 
E               * SEMICOLON

What's Needed

I think we need to figure out how to allow an indeterminate amount of white-space to be allowed in these chained-method cases. I'll have to do some poking around to see if I might be able to figure out how to make that work. Any suggestions are welcome.

I have a new test case that demonstrates this issue here: https://github.com/engineerjoe440/blark/blob/bugfix/newline-separated-oop-logic/blark/tests/source/object_oriented_dotaccess.st#L8-L10

Definitely an interesting pattern in the ST. I have to admit, it's kinda cool...

engineerjoe440 commented 1 year ago

Ok.... so I oversimplified this, actually. It seems that chained method statements (as a whole) are the problem. That is, the following logic will cause a lark failure.

uut.DoSomething(input_1:='foo', input_2:='bar').DoSomethingElse(input_1:=5).Finish();

I think this will be best modified by way of the function_call grammar element, but will need to explore...

klauer commented 1 year ago

Good find, @engineerjoe440!

Agreed on the whitespace not being an issue but rather the dotted method access on the return value of a function call. I haven't seen this in our PLC code, but this reference at least confirms it's a thing in TwinCAT: