/src/lib/regular_expression/low_level/python_regular_expression_builder.e

http://github.com/tybor/Liberty · Specman e · 202 lines · 67 code · 3 blank · 132 comment · 6 complexity · 77320287c16b2d5949c8fd273c8f0544 MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class PYTHON_REGULAR_EXPRESSION_BUILDER
  5. inherit
  6. PERL5_REGULAR_EXPRESSION_BUILDER
  7. redefine parse_extended_pattern
  8. end
  9. create {ANY}
  10. make
  11. feature {} -- parsing
  12. parse_extended_pattern
  13. local
  14. dont_restore, saved_is_case_insensitive, saved_does_match_line_boundary, saved_does_any_match_newline,
  15. saved_has_extended_legibility: BOOLEAN
  16. do
  17. -- skip known characters
  18. read_character
  19. read_character
  20. -- save the state of the flags
  21. saved_is_case_insensitive := is_case_insensitive
  22. saved_does_match_line_boundary := does_match_line_boundary
  23. saved_does_any_match_newline := does_any_match_newline
  24. saved_has_extended_legibility := has_extended_legibility
  25. -- read the flags
  26. read_modifiers(True)
  27. if not end_of_input and then last_character = '-' then
  28. read_character
  29. read_modifiers(False)
  30. end
  31. if not end_of_input then
  32. inspect
  33. last_character
  34. when ')' then
  35. -- flag alteration only
  36. emit(the_true_node)
  37. dont_restore := True
  38. when '#' then
  39. -- comment
  40. emit(the_true_node)
  41. from
  42. until
  43. end_of_input or else last_character = ')'
  44. loop
  45. read_character
  46. end
  47. when ':' then
  48. -- not capturing
  49. read_character
  50. if not end_of_input then
  51. parse_alternative
  52. end
  53. when '=' then
  54. -- zero width positive look-ahead
  55. parse_looking(True)
  56. when '!' then
  57. -- zero width negative look-ahead
  58. parse_looking(True)
  59. when '<' then
  60. -- zero width look-behind
  61. read_character
  62. if not end_of_input then
  63. inspect
  64. last_character
  65. when '=' then
  66. -- zero width positive look-behind
  67. parse_looking(False)
  68. when '!' then
  69. -- zero width negative look-behind
  70. parse_looking(False)
  71. else
  72. set_error(once "bad zero width look-behind")
  73. end
  74. end
  75. when '{', '?', '(', '>' then
  76. -- unsupported
  77. set_error(once "unsupported experimental extended pattern")
  78. when 'P' then
  79. parse_named_group
  80. else
  81. set_error(once "unknown extended pattern")
  82. end
  83. end
  84. if not has_error then
  85. if end_of_input or else last_character /= ')' then
  86. set_error(once "extended pattern not finished")
  87. else
  88. if dont_restore then
  89. else
  90. -- restore the flags
  91. is_case_insensitive := saved_is_case_insensitive
  92. does_match_line_boundary := saved_does_match_line_boundary
  93. does_any_match_newline := saved_does_any_match_newline
  94. has_extended_legibility := saved_has_extended_legibility
  95. end
  96. read_character
  97. end
  98. end
  99. end
  100. parse_named_group
  101. local
  102. group_name: FIXED_STRING; group_id: INTEGER
  103. do
  104. read_character
  105. if not end_of_input then
  106. inspect
  107. last_character
  108. when '=' then
  109. -- backtrack match by name
  110. from
  111. last_string.clear_count
  112. read_character
  113. until
  114. end_of_input or else last_character = ')'
  115. loop
  116. last_string.add_last(last_character)
  117. read_character
  118. end
  119. if end_of_input or else last_string.is_empty then
  120. set_error(once "premature end of group name")
  121. else
  122. group_name := last_string.intern
  123. if last_substrings_names.fast_has(group_name) then
  124. group_id := last_substrings_names.fast_at(group_name)
  125. check
  126. group_id.in_range(1, last_group_count)
  127. end
  128. if group_stack.has(group_id) then
  129. set_error(once "unsupported forward group number")
  130. else
  131. emit_match_previous_group(group_id)
  132. end
  133. else
  134. set_error(once "undefined named group")
  135. end
  136. end
  137. when '<' then
  138. -- new named group
  139. from
  140. last_string.clear_count
  141. read_character
  142. until
  143. end_of_input or else last_character = '>' or else last_character = ')'
  144. loop
  145. last_string.add_last(last_character)
  146. read_character
  147. end
  148. if end_of_input or else last_character = ')' or else last_string.is_empty then
  149. set_error(once "unfinished group name")
  150. else
  151. group_name := last_string.intern
  152. if last_substrings_names.fast_has(group_name) then
  153. set_error(once "duplicate group name")
  154. else
  155. check
  156. last_character = '>'
  157. end
  158. read_character
  159. prepare_group
  160. group_id := last_group_count
  161. parse_alternative
  162. if not has_error then
  163. emit_group
  164. if not has_error then
  165. last_substrings_names.add(group_id, group_name)
  166. end
  167. end
  168. end
  169. end
  170. else
  171. set_error(once "unknown character following a ?P grouping")
  172. end
  173. end
  174. ensure
  175. error_or_stack_incremented_by_one: has_error or else stack.count = old stack.count + 1
  176. end
  177. end -- class PYTHON_REGULAR_EXPRESSION_BUILDER
  178. --
  179. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  180. --
  181. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  182. -- of this software and associated documentation files (the "Software"), to deal
  183. -- in the Software without restriction, including without limitation the rights
  184. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  185. -- copies of the Software, and to permit persons to whom the Software is
  186. -- furnished to do so, subject to the following conditions:
  187. --
  188. -- The above copyright notice and this permission notice shall be included in
  189. -- all copies or substantial portions of the Software.
  190. --
  191. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  192. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  193. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  194. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  195. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  196. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  197. -- THE SOFTWARE.