speced / bikeshed

:bike: A preprocessor for anyone writing specifications that converts source files into actual specs.
https://speced.github.io/bikeshed
Creative Commons Zero v1.0 Universal
1.12k stars 200 forks source link

"butterfly" crossover in railroad diagrams #1184

Open zygoloid opened 6 years ago

zygoloid commented 6 years ago

Suppose we want to describe a grammar that recognizes an alternating sequence of identifiers and *s (describing a glob pattern). The natural way to render this in a railroad diagram would be to have two nodes, with the entry path going to both, the exit path coming from both, and each connected to the other.

(Can provide diagram if the above is not sufficient.) There appears to be no way to represent this in bikeshed's railroad diagram language without significant node duplication. Here a couple of bad ways of expressing this:

<pre class="railroad">
Or:
    Seq:
        OneOrMore:
            N: identifier
            T: *
        Opt:
            T: *
    Seq:
        OneOrMore:
            T: *
            N: identifier
        Opt:
            N: identifier
</pre>
<pre class="railroad">
Or:
    Seq:
        Opt:
            T: *
        OneOrMore:
            N: identifier
            T: *
        Opt:
            T: *
    T: *
</pre>
tabatkins commented 6 years ago

Hmm, yeah, there really is no good way to do this. If you allowed any sequence of identifiers and * characters, this is easy - I apparently haven't updated the parser yet to work with this, but I added a MultipleChoice node to the official repo (https://github.com/tabatkins/railroad-diagrams) that makes this simple:

Plus:
  AnyOf:
    T: *
    N: identifier

But if you have to explicitly alternate, and can start and end with either one, it's definitely harder. Another new node I've added to the official repo but apparently not mirrored over here (jeez...) is OptionalSequence, which does exactly reproduce what you want and reduces the duplication a little bit, at least:

OptionalSeq:
    T: *
    Plus:
        N: identifier
        T: *
    T: *

This seems reasonable overall, and I'm willing to add a new node. Can you give me a sketch of what you think it would look like?

zygoloid commented 6 years ago

Maybe something like this: image

tabatkins commented 6 years ago

Ah, that's cute and I like it. Yeah, I'll happily add this - I've just ported it over to an issue on the right repo https://github.com/tabatkins/railroad-diagrams/issues/50

tabatkins commented 6 years ago

Okay, JS version of the new node is complete - check it out at https://tabatkins.github.io/railroad-diagrams/example.html#glob. Just need to write the Python version, copy it over here, then write the parsing code for it (and the other two new constructs that I haven't ported over to Bikeshed).

zygoloid commented 6 years ago

Thank you, that looks great.