FreeBASIC  0.91.0
parser-decl-const.bas
Go to the documentation of this file.
1 '' constant (CONST) declarations
2 ''
3 '' chng: sep/2004 written [v1ctor]
4 
5 #include once "fb.bi"
6 #include once "fbint.bi"
7 #include once "parser.bi"
8 #include once "ast.bi"
9 
10 sub hGetType( byref dtype as integer, byref subtype as FBSYMBOL ptr )
11  '' (AS SymbolType)?
12  if( lexGetToken( ) = FB_TK_AS ) then
13  lexSkipToken( )
14 
15  if( cSymbolType( dtype, subtype, 0 ) = FALSE ) then
16  errReport( FB_ERRMSG_EXPECTEDIDENTIFIER )
17  dtype = FB_DATATYPE_INTEGER
18  subtype = NULL
19  end if
20 
21  '' check for invalid types
22  if( subtype <> NULL ) then
23  '' only allow if it's an enum
24  if( dtype <> FB_DATATYPE_ENUM ) then
25  errReport( FB_ERRMSG_INVALIDDATATYPES, TRUE )
26  '' error recovery: discard type
27  dtype = FB_DATATYPE_INVALID
28  subtype = NULL
29  end if
30  end if
31 
32  select case as const typeGet( dtype )
33  case FB_DATATYPE_VOID, FB_DATATYPE_FIXSTR, _
34  FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR
35  errReport( FB_ERRMSG_INVALIDDATATYPES, TRUE )
36  '' error recovery: discard type
37  dtype = FB_DATATYPE_INVALID
38  subtype = NULL
39  end select
40  else
41  dtype = FB_DATATYPE_INVALID
42  subtype = NULL
43  end if
44 end sub
45 
46 '' ConstAssign = ID (AS SymbolType)? '=' ConstExpression .
47 sub cConstAssign _
48  ( _
49  byval dtype as integer, _
50  byval subtype as FBSYMBOL ptr, _
51  byval attrib as FB_SYMBATTRIB _
52  )
53 
54  static as zstring * FB_MAXNAMELEN+1 id
55  dim as integer doskip = any, suffix = any
56  dim as ASTNODE ptr expr = any
57  dim as FBSYMBOL ptr litsym = any
58  dim as FBVALUE value = any
59 
60  '' Namespace identifier if it matches the current namespace
62 
63  '' ID
64  select case as const lexGetClass( )
65  case FB_TKCLASS_IDENTIFIER
66  if( fbLangOptIsSet( FB_LANG_OPT_PERIODS ) ) then
67  '' if inside a namespace, symbols can't contain periods (.)'s
68  if( symbIsGlobalNamespc( ) = FALSE ) then
69  if( lexGetPeriodPos( ) > 0 ) then
70  errReport( FB_ERRMSG_CANTINCLUDEPERIODS )
71  end if
72  end if
73  end if
74 
75  case FB_TKCLASS_QUIRKWD
76  if( env.clopt.lang <> FB_LANG_QB ) then
77  '' only if inside a ns and if not local
78  if( (symbIsGlobalNamespc( )) or (parser.scope > FB_MAINSCOPE) ) then
79  errReport( FB_ERRMSG_DUPDEFINITION )
80  '' error recovery: skip until next stmt or const decl
81  hSkipUntil( FB_TK_DECLSEPCHAR )
82  exit sub
83  end if
84  end if
85 
86  case FB_TKCLASS_KEYWORD, FB_TKCLASS_OPERATOR
87  if( env.clopt.lang <> FB_LANG_QB ) then
88  errReport( FB_ERRMSG_DUPDEFINITION )
89  '' error recovery: skip until next stmt or const decl
90  hSkipUntil( FB_TK_DECLSEPCHAR )
91  exit sub
92  end if
93 
94  case else
95  errReport( FB_ERRMSG_EXPECTEDIDENTIFIER )
96  '' error recovery: skip until next stmt or const decl
97  hSkipUntil( FB_TK_DECLSEPCHAR )
98  exit sub
99  end select
100 
101  suffix = lexGetType( )
102  id = *lexGetText( )
103 
104  hCheckSuffix( suffix )
105 
106  '' ID
107  lexSkipToken( )
108 
109  '' not multiple?
110  if( dtype = FB_DATATYPE_INVALID ) then
111  '' (AS SymbolType)?
112  hGetType( dtype, subtype )
113  end if
114 
115  '' both suffix and type given?
116  if( suffix <> FB_DATATYPE_INVALID ) then
117  if( dtype <> FB_DATATYPE_INVALID ) then
118  errReportEx( FB_ERRMSG_SYNTAXERROR, id )
119  end if
120 
121  dtype = suffix
122  subtype = NULL
123 
124  attrib or= FB_SYMBATTRIB_SUFFIXED
125  end if
126 
127  '' '='
128  doskip = FALSE
129  if( cAssignToken( ) = FALSE ) then
130  errReport( FB_ERRMSG_EXPECTEDEQ )
131  doskip = TRUE
132  end if
133 
134  '' ConstExpression
135  expr = cExpression( )
136  if( expr = NULL ) then
137  errReportEx( FB_ERRMSG_EXPECTEDCONST, id )
138  doskip = TRUE
139  '' error recovery: create a fake node
140  expr = astNewCONSTz( dtype, subtype )
141  end if
142 
143  '' check if it's an string
144  dim as integer exprdtype = astGetDataType( expr )
145  litsym = NULL
146  select case exprdtype
147  case FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR
148  litsym = astGetStrLitSymbol( expr )
149  end select
150 
151  '' string?
152  if( litsym <> NULL ) then
153  if( dtype <> FB_DATATYPE_INVALID ) then
154  '' not a string?
155  if( typeGetDtAndPtrOnly( dtype ) <> FB_DATATYPE_STRING ) then
156  errReportEx( FB_ERRMSG_INVALIDDATATYPES, id )
157  end if
158  end if
159 
160  value.s = litsym
161  if( symbAddConst( @id, exprdtype, NULL, @value, attrib ) = NULL ) then
162  errReportEx( FB_ERRMSG_DUPDEFINITION, id )
163  end if
164  '' anything else..
165  else
166  '' not a constant?
167  if( astIsCONST( expr ) = FALSE ) then
168  errReportEx( FB_ERRMSG_EXPECTEDCONST, id )
169  '' error recovery: create a fake node
170  astDelTree( expr )
171  expr = astNewCONSTi( 0 )
172  exprdtype = FB_DATATYPE_INTEGER
173  end if
174 
175  '' Type explicitly specified?
176  if( dtype <> FB_DATATYPE_INVALID ) then
177  '' string?
178  if( typeGet( dtype ) = FB_DATATYPE_STRING ) then
179  errReportEx( FB_ERRMSG_INVALIDDATATYPES, id )
180  '' error recovery: create a fake node
181  astDelTree( expr )
182  exprdtype = dtype
183  subtype = NULL
184  expr = astNewCONSTstr( NULL )
185  end if
186 
187  '' Convert expression to given type if needed
188  if( (dtype <> exprdtype) or _
189  (subtype <> astGetSubtype( expr )) ) then
190 
191  expr = astNewCONV( dtype, subtype, expr )
192  if( expr = NULL ) then
193  errReportEx( FB_ERRMSG_INVALIDDATATYPES, id )
194  '' error recovery: create a fake node
195  expr = astNewCONSTi( 0 )
196  dtype = FB_DATATYPE_INTEGER
197  subtype = NULL
198  end if
199  end if
200  else
201  '' Use expression's type
202  '' (no need to check for conversion overflow,
203  '' since it's the same type)
204  dtype = exprdtype
205  subtype = astGetSubtype( expr )
206  end if
207 
208  if( symbAddConst( @id, dtype, subtype, astConstGetVal( expr ), attrib ) = NULL ) then
209  errReportEx( FB_ERRMSG_DUPDEFINITION, id )
210  end if
211  end if
212 
213  astDelNode( expr )
214 
215  if( doskip ) then
216  '' error recovery: skip until next stmt or const decl
217  hSkipUntil( FB_TK_DECLSEPCHAR )
218  end if
219 end sub
220 
221 '' ConstDecl = CONST (AS SymbolType)? ConstAssign (DECL_SEPARATOR ConstAssign)* .
222 sub cConstDecl( byval attrib as integer )
223  dim as integer dtype = any
224  dim as FBSYMBOL ptr subtype = any
225 
226  '' CONST
227  lexSkipToken( )
228 
229  '' (AS SymbolType)?
230  hGetType( dtype, subtype )
231 
232  do
233  '' ConstAssign
234  cConstAssign( dtype, subtype, attrib )
235 
236  '' ','?
237  if( lexGetToken( ) <> FB_TK_DECLSEPCHAR ) then
238  exit do
239  end if
240 
241  lexSkipToken( )
242  loop
243 end sub
244