Re: More than one #v(expression) in a single line of a macro
"Scott Dattalo" <[email protected]>
| Newsgroups | gmane.comp.hardware.microcontrollers.gnupic |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 2005-09-07 at 09:35 -0400, Ben Dugan wrote: <snip> info about gpasm macro limitations. > Does anyone have a clever suggestion for a workaround, or do the > developers have any pointers about how I might, for example, tweak > scan.l to do this? (I was thinking a brute force approach might be to > add a #w(expression) "operator", but that's not very good.) Ben, I'm not an expert with Bison/Flex, but the real solution to gpasm macro problems lies there. The (or maybe 'a') proper way to tackle this problem is by introduce recursive parsing. This can be done by adding a new lexer state that is entered during the #v() processing. The idea here is that the #v() really needs to be evaluated when it is encountered, turned into a string (actually that's the result of the evaluation), and then fed back into yybuffer. The recursive aspect is that it's possible for an expression to be evaluated and recycled in the input stream multiple times until something stable eventually pops out. Your particular example, didn't involve recursion so it may be much simpler then what I am about to describe... but I recently solved a somewhat similar problem in gpsim's parser. Let me describe the problem and the solution and then maybe this can inspire you to tackle gpasm. gpsim supports parameterized macros. These are defined with the macro command. When a macro is defined, it's pretty much stored verbatim in a structure. The only parsing done is that the text names for the parameters are stored in a list separate from the text for the body. The only difficult part is that you have to differentiate text that is for a macro definition from text that is for a command that needs to be executed now. This is accomplished with a lexer state. A lexer state or mode defines how an incoming stream is to be lexed. In other words, it controls how the lexer should turn the input strings into tokens. A simple example could be something like a numeric string. In one mode it could be interpreted as a number where as in another it could be interpreted as an identifier. (This example is trivial and there are better ways of deciphering how a numeric string should be interpreted.) gpsim has a MACRO_BODY lexer mode to handle macro definitions. Expanding macros in gpsim is also a fairly straightforward process. When an identifier is encountered and recognized to be macro, then the macro arguments are stored in a list and the macro body along with its parameters are accessed for the macro expansion. During an expansion, unidentifiable identifiers (i.e. strings of text that are neither commands or symbols) are compared against the macro parameter list. If a match is found then the unidentified text is substituted with the invocation argument. The expansion process involves creating text and feeding it back into the lexer. One challenge here is that the normal input stream (i.e. the command line) has to be interrupted while the macro is being expanded. But the idea is that a single command line consisting of a macro invocation can turn into many gpsim commands that ultimately are fed back into the lexer. Macro definitions and expansions are relatively simple until you consider nested macro invocations. A nested macro invocation consists of a macro that references another macro. For example, you may create a "step and examine" macro to execute the step instruction N times and to examine the contents of a variable. The number of steps and the variable to examine are both parameters. Now you may also create the "run and examine macro" where this macro will set a break 1000 cycles into the future, call the "step and examine" macro, start running, and examine a variable when the simulation stops. The variable to be examined is a parameter to both macros. There are several challenges with nested macro invocations. First, while expanding a nested macro, the expansion state of the previous macro has to be saved. gpsim handles this with a macro invocation stack. Second, parameters for an outer invocation may be passed down as arguments to nested invocations. Again, the argument and parameter lists are saved in stacks. I'd say there are many challenges involved here: one is to identify if a new lexer state is even needed. Then if so, how are the input and output streams to be handled. Another related issue is how to manage input streams in the context of the current design. Fortunately Craig has created a regression test suite so you'll know when something breaks! I hope this helps. Scott