switch on span?
drom opened this issue · 16 comments
Very cool project.
I am trying to build Verilog preprocessor using llparse here: https://github.com/drom/vpreproc
I have encounter one difficulty that I don't know how to solve.
- preprocessor looking for ``` character in the stream. https://github.com/drom/vpreproc/blob/master/bin/build.js#L27
- Then it should chop a string (span) of characters (identifier) terminated by non-identifier.
- By looking at the span if should classify it as:
- one of the known directives and continue accordingly.
- unknown string (defined value) and jump to a different state.
The difficulty I have is to how to implement, span Lookup without select
or match
API?
Thanks!
I think combination of span
and select
should do it. Why do you want to avoid select
?
I am fine with select
. But I have not found a good example of doing multiple selects and a span in parallel.
Here's how I do it in llhttp: https://github.com/nodejs/llhttp/blob/d8d480a57df82203fa2f8733178696073451fd7d/src/llhttp/http.ts#L348-L370 . It just starts a span and then does whatever it wants, and ends the span when needed.
How do you do select that ends with one of non-identifier symbols like \s \t \n \r .... ?
Could you write a couple of examples of the possible inputs? I'm not sure I fully understand the use-case yet.
some text
`include "something.vh"
some text
`define FOO 5
more text
text with `FOO in the middle
more text
`undef FOO
text again
`undefineall
even more text
There are multiple standard defined directives: like \
define,
`undef,
`undefineall,
`includewith a different number of standard arguments. And there are defined values like
`FOO` that can also appear in the text.
http://ecee.colorado.edu/~mathys/ecen2350/IntelSoftware/pdf/IEEE_Std1800-2017_8299595.pdf
Chapter 22
Okay... Perhaps:
const directive = p.node('directive');
span.start(directive);
directive.select({ include: 1, define: 2, undef: 3, undefineall: 4 }, directiveParamStart);
directiveParamsStart.match([ '\s', '\t', '\n', '\r' ], directiveParams)
// Do something in directiveParams
directiveParamsEnd.otherwise(span.end(afterDirective))
Oh wait, this is not what you asked about.
Second attempt:
const directive = p.node('directive');
const knownDirective = p.invoke(p.code.store('directive'));
const directiveEnd = span.end(afterDirective);
span.start(directive);
directive.select({ include: 1, define: 2, undef: 3, undefinedall: 4 }, knownDirective);
directive.otherwise(unknownDirective);
unknownDirective
.match([ '\s', '\t', '\n', '\r' ], p.invoke(p.code.update('directive', -1).otherwise(directiveEnd))
.skipTo(unknownDirective);
Will undef
and undefineall
conflict?
Oh, that's a good one. They will. Perhaps, you'll have to use .match('undef')
as well with further branch to either \s\t\n\r
or ineall
.
I think this conflicting matching should be supported. Created an issue to track progress on it: #28 . It might be wise to move on with a solution above at the moment, though.
Can I do multiple select
groups?
- group1:
resetall
,undefineall
,endif
... has no arguments - group2:
ifdef
,ifndef
,elsif
,undef
has single argument - group3:
include
...
I think it should work. Give it a try 😉
Thank you. I will try.
Yes, thank you. All works fine!