FreeBASIC  0.91.0
parser-quirk-data.bas
Go to the documentation of this file.
1 '' quirk storage statements (RESTORE, READ, DATA) 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 ''DataStmt = RESTORE LABEL?
14 '' | READ Variable{int|flt|str} (',' Variable{int|flt|str})*
15 '' | DATA literal|constant (',' literal|constant)*
16 ''
17 function cDataStmt _
18  ( _
19  byval tk as FB_TOKEN _
20  ) as integer
21 
22  function = FALSE
23 
24  select case tk
25  '' RESTORE LABEL?
26  case FB_TK_RESTORE
27  lexSkipToken( )
28 
29  '' LABEL?
30  dim as FBSYMBOL ptr sym = NULL
31  select case lexGetClass( )
32  case FB_TKCLASS_IDENTIFIER, FB_TKCLASS_QUIRKWD, FB_TKCLASS_NUMLITERAL
33  dim as FBSYMCHAIN ptr chain_ = any
34  dim as FBSYMBOL ptr base_parent = any
35 
36  chain_ = cIdentifier( base_parent )
37 
38  sym = symbFindByClass( chain_, FB_SYMBCLASS_LABEL )
39  if( sym = NULL ) then
40  sym = symbAddLabel( lexGetText( ), _
41  FB_SYMBOPT_MOVETOGLOB or FB_SYMBOPT_CREATEALIAS )
42  if( sym = NULL ) then
43  errReport( FB_ERRMSG_DUPDEFINITION )
44  hSkipStmt( )
45  return TRUE
46  end if
47  end if
48  lexSkipToken( )
49  end select
50 
51  function = rtlDataRestore( sym )
52 
53  '' READ Variable{int|flt|str} (',' Variable{int|flt|str})*
54  case FB_TK_READ
55  lexSkipToken( )
56 
57  dim as ASTNODE ptr expr = NULL
58  do
59  expr = cVarOrDeref( )
60  if( expr = NULL ) then
61  errReport( FB_ERRMSG_EXPECTEDIDENTIFIER )
62  hSkipUntil( CHAR_COMMA )
63  else
64  if( rtlDataRead( expr ) = FALSE ) then
65  exit function
66  end if
67  end if
68  loop while( hMatch( CHAR_COMMA ) )
69 
70  function = TRUE
71 
72  '' DATA literal|constant expr (',' literal|constant expr)*
73  case FB_TK_DATA
74 
75  if( env.clopt.lang <> FB_LANG_QB ) then
76  '' allowed?
77  if( cCompStmtIsAllowed( FB_CMPSTMT_MASK_DATA ) = FALSE ) then
78  hSkipStmt( )
79  exit function
80  end if
81 
82  '' not in module-level?
83  if( parser.scope > FB_MAINSCOPE ) then
84  if( fbIsModLevel( ) = FALSE ) then
85  errReport( FB_ERRMSG_ILLEGALINSIDEASUB )
86  else
87  errReport( FB_ERRMSG_ILLEGALINSIDEASCOPE )
88  end if
89  hSkipStmt( )
90  return FALSE
91  end if
92 
93  else
94  '' in QB, DATA can be declared inside compound stmts..
95  if( fbIsModLevel( ) = FALSE ) then
96  errReport( FB_ERRMSG_ILLEGALINSIDEASUB )
97  hSkipStmt( )
98  return FALSE
99  end if
100  end if
101 
102  dim as ASTNODE ptr tree = astDataStmtBegin( )
103 
104  dim as ASTNODE ptr expr = NULL
105 
106  if( env.clopt.lang <> FB_LANG_QB ) then
107  lexSkipToken( )
108 
109  do
110  hMatchExpressionEx( expr, FB_DATATYPE_INTEGER )
111 
112  '' not a constant?
113  dim as integer isconst = astIsCONST( expr )
114  if( isconst = FALSE ) then
115  if( astIsOFFSET( expr ) ) then
116  isconst = TRUE
117  else
118  '' not a literal string?
119  select case astGetDataType( expr )
120  case FB_DATATYPE_CHAR, FB_DATATYPE_WCHAR
121  isconst = astGetStrLitSymbol( expr ) <> NULL
122  end select
123  end if
124  end if
125 
126  if( isconst = FALSE ) then
127  errReport( FB_ERRMSG_EXPECTEDCONST )
128  astDelTree( expr )
129  else
130  if( astDataStmtStore( tree, expr ) = NULL ) then
131  exit function
132  end if
133  end if
134  loop while( hMatch( CHAR_COMMA ) )
135 
136  '' qb mode, read tokens as-is, no lookup, no expressions..
137  else
138  const LEX_FLAGS = LEXCHECK_NOWHITESPC or _
139  LEXCHECK_NOSUFFIX or _
140  LEXCHECK_NODEFINE or _
141  LEXCHECK_NOQUOTES or _
142  LEXCHECK_NOSYMBOL
143 
144  lexSkipToken( LEX_FLAGS )
145 
146  dim as integer do_exit = FALSE
147  dim as string text
148 
149  do
150  '' read until a ',' or EOL is found
151  dim as integer tokens = 0
152  text = ""
153  do
154  select case as const lexGetToken( LEX_FLAGS )
155  case CHAR_COMMA
156  lexSkipToken( LEX_FLAGS )
157  exit do
158 
159  case CHAR_SPACE, CHAR_TAB
160  '' don't count white-spaces
161  tokens -= 1
162 
163  case FB_TK_EOF, FB_TK_EOL, FB_TK_COMMENT, FB_TK_REM, FB_TK_STMTSEP
164  do_exit = TRUE
165  exit do
166  end select
167 
168  text += *lexGetText( )
169  lexSkipToken( LEX_FLAGS )
170  tokens += 1
171  loop
172 
173  '' trim it (as it could be a literal number)
174  text = trim( text )
175 
176  '' another quirk: remove the quotes if it's a single token
177  if( tokens = 1 ) then
178  if( len( text ) > 1 ) then
179  if( text[0] = asc( """" ) ) then
180  if( text[len( text )-1] = asc( """" ) ) then
181  text = mid( text, 2, len( text ) - 2 )
182  end if
183  end if
184  end if
185  end if
186 
187  if( astDataStmtStore( tree, astNewCONSTstr( text ) ) = NULL ) then
188  exit function
189  end if
190  loop until( do_exit )
191  end if
192 
193  astDataStmtEnd( tree )
194 
195  '' node is unused, the tree will become an initialized static array
196  astDelNode( tree )
197 
198  function = TRUE
199 
200  end select
201 
202 end function
203 
204