FreeBASIC  0.91.0
parser-compound-namespace.bas
Go to the documentation of this file.
1 '' NAMESPACE..END NAMESPACE compound statement parsing
2 ''
3 '' chng: may/2006 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 sub namespaceBegin _
12  ( _
13  byval stk as FB_CMPSTMTSTK ptr, _
14  byval sym as FBSYMBOL ptr _
15  )
16 
17  if( sym = NULL ) then
18  '' Fake id for anonymous namespaces or error recovery
19  sym = symbAddNamespace( symbUniqueLabel( ), NULL )
20  end if
21 
22  stk->nspc.sym = sym
23  stk->nspc.levels = 1
24 
25  symbNestBegin( sym, FALSE )
26 end sub
27 
28 '' NamespaceStmtBegin = NAMESPACE (ID (ALIAS LITSTR)?)? .
30  static as zstring * FB_MAXNAMELEN+1 id
31  dim as zstring ptr palias = any
32  dim as FBSYMBOL ptr sym = any
33  dim as FBSYMCHAIN ptr chain_ = any
34  dim as FB_CMPSTMTSTK ptr stk = any
35  dim as integer levels = any
36 
37  if( fbLangOptIsSet( FB_LANG_OPT_NAMESPC ) = FALSE ) then
38  errReportNotAllowed(FB_LANG_OPT_NAMESPC )
39  '' error recovery: skip the whole compound stmt
40  hSkipCompound( FB_TK_NAMESPACE )
41  exit sub
42  end if
43 
44  if( cCompStmtIsAllowed( FB_CMPSTMT_MASK_NAMESPC ) = FALSE ) then
45  '' error recovery: skip the whole compound stmt
46  hSkipCompound( FB_TK_NAMESPACE )
47  exit sub
48  end if
49 
50  '' skip NAMESPACE
51  lexSkipToken( LEXCHECK_NOPERIOD )
52 
53  '' ID?
54  palias = NULL
55 
56  select case as const lexGetToken( )
57  '' COMMENT|NEWLINE?
58  case FB_TK_COMMENT, FB_TK_REM, FB_TK_EOL, FB_TK_EOF, FB_TK_STMTSEP
59  '' Anonymous namespace
60  stk = cCompStmtPush(FB_TK_NAMESPACE, _
61  FB_CMPSTMT_MASK_ALL and (not FB_CMPSTMT_MASK_CODE) _
62  and (not FB_CMPSTMT_MASK_EXTERN) _
63  and (not FB_CMPSTMT_MASK_DATA))
64  namespaceBegin(stk, NULL)
65  exit sub
66  end select
67 
68  levels = 0
69  do
70  if( parser.nspcrec + levels >= FB_MAXNAMESPCRECLEVEL ) then
71  errReport( FB_ERRMSG_RECLEVELTOODEEP )
72  exit sub
73  end if
74 
75  levels += 1
76 
77  '' not an id?
78  select case lexGetClass( )
79  case FB_TKCLASS_IDENTIFIER
80  id = *lexGetText( )
81  chain_ = lexGetSymChain( )
82 
83  case FB_TKCLASS_QUIRKWD
84  '' only if inside another ns
85  if( symbIsGlobalNamespc( ) ) then
86  errReport( FB_ERRMSG_DUPDEFINITION )
87  id[0] = 0 '' id = ""
88  chain_ = NULL
89  else
90  id = *lexGetText( )
91  chain_ = lexGetSymChain( )
92  end if
93 
94  case else
95  errReport( FB_ERRMSG_EXPECTEDIDENTIFIER )
96  id[0] = 0 '' id = ""
97  chain_ = NULL
98  end select
99 
100  '' already defined?
101  if( chain_ <> NULL ) then
102  sym = chain_->sym
103  '' not a namespace?
104  if( symbIsNamespace( sym ) = FALSE ) then
105  errReportEx( FB_ERRMSG_DUPDEFINITION, id )
106  '' error recovery: fake an id
107  id = *symbUniqueLabel( )
108  sym = NULL
109  else
110  '' not the same hash tb?
111  if( symbGetHashTb( sym ) <> symbGetCurrentHashTb( ) ) then
112  '' then it's an inner ns with the same name as an outer one..
113  sym = NULL
114  end if
115  end if
116  else
117  sym = NULL
118  end if
119 
120  '' skip ID
121  if( id[0] <> 0 ) then
122  lexSkipToken( LEXCHECK_NOPERIOD )
123  end if
124 
125  '' create a new symbol?
126  if( sym = NULL ) then
127  if( levels = 1 ) then
128  '' [ALIAS "id"]
129  palias = cAliasAttribute()
130  end if
131 
132  sym = symbAddNamespace( @id, palias )
133  if( sym = NULL ) then
134  errReportEx( FB_ERRMSG_DUPDEFINITION, id )
135  end if
136  end if
137 
138  stk = cCompStmtPush(FB_TK_NAMESPACE, _
139  FB_CMPSTMT_MASK_ALL and (not FB_CMPSTMT_MASK_CODE) _
140  and (not FB_CMPSTMT_MASK_DATA))
141  namespaceBegin(stk, sym)
142 
143  '' ALIAS used?
144  if( palias <> NULL ) then
145  exit do
146  end if
147 
148  '' not a '.'?
149  if( lexGetToken( ) <> CHAR_DOT ) then
150  exit do
151  end if
152 
153  lexSkipToken( LEXCHECK_NOPERIOD )
154  loop
155 
156  '' The new top namespace entry on the stack is used to hold the number
157  '' of entries for nested namespaces (from <.nested1.nested2...>
158  '' following the "main" namespace block's id) that need to be popped
159  '' to reach the entry representing the actual namespace compound block.
160  stk->nspc.levels = levels
161  parser.nspcrec += levels
162 end sub
163 
164 '' NamespaceStmtEnd = END NAMESPACE .
166  dim as FB_CMPSTMTSTK ptr stk = any
167  dim as integer levels = any
168 
169  stk = cCompStmtGetTOS( FB_TK_NAMESPACE )
170  if( stk = NULL ) then
171  hSkipStmt( )
172  exit sub
173  end if
174 
175  '' END NAMESPACE
176  lexSkipToken( )
177  lexSkipToken( )
178 
179  levels = stk->nspc.levels
180 
181  parser.nspcrec -= levels
182 
183  do while( levels > 0 )
184  '' back to parent
185  symbNestEnd( FALSE )
186 
187  '' reimplementation?
188  dim as FBSYMBOL ptr ns = stk->nspc.sym
189  symbGetNamespaceCnt( ns ) += 1
190  if( symbGetNamespaceCnt( ns ) > 1 ) then
192  end if
193  symbGetNamespaceLastTail( ns ) = symbGetCompSymbTb( ns ).tail
194 
195  '' pop from stmt stack
196  cCompStmtPop( stk )
197 
198  stk = cCompStmtGetTOS( FB_TK_NAMESPACE, FALSE )
199  if( stk = NULL ) then
200  exit do
201  end if
202 
203  levels -= 1
204  loop
205 end sub
206 
207 '' Usingtmt = USING ID (',' ID)*
209  dim as FBSYMBOL ptr sym = any
210 
211  if( fbLangOptIsSet( FB_LANG_OPT_NAMESPC ) = FALSE ) then
212  errReportNotAllowed( FB_LANG_OPT_NAMESPC )
213  '' error recovery: skip stmt
214  hSkipStmt( )
215  exit sub
216  end if
217 
218  '' USING
219  lexSkipToken( LEXCHECK_NOPERIOD )
220 
221  do
222  '' ID
223  sym = cParentId( FB_IDOPT_DONTCHKPERIOD )
224  if( sym = NULL ) then
225  if( lexGetToken( ) <> FB_TK_ID ) then
226  errReport( FB_ERRMSG_EXPECTEDIDENTIFIER )
227  else
228  errReport( FB_ERRMSG_UNDEFINEDSYMBOL )
229  end if
230 
231  '' error recovery: skip until next ','
232  hSkipUntil( CHAR_COMMA )
233  else
234  '' not a namespace?
235  if( symbIsNamespace( sym ) = FALSE ) then
236  errReport( FB_ERRMSG_TYPEMISMATCH )
237  else
238  symbNamespaceImport( sym )
239  end if
240  end if
241 
242  '' ','?
243  loop while( hMatch( CHAR_COMMA ) )
244 end sub
245