nodejs / llparse

Generating parsers in LLVM IR
http://llparse.org
Other
584 stars 30 forks source link

switch on span? #27

Closed drom closed 4 years ago

drom commented 5 years ago

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.

1) preprocessor looking for ``` character in the stream. https://github.com/drom/vpreproc/blob/master/bin/build.js#L27 2) Then it should chop a string (span) of characters (identifier) terminated by non-identifier. 3) By looking at the span if should classify it as:

The difficulty I have is to how to implement, span Lookup without select or match API?

indutny commented 5 years ago

Thanks!

I think combination of span and select should do it. Why do you want to avoid select?

drom commented 5 years ago

I am fine with select. But I have not found a good example of doing multiple selects and a span in parallel.

indutny commented 5 years ago

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.

drom commented 5 years ago

How do you do select that ends with one of non-identifier symbols like \s \t \n \r .... ?

indutny commented 5 years ago

Could you write a couple of examples of the possible inputs? I'm not sure I fully understand the use-case yet.

drom commented 5 years ago
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,`include with 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

indutny commented 5 years ago

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))
indutny commented 5 years ago

Oh wait, this is not what you asked about.

indutny commented 5 years ago

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);
drom commented 5 years ago

Will undef and undefineall conflict?

indutny commented 5 years ago

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.

indutny commented 5 years ago

I think this conflicting matching should be supported. Created an issue to track progress on it: https://github.com/nodejs/llparse/issues/28 . It might be wise to move on with a solution above at the moment, though.

drom commented 5 years ago

Can I do multiple select groups?

indutny commented 5 years ago

I think it should work. Give it a try :wink:

drom commented 5 years ago

Thank you. I will try.

drom commented 4 years ago

Yes, thank you. All works fine!