hsutter / cppfront

A personal experimental C++ Syntax 2 -> Syntax 1 compiler
Other
5.53k stars 246 forks source link

[BUG] Confusion between postifx and binary use of `&` and `*` when keyword is part of the second argument. #1216

Open tsoj opened 3 months ago

tsoj commented 3 months ago

Describe the bug

main: () -> int = {
    b := 2 & int(3);
    std::cout << b << std::endl;
}

Compiling this results in an error:

[1/5] Generating _cppfront/main.cpp
FAILED: _cppfront/main.cpp /home/tsoj/Dokumente/Projects/Starthinker/build/_cppfront/main.cpp 
cd /home/tsoj/Dokumente/Projects/Starthinker/build && /home/tsoj/Dokumente/Projects/Starthinker/ext/cppfront/target/bin/cppfront /home/tsoj/Dokumente/Projects/Starthinker/src/main.cpp2 -o /home/tsoj/Dokumente/Projects/Starthinker/build/_cppfront/main.cpp
/home/tsoj/Dokumente/Projects/Starthinker/src/main.cpp2...
main.cpp2(2,10): error: ill-formed initializer (at '2')
main.cpp2(2,5): error: ill-formed initializer (at 'b')
main.cpp2(1,1): error: unexpected text at end of Cpp2 code section (at 'main')
main.cpp2(1,0): error: parse failed for section starting here

The same happens if I change the & to a *. However, if I change the line to

b := 2 & (int(3));

it works.

Maybe the problem is that here https://github.com/hsutter/cppfront/blob/c618ed507573e935d351b2918a6f1121a6e5bb5c/source/parse.h#L6058-L6073 it is not checked if the next token is one of the keywords that also suggest a binary & instead of a postfix one (i.e. this, const_cast, all the fundamental types, probably more that I am missing right now)

EDIT: I guess this also happens with cases like a := 1 * -(1); though here the error happens in the cpp1 compilation. Or

a: Hello = (); // Hello has a () operator
b := a&;
c := b*();
tsoj commented 2 months ago
Harry: type = {
    operator(): (this, i: int) -> int = 123 + i;
}

Spiderman: type = {
    operator*: (this) -> Harry = Harry();
    operator*: (this, i: int) -> int = 456 + i;
}

main: () -> int = {
    a:  Spiderman = ();
    b := (a*)(1 + 1);
    c := a*(1 + 1);
    std::cout << c << std::endl;
    std::cout << b << std::endl;
}

I don't think in this case there is a way to disambiguate without parenthesis.

EDIT: ah, i guess this is basically the same as #1068