Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to run a sub-grammar inside a grammar nqp?

Tags:

regex

raku

nqp

If I have Grammar a and define a Grammar b that have a block '{ ... }' that has syntax of Grammar a, is it possible to somehow link these grammars together? I.e. Grammar a is Tcl and Grammar b is embedded C. How does Rakudo do this when switching from Perl6 grammar to Regex grammar?

like image 724
Konrad Eisele Avatar asked May 11 '20 09:05

Konrad Eisele


2 Answers

use Liz's-Answer;

answer Mine { ... }
say ?Mine if prompt 'Does that answer your question?' eq 'n' ;

answer Mine is B does Or-Perhaps-This does Or-Perhaps-That { }

role Or-Perhaps-This {
   token baz { <Liz's-Answer::B::foo> }
}

role Or-Perhaps-That {
   https://repl.it/@RalphMellor/Simple-slang
}

Liz's-Answer

Liz's initial answer wisely started at the beginning: declaring that a Raku grammar/role has one or more of its rules textually declared in another Raku grammar/role.

But then you edited your question to add:

I.e. Grammar a is Tcl and Grammar b is embedded C.

It's pretty unlikely that it would make sense for grammars for c and tcl to textually share any rules. :)

Or-Perhaps-This

Another possibly relevant solution is to have a method within a grammar call another one in some other class. This can include a rule in one grammar calling a rule in another grammar.

This could be what you want for a tcl grammar/parser calling a c grammar/parser, or vice-versa, or both:

grammar c { ... }

grammar tcl {
    rule TOP { ... }
    ...
    rule block { 'c {' <c::TOP> '}' }
    ...
}

grammar c {
    rule TOP { ... }
    ...
    rule block { 'tcl {' <tcl::TOP> '}' }
    ...
}

Or-Perhaps-That

How does Rakudo do this when switching from Perl6 grammar to Regex grammar?

The above Or-Perhaps-This example kept things simple. It hard coded the call from tcl to c, and vice-versa, and did not add any "userland" code that tracked that a switch had occurred.

What if one wanted to:

  • Have an arbitrary collection of languages calling into each other using the above Or-Perhaps-This technique;

  • Be able to replace or tweak any grammar in the collection;

  • Be able to add a new one (in conjunction with replacing/modifying an existing one to call the new one);

  • Dynamically track precisely which grammar one is "in", in a dynamic/innermost sense, at any given time?

Also, what about that being the approach adopted for Raku itself, using its own grammar construct to define itself as a braid of languages?

This is indeed the approach adopted for Raku, and, in turn, nqp, via a feature called "slangs", short for "sub-languages".

Slangs

While the Raku implemented in Rakudo is actually constructed using slangs, they are not an official feature. I'm sure they will be one day but it could easily be years.

In the meantime, I think the best I can provide is:

  • The repl.it example.

  • A link to SO's matching "[raku] slang".

  • Friendly advice: liberally apply the compiler optimization flag -Ofun as you spelunk the compiler's code and maybe use Comma on Rakudo to figure out what's going on...

like image 190
raiph Avatar answered Oct 20 '22 21:10

raiph


Grammars are really classes. So you can inherit from them. Or you can create a role and does that in both Grammars.

role A {
   token foo { bar }
}
grammar B does A {
    ...  # other stuff
}

Does that answer your question?

like image 4
Elizabeth Mattijsen Avatar answered Oct 20 '22 20:10

Elizabeth Mattijsen