Yet another parsing rule question (cross reference) [message #1194497] |
Mon, 18 November 2013 14:45 |
Gary Worsham Messages: 176 Registered: September 2013 |
Senior Member |
|
|
Bottom line on this one: I need to be able to parse a literal OR a cross reference, but can't figure out how to do this.
Supposing I had these statements in my DSL file:
equ offset 25
mem buffer 300
rdax buffer+offset, 0.5
I'd like the "buffer + offset" part to get converted to "buffer + 25".
My DSL needs to consume memory expressions with the following possible structures:
buffer
buffer+25
buffer^
buffer^+25
buffer^-25
buffer#
buffer#-25
Not that it really matters, but "buffer" by itself represents the start address of the buffer, buffer^ represents the middle of the buffer, and buffer# represents the end of the buffer. That's why buffer-25 and buffer#+25 are not valid because they represent addresses outside of the allocated memory space.
Here's my current rule, which picks up all of these as a single string which I can manipulate in Java to get the correct numeric representation:
SPINMEM:
ID ('#' | '^')? (('+' | '-') (INT | ID))?
;
You'll notice that I have the possibility of an ID at the end, so that I can also get expressions like:
buffer+offset
where earlier, offset was declared like this (with corresponding rules also shown):
equ offset 25
Equate:
'equ' ename = ID value = SPINDOUBLE
;
SPINDOUBLE:
'-'? (ID | (INT ( '.' INT)?))
;
Anyway, my currently defined rule will pick up an expression like
and convert the whole thing to a string available to my Java code. Now since several DSL instructions reference the same type of memory expression, dealing with that is a separate method, meaning that the reference to "offset" is not in the scope where "offset" was declared.
I tried changing "SPINMEM" rule to include a cross reference to a "mem" statement, but Xtext did not like it:
SPINMEM:
ID ('#' | '^')? (('+' | '-') (INT | [Mem]))?
;
Gives the error: "No viable alternative at '['". So it really wasn't expecting that. The examples suggest I need to create a "super class" but I'm missing how to do that exactly. Thanks for any suggestions.
GW
[Updated on: Tue, 19 November 2013 05:19] Report message to a moderator
|
|
|
|
Re: Yet another parsing rule question (cross reference) [message #1197005 is a reply to message #1196881] |
Tue, 19 November 2013 18:05 |
Gary Worsham Messages: 176 Registered: September 2013 |
Senior Member |
|
|
Thanks, that does appear to match my experience. Also, I think it will be helpful to break the expression into more than 1 token.
So for example the worst case, something like:
buffer#-256
or
buffer^+offset
would want to get broken into two or three tokens to be consumed as individual arguments by the parser. So rather than only having "buffer#-offset" to work with, I could have "buffer#" or "buffer" or "buffer^" and either null or "+256" or "-offset". If I want to use "offset" as a literal variable name in my template code, it might be better to break it up further, ("+" | "-") followed by (INT | ID). I haven't experimented with it yet.
I can even probably avoid needing to use a cross reference at all, by coming up with a special data type rule for this type of variable in the code, e.g.
MEMOFFSET: 'memofs' name = ID value = INT;
This would then generate Java code such as:
int name = value;
Then later, substitute "value" in the template code where the instruction references this constant.
Thanks,
GW
[Updated on: Tue, 19 November 2013 18:12] Report message to a moderator
|
|
|
|
|
|
|
Re: Yet another parsing rule question (cross reference) [message #1200101 is a reply to message #1198831] |
Thu, 21 November 2013 04:49 |
Gary Worsham Messages: 176 Registered: September 2013 |
Senior Member |
|
|
OK, now I have another little subtle issue.
Here's my relevant rules in my xtext grammar:
ReadDelay: 'rda' arg1 = SPINMEM ',' arg2 = SPINDOUBLE;
SPINMEM:
buffer = SPINBUF (value = INT | offset=[Offset])?
;
SPINBUF: ID('#'|'^')?('+'|'-')?;
SPINDOUBLE:
'-'? (ID | (INT ( '.' INT)?))
;
and here's the section which consumes it in the generator xtend:
def genReadDelay(ReadDelay inst) {
if(inst.getArg1.getOffset.name != "") {'''
// get offset
sfxb.FXreadDelay("«inst.getArg1.getBuffer»", «inst.getArg1.getOffset.name», «inst.getArg2»);
'''
}
else
if(inst.getArg1.getValue != 0) {'''
// get value
sfxb.FXreadDelay("«inst.getArg1.getBuffer»", «inst.getArg1.getValue», «inst.getArg2»);
'''
}
else {'''
// default 0
sfxb.FXreadDelay("«inst.getArg1.getBuffer»", 0, «inst.getArg2»);
'''
}
}
I have 3 possibilities for the "offset" part of the memory expression.
#1 - it's not there at all, and the value should be set to 0.
#2 - it's an INT literal, and the value should be that literal.
#3 - it's a cross-reference to an Offset, and the value parsed should be the name of that Offset.
So far I am only able to get the correct answer to cases #1 and #2. Any attempts to access the cross reference when there isn't one defined result in a null pointer exception.
[Updated on: Thu, 21 November 2013 13:21] Report message to a moderator
|
|
|
Powered by
FUDForum. Page generated in 0.04078 seconds