Thread overview
[Issue 18336] Add std.algorithm.findMatchingParen
[Issue 18336] Add std.algorithm.untilClosingParens
Jan 30, 2018
Jack Stouffer
Jan 30, 2018
Seb
Dec 17, 2022
Iain Buclaw
January 30, 2018
https://issues.dlang.org/show_bug.cgi?id=18336

Jack Stouffer <jack@jackstouffer.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jack@jackstouffer.com

--- Comment #1 from Jack Stouffer <jack@jackstouffer.com> ---
I'm wondering how useful something like this would be in real world parsing situations like math statements or languages. If you have nested parens you'd have to do recursive calls to untilClosingParentheses to properly break up a statement like "(5 + (10 - 2))".

Maybe it's be more useful to have some function that returns the following

------
assert("(5 + (10 - 2))".func().equals(
    [tuple(1UL, "5 + "), tuple(2UL, "10 - 2")]
));
assert("7 + (4 * (2^^(-1)))".func().equals(
    [tuple(0UL, "7 + "), tuple(1UL, "4 * "), tuple(2UL, "2^^"), tuple(3UL,
"-1")]
));
------

But at that point I don't know if it would be a good fit for Phobos.

--
January 30, 2018
https://issues.dlang.org/show_bug.cgi?id=18336

Seb <greensunny12@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Add                         |Add
                   |std.algorithm.untilClosingP |std.algorithm.findMatchingP
                   |arens                       |aren

--- Comment #2 from Seb <greensunny12@gmail.com> ---
I just opened this issue because balancedParens is quite limited and could be generalized.

For the archive. Here's Andrei's response:

> Yah we should have an algorithm findMatchingParen that assumes r.front is the opening paren and advances the range until it's positioned on the corresponding closing paren. An optional rParen can be passed for unusual closing parens.

@Jack:

> I'm wondering how useful something like this would be in real world

There's the example from dlang.org to parse ddoc strings.
Here's another for finding everything within one HTML tag or all it's enclosing
ones:

"<foo foo=bar/>".findMatchingParen('<', '>').writeln; // foo foo=bar/
"<foo><bar/><foobar><bar/></foobar></foo>".findMatchingParen('<', '>',
2).writeln; // foo><bar/><foobar><bar/></foobar></foo>

https://run.dlang.io/is/ah7wmd

Of course, it would require a better, intuitive API to allow both use cases nicely.

--
January 30, 2018
https://issues.dlang.org/show_bug.cgi?id=18336

hsteoh@quickfur.ath.cx changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |hsteoh@quickfur.ath.cx

--- Comment #3 from hsteoh@quickfur.ath.cx ---
As Andrei suggested, one way to implement this would be something like this:

-----
R untilMatchingParens(R)(R range, dchar rightParen=')')
if (isInputRange!R)
{
    if (range.empty) return range; // base case
    auto leftParen = range.front; // <-- this is how we know what the starting
parens is
    range.popFront;

    int nesting = 1;
    foreach (ch; range)
    {
        if (ch == leftParen) nesting++;
        else if (ch == rightParen) nesting--;
        if (nesting == 0) break;
    }
    return range;
}
-----

Basically, the start of the range determines what the opening parens is, and the optional argument specifies what the closing parens is.

Of course, the above implementation could be improved (e.g., using memchr or whatever to find the parens characters), but this is just a proof-of-concept.

--
January 30, 2018
https://issues.dlang.org/show_bug.cgi?id=18336

Andrei Alexandrescu <andrei@erdani.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei@erdani.com

--- Comment #4 from Andrei Alexandrescu <andrei@erdani.com> ---
(In reply to hsteoh from comment #3)
> As Andrei suggested, one way to implement this would be something like this:
> 
> -----
> R untilMatchingParens(R)(R range, dchar rightParen=')')
> if (isInputRange!R)
> {
>     if (range.empty) return range; // base case
>     auto leftParen = range.front; // <-- this is how we know what the
> starting parens is
>     range.popFront;
> 
>     int nesting = 1;
>     foreach (ch; range)
>     {
>         if (ch == leftParen) nesting++;
>         else if (ch == rightParen) nesting--;
>         if (nesting == 0) break;
>     }
>     return range;
> }
> -----
> 
> Basically, the start of the range determines what the opening parens is, and the optional argument specifies what the closing parens is.

Yes, with the amendment there is no default for the closing paren. Instead, there's an overload without the closing paren:

R findMatchingParen(R)(R range) { ... }

That looks at range.front and then infers the closing paren as follows: ")" for "(", "}" for "{", "[" for "]", ">" for "<", and perhaps a few Unicode fancy parens too.

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=18336

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P4

--
December 01
https://issues.dlang.org/show_bug.cgi?id=18336

--- Comment #5 from dlangBugzillaToGithub <robert.schadek@posteo.de> ---
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/phobos/issues/9740

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB

--