PageRenderTime 10ms CodeModel.GetById 1ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/src/lib/cli/internal/clarg_parser.e

http://github.com/tybor/Liberty
Specman e | 322 lines | 82 code | 11 blank | 229 comment | 7 complexity | 78c6f2182fb3bd334d2ed6436fd7328d MD5 | raw file
  1-- This file is part of a Liberty Eiffel library.
  2-- See the full copyright at the end.
  3--
  4deferred class CLARG_PARSER
  5
  6insert
  7   ARGUMENTS
  8      redefine
  9         out_in_tagged_out_memory
 10      end
 11   CLARG_OPTIONS
 12      redefine
 13         out_in_tagged_out_memory
 14      end
 15
 16feature {ANY}
 17   name: FIXED_STRING
 18   usage: FIXED_STRING
 19   index: INTEGER
 20   is_mandatory: BOOLEAN
 21
 22   is_set: BOOLEAN
 23      deferred
 24      end
 25
 26   force_index (a_index: like index)
 27      do
 28         index := a_index
 29      ensure
 30         index = a_index
 31      end
 32
 33   is_optional: BOOLEAN
 34      do
 35         Result := not is_mandatory and then not is_positional
 36      end
 37
 38   is_positional: BOOLEAN
 39      do
 40         Result := short = Void and then long = Void
 41      end
 42
 43   can_be_mandatory: BOOLEAN True
 44
 45   can_be_optional: BOOLEAN
 46      do
 47         Result := is_optional
 48      end
 49
 50   out_in_tagged_out_memory
 51      do
 52         tagged_out_memory.append(name)
 53      end
 54
 55feature {COMMAND_LINE_ARGUMENTS, COMMAND_LINE_ARGUMENT}
 56   parse_command_line (context: COMMAND_LINE_CONTEXT): COMMAND_LINE_CONTEXT
 57      do
 58         if is_positional then
 59            Result := parse_positional(context)
 60         else
 61            if short /= Void then
 62               Result := parse_short(context)
 63            end
 64            if not is_set and then long /= Void then
 65               Result := context
 66               if Result.is_short then
 67                  Result.set_index(Result.short_index)
 68               end
 69               Result := parse_long(Result)
 70            end
 71         end
 72      end
 73
 74   usage_summary (stream: OUTPUT_STREAM)
 75      do
 76         if not is_mandatory then
 77            stream.put_character('{')
 78         end
 79         if short /= Void then
 80            if long /= Void then
 81               stream.put_character('(')
 82               put_short(stream)
 83               stream.put_character('|')
 84               put_long(stream)
 85               stream.put_character(')')
 86            else
 87               put_short(stream)
 88            end
 89            stream.put_character(' ')
 90         elseif long /= Void then
 91            put_long(stream)
 92            stream.put_character(' ')
 93         end
 94         stream.put_character('<')
 95         stream.put_string(name)
 96         stream.put_character('>')
 97         if not is_mandatory then
 98            stream.put_character('}')
 99         end
100         detailed := False
101      end
102
103   usage_details (stream: OUTPUT_STREAM)
104      do
105         if not detailed then
106            usage_summary(stream)
107            stream.put_character(':')
108            stream.put_character(' ')
109            if usage /= Void then
110               stream.put_string(usage)
111            else
112               stream.put_string(once "Set the ")
113               stream.put_string(name)
114               stream.put_character('.')
115            end
116            if is_mandatory then
117               stream.put_string(once " (mandatory)")
118            end
119            stream.put_new_line
120            detailed := True
121         end
122      end
123
124   set_mandatory (parent_option: like Current; enable: BOOLEAN)
125      do
126         parent := parent_option
127         is_mandatory := enable
128      end
129
130   is_set_at (context: COMMAND_LINE_CONTEXT): BOOLEAN
131      deferred
132      end
133
134feature {} -- parsing
135   parse_positional (context: COMMAND_LINE_CONTEXT): COMMAND_LINE_CONTEXT
136      require
137         is_positional
138      local
139         data: STRING
140      do
141         Result := context
142         if context.is_short then
143            context.set_index(context.short_index)
144         end
145         if argument_count >= context.index then
146            if index = 0 or else index = context.index then
147               data := argument(context.index)
148               if is_valid_data(data) then
149                  set_data_(context, data)
150                  Result.set_index(context.index + 1)
151               end
152            end
153         end
154      end
155
156   parse_short (context: COMMAND_LINE_CONTEXT): COMMAND_LINE_CONTEXT
157      require
158         not is_positional
159         short /= Void
160      local
161         data: STRING
162      do
163         Result := context
164         if argument_count >= context.index then
165            if context.is_short then
166               if argument_count >= context.short_index and then is_short(argument(context.index), context.short_option_index) then
167                  data := argument(context.short_index)
168                  if is_valid_data(data) then
169                     set_data_(context, data)
170                     Result.set_index(context.index)
171                     Result.set_short(context.short_index + 1, context.short_option_index + 1)
172                  else
173                     Result := Result.default
174                  end
175               elseif argument_count > context.short_index and then is_short(argument(context.short_index), 1) then
176                  data := argument(context.short_index + 1)
177                  if is_valid_data(data) then
178                     set_data_(context, data)
179                     Result.set_index(context.short_index + 1)
180                     Result.set_short(context.short_index + 2, 2)
181                  else
182                     Result := Result.default
183                  end
184               end
185            elseif is_short(argument(context.index), 1) and then argument_count > context.index then
186               data := argument(context.index + 1)
187               if is_valid_data(data) then
188                  set_data_(context, data)
189                  Result.set_index(context.index)
190                  Result.set_short(context.index + 2, 2)
191               else
192                  Result := Result.default
193               end
194            end
195         end
196      end
197
198   parse_long (context: COMMAND_LINE_CONTEXT): COMMAND_LINE_CONTEXT
199      require
200         not is_positional
201         long /= Void
202      local
203         arg, data: STRING
204      do
205         Result := context
206         if argument_count >= context.index then
207            arg := argument(context.index)
208            if is_long(arg) and then argument_count > context.index then
209               data := argument(context.index + 1)
210               if is_valid_data(data) then
211                  set_data_(context, data)
212                  Result.set_index(context.index + 2)
213               else
214                  Result := Result.default
215               end
216            elseif is_long_equal(arg) then
217               data := long_equal_pattern.named_group_value(arg, once "value")
218               if is_valid_data(data) then
219                  set_data_(context, data)
220                  Result.set_index(context.index + 1)
221               else
222                  Result := Result.default
223               end
224            end
225         end
226      end
227
228feature {CLARG_PARSER}
229   set_data_ (context: COMMAND_LINE_CONTEXT; data: STRING)
230      require
231         is_valid_data(data)
232         parent /= Void implies parent.is_valid_data(data)
233      do
234         set_data(context, data)
235         if parent /= Void then
236            parent.set_data_(context, data)
237         end
238      end
239
240   is_valid_data (data: STRING): BOOLEAN
241      deferred
242      end
243
244feature {}
245   set_data (context: COMMAND_LINE_CONTEXT; data: STRING)
246      require
247         is_valid_data(data)
248      deferred
249      ensure
250         is_set_at(context)
251      end
252
253feature {}
254   optional (a_short, a_long, a_name, a_usage: ABSTRACT_STRING)
255      require
256         a_short /= Void implies a_short.count = 1
257         a_short /= Void or else a_long /= Void
258         a_name /= Void
259      do
260         if a_short /= Void then
261            short := a_short.intern
262         end
263         if a_long /= Void then
264            long := a_long.intern
265         end
266         name := a_name.intern
267         if a_usage /= Void then
268            usage := a_usage.intern
269         end
270      ensure
271         is_optional
272         a_short /= Void implies short.is_equal(a_short)
273         a_long /= Void implies long.is_equal(a_long)
274         name.is_equal(a_name)
275         a_usage /= Void implies usage.is_equal(a_usage)
276      end
277
278   positional (a_name, a_usage: ABSTRACT_STRING)
279      require
280         a_name /= Void
281      do
282         name := a_name.intern
283         if a_usage /= Void then
284            usage := a_usage.intern
285         end
286         is_mandatory := True
287      ensure
288         is_positional
289         is_mandatory
290         name.is_equal(a_name)
291         a_usage /= Void implies usage.is_equal(a_usage)
292      end
293
294   parent: like Current
295
296feature {}
297   detailed: BOOLEAN
298
299invariant
300   short /= Void implies short.count = 1
301
302end -- class CLARG_PARSER
303--
304-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
305--
306-- Permission is hereby granted, free of charge, to any person obtaining a copy
307-- of this software and associated documentation files (the "Software"), to deal
308-- in the Software without restriction, including without limitation the rights
309-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
310-- copies of the Software, and to permit persons to whom the Software is
311-- furnished to do so, subject to the following conditions:
312--
313-- The above copyright notice and this permission notice shall be included in
314-- all copies or substantial portions of the Software.
315--
316-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
317-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
318-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
319-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
320-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
321-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
322-- THE SOFTWARE.