FreeBASIC  0.91.0
parser-expr-binary.bas
Go to the documentation of this file.
1 '' binary operators (+, \, MOD, ...) parsing
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 declare function cLogOrExpression _
13  ( _
14  _
15  ) as ASTNODE ptr
16 
17 declare function cLogAndExpression _
18  ( _
19  _
20  ) as ASTNODE ptr
21 
22 declare function cIsExpression _
23  ( _
24  _
25  ) as ASTNODE ptr
26 
27 '':::::
28 ''Expression = LogExpression .
29 ''
30 function cExpression _
31  ( _
32  _
33  ) as ASTNODE ptr
34 
35  dim as integer last_isexpr = fbGetIsExpression( )
36  fbSetIsExpression( TRUE )
37 
38  '' LogExpression
39  function = cBoolExpression( )
40 
41  fbSetIsExpression( last_isexpr )
42 
43 end function
44 
45 
46 '':::::
47 ''BoolExpression = LogExpression ( (ANDALSO | ORELSE ) LogExpression )* .
48 ''
49 function cBoolExpression( ) as ASTNODE ptr
50  dim as integer op = any, dtorlistcookie = any
51  dim as ASTNODE ptr expr = any, logexpr = any
52 
53  '' LogExpression
54  '' The first operand expression will always be executed
55  logexpr = cLogExpression( )
56  if( logexpr = NULL ) then
57  return NULL
58  end if
59 
60  '' ( ... )*
61  do
62  '' Logical operator
63  select case as const lexGetToken( )
64  case FB_TK_ANDALSO
65  op = AST_OP_ANDALSO
66  case FB_TK_ORELSE
67  op = AST_OP_ORELSE
68  case else
69  exit do
70  end select
71 
72  lexSkipToken( )
73 
74  '' LogExpression
75  '' The second operand expression however only conditionally
77  expr = cLogExpression( )
78  dtorlistcookie = astDtorListScopeEnd( )
79  if( expr = NULL ) then
80  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
81  exit do
82  end if
83 
84  logexpr = astNewBOP( op, logexpr, expr, cptr( any ptr, dtorlistcookie ) )
85  if( logexpr = NULL ) then
86  errReport( FB_ERRMSG_TYPEMISMATCH )
87  '' error recovery: fake a node
88  logexpr = astNewCONSTi( 0 )
89  end if
90  loop
91 
92  function = logexpr
93 end function
94 
95 '':::::
96 ''LogExpression = LogOrExpression ( (XOR | EQV | IMP) LogOrExpression )* .
97 ''
98 function cLogExpression _
99  ( _
100  _
101  ) as ASTNODE ptr
102 
103  dim as integer op = any
104  dim as ASTNODE ptr expr = any, logexpr = any
105 
106  '' LogOrExpression
107  logexpr = cLogOrExpression( )
108  if( logexpr = NULL ) then
109  return NULL
110  end if
111 
112  '' ( ... )*
113  do
114  '' Logical operator
115  select case as const lexGetToken( )
116  case FB_TK_XOR
117  op = AST_OP_XOR
118  case FB_TK_EQV
119  op = AST_OP_EQV
120  case FB_TK_IMP
121  op = AST_OP_IMP
122  case else
123  exit do
124  end select
125 
126  lexSkipToken( )
127 
128  '' LogOrExpression
129  expr = cLogOrExpression( )
130  if( expr = NULL ) then
131  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
132  exit do
133  end if
134 
135  '' do operation
136  logexpr = astNewBOP( op, logexpr, expr )
137 
138  if( logexpr = NULL ) then
139  errReport( FB_ERRMSG_TYPEMISMATCH )
140  '' error recovery: fake a node
141  logexpr = astNewCONSTi( 0 )
142  end if
143 
144  loop
145 
146  function = logexpr
147 
148 end function
149 
150 '':::::
151 ''LogOrExpression = LogAndExpression ( OR LogAndExpression )* .
152 ''
153 function cLogOrExpression _
154  ( _
155  _
156  ) as ASTNODE ptr
157 
158  dim as ASTNODE ptr expr = any, logexpr = any
159 
160  '' LogAndExpression
161  logexpr = cLogAndExpression( )
162  if( logexpr = NULL ) then
163  return NULL
164  end if
165 
166  '' ( ... )*
167  do
168  '' OR?
169  if( lexGetToken( ) <> FB_TK_OR ) then
170  exit do
171  end if
172 
173  lexSkipToken( )
174 
175  '' LogAndExpression
176  expr = cLogAndExpression( )
177  if( expr = NULL ) then
178  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
179  exit do
180  end if
181 
182  '' do operation
183  logexpr = astNewBOP( AST_OP_OR, logexpr, expr )
184 
185  if( logexpr = NULL ) then
186  errReport( FB_ERRMSG_TYPEMISMATCH )
187  '' error recovery: fake a node
188  logexpr = astNewCONSTi( 0 )
189  end if
190 
191  loop
192 
193  function = logexpr
194 
195 end function
196 
197 '':::::
198 ''LogAndExpression = RelExpression ( AND RelExpression )* .
199 ''
200 function cLogAndExpression _
201  ( _
202  _
203  ) as ASTNODE ptr
204 
205  dim as ASTNODE ptr expr = any, logexpr = any
206 
207  '' RelExpression
208  logexpr = cRelExpression( )
209  if( logexpr = NULL ) then
210  return NULL
211  end if
212 
213  '' ( ... )*
214  do
215  '' AND?
216  if( lexGetToken( ) <> FB_TK_AND ) then
217  exit do
218  end if
219 
220  lexSkipToken( )
221 
222  '' RelExpression
223  expr = cRelExpression( )
224  if( expr = NULL ) then
225  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
226  exit do
227  end if
228 
229  '' do operation
230  logexpr = astNewBOP( AST_OP_AND, logexpr, expr )
231 
232  if( logexpr = NULL ) then
233  errReport( FB_ERRMSG_TYPEMISMATCH )
234  '' error recovery: fake a node
235  logexpr = astNewCONSTi( 0 )
236  end if
237 
238  loop
239 
240  function = logexpr
241 
242 end function
243 
244 '':::::
245 ''RelExpression = IsExpression ( (EQ | GT | LT | NE | LE | GE) IsExpression )* .
246 ''
247 function cRelExpression _
248  ( _
249  _
250  ) as ASTNODE ptr
251 
252  dim as integer op = any
253  dim as ASTNODE ptr expr = any, relexpr = any
254 
255  '' IsExpression
256  relexpr = cIsExpression( )
257  if( relexpr = NULL ) then
258  return NULL
259  end if
260 
261  '' ( ... )*
262  do
263  '' Relational operator
264  select case as const lexGetToken( )
265  case FB_TK_EQ
266  parser.have_eq_outside_parens = (parser.prntcnt = 0)
267 
268  '' outside parentheses? (cParentExpression() would have
269  '' unset this flag otherwise)
270  if( fbGetEqInParensOnly( ) ) then
271  exit do
272  end if
273  op = AST_OP_EQ
274  case FB_TK_GT
275  if( fbGetGtInParensOnly( ) ) then
276  exit do
277  end if
278  op = AST_OP_GT
279  case FB_TK_LT
280  op = AST_OP_LT
281  case FB_TK_NE
282  op = AST_OP_NE
283  case FB_TK_LE
284  op = AST_OP_LE
285  case FB_TK_GE
286  op = AST_OP_GE
287  assert( fbGetGtInParensOnly( ) = FALSE )
288  case else
289  exit do
290  end select
291 
292  lexSkipToken( )
293 
294  '' IsExpression
295  expr = cIsExpression( )
296  if( expr = NULL ) then
297  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
298  exit do
299  end if
300 
301  '' do operation
302  relexpr = astNewBOP( op, relexpr, expr )
303 
304  if( relexpr = NULL ) Then
305  errReport( FB_ERRMSG_TYPEMISMATCH )
306  '' error recovery: fake a node
307  relexpr = astNewCONSTi( 0 )
308  end if
309  loop
310 
311  function = relexpr
312 
313 end function
314 
315 '':::::
316 ''IsExpression = CatExpression IS SymbolType .
317 ''
318 function cIsExpression _
319  ( _
320  _
321  ) as ASTNODE ptr
322 
323  '' CatExpression
324  dim as ASTNODE ptr isexpr = cCatExpression( )
325  if( isexpr = NULL ) then
326  return NULL
327  end if
328 
329  '' IS?
330  if( lexGetToken( ) <> FB_TK_IS ) then
331  return isexpr
332  end if
333 
334  '' must be a struct with RTTI info
335  if( astGetDataType( isexpr ) = FB_DATATYPE_STRUCT ) then
336  if( symbGetHasRTTI( astGetSubtype( isexpr ) ) = FALSE ) then
337  errReport( FB_ERRMSG_TYPEHASNORTTI )
338  '' error recovery: fake a node
339  isexpr = astNewCONSTi( 0 )
340  end if
341  else
342  errReport( FB_ERRMSG_TYPEMUSTBEAUDT )
343  '' error recovery: fake a node
344  isexpr = astNewCONSTi( 0 )
345  end if
346 
347  lexSkipToken( )
348 
349  '' SymbolType
350  dim as integer dtype = any
351  dim as FBSYMBOL ptr subtype = any
352  if( cSymbolType( dtype, subtype, 0 ) = FALSE ) then
353  return NULL
354  end if
355 
356  '' must be a struct type with RTTI info
357  if( typeGetDtAndPtrOnly( dtype ) = FB_DATATYPE_STRUCT ) then
358  if( symbGetHasRTTI( subtype ) = FALSE ) then
359  errReport( FB_ERRMSG_TYPEHASNORTTI )
360  '' error recovery: fake a node
361  return astNewCONSTi( 0 )
362 
363  elseif( symbGetUDTBaseLevel( subtype, astGetSubtype( isexpr ) ) = 0 ) then
364  errReport( FB_ERRMSG_TYPESARENOTRELATED )
365  '' error recovery: fake a node
366  return astNewCONSTi( 0 )
367  end if
368  else
369  errReport( FB_ERRMSG_TYPEMUSTBEAUDT )
370  '' error recovery: fake a node
371  return astNewCONSTi( 0 )
372  end if
373 
374  '' point to the RTTI table
375  var expr = astNewVAR( subtype->udt.ext->rtti )
376 
377  '' do operation
378  isexpr = astNewBOP( AST_OP_IS, isexpr, expr )
379 
380  if( isexpr = NULL ) Then
381  errReport( FB_ERRMSG_TYPEMISMATCH )
382  '' error recovery: fake a node
383  isexpr = astNewCONSTi( 0 )
384  end if
385 
386  function = isexpr
387 
388 end function
389 
390 '':::::
391 ''CatExpression = AddExpression ( & AddExpression )* .
392 ''
393 function cCatExpression _
394  ( _
395  _
396  ) as ASTNODE ptr
397 
398  dim as ASTNODE ptr expr = any, catexpr = any
399 
400  '' AddExpression
401  catexpr = cAddExpression( )
402  if( catexpr = NULL ) then
403  return NULL
404  end if
405 
406  '' ( ... )*
407  do
408  '' &
409  if( lexGetToken( ) <> CHAR_AMP ) then
410  exit do
411  end if
412 
413  lexSkipToken( )
414 
415  '' AddExpression
416  expr = cAddExpression( )
417  if( expr = NULL ) then
418  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
419  exit do
420  end if
421 
422  '' concatenate
423  catexpr = astNewBOP( AST_OP_CONCAT, catexpr, expr )
424 
425  if( catexpr = NULL ) then
426  errReport( FB_ERRMSG_TYPEMISMATCH )
427  '' error recovery: fake a new node
428  catexpr = astNewCONSTstr( NULL )
429  end if
430 
431  loop
432 
433  function = catexpr
434 
435 end function
436 
437 '':::::
438 ''AddExpression = ShiftExpression ( ('+' | '-') ShiftExpression )* .
439 ''
440 function cAddExpression _
441  ( _
442  _
443  ) as ASTNODE ptr
444 
445  dim as integer op = any
446  dim as ASTNODE ptr expr = any, addexpr = any
447 
448  '' ShiftExpression
449  addexpr = cShiftExpression( )
450  if( addexpr = NULL ) then
451  return NULL
452  end if
453 
454  '' ( ... )*
455  do
456  '' Add operator
457  select case lexGetToken( )
458  case CHAR_PLUS
459  op = AST_OP_ADD
460  case CHAR_MINUS
461  op = AST_OP_SUB
462  case else
463  exit do
464  end select
465 
466  lexSkipToken( )
467 
468  '' ShiftExpression
469  expr = cShiftExpression( )
470  if( expr = NULL ) then
471  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
472  exit do
473  end if
474 
475  addexpr = astNewBOP( op, _
476  addexpr, _
477  expr, _
478  NULL, _
479  AST_OPOPT_DEFAULT or AST_OPOPT_DOPTRARITH )
480 
481  if( addexpr = NULL ) Then
482  errReport( FB_ERRMSG_TYPEMISMATCH )
483  '' error recovery: fake a node
484  addexpr = astNewCONSTi( 0 )
485  end if
486  loop
487 
488  function = addexpr
489 
490 end function
491 
492 '':::::
493 ''ShiftExpression = ModExpression ( (SHL | SHR) ModExpression )* .
494 ''
495 function cShiftExpression _
496  ( _
497  _
498  ) as ASTNODE ptr
499 
500  dim as integer op = any
501  dim as ASTNODE ptr expr = any, shiftexpr = any
502 
503  '' ModExpression
504  shiftexpr = cModExpression( )
505  if( shiftexpr = NULL ) then
506  return NULL
507  end if
508 
509  '' ( ... )*
510  do
511  '' Shift operator
512  select case lexGetToken( )
513  case FB_TK_SHL
514  op = AST_OP_SHL
515  case FB_TK_SHR
516  op = AST_OP_SHR
517  case else
518  exit do
519  end select
520 
521  lexSkipToken( )
522 
523  '' ModExpression
524  expr = cModExpression( )
525  if( expr = NULL ) then
526  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
527  exit do
528  end if
529 
530  '' do operation
531  shiftexpr = astNewBOP( op, shiftexpr, expr )
532 
533  if( shiftexpr = NULL ) Then
534  errReport( FB_ERRMSG_TYPEMISMATCH )
535  '' error recovery: fake a node
536  shiftexpr = astNewCONSTi( 0 )
537  end if
538  loop
539 
540  function = shiftexpr
541 
542 end function
543 
544 '':::::
545 ''ModExpression = IntDivExpression ( MOD IntDivExpression )* .
546 ''
547 function cModExpression _
548  ( _
549  _
550  ) as ASTNODE ptr
551 
552  dim as ASTNODE ptr expr = any, modexpr = any
553 
554  '' IntDivExpression
555  modexpr = cIntDivExpression( )
556  if( modexpr = NULL ) then
557  return NULL
558  end if
559 
560  '' ( ... )*
561  do
562  '' Add operator
563  if( lexGetToken( ) = FB_TK_MOD ) then
564  lexSkipToken( )
565  else
566  exit do
567  end if
568 
569  '' IntDivExpression
570  expr = cIntDivExpression( )
571  if( expr = NULL ) then
572  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
573  exit do
574  end if
575 
576  '' do operation
577  modexpr = astNewBOP( AST_OP_MOD, modexpr, expr )
578 
579  if( modexpr = NULL ) Then
580  errReport( FB_ERRMSG_TYPEMISMATCH )
581  '' error recovery: fake a node
582  modexpr = astNewCONSTi( 0 )
583  end if
584  loop
585 
586  function = modexpr
587 
588 end function
589 
590 '':::::
591 ''IntDivExpression= MultExpression ( '\' MultExpression )* .
592 ''
593 function cIntDivExpression _
594  ( _
595  _
596  ) as ASTNODE ptr
597 
598  dim as ASTNODE ptr expr = any, idivexpr = any
599 
600  '' MultExpression
601  idivexpr = cMultExpression( )
602  if( idivexpr = NULL ) then
603  return NULL
604  end if
605 
606  '' ( ... )*
607  do
608  '' '\'
609  if( lexGetToken( ) = CHAR_RSLASH ) then
610  lexSkipToken( )
611  else
612  exit do
613  end if
614 
615  '' MultExpression
616  expr = cMultExpression( )
617  if( expr = NULL ) then
618  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
619  exit do
620  end if
621 
622  '' do operation
623  idivexpr = astNewBOP( AST_OP_INTDIV, idivexpr, expr )
624 
625  if( idivexpr = NULL ) Then
626  errReport( FB_ERRMSG_TYPEMISMATCH )
627  '' error recovery: fake a node
628  idivexpr = astNewCONSTi( 0 )
629  end if
630  loop
631 
632  function = idivexpr
633 
634 end function
635 
636 '':::::
637 ''MultExpression = ExpExpression ( ('*' | '/') ExpExpression )* .
638 ''
639 function cMultExpression _
640  ( _
641  _
642  ) as ASTNODE ptr
643 
644  dim as integer op = any
645  dim as ASTNODE ptr expr = any, mulexpr = any
646 
647  '' ExpExpression
648  mulexpr = cExpExpression( )
649  if( mulexpr = NULL ) then
650  return NULL
651  end if
652 
653  '' ( ... )*
654  do
655  '' Mult operator
656  select case lexGetToken( )
657  case CHAR_TIMES
658  op = AST_OP_MUL
659  case CHAR_SLASH
660  op = AST_OP_DIV
661  case else
662  exit do
663  end select
664 
665  lexSkipToken( )
666 
667  '' ExpExpression
668  expr = cExpExpression( )
669  if( expr = NULL ) then
670  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
671  exit do
672  end if
673 
674  '' do operation
675  mulexpr = astNewBOP( op, mulexpr, expr )
676 
677  if( mulexpr = NULL ) Then
678  errReport( FB_ERRMSG_TYPEMISMATCH )
679  '' error recovery: fake a node
680  mulexpr = astNewCONSTi( 0 )
681  end if
682  loop
683 
684  function = mulexpr
685 
686 end function
687 
688 '':::::
689 ''ExpExpression = NegNotExpression ( '^' NegNotExpression )* .
690 ''
691 function cExpExpression _
692  ( _
693  _
694  ) as ASTNODE ptr
695 
696  dim as ASTNODE ptr expr = any, expexpr = any
697 
698  '' NegNotExpression
699  expexpr = cNegNotExpression( )
700  if( expexpr = NULL ) then
701  return NULL
702  end if
703 
704  '' ( '^' NegNotExpression )*
705  do
706  if( lexGetToken( ) <> CHAR_CART ) then
707  exit do
708  else
709  lexSkipToken( )
710  end if
711 
712  '' NegNotExpression
713  expr = cNegNotExpression( )
714  if( expr = NULL ) then
715  errReport( FB_ERRMSG_EXPECTEDEXPRESSION )
716  exit do
717  end if
718 
719  '' do operation
720  expexpr = astNewBOP( AST_OP_POW, expexpr, expr )
721 
722  if( expexpr = NULL ) Then
723  errReport( FB_ERRMSG_TYPEMISMATCH )
724  '' error recovery: fake a node
725  expexpr = astNewCONSTf( 0, FB_DATATYPE_DOUBLE )
726  end if
727  loop
728 
729  function = expexpr
730 
731 end function
732