I wanna create DSL for rule modbus devices over the local network. I'll give you some context so that you better understand what I mean.First of all, imagine a device (let's say an oscilloscope), we can control it by sending commands to the device. Usually, all of these devices have similar features. They have input and output channels.We can set the parameters for the channels. (for example, for a power supply unit, we can set the output via channel number 1 to 1 Ampere and 10 Volts)
I have created a simple grammar for this. In the BNF format:
ranges ::= range ( ',' range )*
range ::= | number '-' number
| number
More generally, we have this grammar:
expr ::= ranges '=' configuration
I have no problem with the lexer and expression parser stage.To learn, I write everything from scratch. Without using any generators (like bison). I use the book very much for learning.The pseudocode for parsing such expressions is very simple:
def ranges(self):
self.range()
while self.match(TokenType.COMMA):
self.range()
def range(self):
if self.check(TokenType.NUMBER):
left = int(self.current.lexeme)
self.advance()
if self.match(TokenType.MINUS):
if self.check(TokenType.NUMBER):
right = int(self.current.lexeme)
self.advance()
# have range here
# can emit it to VM
The problems start further. There are a lot of devices using the modbus protocol. I would like to have some kind of universal solution for them. So I decided to create a virtual machine. We usually create a VM in order not to depend on the target architecture, right? I use a similar principle, but I imagine that instead of the target architecture, I have a set of different devices.
I don't quite understand what to do next between the parser and the VM.
My idea was to simply generate the range itself at the parsing stage (let's say for 1-5 = [1,2,3,4,5] and then just push it to the VM.
I would create something like OP_PUSH_RANGE (Op code) and do push to the stack of the VM.
The problem is when you write something like "1=10V" The stack of the virtual machine will look something like this:
[1, 10,]
I could add special tag values (for example for range values and for configuration values)
Then my VM stack would look like this:
[<rng>, 1, <rng>, <cfg>, 10, <cfg>]
Now I can just start the get stack function and iterate through it and pull out the ranges and settings separately. This sounds like a solution to the problem. But I'm not sure about him yet. My question is still how to distinguish between the values before the '=' character (because they have numeric values) and after. And also how to develop a VM for languages of this type. Yes, I know the language sounds too loud. Let it be a tiny language
digit+for the range parts, but your parser consumes only a singleTokenType.NUMBERfor each of those parts. Also, if each digit is a separate token (as the naming and the grammar suggest), thendigit+would match text like4 5 6, which you presumably don't want. I'm guessing that the way you've actually implemented it,456is a single "number" token rather than three "digit" tokens, so your grammar should saynumberinstead ofdigit+. $\endgroup$