Search code examples
regexrakunqp

Is it possible to run a sub-grammar inside a grammar 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?


Solution

  • 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: