()
| 676 | |
| 677 | // t = int|i8|i16|i32|i64|u8|u16|u32|u64|byte|bool | flt|f32|f64 | val | var | struct[?] |
| 678 | private Type type() { |
| 679 | int old1 = pos(); |
| 680 | String tname = _lexer.matchId(); |
| 681 | if( tname==null ) return null; |
| 682 | // Convert the type name to a type. |
| 683 | Type t0 = TYPES.get(tname); |
| 684 | // No new types as keywords |
| 685 | if( t0 == null && KEYWORDS.contains(tname) ) |
| 686 | return posT(old1); |
| 687 | Type t1 = t0 == null ? TypeMemPtr.make(TypeStruct.makeFRef(tname)) : t0; // Null: assume a forward ref type |
| 688 | // Nest arrays and '?' as needed |
| 689 | Type t2 = t1; |
| 690 | while( true ) { |
| 691 | assert !(t2 instanceof TypeStruct); |
| 692 | if( match("?") ) { |
| 693 | if( !(t2 instanceof TypeMemPtr tmp) ) |
| 694 | throw error("Type "+t0+" cannot be null"); |
| 695 | if( tmp._nil ) throw error("Type "+t2+" already allows null"); |
| 696 | t2 = TypeMemPtr.make(tmp._obj,true); |
| 697 | } else if( match("[]") ) { |
| 698 | t2 = typeAry(t2); |
| 699 | } else |
| 700 | break; |
| 701 | } |
| 702 | |
| 703 | // Check no forward ref |
| 704 | if( t0 != null ) return t2; |
| 705 | // Check valid forward ref, after parsing all the type extra bits. |
| 706 | // Cannot check earlier, because cannot find required 'id' until after "[]?" syntax |
| 707 | int old2 = pos(); |
| 708 | String id = _lexer.matchId(); |
| 709 | pos(old2); // Reset lexer to reparse |
| 710 | if( id==null || _scope.lookup(id)!=null ) |
| 711 | return posT(old1); // Reset lexer to reparse |
| 712 | // Yes a forward ref, so declare it |
| 713 | TYPES.put(tname,t1); |
| 714 | return t2; |
| 715 | } |
| 716 | |
| 717 | // Make an array type of t |
| 718 | private TypeMemPtr typeAry( Type t ) { |
no test coverage detected