03-26-2010 09:32 AM
I think this is what your looking for. I did this really quick so please dont think this is my normal style of coding, i too think it is really sloppy BD. Let me know if its just to sloppy to follow.
03-26-2010 10:13 AM - edited 03-26-2010 10:14 AM
C.DOT, Look up stacks and reverse polish to give you an idea of how they organise themselves (classically with a data tree) and apply that to your problem. Create a flow diagram of how to process a single command and how or if to add it to the stack. Read through Mark's reply on pushing a popping elements to the stack. You'll have it sorted in no tim. Your biggest worry will be sanitising your users' inputs!
03-26-2010 10:44 AM
Can you use another variable to keep track of which nested loop is being executed? Like this:
For
Nest=0
some code
For
Nest=1
some code
End For
Nest=0
End For
When you encounter the inner most End For, Nest is 1. This tells you which For it belongs to. You need to immediately redefine the Nest variable after each End For. This may seem awkward, but I think it would work.
03-26-2010 12:53 PM
I like your challanges C.DOT, they remind me a lot about my early SW days when I did assembler on an Atari ST as a kid.
What you basically need is an program pointer that is referencing the line of code. This is actually as easy as an I32 used to index your array.
Using the program pointer you can implement a GOTO statement (in assembler you had the jnz = jump not zero which was handy to implement for loops). o.k., GOTO is bad so we don't finish here.
When you encounter the for statement, push the current program address on the stack, this is the return point when you need another iteration. So when you reach the end for you pop the return address from the stack. If your loop shall terminate, you can dismiss and continue with the line after the end for statement. If you need to do another loop, jump to the for statement, so again you will push thesame address on the stack...
This works if you can write statements like
for i=0 to 20
for j=0 to 5
...
So you have to create a unique name for each counter, either the use has to, or your compiler does it (think about namespaces in an OOP language, the i inside one object is not the same as the i in the other).
To go further (or an even more elegant solution), we need to look how procedures work. If I had to call an procedure in assembler, I had to make sure that all my registers (so the data) is safed, as the other procedure will use the same registers. So I push them all on the stack (not necessary the same stack as the return address, but a single stack is possible as well). After the call of the procedure, I pop up all register values from the stack (reverse order). The call statement is placing the current program adresss + 1 (the next line after the call) on the stack. When the end of the procedure is reached (I don't remember the statement), the adress is poped from the stack and you jmp there.
Well, the same you would do with for loops, you always push the current counter on the stack and pop it up after the for end statement.
Summary: Use one or two stacks and use a program pointer
Felix
03-26-2010 03:12 PM
I had to do something just like this for the test list parser for the exec shell we use here. The test list defines the tests to run, and you can use <loop> directives to specify looping a test or a set of tests. I used the approach of naming the loops within the list. Thus, a test list with multiple (and nested) loops would look like this:
<loop wait1 5>
Test1, Param1:=5000
<loop meas1 4>
Test2, Param1:=4, Param2:=8, Param3:=23.45
<loop wait2 2>
Standard:Misc:Wait, Time:=5000
</loop wait2>
</loop meas1>
</loop wait1>
Standard:Misc:Limit Check, No. of Measurements:=4
As you can see, each loop is named, and the numeric value indicates how many times to run the loop. The parser is similar to the code shown earlier by herrlin (see attached picture of code). If I felt like it I could implement it using stacks and popping, but I don't really feel like it at the moment. Maybe in a few months if I've got nothing better to do I will.
03-27-2010 02:36 AM
03-27-2010 02:55 AM
03-27-2010 03:33 AM
Okay boss! Whatever you say boss!. Joke aside, what you have stated is of course a good programming practice. But sometimes when you are working on upgrading a project it is a bit difficult (if time constraints are also pressing) to redo the architecture from scratch. Applying pathces here and there is the only solution. Anyway, I'll keep you advice in mind for the new projects. I need to learn about reverse polish notation though (learnt it during the MS time but have forgotten it since). Can you point to some articles (with LabVIEW coding examples)?
Thanks a lot!
03-27-2010 03:40 AM
Thanks for helping! This is not what I was looking for (for the particular problem at hand at he moment). But I'll keep it in mind, would be useful for other such nested looping problems.
Have a pleasant wekend!
03-27-2010 03:48 AM