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