FreeBASIC  0.91.0
parser-expr-function.bas
Go to the documentation of this file.
1 '' function call 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 
11 '':::::
12 #macro hParseRPNT( )
13  if( lexGetToken( ) <> CHAR_RPRNT ) then
14  errReport( FB_ERRMSG_EXPECTEDRPRNT )
15  '' error recovery: skip until next ')'
16  hSkipUntil( CHAR_RPRNT, TRUE )
17  else
18  lexSkipToken( )
19  end if
20 #endmacro
21 
22 '':::::
23 function cFunctionCall _
24  ( _
25  byval base_parent as FBSYMBOL ptr, _
26  byval sym as FBSYMBOL ptr, _
27  byval ptrexpr as ASTNODE ptr, _
28  byval thisexpr as ASTNODE ptr, _
29  byval options as FB_PARSEROPT _
30  ) as ASTNODE ptr
31 
32  dim as ASTNODE ptr funcexpr = any
33  dim as FB_CALL_ARG_LIST arg_list = ( 0, NULL, NULL )
34 
35  function = NULL
36 
37  if( sym = NULL ) then
38  exit function
39  end if
40 
41  options or= FB_PARSEROPT_ISFUNC
42 
43  hMethodCallAddInstPtrOvlArg( sym, thisexpr, @arg_list, @options )
44 
45  '' property?
46  if( symbIsProperty( sym ) ) then
47 
48  options or= FB_PARSEROPT_ISPROPGET
49 
50  '' '('? indexed..
51  if( lexGetToken( ) = CHAR_LPRNT ) then
52  if( symbGetUDTHasIdxGetProp( symbGetParent( sym ) ) = FALSE ) then
53  errReport( FB_ERRMSG_PROPERTYHASNOIDXGETMETHOD, TRUE )
54  end if
55 
56  lexSkipToken( )
57 
58  funcexpr = cProcArgList( base_parent, sym, ptrexpr, @arg_list, options )
59  if( funcexpr = NULL ) then
60  exit function
61  end if
62 
63  '' ')'
64  hParseRPNT( )
65 
66  '' not indexed..
67  else
68  if( symbGetUDTHasGetProp( symbGetParent( sym ) ) = FALSE ) then
69  errReport( FB_ERRMSG_PROPERTYHASNOGETMETHOD )
70  end if
71 
72  '' no args
73  funcexpr = cProcArgList( base_parent, _
74  sym, _
75  ptrexpr, _
76  @arg_list, _
77  options or FB_PARSEROPT_OPTONLY )
78  if( funcexpr = NULL ) then
79  exit function
80  end if
81  end if
82 
83  else
84  '' '('?
85  if( lexGetToken( ) = CHAR_LPRNT ) then
86  lexSkipToken( )
87 
88  '' ProcArgList
89  funcexpr = cProcArgList( base_parent, sym, ptrexpr, @arg_list, options )
90  if( funcexpr = NULL ) then
91  exit function
92  end if
93 
94  '' ')'
95  hParseRPNT( )
96 
97  else
98  '' ProcArgList (function could have optional params)
99  funcexpr = cProcArgList( base_parent, _
100  sym, _
101  ptrexpr, _
102  @arg_list, _
103  options or FB_PARSEROPT_OPTONLY )
104  if( funcexpr = NULL ) then
105  exit function
106  end if
107  end if
108 
109  end if
110 
111  '' is it really a function?
112  if( astGetDataType( funcexpr ) = FB_DATATYPE_VOID ) then
113  errReport( FB_ERRMSG_SYNTAXERROR )
114  '' error recovery: remove the SUB call, return a fake node
115  astDelTree( funcexpr )
116  return astNewCONSTi( 0 )
117  end if
118 
119  '' Take care of functions returning BYREF
120  funcexpr = astBuildByrefResultDeref( funcexpr )
121 
122  ''
123  function = cStrIdxOrMemberDeref( funcexpr )
124 end function
125 
126 '':::::
127 ''Function = ID ('(' ProcParamList ')')? FuncPtrOrMemberDeref? .
128 ''
129 function cFunctionEx _
130  ( _
131  byval base_parent as FBSYMBOL ptr, _
132  byval sym as FBSYMBOL ptr, _
133  byval options as FB_PARSEROPT _
134  ) as ASTNODE ptr
135 
136  '' ID
137  lexSkipToken( )
138 
139  function = cFunctionCall( base_parent, sym, NULL, NULL, options )
140 
141 end function
142 
143 '':::::
144 function cMethodCall _
145  ( _
146  byval sym as FBSYMBOL ptr, _
147  byval thisexpr as ASTNODE ptr, _
148  byval options as FB_PARSEROPT _
149  ) as ASTNODE ptr
150 
151  dim as ASTNODE ptr expr = any
152 
153  '' ID
154  lexSkipToken( )
155 
156  '' inside an expression? (can't check sym type, it could be an overloaded proc)
157  if( fbGetIsExpression( ) ) then
158  expr = cFunctionCall( NULL, sym, NULL, thisexpr, options )
159 
160  '' no need to check expr, cFunctionCall() will handle VOID calls
161 
162  '' assignment..
163  else
164  expr = cProcCall( NULL, sym, NULL, thisexpr, FALSE, options )
165 
166  '' ditto
167  end if
168 
169  function = expr
170 
171 end function
172 
173 '':::::
174 function cCtorCall _
175  ( _
176  byval sym as FBSYMBOL ptr _
177  ) as ASTNODE ptr
178 
179  dim as FBSYMBOL ptr tmp = any
180  dim as integer isprnt = any
181  dim as ASTNODE ptr procexpr = any
182  dim as FB_CALL_ARG_LIST arg_list = ( 0, NULL, NULL )
183 
184  '' alloc temp var
185  tmp = symbAddTempVar( symbGetType( sym ), sym )
186  astDtorListAdd( tmp )
187 
188  '' '('?
189  if( lexGetToken( ) = CHAR_LPRNT ) then
190  lexSkipToken( )
191  isprnt = TRUE
192  else
193  isprnt = FALSE
194  end if
195 
196  '' pass the instance ptr
197  dim as FB_CALL_ARG ptr arg = symbAllocOvlCallArg( @parser.ovlarglist, @arg_list, FALSE )
198  arg->expr = astBuildVarField( tmp )
199  arg->mode = INVALID
200 
201  procexpr = cProcArgList( NULL, _
202  symbGetCompCtorHead( sym ), _
203  NULL, _
204  @arg_list, _
205  FB_PARSEROPT_ISFUNC or _
206  FB_PARSEROPT_HASINSTPTR or _
207  iif( isprnt = FALSE, _
208  FB_PARSEROPT_OPTONLY, _
209  FB_PARSEROPT_NONE ) )
210 
211  '' Try to parse the ')' even in case of error recovery; it belongs to
212  '' the type() construct afterall, and nothing else would handle it.
213 
214  if( isprnt ) then
215  '' ')'?
216  if( lexGetToken( ) <> CHAR_RPRNT ) then
217  errReport( FB_ERRMSG_EXPECTEDRPRNT )
218  '' error recovery: skip until next ')'
219  hSkipUntil( CHAR_RPRNT, TRUE )
220  else
221  lexSkipToken( )
222  end if
223  end if
224 
225  '' cProcArgList() usually returns a CALL, but it can be NULL or a CONST
226  '' etc. in case of error recovery
227  if( procexpr = NULL ) then
228  function = NULL
229  elseif( astIsCALL( procexpr ) = FALSE ) then
230  function = procexpr
231  else
232  function = astNewCALLCTOR( procexpr, astBuildVarField( tmp ) )
233  end if
234 end function
235