Thread overview
Structure initializer VS lambda function
Dec 12, 2022
realhet
Dec 12, 2022
Tim
Feb 19, 2023
realhet
December 12, 2022

Hi,

I'm writing a DLang parser and got confused of this.
What is a good way to distinguish lambda functions and structure initialization blocks.

Both of them are {} blocks.

I'm thinking of something like this:

  1. checking inside (on the first hierarchy level inside {})
    , => must be a struct initializer
    ; => must be a lambda
    no , and no ; => check it from the outside

  2. checking outside (on the same hierarchy level as the {}):
    () before {} -> lambda
    => before {} -> lambda
    () after {} -> lambda //this check feels wrong to me.
    otherwise -> struct initializer

But I think it's logically loose.
I have only the syntax tree, I have no access to semantics. I don't know if an identifier is a struct for example.

Is there a better way to do this?

Thank You in advance!

December 12, 2022

On 12/12/22 3:54 AM, realhet wrote:

>

Hi,

I'm writing a DLang parser and got confused of this.
What is a good way to distinguish lambda functions and structure initialization blocks.

Both of them are {} blocks.

I'm thinking of something like this:

  1. checking inside (on the first hierarchy level inside {})
       ,   => must be a struct initializer
       ;   => must be a lambda
       no , and no ;  => check it from the outside

  2. checking outside (on the same hierarchy level as the {}):
       () before {}   ->  lambda
       => before {}   ->  lambda
       () after {}    ->  lambda  //this check feels wrong to me.
       otherwise      ->  struct initializer

But I think it's logically loose.
I have only the syntax tree, I have no access to semantics. I don't know if an identifier is a struct for example.

Is there a better way to do this?

Thank You in advance!

This has actually been discussed recently on discord, I believe the difference is if you see a statement inside the braces (e.g. a semicolon).

It's not a great situation, and I think if we removed the ability to do lambdas with {} without leading parentheses, it could clear this up pretty well.

-Steve

December 12, 2022

On Monday, 12 December 2022 at 08:54:33 UTC, realhet wrote:

>
  1. checking inside (on the first hierarchy level inside {})
    , => must be a struct initializer
    ; => must be a lambda
    no , and no ; => check it from the outside

Some statements don't end in a semicolon, so you would also need to check for those. For example:

auto lambda = { while(f()){} };

A lambda can also contain a comma expression:

auto lambda = { f(), g(); };
February 19, 2023

Hi again and thanks for the suggestions.

I ended up checking every {} block with the following program:
It works on a string where all the nested blocks are reduced to a single symbol. For example: '{', '"', '['
And all the comments and whitespaces are reduced to ' ' space.

enum CurlyBlockKind { empty, declarationsOrStatements, list }

auto detectCurlyBlock(CodeColumn col_)
{
    auto p = col_.extractThisLevelDString.text;
    p = p.replace("\n", " ");
    p = p.replace("  ", " ");
    p = p.replace(" {", "{");
    p = p.replace(" [", "]");
    p = p.replace(" (", ")");
    //opt: these replaces are slow.
    p = p.strip;

    //first start with easy decisions at the end of the block
    if(p=="") return CurlyBlockKind.empty;
    if(p.endsWith(';') || p.endsWith(':')) return CurlyBlockKind.declarationsOrStatements;

    if(p.canFind("{,") || p.canFind(",{")) return CurlyBlockKind.list;
    if(p.canFind(';')||p.canFind('{')) return CurlyBlockKind.declarationsOrStatements;

    //give it up: it's not a declaration, neither a statement block
    return CurlyBlockKind.list;
}

Since 2.5 months I didn't changed it, and I use it every day, so it seems ok.

The only unsure thing in this detector is the empty block. That would require to check what's around the empty block, but I just decided to represent it with it's own category: "empty".

The recursive detection of all D statements and declarations become easy:

  • declarationsOrStatements -> Go inside this block and detect all the statements and declarations.
  • list -> Discover the nested blocks inside this block, but don't treat this block as declarations or statements, this is a list!
  • empty -> do nothing