Skip to content

Commit

Permalink
Resolve issue #19
Browse files Browse the repository at this point in the history
  • Loading branch information
Aunsiels committed Jan 25, 2024
1 parent dc535ab commit 81d69bd
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 15 deletions.
14 changes: 11 additions & 3 deletions pyformlang/regular_expression/python_regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,14 @@ def _preprocess_brackets(self):
in_brackets = 0
in_brackets_temp = []
for symbol in self._python_regex:
if symbol == "[" and (not regex_temp or regex_temp[-1] != "\\"):
if symbol == "[" and (not regex_temp or regex_temp[-1] != "\\") and \
(in_brackets == 0 or not in_brackets_temp[-1] or in_brackets_temp[-1][-1] != "\\"):
in_brackets += 1
in_brackets_temp.append([])
elif symbol == "]" and (not regex_temp or regex_temp[-1] != "\\"):
elif symbol == "]" and (not regex_temp or regex_temp[-1] != "\\") and \
(in_brackets == 0 or not in_brackets_temp[-1] or
(in_brackets_temp[-1][-1] != "\\" or
(len(in_brackets_temp[-1]) > 1 and in_brackets_temp[-1][-2] == "\\"))):
if len(in_brackets_temp) == 1:
regex_temp.append("(")
regex_temp += self._preprocess_brackets_content(
Expand Down Expand Up @@ -151,7 +155,11 @@ def _preprocess_brackets_content(self, bracket_content):
else:
for j in range(ord(bracket_content[i - 1]) + 1,
ord(bracket_content[i + 1])):
bracket_content_temp.append(chr(j))
next_char = chr(j)
if next_char in TRANSFORMATIONS:
bracket_content_temp.append(TRANSFORMATIONS[next_char])
else:
bracket_content_temp.append(next_char)
previous_is_valid_for_range = False
else:
if self._should_escape_next_symbol(bracket_content_temp):
Expand Down
42 changes: 31 additions & 11 deletions pyformlang/regular_expression/tests/test_python_regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,12 @@ def test_escape_backslash_opening_bracket(self):
regex = PythonRegex(r"a\\[ab]")
self.assertTrue(regex.accepts(["a", "\\", "a"]))
self.assertTrue(regex.accepts(["a", "\\", "b"]))
self._test_compare(r"a\\[ab]", "a\\a")

def test_escape_backslash_closing_bracket(self):
regex = PythonRegex(r"a[ab\\]")
self.assertTrue(regex.accepts(["a", "a"]))
self.assertTrue(regex.accepts(["a", "b"]))
self.assertTrue(regex.accepts(["a", "\\"]))
self._test_compare(r"a[ab\\]", "aa")
self._test_compare(r"a[ab\\]", "ab")
self._test_compare(r"a[ab\\]", "a\\")

def test_escape_backslash_question_mark(self):
regex = PythonRegex(r"a\\?")
Expand Down Expand Up @@ -196,13 +196,33 @@ def test_shortcut_word(self):
self.assertTrue(regex.accepts(["a", "A"]))
self.assertTrue(regex.accepts(["a", "f"]))

def _test_compare(self, regex, s_test):
r_pyformlang = PythonRegex(regex)
r_python = re.compile(regex)
self.assertEqual(r_pyformlang.accepts(s_test), r_python.match(s_test) is not None)

def test_backslash(self):
r_all = PythonRegex('.*')
r_python = re.compile(".*")
self.assertEqual(r_all.accepts(']'), r_python.match("]") is not None)
self.assertEqual(r_all.accepts('\\'), r_python.match("\\") is not None)
self._test_compare(".*", "]")
self._test_compare(".*", "\\")

def test_escape_dot(self):
r_pyformlang = PythonRegex('\\.')
r_re = re.compile("\\.")
self.assertEqual(r_pyformlang.accepts("."), r_re.match(".") is not None)
self._test_compare("\\.", ".")

def test_brackets(self):
self._test_compare(r"[{}]", "{")
self._test_compare(r"[{-}]", "{")
self._test_compare(r"[{-}]", "-")
self._test_compare(r"[{-}]", "}")

def test_brackets_escape(self):
self._test_compare(r"[\[]", "[")
self._test_compare(r"[Z-\[]", "Z")
self._test_compare(r"[Z-\[]", "[")
self._test_compare(r"[\[-a]", "[")
self._test_compare(r"[\[-a]", "a")
self._test_compare(r"[\[-\]]", "[")
self._test_compare(r"[\[-\]]", "]")
self._test_compare(r"[Z-\]]", "Z")
self._test_compare(r"[Z-\]]", "]")
self._test_compare(r"[\]-a]", "]")
self._test_compare(r"[\]-a]", "a")
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

setuptools.setup(
name='pyformlang',
version='1.0.4',
version='1.0.5',
#scripts=['pyformlang'] ,
author="Julien Romero",
author_email="[email protected]",
Expand Down

1 comment on commit 81d69bd

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
pyformlang
   __init__.py10100% 
pyformlang/cfg
   __init__.py70100% 
   cfg.py5500100% 
   cfg_object.py100100% 
   cyk_table.py720100% 
   epsilon.py60100% 
   llone_parser.py15622 99%
   parse_tree.py6211 98%
   pda_object_creator.py310100% 
   production.py330100% 
   recursive_decent_parser.py5611 98%
   set_queue.py140100% 
   terminal.py150100% 
   utils.py100100% 
   utils_cfg.py250100% 
   variable.py260100% 
pyformlang/cfg/tests
   __init__.py00100% 
   test_cfg.py59811 99%
   test_llone_parser.py11811 99%
   test_production.py220100% 
   test_recursive_decent_parser.py250100% 
   test_terminal.py190100% 
   test_variable.py160100% 
pyformlang/fcfg
   __init__.py40100% 
   fcfg.py11711 99%
   feature_production.py260100% 
   feature_structure.py19133 98%
   state.py350100% 
pyformlang/fcfg/tests
   __init__.py00100% 
   test_fcfg.py1230100% 
   test_feature_structure.py1590100% 
pyformlang/finite_automaton
   __init__.py100100% 
   deterministic_finite_automaton.py20722 99%
   doubly_linked_list.py340100% 
   doubly_linked_node.py150100% 
   epsilon.py100100% 
   epsilon_nfa.py3720100% 
   finite_automaton.py1620100% 
   finite_automaton_object.py100100% 
   hopcroft_processing_list.py220100% 
   nondeterministic_finite_automaton.py220100% 
   nondeterministic_transition_function.py500100% 
   partition.py360100% 
   regexable.py160100% 
   state.py150100% 
   symbol.py110100% 
   transition_function.py5111 98%
pyformlang/finite_automaton/tests
   __init__.py00100% 
   test_deterministic_finite_automaton.py2610100% 
   test_epsilon.py100100% 
   test_epsilon_nfa.py6210100% 
   test_nondeterministic_finite_automaton.py930100% 
   test_nondeterministic_transition_function.py610100% 
   test_state.py280100% 
   test_symbol.py270100% 
   test_transition_function.py600100% 
pyformlang/fst
   __init__.py20100% 
   fst.py2420100% 
pyformlang/fst/tests
   __init__.py00100% 
   test_fst.py1600100% 
pyformlang/indexed_grammar
   __init__.py70100% 
   consumption_rule.py340100% 
   duplication_rule.py300100% 
   end_rule.py300100% 
   indexed_grammar.py25722 99%
   production_rule.py320100% 
   reduced_rule.py250100% 
   rule_ordering.py700100% 
   rules.py690100% 
pyformlang/indexed_grammar/tests
   __init__.py00100% 
   test_indexed_grammar.py2250100% 
   test_rules.py360100% 
pyformlang/pda
   __init__.py60100% 
   cfg_variable_converter.py6744 94%
   epsilon.py40100% 
   pda.py3090100% 
   stack_symbol.py160100% 
   state.py180100% 
   symbol.py140100% 
   transition_function.py460100% 
   utils.py360100% 
pyformlang/pda/tests
   __init__.py00100% 
   test_pda.py2460100% 
pyformlang/regular_expression
   __init__.py40100% 
   python_regex.py13611 99%
   regex.py1430100% 
   regex_objects.py790100% 
   regex_reader.py16044 98%
pyformlang/regular_expression/tests
   __init__.py00100% 
   test_python_regex.py1820100% 
   test_regex.py2450100% 
pyformlang/rsa
   __init__.py30100% 
   box.py3866 84%
   recursive_automaton.py8766 93%
pyformlang/rsa/tests
   __init__.py00100% 
   test_rsa.py510100% 
pyformlang/tests
   __init__.py00100% 
TOTAL78403699% 

Tests Skipped Failures Errors Time
260 0 💤 0 ❌ 0 🔥 3.373s ⏱️

Please sign in to comment.