FreeBASIC  0.91.0
parser-decl-symbtype.bas
Go to the documentation of this file.
1 '' symbol type (BYTE, INTEGER, STRING, ...) declarations
2 ''
3 '' chng: sep/2004 written [v1ctor]
4 
5 
6 #include once "fb.bi"
7 #include once "fbint.bi"
8 #include once "parser.bi"
9 #include once "ast.bi"
10 #include once "rtl.bi"
11 
12 function cConstIntExpr _
13  ( _
14  byval expr as ASTNODE ptr, _
15  byval defaultvalue as longint _
16  ) as longint
17 
18  if( expr = NULL ) then
19  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
20  expr = astNewCONSTi( defaultvalue )
21  end if
22 
23  if( astIsCONST( expr ) = FALSE ) then
24  errReport( FB_ERRMSG_EXPECTEDCONST )
25  astDelTree( expr )
26  expr = astNewCONSTi( defaultvalue )
27  end if
28 
29  function = astConstFlushToInt( expr )
30 end function
31 
32 function cSymbolTypeFuncPtr( byval is_func as integer ) as FBSYMBOL ptr
33  dim as integer dtype = any, mode = any, attrib = any
34  dim as FBSYMBOL ptr proc = any, subtype = any
35 
36  function = NULL
37  attrib = 0
38  subtype = NULL
39 
40  ' no need for naked check here, naked only effects the way a function
41  ' is emitted, not the way it's called
42 
43  '' mode
44  mode = cProcCallingConv( )
45 
46  proc = symbPreAddProc( NULL )
47 
48  '' Parameters?
49  cParameters( NULL, proc, mode, TRUE )
50 
51  '' BYREF?
52  cByrefAttribute( attrib, is_func )
53 
54  '' (AS SymbolType)?
55  if( lexGetToken( ) = FB_TK_AS ) then
56  '' if it was SUB, don't allow a return type
57  if( is_func = FALSE ) then
58  errReport( FB_ERRMSG_SYNTAXERROR )
59  dtype = FB_DATATYPE_VOID
60  else
61  cProcRetType( attrib, proc, TRUE, dtype, subtype )
62  end if
63  else
64  '' if it's a function and type was not given, it can't be guessed
65  if( is_func ) then
66  errReport( FB_ERRMSG_EXPECTEDRESTYPE )
67  '' error recovery: fake a type
68  dtype = FB_DATATYPE_INTEGER
69  else
70  dtype = FB_DATATYPE_VOID
71  end if
72  end if
73 
74  function = symbAddProcPtr( proc, dtype, subtype, attrib, mode )
75 end function
76 
77 function cTypeOrExpression _
78  ( _
79  byval is_len as integer, _
80  byref dtype as integer, _
81  byref subtype as FBSYMBOL ptr, _
82  byref lgt as longint _
83  ) as ASTNODE ptr
84 
85  dim as ASTNODE ptr expr = any
86  dim as integer maybe_type = any, check_array = any
87 
88  '' This is ambiguous because functions/variables may use the same name
89  '' as types, for example STRING and STRING(). The same can happen with
90  '' user-defined types/aliases.
91  '' Disambiguation:
92  '' - Types can't be followed by an operator, except for '*', which can
93  '' be used in 'STRING * N'. Note: We can't just check for
94  '' '{Z|W}STRING *' because '*' also works with {z|w}string typedefs,
95  '' e.g. 'myZstringTypedef * N'.
96  '' - Types can't be followed by '[' or '(', except for:
97  '' TYPEOF|SUB|FUNCTION(...)
98  '' - Note: '.' doesn't make it an expression, because it could be a
99  '' type in a namespace.
100 
101  maybe_type = TRUE
102 
103  '' Token followed by an operator except '*' / '<'?
104  if( (lexGetLookAheadClass( 1 ) = FB_TKCLASS_OPERATOR) andalso _
105  (lexGetLookAhead( 1 ) <> CHAR_TIMES) andalso _
106  (lexGetLookAhead( 1 ) <> FB_TK_LT) ) then
107  maybe_type = FALSE
108  else
109  '' Check for some non-operator tokens
110  select case( lexGetLookAhead( 1 ) )
111  case CHAR_LBRACKET '' [
112  maybe_type = FALSE
113  case CHAR_LPRNT '' (
114  '' Not a TYPEOF/SUB/FUNCTION though?
115  select case( lexGetToken( ) )
116  case FB_TK_TYPEOF, FB_TK_SUB, FB_TK_FUNCTION
117 
118  case else
119  maybe_type = FALSE
120  end select
121  end select
122  end if
123 
124  '' QB quirk: LEN() only takes expressions
125  if( maybe_type and is_len and fbLangIsSet( FB_LANG_QB ) ) then
126  maybe_type = FALSE
127  end if
128 
129  if( maybe_type ) then
130  '' Parse as type
131  if( cSymbolType( dtype, subtype, lgt, FB_SYMBTYPEOPT_NONE ) ) then
132  '' Successful -- it's a type, not an expression
133  return NULL
134  end if
135  end if
136 
137  '' Parse as expression, allowing NIDXARRAYs
138  check_array = fbGetCheckArray( )
139  fbSetCheckArray( FALSE )
140  expr = cExpression( )
141  fbSetCheckArray( check_array )
142  if( expr = NULL ) then
143  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
144  '' error recovery: fake an expr
145  expr = astNewCONSTi( 0 )
146  end if
147 
148  function = expr
149 end function
150 
151 sub cTypeOf _
152  ( _
153  byref dtype as integer, _
154  byref subtype as FBSYMBOL ptr, _
155  byref lgt as longint _
156  )
157 
158  dim as ASTNODE ptr expr = any
159 
160  '' Type or an Expression
161  expr = cTypeOrExpression( FALSE, dtype, subtype, lgt )
162 
163  '' Was it a type?
164  if( expr = NULL ) then
165  exit sub
166  end if
167 
168  '' ugly hack to deal with arrays w/o indexes
169  if( astIsNIDXARRAY( expr ) ) then
170  dim as ASTNODE ptr temp_node = expr
171  expr = astGetLeft( expr )
172  astDelNode( temp_node )
173  end if
174 
175  dtype = astGetFullType( expr )
176  subtype = astGetSubtype( expr )
177  lgt = astSizeOf( expr )
178 
179  astDelTree( expr )
180 end sub
181 
182 function hIntegerTypeFromBitSize _
183  ( _
184  byval bitsize as longint, _
185  byval is_unsigned as integer _
186  ) as FB_DATATYPE
187 
188  dim as FB_DATATYPE dtype
189 
190  select case bitsize
191  case 8
192  dtype = FB_DATATYPE_BYTE
193  case 16
194  dtype = FB_DATATYPE_SHORT
195  case 32
196  dtype = FB_DATATYPE_LONG
197  case 64
198  dtype = FB_DATATYPE_LONGINT
199  case else
200  errReport( FB_ERRMSG_INVALIDSIZE, TRUE )
201  dtype = FB_DATATYPE_INTEGER
202  end select
203 
204  if( is_unsigned ) then
205  dtype = typeToUnsigned( dtype )
206  end if
207 
208  return dtype
209 
210 end function
211 
212 '':::::
213 ''SymbolType = CONST? UNSIGNED? (
214 '' ANY
215 '' | CHAR|BYTE
216 '' | SHORT|WORD
217 '' | INTEGER|LONG|DWORD
218 '' | SINGLE
219 '' | DOUBLE
220 '' | STRING ('*' NUM_LIT)?
221 '' | USERDEFTYPE
222 '' | (FUNCTION|SUB) ('(' args ')') (AS SymbolType)?
223 '' (CONST? (PTR|POINTER))* .
224 ''
225 function cSymbolType _
226  ( _
227  byref dtype as integer, _
228  byref subtype as FBSYMBOL ptr, _
229  byref lgt as longint, _
230  byval options as FB_SYMBTYPEOPT _
231  ) as integer
232 
233  dim as integer isunsigned = any, isfunction = any
234 
235  function = FALSE
236 
237  lgt = 0
238  dtype = FB_DATATYPE_INVALID
239  subtype = NULL
240 
241  dim as integer is_const = FALSE
242  dim as integer ptr_cnt = 0
243 
244  '' TYPEOF?
245  if( lexGetToken( ) = FB_TK_TYPEOF ) then
246  lexSkipToken( )
247 
248  '' '('
249  if( hMatch( CHAR_LPRNT ) = FALSE ) then
250  errReport( FB_ERRMSG_EXPECTEDLPRNT )
251  '' error recovery: skip until ')'
252  hSkipUntil( CHAR_RPRNT, TRUE )
253  end if
254 
255  '' datatype
256  cTypeOf( dtype, subtype, lgt )
257 
258  '' ')'
259  if( hMatch( CHAR_RPRNT ) = FALSE ) then
260  errReport( FB_ERRMSG_EXPECTEDRPRNT )
261  '' error recovery: skip until ')'
262  hSkipUntil( CHAR_RPRNT, TRUE )
263  end if
264  else
265  '' CONST?
266  if( lexGetToken( ) = FB_TK_CONST ) then
267  lexSkipToken( )
268  is_const = TRUE
269  end if
270 
271  '' UNSIGNED?
272  isunsigned = hMatch( FB_TK_UNSIGNED )
273 
274  ''
275  select case as const lexGetToken( )
276  case FB_TK_ANY
277  lexSkipToken( )
278  dtype = FB_DATATYPE_VOID
279 
280  case FB_TK_BYTE
281  lexSkipToken( )
282  dtype = FB_DATATYPE_BYTE
283 
284  case FB_TK_UBYTE
285  lexSkipToken( )
286  dtype = FB_DATATYPE_UBYTE
287 
288  case FB_TK_SHORT
289  lexSkipToken( )
290  dtype = FB_DATATYPE_SHORT
291 
292  case FB_TK_USHORT
293  lexSkipToken( )
294  dtype = FB_DATATYPE_USHORT
295 
296  case FB_TK_INTEGER
297  lexSkipToken( )
298 
299  '' ['<' lgt '>']
300  if( hMatch( FB_TK_LT ) ) then
301 
302  '' expr
304 
305  dtype = hIntegerTypeFromBitSize( lgt, FALSE )
306 
307  if( hMatch( FB_TK_GT ) = FALSE ) then
308  errReport( FB_ERRMSG_EXPECTEDGT, TRUE )
309  end if
310  else
311 
312  dtype = env.lang.integerkeyworddtype
313 
314  end if
315 
316  case FB_TK_UINT
317  lexSkipToken( )
318 
319  '' ['<' lgt '>']
320  if( hMatch( FB_TK_LT ) ) then
321 
322  '' expr
324 
325  dtype = hIntegerTypeFromBitSize( lgt, TRUE )
326 
327  if( hMatch( FB_TK_GT ) = FALSE ) then
328  errReport( FB_ERRMSG_EXPECTEDGT, TRUE )
329  end if
330 
331  else
332 
333  dtype = FB_DATATYPE_UINT
334 
335  end if
336 
337  case FB_TK_LONG
338  lexSkipToken( )
339  dtype = FB_DATATYPE_LONG
340 
341  case FB_TK_ULONG
342  lexSkipToken( )
343  dtype = FB_DATATYPE_ULONG
344 
345  case FB_TK_LONGINT
346  lexSkipToken( )
347  dtype = FB_DATATYPE_LONGINT
348 
349  case FB_TK_ULONGINT
350  lexSkipToken( )
351  dtype = FB_DATATYPE_ULONGINT
352 
353  case FB_TK_SINGLE
354  lexSkipToken( )
355  dtype = FB_DATATYPE_SINGLE
356 
357  case FB_TK_DOUBLE
358  lexSkipToken( )
359  dtype = FB_DATATYPE_DOUBLE
360 
361  case FB_TK_STRING
362  lexSkipToken( )
363 
364  '' assume it's a var-len string, see below for fixed-len
365  dtype = FB_DATATYPE_STRING
366 
367  case FB_TK_ZSTRING
368  lexSkipToken( )
369 
370  '' assume it's a pointer, see below for fixed-len
371  dtype = FB_DATATYPE_CHAR
372 
373  case FB_TK_WSTRING
374  lexSkipToken( )
375 
376  '' ditto
377  dtype = FB_DATATYPE_WCHAR
378 
379  case FB_TK_FUNCTION, FB_TK_SUB
380  isfunction = (lexGetToken( ) = FB_TK_FUNCTION)
381  lexSkipToken( )
382 
383  dtype = typeAddrOf( FB_DATATYPE_FUNCTION )
384  ptr_cnt += 1
385 
386  subtype = cSymbolTypeFuncPtr( isfunction )
387  if( subtype = NULL ) then
388  exit function
389  end if
390 
391  end select
392 
393  if( dtype <> FB_DATATYPE_INVALID ) then
394  lgt = typeGetSize( dtype )
395  else
396  dim as FBSYMCHAIN ptr chain_ = NULL
397  dim as FBSYMBOL ptr base_parent = any
398  dim as integer check_id = TRUE
399 
400  if( parser.stmt.with.sym <> NULL ) then
401  if( lexGetToken( ) = CHAR_DOT ) then
402  '' not a '..'?
403  check_id = (lexGetLookAhead( 1, LEXCHECK_NOPERIOD ) = CHAR_DOT)
404  end if
405  end if
406 
407  if( check_id ) then
408  chain_ = cIdentifier( base_parent, FB_IDOPT_DEFAULT or FB_IDOPT_ALLOWSTRUCT )
409  end if
410 
411  if( chain_ ) then
412  do
413  dim as FBSYMBOL ptr sym = chain_->sym
414  do
415  select case symbGetClass( sym )
416  case FB_SYMBCLASS_STRUCT
417  lexSkipToken( )
418  dtype = FB_DATATYPE_STRUCT
419  subtype = sym
420  lgt = symbGetLen( sym )
421  exit do, do
422 
423  case FB_SYMBCLASS_ENUM
424  lexSkipToken( )
425  dtype = FB_DATATYPE_ENUM
426  subtype = sym
427  lgt = typeGetSize( FB_DATATYPE_ENUM )
428  exit do, do
429 
430  case FB_SYMBCLASS_TYPEDEF
431  lexSkipToken( )
432  dtype = symbGetFullType( sym )
433  subtype = symbGetSubtype( sym )
434  lgt = symbGetLen( sym )
435  ptr_cnt += typeGetPtrCnt( dtype )
436  exit do, do
437  end select
438 
439  sym = sym->hash.next
440  loop while( sym <> NULL )
441 
442  chain_ = symbChainGetNext( chain_ )
443  loop while( chain_ <> NULL )
444  end if
445  end if
446 
447  '' no type?
448  if( dtype = FB_DATATYPE_INVALID ) then
449  if( isunsigned ) then
450  errReport( FB_ERRMSG_SYNTAXERROR )
451  end if
452 
453  if( is_const ) then
454  dtype = typeSetIsConst( FB_DATATYPE_VOID )
455  end if
456 
457  return FALSE
458  end if
459 
460  '' unsigned?
461  if( isunsigned ) then
462  '' remap type, if valid
463  select case as const typeGet( dtype )
464  case FB_DATATYPE_BYTE
465  dtype = FB_DATATYPE_UBYTE
466 
467  case FB_DATATYPE_SHORT
468  dtype = FB_DATATYPE_USHORT
469 
470  case FB_DATATYPE_INTEGER
471  dtype = FB_DATATYPE_UINT
472 
473  case FB_DATATYPE_LONG
474  dtype = FB_DATATYPE_ULONG
475 
476  case FB_DATATYPE_LONGINT
477  dtype = FB_DATATYPE_ULONGINT
478 
479  case else
480  errReport( FB_ERRMSG_SYNTAXERROR, TRUE )
481  end select
482  end if
483  end if
484 
485  '' fixed-len z|w|string? (must be handled here because the typedefs)
486  if( lexGetToken( ) = CHAR_TIMES ) then
487  lexSkipToken( )
488 
489  '' expr
491 
492  select case as const typeGet( dtype )
493  case FB_DATATYPE_STRING
494  '' plus the null-term
495  lgt += 1
496 
497  '' min 1 char (+ null-term)
498  if( lgt <= 1 ) then
499  errReport( FB_ERRMSG_SYNTAXERROR, TRUE )
500  '' error recovery: fake a len
501  lgt = 2
502  end if
503 
504  '' remap type
505  dtype = FB_DATATYPE_FIXSTR
506 
507  case FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR
508  '' min 1 char
509  if( lgt < 1 ) then
510  errReport( FB_ERRMSG_SYNTAXERROR, TRUE )
511  '' error recovery: fake a len
512  lgt = 1
513  end if
514 
515  '' note: len of "wstring * expr" symbols will be actually
516  '' the number of chars times sizeof(wstring), so
517  '' always use symbGetWstrLen( ) to retrieve the
518  '' len in characters, not the bytes
519  if( typeGet( dtype ) = FB_DATATYPE_WCHAR ) then
520  lgt *= typeGetSize( FB_DATATYPE_WCHAR )
521  end if
522 
523  case else
524  errReport( FB_ERRMSG_SYNTAXERROR, TRUE )
525 
526  end select
527 
528  '' const?
529  if( is_const ) then
530  dtype = typeSetIsConst( dtype )
531  end if
532  else
533  '' const?
534  if( is_const ) then
535  dtype = typeSetIsConst( dtype )
536  end if
537 
538  '' (CONST (PTR|POINTER) | (PTR|POINTER))*
539  do
540  select case as const lexGetToken( )
541  '' CONST PTR?
542  case FB_TK_CONST
543  lexSkipToken( )
544 
545  select case lexGetToken( )
546  case FB_TK_PTR, FB_TK_POINTER
547  if( ptr_cnt >= FB_DT_PTRLEVELS ) then
548  errReport( FB_ERRMSG_TOOMANYPTRINDIRECTIONS )
549  else
550  dtype = typeSetIsConst( typeAddrOf( dtype ) )
551  ptr_cnt += 1
552  end if
553 
554  lexSkipToken( )
555 
556  case else
557  errReport( FB_ERRMSG_EXPECTEDPTRORPOINTER )
558  exit do
559  end select
560 
561  '' PTR|POINTER?
562  case FB_TK_PTR, FB_TK_POINTER
563  if( ptr_cnt >= FB_DT_PTRLEVELS ) then
564  errReport( FB_ERRMSG_TOOMANYPTRINDIRECTIONS )
565  else
566  dtype = typeAddrOf( dtype )
567  ptr_cnt += 1
568  end if
569 
570  lexSkipToken( )
571 
572  case else
573  exit do
574  end select
575  loop
576  end if
577 
578  if( ptr_cnt > 0 ) then
579  lgt = typeGetSize( dtype )
580  else
581  '' can't have forward typedef's if they aren't pointers
582  if( typeGet( dtype ) = FB_DATATYPE_FWDREF ) then
583  '' forward types are allowed in func prototypes with byref params
584  if( (options and FB_SYMBTYPEOPT_ALLOWFORWARD) = 0 ) then
585  errReport( FB_ERRMSG_INCOMPLETETYPE, TRUE )
586  '' error recovery: fake a type
587  dtype = typeAddrOf( FB_DATATYPE_VOID )
588  subtype = NULL
589  end if
590 
591  elseif( lgt <= 0 ) then
592  select case as const typeGet( dtype )
593  case FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR
594  '' LEN() and SIZEOF() allow Z|WSTRING to be used w/o PTR
595  '' (and also BYREF parameters/results)
596  if( (options and FB_SYMBTYPEOPT_CHECKSTRPTR) <> 0 ) then
597  errReport( FB_ERRMSG_EXPECTEDPOINTER )
598  '' error recovery: make pointer
599  dtype = typeAddrOf( dtype )
600  end if
601  lgt = typeGetSize( dtype )
602  end select
603  end if
604  end if
605 
606  function = TRUE
607 
608 end function
609