@@ -599,32 +599,16 @@ fn Expr* Parser.parseSizeof(Parser* p) {
599
599
p.expectAndConsume(Kind.LParen);
600
600
601
601
Expr* res = nil;
602
- bool has_brackets = false;
603
602
SrcLoc type_loc = p.tok.loc;
604
- if (p.parseAsType(&has_brackets)) {
605
- if (has_brackets) {
606
- while (p.tok.kind != Kind.LSquare) p.consumeToken();
607
- p.error("arrays or subscripts expressions are not allowed inside a sizeof expression");
608
- }
609
- TypeRefHolder ref.init();
610
- p.parseTypeSpecifier(&ref, false, true);
603
+ if (p.parseAsType()) {
604
+ TypeRefHolder ref;
605
+ ref.init();
606
+ p.parseTypeSpecifier(&ref, true, true);
611
607
u32 src_len = p.prev_loc - type_loc;
612
608
res = p.builder.actOnTypeExpr(type_loc, src_len, &ref);
613
- } else { // parse as variable
614
- if (p.tok.kind != Kind.Identifier) {
615
- p.error("expect a type or variable name");
616
- }
617
- res = p.parseFullIdentifier();
618
-
619
- // parse optional array indexes (like array[0])
620
- while (p.tok.kind == Kind.LSquare) {
621
- SrcLoc loc1 = p.tok.loc;
622
- p.consumeToken();
623
- Expr* idx = p.parseExpr();
624
- u32 src_len = p.tok.loc + 1 - loc1;
625
- p.expectAndConsume(Kind.RSquare);
626
- res = p.builder.actOnArraySubscriptExpr(loc1, src_len, res, idx);
627
- }
609
+ } else {
610
+ // parse as expression
611
+ res = p.parseExpr();
628
612
}
629
613
630
614
u32 src_len = p.tok.loc + 1 - loc;
@@ -807,11 +791,9 @@ fn Expr* Parser.parseFullIdentifier(Parser* p) {
807
791
/*
808
792
parsing sizeof() is nasty, since the inner argument can be either an Expr or a Type!
809
793
810
- The reason we forbid brackets [] inside a sizeof is that its ambiguous; it can be
811
- an array (eg Foo[2]) or a subscript expression (a[2]). Also there is no real reason
812
- to keep them. Keep it simple.
813
-
814
- also: Foo can be type or Constant, just return Identifier (or Member if prefixed)
794
+ The reason we test brackets [] inside a sizeof is that it is potentially ambiguous;
795
+ it can be an array (eg Foo[2]) or a subscript expression (a[2]). We assume Foo to be
796
+ a type, but it could be a global Constant, in which case an error will be generated later.
815
797
816
798
i8,u8,. - type
817
799
X* - type
@@ -822,41 +804,67 @@ fn Expr* Parser.parseFullIdentifier(Parser* p) {
822
804
test.Foo - member (upper case, can be Constant or Type)
823
805
f.a - member (lower case)
824
806
test.f.a - member (lower case)
825
- Foo[..] - error ([] not allowed)
826
- test.Foo[..] - error ([] not allowed)
827
- (test.)a[..] - error ([] not allowed)
828
- Foo.a - error (need instantiation)
829
- test.Foo.a - error (need instantiation)
830
- (test.)a* - type (but will give error later)
807
+ Foo[..] - can be Constant element or Type array, assume Type array
808
+ test.Foo[..] - can be Constant element or Type array, assume Type array
809
+ a[..] - subscript expression
810
+ test.a[..] - subscript expression
811
+ Foo.a - error (need instantiation, should accept as extension)
812
+ test.Foo.a - error (need instantiation, should accept as extension)
813
+ a* - type (but will give error later)
814
+ test.a* - type (but will give error later)
831
815
*/
832
- fn bool Parser.parseAsType(Parser* p, bool* has_brackets) {
833
- const Kind kind = p.tok.kind;
816
+ fn bool Parser.parseAsType(Parser* p) {
817
+ Token t2 = p.tok;
818
+ bool is_lower = false;
819
+ u32 ahead = 1;
820
+
821
+ Kind kind = t2.kind;
834
822
if (kind.isQualifier()) return true;
835
823
if (p.tok.kind != Kind.Identifier) {
836
824
if (kind.isBuiltinType())
837
825
return (p.tokenizer.lookahead(1, nil) != Kind.Dot);
838
826
}
839
827
840
- u32 lookahead = 1;
841
- while (1) {
842
- switch (p.tokenizer.lookahead(lookahead, nil)) {
843
- case Identifier:
828
+ // parse member list
829
+ for (;;) {
830
+ // is_lower is true if the last identifier starts with a lowercase letter
831
+ is_lower = islower(p.pool.idx2str(t2.name_idx)[0]);
832
+ if (p.tokenizer.lookahead(ahead, nil) != Kind.Dot)
844
833
break;
834
+ ahead++;
835
+ if (p.tokenizer.lookahead(ahead, &t2) != Kind.Identifier)
836
+ return false;
837
+ ahead++;
838
+ }
839
+ i32 stars = 0;
840
+ while (1) {
841
+ switch (p.tokenizer.lookahead(ahead, nil)) {
845
842
case Star:
846
- return true;
847
- case Dot:
843
+ if (stars) return true; // sizeof(a**...)
844
+ stars++;
845
+ ahead++;
848
846
break;
847
+ case RParen:
848
+ if (stars) return true; // sizeof(a.b*)
849
+ return false; // unknown
849
850
case LSquare:
850
- *has_brackets = true;
851
+ if (stars) return true; // sizeof(MyType*[...])
852
+ // if last identifier starts with lowercase, it must be a variable
853
+ // hence reject as type and parse as expression
854
+ if (is_lower) return false;
855
+ // otherwise cannot distinguish typename from global constant
856
+ // let's assume capitalized name is type (eg: sizeof(MyType[20]))
857
+ // cannot handle sizeof(GlobalConst[0])
851
858
return true;
852
859
case Less:
853
- return true;
860
+ // parametric type sizeof(Type<X>)
861
+ if (is_lower) return false;
862
+ return true; // sizeof(a < b)
854
863
default:
855
864
return false;
856
865
}
857
- lookahead++;
858
866
}
859
-
867
+ // never reached
860
868
return false;
861
869
}
862
870
0 commit comments