()
| 833 | |
| 834 | // t = int|i8|i16|i32|i64|u8|u16|u32|u64|byte|bool | flt|f32|f64 | val | var | struct[?] |
| 835 | private Type type() { |
| 836 | int old1 = pos(); |
| 837 | // Only type with a leading `{` is a function pointer... |
| 838 | if( peek('{') ) return typeFunPtr(); |
| 839 | |
| 840 | // Otherwise you get a type name |
| 841 | String tname = _lexer.matchId(); |
| 842 | if( tname==null ) return null; |
| 843 | |
| 844 | // Convert the type name to a type. |
| 845 | Type t0 = TYPES.get(tname); |
| 846 | // No new types as keywords |
| 847 | if( t0 == null && KEYWORDS.contains(tname) ) |
| 848 | return posT(old1); |
| 849 | if( t0 == Type.BOTTOM || t0 == Type.TOP ) return t0; // var/val type inference |
| 850 | |
| 851 | // Check for subtype. |
| 852 | while( true ) { |
| 853 | int old2 = pos(); |
| 854 | if( !match(".") ) break; |
| 855 | String sname = _lexer.matchId(); |
| 856 | if( sname==null ) { pos(old2); break; } |
| 857 | String tsname = tname+"."+sname; |
| 858 | t0 = TYPES.get(tsname); |
| 859 | if( t0==null ) { pos(old2); t0 = TYPES.get(tname); break; } |
| 860 | tname = tsname; |
| 861 | } |
| 862 | |
| 863 | // Still no type found? Assume forward reference |
| 864 | Type t1 = t0 == null ? TypeMemPtr.make(TypeStruct.makeFRef(tname)) :t0; // Null: assume a forward ref type |
| 865 | // Nest arrays and '?' as needed |
| 866 | Type t2 = t1; |
| 867 | while( true ) { |
| 868 | if( match("?") ) { |
| 869 | if( !(t2 instanceof TypeMemPtr tmp) ) |
| 870 | throw error("Type "+t0+" cannot be null"); |
| 871 | if( tmp.nullable() ) throw error("Type "+t2+" already allows null"); |
| 872 | t2 = tmp.makeNullable(); |
| 873 | } else if( match("[~]") ) { |
| 874 | TypeMemPtr tmp = typeAry(t2); |
| 875 | t2 = tmp.makeFrom(tmp._obj.makeRO()); |
| 876 | } else if( match("[]") ) { |
| 877 | t2 = typeAry(t2); |
| 878 | } else |
| 879 | break; |
| 880 | } |
| 881 | |
| 882 | // Check no forward ref |
| 883 | if( t0 != null ) return t2; |
| 884 | // Check valid forward ref, after parsing all the type extra bits. |
| 885 | // Cannot check earlier, because cannot find required 'id' until after "[]?" syntax |
| 886 | int old2 = pos(); |
| 887 | match("!"); |
| 888 | String id = _lexer.matchId(); |
| 889 | if( !(peek(',') || peek(';') || match("->")) || id==null ) |
| 890 | return posT(old1); // Reset lexer to reparse |
| 891 | pos(old2); // Reset lexer to reparse |
| 892 | // Yes a forward ref, so declare it |
no test coverage detected