File: mini_buffer.e

package info (click to toggle)
smarteiffel 1.1-11
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 12,288 kB
  • ctags: 40,785
  • sloc: ansic: 35,791; lisp: 4,036; sh: 1,783; java: 895; ruby: 613; python: 209; makefile: 115; csh: 78; cpp: 50
file content (298 lines) | stat: -rw-r--r-- 6,981 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
-- This file is part of SmartEiffel The GNU Eiffel Compiler Tools and Libraries
--
-- SmartEiffel is  free software;  you can redistribute it and/or  modify it
-- under  the terms of the  GNU General Public License, as published by  the
-- Free Software Foundation; either version 2, or (at your option) any later
-- version.
-- SmartEiffel is distributed in the hope that it will be useful but WITHOUT 
-- ANY WARRANTY;  without  even the implied warranty  of MERCHANTABILITY  or
-- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-- more details.  You should have received a copy of  the GNU General Public
-- License along with SmartEiffel;  see the file COPYING.  If not,  write to
-- the Free Software Foundation,  Inc., 59 Temple Place - Suite 330,  Boston, 
-- MA 02111-1307, USA.
--
-- Copyright(C) 1994-2002: INRIA - LORIA (INRIA Lorraine) - ESIAL U.H.P.
--			   - University of Nancy 1 - FRANCE
-- Copyright(C) 2003:      INRIA - LORIA (INRIA Lorraine) - I.U.T. Charlemagne
--			   - University of Nancy 2 - FRANCE
--
--		 Dominique COLNET, Suzanne COLLIN, Olivier ZENDRA,
--			   Philippe RIBET, Cyril ADRIAN
--
-- http://SmartEiffel.loria.fr - SmartEiffel@loria.fr
--
class MINI_BUFFER
   --
   -- This mini buffer is used to parse information inside MANIFEST_STRING 
   -- objects (used for example to parse external feature definition). This 
   -- singleton object is shared via the GLOBALS.`mini_buffer' once function.

inherit
   GLOBALS
   VISITABLE

feature {MINI_BUFFER_VISITOR}

   accept(visitor: MINI_BUFFER_VISITOR) is
      do
         visitor.visit_mini_buffer(Current)
      end

feature -- A simple ITERATOR like interface:

   start_with(ms: MANIFEST_STRING) is
	 -- Getting started with `ms', the `item' is set with the 
	 -- first non-blank character.
      require
	 ms /= Void
      do
	 manifest_string := ms
	 to_string := manifest_string.to_string
	 count := to_string.count
	 idx := 1
	 skip_separators
      ensure
	 manifest_string = ms
	 not is_off implies not item.is_separator
      end

   item: CHARACTER is
	 -- The one at current position.
      require
	 not is_off
      do
	 Result := to_string.item(idx)
      end

   is_off: BOOLEAN is
      do
	 Result := idx > count
      end

   next is
      require
	 not is_off
      do
	 idx := idx + 1
      end

feature

   skip_separators is
	 -- (Use `is_separator' of class CHARACTER.)
      do
	 from 
	 until
	    idx > count or else not to_string.item(idx).is_separator
	 loop
	    idx := idx + 1
	 end
      ensure
	 not is_off implies not item.is_separator
      end

   a_keyword(keyword: STRING): BOOLEAN is
	 -- Look for a `keyword' beginning strictly at current position, then,
	 -- `skip_separators' is automatically called. A keyword is never followed 
	 -- by a character of this set: {'A'..'Z','a'..'z','0'..'9','_'}.
      require
	 not item.is_separator
      local
	 idx_memory, i: INTEGER; stop: BOOLEAN
      do
	 idx_memory := idx
	 from
	    i := 1
	 until
	    stop
	 loop
	    if i > keyword.count then
	       stop := true
	    elseif idx > count then
	       stop := true
	    elseif to_string.item(idx) = keyword.item(i) then
	       i := i + 1
	       idx := idx + 1
	    else
	       stop := true
	    end
	 end
	 if i > keyword.count then
	    skip_separators
	    Result := true
	 else
	    idx := idx_memory
	 end
      ensure
	 is_off or else not item.is_separator
      end
   
   a_word(keyword: STRING): BOOLEAN is
	 -- Is it a single stand-alone `keyword'?
      require
	 not item.is_separator
      local
	 idx_memory: INTEGER
      do
	 idx_memory := idx
	 if a_keyword(keyword) then
	    if idx > count then
	       Result := true
	    else
	       idx := idx_memory
	    end
	 end
      ensure
	 Result implies is_off
      end

   a_include: STRING is
	 -- Always return some file name wich may looks like a file 
	 -- to include: "....foo.h" or <...foo.h>. When the file name 
	 -- is not properly brace with "..." or <...>, the standard 
	 -- "..." are automatically added.
      require
	 not item.is_separator
      local
	 stop: BOOLEAN
      do
	 from
	    Result := once ".... local unique buffer ...."
	    Result.clear
	    Result.extend(item)
	    next
	 until
	    stop
	 loop
	    if is_off then
	       stop := true
	    elseif item.is_separator then
	       stop := true
	    elseif item = ',' then
	       stop := true
	    else
	       Result.extend(item)
	       next
	    end
	 end
	 inspect
	    Result.first
	 when '%"', '<' then
	 else
	    Result.add_first('%"')
	    Result.add_last('%"')
	 end
	 Result := Result.twin
      ensure
	 is_off or else not item.is_separator
      end

   a_field_or_variable_name: STRING is
      do
	 Result := a_type_cast
      ensure
	 is_off or else not item.is_separator
      end

   a_type_cast: STRING is
	 -- Read an expected C cast.
      require
	 not item.is_separator      
      local
	 stop: BOOLEAN
      do
	 from
	    Result := once ".... local unique buffer ...."
	    Result.clear
	    Result.extend(item)
	    next
	 until
	    stop
	 loop
	    if is_off then
	       stop := true
	    elseif item = ',' then
	       stop := true
	    elseif item.is_separator then
	       stop := true;	       
	    else
	       Result.extend(item)
	       next
	       if Result.last = ')' then
		  if Result.occurrences('(') < Result.occurrences(')') then
		     idx := idx - 1
		     Result.remove_last(1)
		     stop := true
		  end
	       end
	    end
	 end
	 Result := Result.twin
	 skip_separators
      ensure
	 is_off or else not item.is_separator
      end

   a_signature: FIXED_ARRAY[STRING] is
	 -- Read the expected external signature.
      require
	 not item.is_separator      
      local
	 stop: BOOLEAN; external_cast: STRING
      do
	 if item /= '(' then
	    error_handler.append("Bad external signature (missing opening %"(%" %
		      %delimiter.")
	    error_handler.print_as_fatal_error
	 end
	 from
	    next; skip_separators
	    create Result.with_capacity(8)
	    Result.add_last(Void)
	 until
	    stop
	 loop
	    if is_off then
	       error_handler.append("Bad external signature (missing %")%" %
                         %delimiter.")
	       error_handler.print_as_fatal_error
	    elseif item = ',' then
	       next; skip_separators
	    elseif item = ')' then
	       stop := true
	       next; skip_separators
	    else
	       external_cast := a_type_cast
	       Result.add_last(external_cast)
	    end
	 end
      ensure
         Result.count > 1
	 is_off or else not item.is_separator
      end

feature {NONE}

   manifest_string: MANIFEST_STRING
	 -- The one currently parsed.

   to_string: STRING
	 -- To cache `manifest_string.to_string'.

   count: INTEGER
	 -- To cache `to_string.count'.

   idx: INTEGER
	 -- The current position in `to_string'.

   singleton_memory: MINI_BUFFER is
      once
	 Result := Current
      end

invariant

   is_real_singleton: Current = singleton_memory

end -- MINI_BUFFER