FreeBASIC  0.91.0
parser-quirk-goto-return.bas
Go to the documentation of this file.
1 '' quirk branch statements (GOTO, GOSUB, RETURN, RESUME) 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 '':::::
13 function hFuncReturn _
14  ( _
15  ) as integer
16 
17  dim as integer checkexpr = any
18 
19  function = FALSE
20 
21  dim as FBSYMBOL ptr label = NULL
22  if( parser.stmt.proc <> NULL ) then
23  label = parser.stmt.proc->proc.endlabel
24  end if
25 
26  if( label = NULL ) then
27  errReport( FB_ERRMSG_ILLEGALOUTSIDEAPROC )
28  hSkipStmt( )
29  return TRUE
30  end if
31 
32  '' skip RETURN
33  lexSkipToken( )
34 
35  '' function?
36  if( symbGetType( parser.currproc ) <> FB_DATATYPE_VOID ) then
37  checkexpr = TRUE
38  else
39  '' Comment|StmtSep|EOF|ELSE|END IF|END IF? just exit
40  select case as const lexGetToken( )
41  case FB_TK_EOL, FB_TK_STMTSEP, FB_TK_EOF, FB_TK_COMMENT, FB_TK_REM, _
42  FB_TK_ELSE, FB_TK_END, FB_TK_ENDIF
43  checkexpr = FALSE
44  case else
45  checkexpr = TRUE
46  end select
47  end if
48 
49  if( checkexpr ) then
50  if( cAssignFunctResult( TRUE ) = FALSE ) then
51  exit function
52  end if
53  end if
54 
55  '' do an implicit exit function
56  astScopeBreak( label )
57  function = TRUE
58 
59 end function
60 
61 '':::::
62 function hGetLabelId _
63  ( _
64  _
65  ) as FBSYMBOL ptr
66 
67  dim as FBSYMBOL ptr sym = any
68 
69  select case as const lexGetClass( )
70  case FB_TKCLASS_NUMLITERAL
71  sym = symbLookupByNameAndClass( symbGetCurrentNamespc( ), _
72  lexGetText( ), _
73  FB_SYMBCLASS_LABEL, _
74  FALSE, _
75  FALSE )
76 
77  case FB_TKCLASS_IDENTIFIER, FB_TKCLASS_QUIRKWD, FB_TKCLASS_KEYWORD
78  dim as FBSYMBOL ptr base_parent = any
79  dim as FBSYMCHAIN ptr chain_ = cIdentifier( base_parent, _
80  FB_IDOPT_ISDECL or FB_IDOPT_DEFAULT )
81 
82  sym = symbFindByClass( chain_, FB_SYMBCLASS_LABEL )
83 
84  case else
85  errReport( FB_ERRMSG_EXPECTEDIDENTIFIER )
86  hSkipStmt( )
87  return NULL
88  end select
89 
90  if( sym = NULL ) then
91  sym = symbAddLabel( lexGetText( ), FB_SYMBOPT_CREATEALIAS )
92  if( sym = NULL ) then
93  errReport( FB_ERRMSG_EXPECTEDIDENTIFIER )
94  end if
95  end if
96 
97  lexSkipToken( )
98 
99  function = sym
100 
101 end function
102 
104  dim as FBSYMBOL ptr l = any
105 
106  lexSkipToken( )
107 
108  l = hGetLabelId( )
109  if( l <> NULL ) then
110  astGosubAddJmp( parser.currproc, l )
111  end if
112 end sub
113 
114 '':::::
115 function hGosubReturn _
116  ( _
117  ) as integer
118 
119  dim as FBSYMBOL ptr l = any
120 
121  '' it's a GOSUB's RETURN..
122  lexSkipToken( )
123 
124  '' Comment|StmtSep|EOF|ELSE|END IF|ENDIF? just return
125  select case as const lexGetToken( )
126  case FB_TK_EOL, FB_TK_STMTSEP, FB_TK_EOF, FB_TK_COMMENT, _
127  FB_TK_REM, FB_TK_ELSE, FB_TK_END, FB_TK_ENDIF
128 
129  function = astGosubAddReturn( parser.currproc, NULL )
130 
131  '' label?
132  case else
133  l = hGetLabelId( )
134  if( l <> NULL ) then
135  function = astGosubAddReturn( parser.currproc, l )
136  else
137  function = TRUE
138  end if
139  end select
140 
141 end function
142 
143 '':::::
144 ''GotoStmt = GOTO LABEL
145 '' | GOSUB LABEL
146 '' | RETURN LABEL?
147 '' | RESUME NEXT? .
148 ''
149 function cGotoStmt _
150  ( _
151  byval tk as FB_TOKEN _
152  ) as integer
153 
154  dim as FBSYMBOL ptr l = any
155 
156  function = FALSE
157 
158  select case as const tk
159  '' GOTO LABEL
160  case FB_TK_GOTO
161  lexSkipToken( )
162 
163  l = hGetLabelId( )
164  if( l <> NULL ) then
165  astScopeBreak( l )
166  end if
167  function = TRUE
168 
169  '' GOSUB LABEL
170  case FB_TK_GOSUB
171 
172  if( fbLangOptIsSet( FB_LANG_OPT_GOSUB ) = FALSE ) then
173  errReportNotAllowed( FB_LANG_OPT_GOSUB )
174  hSkipStmt( )
175  return TRUE
176  end if
177 
178  '' gosub allowed by OPTION GOSUB?
179  if( env.opt.gosub ) then
180  hGosubBranch()
181  else
182  '' GOSUB is allowed, but hasn't been enabled with OPTION GOSUB
183  errReport( FB_ERRMSG_NOGOSUB )
184  hSkipStmt( )
185  end if
186 
187  return TRUE
188 
189  '' RETURN ((LABEL? Comment|StmtSep|EOF) | Expression)
190  case FB_TK_RETURN
191  '' gosub allowed by dialect?
192  if( fbLangOptIsSet( FB_LANG_OPT_GOSUB ) ) then
193  '' gosub allowed by OPTION GOSUB?
194  if( env.opt.gosub ) then
195  return hGosubReturn( )
196  end if
197  end if
198 
199  '' must be proc return?
200  return hFuncReturn( )
201 
202  '' RESUME NEXT?
203  case FB_TK_RESUME
204  if( fbLangOptIsSet( FB_LANG_OPT_ONERROR ) = FALSE ) then
205  errReportNotAllowed( FB_LANG_OPT_ONERROR )
206  hSkipStmt( )
207  return TRUE
208  end if
209 
210  lexSkipToken( )
211 
212  rtlErrorResume( hMatch( FB_TK_NEXT ) )
213 
214  function = TRUE
215  end select
216 
217 end function
218