FreeBASIC  0.91.0
parser-quirk-math.bas
Go to the documentation of this file.
1 '' quirk math functions (ABS, SGN, FIX, LEN, ...) 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 "rtl.bi"
10 #include once "ast.bi"
11 
12 function hMathOp(byval op as AST_OP) as ASTNODE ptr
13  dim as ASTNODE ptr expr = any
14  lexSkipToken( )
15  hMatchLPRNT( )
16  hMatchExpressionEx( expr, FB_DATATYPE_INTEGER )
17  hMatchRPRNT( )
18 
19  expr = astNewUOP( op, expr )
20  if( expr = NULL ) then
21  errReport( FB_ERRMSG_INVALIDDATATYPES )
22  expr = astNewCONSTi( 0 )
23  end if
24 
25  function = expr
26 end function
27 
28 function hAtan2() as ASTNODE ptr
29  dim as ASTNODE ptr expr = any, expr2 = any
30 
31  '' ATAN2( Expression ',' Expression )
32  lexSkipToken( )
33  hMatchLPRNT( )
34  hMatchExpressionEx( expr, FB_DATATYPE_INTEGER )
35  hMatchCOMMA( )
36  hMatchExpressionEx( expr2, FB_DATATYPE_INTEGER )
37  hMatchRPRNT( )
38 
39  expr = astNewBOP( AST_OP_ATAN2, expr, expr2 )
40  if( expr = NULL ) then
41  errReport( FB_ERRMSG_INVALIDDATATYPES )
42  expr = astNewCONSTi( 0 )
43  end if
44 
45  function = expr
46 end function
47 
48 function hLen _
49  ( _
50  byval expr as ASTNODE ptr, _
51  byref lgt as longint _
52  ) as ASTNODE ptr
53 
54  dim as FBSYMBOL ptr litsym = any
55 
56  select case( astGetDataType( expr ) )
57  case FB_DATATYPE_STRING
58  return rtlStrLen( expr )
59 
60  case FB_DATATYPE_CHAR
61  litsym = astGetStrLitSymbol( expr )
62  if( litsym = NULL ) then
63  return rtlStrLen( expr )
64  end if
65 
66  '' String literal, evaluate at compile-time
67  lgt = symbGetStrLen( litsym ) - 1
68 
69  case FB_DATATYPE_WCHAR
70  litsym = astGetStrLitSymbol( expr )
71  if( litsym = NULL ) then
72  return rtlWstrLen( expr )
73  end if
74 
75  '' String literal, evaluate at compile-time
76  lgt = symbGetWstrLen( litsym ) - 1
77 
78  case FB_DATATYPE_FIXSTR
79  '' len( fixstr ) returns the N from STRING * N, i.e. it works
80  '' like sizeof() - 1 (-1 for the implicit null terminator),
81  '' it does not return the length of the stored string data.
82  lgt = astSizeOf( expr ) - 1
83  assert( lgt >= 0 )
84 
85  case else
86  '' For anything else, len() means sizeof()
87  lgt = astSizeOf( expr )
88 
89  end select
90 
91  astDelTree( expr )
92  return NULL
93 end function
94 
95 function hLenSizeof _
96  ( _
97  byval is_len as integer, _
98  byval isasm as integer _
99  ) as ASTNODE ptr
100 
101  dim as ASTNODE ptr expr = any, expr2 = any, initree = any
102  dim as integer dtype = any
103  dim as longint lgt = any
104  dim as FBSYMBOL ptr subtype = any
105 
106  '' LEN | SIZEOF
107  lexSkipToken( )
108 
109  '' '('
110  hMatchLPRNT( )
111 
112  '' Type or an Expression
113  expr = cTypeOrExpression( is_len, dtype, subtype, lgt )
114 
115  '' Was it an expression?
116  if( expr ) then
117  '' Array without index makes this a SIZEOF()
118  if( astIsNIDXARRAY( expr ) ) then
119  is_len = FALSE
120  expr2 = astGetLeft( expr )
121  astDelNode( expr )
122  expr = expr2
123  end if
124 
125  '' Disallow string expressions in SIZEOF()
126  if( is_len = FALSE ) then
127  if( astGetDataClass( expr ) = FB_DATACLASS_STRING ) then
128  if( (astGetSymbol( expr ) = NULL) or astIsCALL( expr ) ) then
129  errReport( FB_ERRMSG_EXPECTEDIDENTIFIER, TRUE )
130  '' error recovery: fake an expr
131  astDelTree( expr )
132  expr = astNewCONSTi( 0 )
133  end if
134  end if
135  end if
136  end if
137 
138  '' ')'
139  if( lexGetToken( ) <> CHAR_RPRNT ) then
140  errReport( FB_ERRMSG_EXPECTEDRPRNT )
141  hSkipUntil( CHAR_RPRNT, TRUE )
142  else
143  if( isasm = FALSE ) then
144  lexSkipToken( )
145  end if
146  end if
147 
148  if( expr ) then
149  if( is_len ) then
150  '' len()
151  '' If an expression is returned, then it's an
152  '' fb_[W]StrLen() call, otherwise it's a sizeof() and
153  '' the length is returned in lgt.
154  expr = hLen( expr, lgt )
155  if( expr = NULL ) then
156  expr = astNewCONSTi( lgt )
157  end if
158  else
159  '' sizeof()
160  lgt = astSizeOf( expr )
161  astDelTree( expr )
162  expr = astNewCONSTi( lgt )
163  end if
164  else
165  expr = astNewCONSTi( lgt )
166  end if
167 
168  function = expr
169 end function
170 
171 '':::::
172 '' cMathFunct = ABS( Expression )
173 '' | SGN( Expression )
174 '' | FIX( Expression )
175 '' | INT( Expression )
176 '' | LEN( data type | Expression ) .
177 ''
178 function cMathFunct _
179  ( _
180  byval tk as FB_TOKEN, _
181  byval isasm as integer _
182  ) as ASTNODE ptr
183 
184  function = FALSE
185 
186  select case as const tk
187  '' ABS( Expression )
188  case FB_TK_ABS
189  function = hMathOp(AST_OP_ABS)
190 
191  '' SGN( Expression )
192  case FB_TK_SGN
193  function = hMathOp(AST_OP_SGN)
194 
195  '' FIX( Expression )
196  case FB_TK_FIX
197  function = hMathOp(AST_OP_FIX)
198 
199  '' FRAC( Expression )
200  case FB_TK_FRAC
201  function = hMathOp(AST_OP_FRAC)
202 
203  '' INT( Expression )
204  case FB_TK_INT
205  function = hMathOp(AST_OP_FLOOR)
206 
207  '' SIN/COS/...( Expression )
208  case FB_TK_SIN
209  function = hMathOp(AST_OP_SIN)
210 
211  case FB_TK_ASIN
212  function = hMathOp(AST_OP_ASIN)
213 
214  case FB_TK_COS
215  function = hMathOp(AST_OP_COS)
216 
217  case FB_TK_ACOS
218  function = hMathOp(AST_OP_ACOS)
219 
220  case FB_TK_TAN
221  function = hMathOp(AST_OP_TAN)
222 
223  case FB_TK_ATN
224  function = hMathOp(AST_OP_ATAN)
225 
226  case FB_TK_SQR
227  function = hMathOp(AST_OP_SQRT)
228 
229  case FB_TK_LOG
230  function = hMathOp(AST_OP_LOG)
231 
232  case FB_TK_EXP
233  function = hMathOp(AST_OP_EXP)
234 
235  '' ATAN2( Expression ',' Expression )
236  case FB_TK_ATAN2
237  function = hAtan2()
238 
239  '' LEN|SIZEOF( data type | Expression{idx-less arrays too} )
240  case FB_TK_LEN
241  function = hLenSizeof( TRUE, isasm )
242 
243  case FB_TK_SIZEOF
244  function = hLenSizeof( FALSE, isasm )
245 
246  end select
247 
248 end function
249