www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Structure initializer VS lambda function

reply realhet <real_het hotmail.com> writes:
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!
Dec 12 2022
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
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
Dec 12 2022
prev sibling parent reply Tim <tim.dlang t-online.de> writes:
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(); }; ```
Dec 12 2022
parent realhet <real_het hotmail.com> writes:
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
Feb 19 2023