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