From 7e66d77cfd67ca9e7ffb20f703af422f00e2dc76 Mon Sep 17 00:00:00 2001 From: Homme769 Date: Sun, 13 Oct 2019 16:54:53 +0800 Subject: [PATCH 1/2] add new code --- project01/nfa.py | 55 ++++++++++++++++++++++----- project01/regular_expression.py | 37 ++++++++++-------- project01/test_REtoNFA.py | 66 ++++++++++++++++++++++++--------- project01/test_ip.py | 2 +- project01/test_retonfa.txt | 1 + project01/visualize_nfa.py | 39 +++++++++++++++++++ 6 files changed, 157 insertions(+), 43 deletions(-) create mode 100644 project01/test_retonfa.txt create mode 100644 project01/visualize_nfa.py diff --git a/project01/nfa.py b/project01/nfa.py index 2c85919..e232fc0 100644 --- a/project01/nfa.py +++ b/project01/nfa.py @@ -42,11 +42,11 @@ class NFA(): Defination of the regular language. Attributes: - alphabet: list object to store finate alphabet + alphabet: list object to store finite alphabet states: list object to store the states s_state: State object (cannot be None) f_states: list object to store the accepted states - t_function: a nesting dict obejct, whose value is also a dict object + t_function: a nesting dict object, whose value is also a dict object that store the states corresponded to the action on the edge """ def __init__(self, alphabet, states, s_state, f_states=[], t_function=None): @@ -224,11 +224,7 @@ def or_nfa(self, other_nfa): return nfa def add_nfa(self, other_nfa): - """ provide an or mehotd for oring two nfas - - plz refered to the P68 in the <>, - for it is hard to explain in words. - QAQ + """ provide an or method for oring two nfas Args: nfa : other NFA object @@ -302,16 +298,57 @@ def __or__(self, other): def __str__(self): ret = ('------------------NFA desciption------------\n' + - 'aphabelt : {}'.format(str(self.alphabet)) + '\n' + + 'alphabet : {}'.format(str(self.alphabet)) + '\n' + 'states : {}'.format(str(self.states)) + '\n' + 'start state : {}'.format(str(self.s_state)) + '\n' + 'accepted states : {}'.format(str(self.f_states)) + '\n' + - 'transition fuctions : ' + '\n') + 'transition functions : ' + '\n') for key in self.t_function.keys(): item_str = str((key, str(self.t_function[key]))) ret += item_str + '\n' return ret +<<<<<<< Updated upstream +======= +#------------------------------------------------------------------------------ +# Recogize if string is legal +#------------------------------------------------------------------------------ + def _run(self, s, present_node): + """ provide a method for using nfa to recognize string, + + The method provides a bfs-like method for recognizing string s, + if s is empty and present_node is in the self.f_states: + we can conclude that string is recognizable. + if not: + first we deals with the EMPTY STRING situation, the functions will + pass s directly to the next search; + secondly, we can check if s[0] is the item of present_node's transition + function in the nfa, and we pass s[1:] (s[0] is used) to the next search; + + Args: + s : string that is needed to be judged + present_node : the current state of current search turn + Returns: + if nfa recognized a string, return True + if string is illegal to this nfa, return False + """ + + if not s: + if present_node in self.f_states: + return True + else: + return False + + if EMPTY_STRING in self.t_function[present_node]: + for to_node in self.t_function[present_node][EMPTY_STRING]: + if self._run(s, to_node): + return True + + if s[0] in self.t_function[present_node]: + for to_node in self.t_function[present_node][s[0]]: + if self._run(s[1:], to_node): + return True +>>>>>>> Stashed changes if __name__ == '__main__': diff --git a/project01/regular_expression.py b/project01/regular_expression.py index f4b6ac5..ffd0f31 100644 --- a/project01/regular_expression.py +++ b/project01/regular_expression.py @@ -4,11 +4,16 @@ class RE(): """Defination of the regular language. Attributes: +<<<<<<< Updated upstream s: the string to describe the regular language +======= + s: the string that describes the regular language + alphabet: list object to store finite alphabet +>>>>>>> Stashed changes """ def __init__(self, alphabet, s): - # TODO check is word in s is in the alphabeta + # TODO check is word in s is in the alphabet self.alphabet = alphabet self.s = s @@ -40,32 +45,32 @@ def __str__(self): return self.s # a function object that can used to produce a re object -# when alphabelt is given -EMPTY_RE = (lambda alphabelt: RE(alphabelt, EMPTY_STRING)) +# when alphabet is given +EMPTY_RE = (lambda alphabet: RE(alphabet, EMPTY_STRING)) -def get_alphabelt_re(alphabelt): - ret = EMPTY_RE(alphabelt) +def get_alphabelt_re(alphabet): + ret = EMPTY_RE(alphabet) - if alphabelt: - ret = RE(alphabelt, alphabelt[0]) - for a in alphabelt[1:]: - ret |= RE(alphabelt, a) + if alphabet: + ret = RE(alphabet, alphabet[0]) + for a in alphabet[1:]: + ret |= RE(alphabet, a) return ret() if __name__ == '__main__': - alphabelt = ['0', '1'] + alphabet = ['0', '1'] - re_01 = (lambda s: RE(alphabelt, s)) + re_01 = (lambda s: RE(alphabet, s)) print(re_01('0').repeat()) - # test pratices in P65 of book + # test practices in P65 of book # test01: 0*10* - # print(RE(alphabelt, '0')) + # print(RE(alphabet, '0')) print(re_01('0').repeat() + re_01('1') + re_01('0').repeat()) - # test02: (alphabelt)*1(alphabelt)* - re_alphabeta = get_alphabelt_re(alphabelt) - print(re_alphabeta.repeat() + re_01('1') + re_alphabeta.repeat()) + # test02: (alphabet)*1(alphabet)* + re_alphabet = get_alphabelt_re(alphabet) + print(re_alphabet.repeat() + re_01('1') + re_alphabet.repeat()) # test03: 01 | 10 print(re_01('01') | re_01('10')) \ No newline at end of file diff --git a/project01/test_REtoNFA.py b/project01/test_REtoNFA.py index 6462645..72750ba 100644 --- a/project01/test_REtoNFA.py +++ b/project01/test_REtoNFA.py @@ -2,6 +2,7 @@ from regular_expression import RE from nfa import NFA, State from nfa import generate_state +from graphviz import Digraph EMPTY_STRING = '' @@ -30,7 +31,7 @@ def generate_head_nfa(alphabet): which is also the the start state and this nfa doesn't have final state Args: - aplhabet : alphabet of the constucting nfa + alphabet : alphabet of the constructing nfa Returns: nfa : A NFA object that only has an initial state, which is also the the start state and this nfa doesn't have final state @@ -45,7 +46,7 @@ def generate_aciton_nfa(action, alphabet): Args: action : means the string needed for transition - aplhabet : alphabet of the constucting nfa + alphabet : alphabet of the constructing nfa Returns: nfa : A NFA object recognizes the action string @@ -72,11 +73,11 @@ def read_or(s, alphabet, nfa1): use or operator to combine these two nfas Args: - aplhabet : alphabet of the constucting nfa - nfa1 : the nfa that recoginize the previous - regular expresssion string + alphabet : alphabet of the constructing nfa + nfa1 : the nfa that recognize the previous + regular expression string Returns: - if nfa is None(haven't recogized string before): return action_nfa + if nfa is None(haven't recognized string before): return action_nfa if not : return nfa + action_nfa Raises: """ @@ -88,7 +89,7 @@ def read_repeat(s, alphabet, nfa): # Your code here pass -def read_parentheses(s, nfa): +def read_parentheses(s, nfa, alphabet): # TODO(ShipXu): This fuction reserved for XiaoHanHou. # Your code here # p_nfa @@ -106,15 +107,15 @@ def read_add(action, alphabet, nfa=None): """ deal with the add situation generate nfa that recognize the action string - if nfa is None(haven't recogized string before): return action_nfa + if nfa is None(haven't recognized string before): return action_nfa if not : return nfa + action_nfa Args: - alphabet : alphabet of the constucting nfa - nfa : the nfa that recoginize the previous - regular expresssion string + alphabet : alphabet of the constructing nfa + nfa : the nfa that recognize the previous + regular expression string Returns: - if nfa is None(haven't recogized string before): return action_nfa + if nfa is None(haven't recognized string before): return action_nfa if not : return nfa + action_nfa Raises: """ @@ -181,10 +182,10 @@ def trans_RE_to_NFA(re): """ return _trans_RE_to_NFA(re.s, re.alphabet) -def add_parathese_repeat(s): - return _add_parathese_repeat(s, 0) +def add_parenthese_repeat(s): + return _add_parenthese_repeat(s, 0) -def _add_parathese_repeat(s, index): +def _add_parenthese_repeat(s, index): if not s: return s @@ -197,10 +198,11 @@ def _add_parathese_repeat(s, index): if new_r_index >= 2 and s[new_r_index - 1] != ')': return (s[0 : new_r_index - 1] + '(' + s[new_r_index - 1] + ')*' - + add_parathese_repeat(s[new_r_index + 1:])) + + add_parenthese_repeat(s[new_r_index + 1:])) if new_r_index >= 1 and s[new_r_index - 1] != ')': return ('(' + s[0 : new_r_index] + ')*' +<<<<<<< Updated upstream + add_parathese_repeat(s[new_r_index + 1:])) if __name__ == '__main__': @@ -215,4 +217,34 @@ def _add_parathese_repeat(s, index): re = RE(alphabet, add_parathese_repeat(regular_string)) nfa = trans_RE_to_NFA(re) - print(nfa) \ No newline at end of file + print(nfa) +======= + + add_parenthese_repeat(s[new_r_index + 1:])) + + return s + +if __name__ == '__main__': + with open('test_retonfa.txt') as f: + count = 1 + for line in f.readlines(): + regular_string = line.replace('\n', '') + print('test {}'.format(str(count))) + print('before add parenthese : {}'.format(regular_string)) + print('after adding parenthese : {}'.format(add_parenthese_repeat(regular_string))) + + alphabet = list(set([word for word in regular_string + if word.isalpha() or word.isdigit()])) + re = RE(alphabet, add_parenthese_repeat(regular_string)) + + nfa = trans_RE_to_NFA(re) + print('the nfa of {}'.format(add_parenthese_repeat(regular_string))) + print(nfa) + + # dot = Digraph() + # for key in nfa.t_function.keys(): + # dot.node('%s'%key, shape="circle") + # for action,node in nfa.t_function[key].keys(): + # dot.edges('%s'%action, '%s%s'%key%node) + # dot.view() + count += 1 +>>>>>>> Stashed changes diff --git a/project01/test_ip.py b/project01/test_ip.py index b96d82e..6800f34 100644 --- a/project01/test_ip.py +++ b/project01/test_ip.py @@ -17,7 +17,7 @@ def ip_match(input_string): Raises: """ - pattern_string = '([0-2]?[0-9]?[0-9]\.){3}([0-2]?[0-9]?[0-9])' + pattern_string = '(([1-9])\.|([1-9][0-9])\.|(1\d\d)\.|(2[0-4]\d)\.|(25[0-5])\.)(([1-9]?\d)\.|(1\d\d)\.|(2[0-4]\d)\.|(25[0-5])\.){2}(([1-9]?\d)|(1\d\d)|(2[0-4]\d)|(25[0-5]))$' match_ret = re.match(pattern_string, input_string) return match_ret is not None diff --git a/project01/test_retonfa.txt b/project01/test_retonfa.txt new file mode 100644 index 0000000..02e7180 --- /dev/null +++ b/project01/test_retonfa.txt @@ -0,0 +1 @@ +(ab|b)* \ No newline at end of file diff --git a/project01/visualize_nfa.py b/project01/visualize_nfa.py new file mode 100644 index 0000000..9f327ae --- /dev/null +++ b/project01/visualize_nfa.py @@ -0,0 +1,39 @@ +# -*- coding:utf-8 -*- +from nfa import EMPTY_STRING +from regular_expression import RE +from test_REtoNFA import trans_RE_to_NFA, add_parentheses_repeat +from graphviz import Digraph + +if __name__ == '__main__': + regular_string = '(ab|a)*' + alphabet = list(set([word for word in regular_string + if word.isalpha() or word.isdigit()])) + re = RE(alphabet, add_parentheses_repeat(regular_string)) + nfa = trans_RE_to_NFA(re) + + graph = Digraph() + + s_node = nfa.get_start_state() + graph.node('%s'%s_node, shape="doublecircle") + + for f_node in nfa.get_f_states(): + if f_node != s_node: + graph.node('%s'%f_node, shape="doublecircle") + + for node in nfa.t_function.keys(): + # if node == nfa.s_state or node in nfa.f_states: + if node != s_node and node not in nfa.get_f_states(): + graph.node('%s'%node, shape="circle") + for action in nfa.t_function[node].keys(): + for to_node in nfa.t_function[node][action]: + if action == EMPTY_STRING: + graph.edge('%s'%node, '%s'%to_node, '%s'%'EMPTY_STRING') + else: + graph.edge('%s'%node, '%s'%to_node, '%s'%graph) + + _s_node = '' + graph.node(_s_node, shape="circle", color='white') + graph.edge(_s_node, '%s'%nfa.get_start_state()) + graph.view() + # graph.format = 'png' + # graph.render('output-graph.gv', view=True) \ No newline at end of file From 4e1076e5d914c7982f7bd861411ec1117f28b128 Mon Sep 17 00:00:00 2001 From: Homme769 Date: Sun, 3 Nov 2019 15:46:18 +0800 Subject: [PATCH 2/2] 1 1 --- .idea/deployment.xml | 14 + .idea/misc.xml | 6 + .idea/vcs.xml | 6 + .idea/workspace.xml | 316 ++++++++++++++++++ project01/Digraph.gv | 36 ++ project01/Digraph.gv.pdf | Bin 0 -> 17582 bytes project01/__pycache__/nfa.cpython-36.pyc | Bin 0 -> 11778 bytes .../regular_expression.cpython-36.pyc | Bin 0 -> 2299 bytes .../__pycache__/test_REtoNFA.cpython-36.pyc | Bin 0 -> 6047 bytes project01/ip.txt | 19 +- project01/nfa.py | 101 +++--- project01/regular_expression.py | 7 +- project01/test_REtoNFA.py | 79 ++--- project01/test_ip.py | 2 +- project01/test_retonfa.txt | 4 + project01/test_run_re.py | 15 + project01/test_run_re.txt | 5 + project01/visualize_nfa.py | 24 +- 18 files changed, 512 insertions(+), 122 deletions(-) create mode 100644 .idea/deployment.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 project01/Digraph.gv create mode 100644 project01/Digraph.gv.pdf create mode 100644 project01/__pycache__/nfa.cpython-36.pyc create mode 100644 project01/__pycache__/regular_expression.cpython-36.pyc create mode 100644 project01/__pycache__/test_REtoNFA.cpython-36.pyc create mode 100644 project01/test_run_re.py create mode 100644 project01/test_run_re.txt diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 0000000..7a6a01f --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..115a47a --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1570932161168 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/project01/Digraph.gv b/project01/Digraph.gv new file mode 100644 index 0000000..79d40a4 --- /dev/null +++ b/project01/Digraph.gv @@ -0,0 +1,36 @@ +digraph { + graph [rankdir=LR] + "" [color=white shape=circle] + node4 [shape=doublecircle] + node5 [shape=doublecircle] + node13 [shape=doublecircle] + node14 [shape=doublecircle] + node1 [shape=circle] + node1 -> node2 [label=a] + node2 [shape=circle] + node2 -> node5 [label="ε"] + node3 [shape=circle] + node3 -> node4 [label=a] + node4 -> node3 [label="ε"] + node5 -> node3 [label="ε"] + node6 [shape=circle] + node6 -> node7 [label=a] + node7 [shape=circle] + node7 -> node8 [label="ε"] + node8 [shape=circle] + node8 -> node9 [label=b] + node9 [shape=circle] + node9 -> node14 [label="ε"] + node10 [shape=circle] + node10 -> node11 [label=a] + node11 [shape=circle] + node11 -> node12 [label="ε"] + node12 [shape=circle] + node12 -> node13 [label=b] + node13 -> node10 [label="ε"] + node14 -> node10 [label="ε"] + node15 [shape=circle] + node15 -> node1 [label="ε"] + node15 -> node6 [label="ε"] + "" -> node15 +} diff --git a/project01/Digraph.gv.pdf b/project01/Digraph.gv.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cbd4debab585865f08cd5980fc1a7f4f393d3399 GIT binary patch literal 17582 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 TV{v*`dUj?=Vq#%g5y<}s3BQ3X literal 0 HcmV?d00001 diff --git a/project01/__pycache__/nfa.cpython-36.pyc b/project01/__pycache__/nfa.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7f311c57f785d5cb99948862a074482a21604c91 GIT binary patch literal 11778 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, + for it is hard to explain in words. + QAQ Args: nfa : other NFA object @@ -261,27 +266,17 @@ def repeat_nfa(self): Raises: """ # TODO(ShipXu): XiaoHanHou implement this function. - # new_s_state = generate_state() - # old_s_state = self.get_start_state() - # new_f_states = self.f_states + [new_s_state] - # nfa = NFA(self.alphabet, self.states, new_s_state, new_f_states, self.t_function) - # nfa.add_state(new_s_state) - # nfa.set_start_state(new_s_state) - # nfa.add_function_item(new_s_state, EMPTY_STRING, old_s_state) - - # for f_state in self.f_states: - # nfa.add_function_item(f_state, EMPTY_STRING, old_s_state) - new_s_state = generate_state() old_s_state = self.get_start_state() - nfa = NFA(self.alphabet, self.states, new_s_state, self.f_states, self.t_function) + new_f_states = self.f_states.copy() + [new_s_state] + nfa = NFA(self.alphabet, self.states.copy(), new_s_state, new_f_states, self.t_function) + nfa.add_state(new_s_state) nfa.set_start_state(new_s_state) - nfa.add_f_state(new_s_state) + nfa.add_function_item(new_s_state, EMPTY_STRING, old_s_state) for f_state in self.f_states: nfa.add_function_item(f_state, EMPTY_STRING, old_s_state) - return nfa #------------------------------------------------------------------------------ @@ -298,21 +293,33 @@ def __or__(self, other): def __str__(self): ret = ('------------------NFA desciption------------\n' + - 'alphabet : {}'.format(str(self.alphabet)) + '\n' + + 'aphabelt : {}'.format(str(self.alphabet)) + '\n' + 'states : {}'.format(str(self.states)) + '\n' + 'start state : {}'.format(str(self.s_state)) + '\n' + 'accepted states : {}'.format(str(self.f_states)) + '\n' + - 'transition functions : ' + '\n') + 'transition fuctions : ' + '\n') for key in self.t_function.keys(): item_str = str((key, str(self.t_function[key]))) ret += item_str + '\n' return ret -<<<<<<< Updated upstream -======= #------------------------------------------------------------------------------ # Recogize if string is legal #------------------------------------------------------------------------------ + def run(self, s): + """ provide a method for using nfa to recognize string, + + nfa will determine if the string is belong to the grammar of nfa. + + Args: + s : string that is needed to be judged + Returns: + if nfa recognized a string, return True + if string is illegal to this nfa, return False + Raises: + """ + return self._run(s, self.s_state) + def _run(self, s, present_node): """ provide a method for using nfa to recognize string, @@ -348,25 +355,26 @@ def _run(self, s, present_node): for to_node in self.t_function[present_node][s[0]]: if self._run(s[1:], to_node): return True ->>>>>>> Stashed changes + return False if __name__ == '__main__': alphabet = ['a', 'b'] # test01: generate_state + print('test01: generate_state') s1 = generate_state() s2 = generate_state() s3 = generate_state() print(s1, s2, s3) # test02: nfa + print('test02: generate nfa') states = [s1, s2] s_state = s1 f_states = [s1, s2] nfa = NFA(alphabet, states, s_state, f_states) nfa.add_function_item(s1, 'a', s2) - nfa.add_function_item(s2, 'a', s2) print(nfa) # generate states variable @@ -376,6 +384,7 @@ def _run(self, s, present_node): print(states) # test03: nfa a ; nfa b + print('test03: nfa a ; nfa b') nfa1 = NFA(alphabet, states[0:2], states[0], [states[1]]) nfa1.add_function_item(states[0], 'a', states[1]) print('-------nfa1--------') @@ -385,7 +394,14 @@ def _run(self, s, present_node): print('-------nfa2--------') print(nfa2) + new_states = generate_states(2) + nfa3 = NFA(alphabet, new_states[0:2], new_states[0], [new_states[1]]) + nfa3.add_function_item(new_states[0], 'a', new_states[1]) + print('-------nfa3--------') + print(nfa3) + # test04: test for t_function_union + print('test04: for t_function_union') t_function1 = nfa1.get_t_function() t_function2 = nfa2.get_t_function() @@ -395,18 +411,17 @@ def _run(self, s, present_node): print(union_t_function(t_function1, t_function2)) # test05: test for '+' + print('test05: test for +') print('-------nfa1 + nfa2--------') print(nfa1 + nfa2) # test05: test for '|' + print('test05: test for |') print('-------(nfa1 + nfa2) | nfa3--------') - new_states = generate_states(2) - - nfa3 = NFA(alphabet, new_states[0:2], new_states[0], [new_states[1]]) - nfa3.add_function_item(new_states[0], 'a', new_states[1]) print((nfa1 + nfa2) | nfa3) # test06: test for '*' - # print('-------((nfa1 + nfa2) | nfa1).repeat()--------') - # print(((nfa1 + nfa2) | nfa1).repeat()) - print(nfa2.repeat()) \ No newline at end of file + print('test06: test for *') + print('-------((nfa1 + nfa2) | nfa3).repeat()--------') + print(((nfa1 + nfa2) | nfa3).repeat()) + nfa4 = ((nfa1 + nfa2) | nfa3).repeat() \ No newline at end of file diff --git a/project01/regular_expression.py b/project01/regular_expression.py index ffd0f31..fba696e 100644 --- a/project01/regular_expression.py +++ b/project01/regular_expression.py @@ -1,16 +1,11 @@ EMPTY_STRING = '' class RE(): - """Defination of the regular language. + """Definition of the regular language. Attributes: -<<<<<<< Updated upstream - s: the string to describe the regular language - -======= s: the string that describes the regular language alphabet: list object to store finite alphabet ->>>>>>> Stashed changes """ def __init__(self, alphabet, s): # TODO check is word in s is in the alphabet diff --git a/project01/test_REtoNFA.py b/project01/test_REtoNFA.py index 72750ba..b258336 100644 --- a/project01/test_REtoNFA.py +++ b/project01/test_REtoNFA.py @@ -2,7 +2,6 @@ from regular_expression import RE from nfa import NFA, State from nfa import generate_state -from graphviz import Digraph EMPTY_STRING = '' @@ -31,7 +30,7 @@ def generate_head_nfa(alphabet): which is also the the start state and this nfa doesn't have final state Args: - alphabet : alphabet of the constructing nfa + aplhabet : alphabet of the constucting nfa Returns: nfa : A NFA object that only has an initial state, which is also the the start state and this nfa doesn't have final state @@ -46,7 +45,7 @@ def generate_aciton_nfa(action, alphabet): Args: action : means the string needed for transition - alphabet : alphabet of the constructing nfa + aplhabet : alphabet of the constucting nfa Returns: nfa : A NFA object recognizes the action string @@ -73,11 +72,11 @@ def read_or(s, alphabet, nfa1): use or operator to combine these two nfas Args: - alphabet : alphabet of the constructing nfa - nfa1 : the nfa that recognize the previous - regular expression string + aplhabet : alphabet of the constucting nfa + nfa1 : the nfa that recoginize the previous + regular expresssion string Returns: - if nfa is None(haven't recognized string before): return action_nfa + if nfa is None(haven't recogized string before): return action_nfa if not : return nfa + action_nfa Raises: """ @@ -89,7 +88,7 @@ def read_repeat(s, alphabet, nfa): # Your code here pass -def read_parentheses(s, nfa, alphabet): +def read_parentheses(s, alphabet, nfa): # TODO(ShipXu): This fuction reserved for XiaoHanHou. # Your code here # p_nfa @@ -107,15 +106,15 @@ def read_add(action, alphabet, nfa=None): """ deal with the add situation generate nfa that recognize the action string - if nfa is None(haven't recognized string before): return action_nfa + if nfa is None(haven't recogized string before): return action_nfa if not : return nfa + action_nfa Args: - alphabet : alphabet of the constructing nfa - nfa : the nfa that recognize the previous - regular expression string + alphabet : alphabet of the constucting nfa + nfa : the nfa that recoginize the previous + regular expresssion string Returns: - if nfa is None(haven't recognized string before): return action_nfa + if nfa is None(haven't recogized string before): return action_nfa if not : return nfa + action_nfa Raises: """ @@ -143,12 +142,13 @@ def read_token(s, alphabet, nfa=None): if not s: return nfa - if s[0] == '*': - return read_repeat(s[1:], alphabet, nfa) - elif s[0] == '|': + # if s[0] == '*': + # return read_repeat(s[1:], alphabet, nfa) + # el + if s[0] == '|': return read_or(s[1:], alphabet, nfa) elif s[0] == '(': - index_rp, p_nfa = read_parentheses(s[1:], nfa) + index_rp, p_nfa = read_parentheses(s[1:], alphabet, nfa) # consider the left parentheses index_rp += 1 if len(s) >= index_rp + 2 and s[index_rp + 1] == '*': @@ -182,10 +182,10 @@ def trans_RE_to_NFA(re): """ return _trans_RE_to_NFA(re.s, re.alphabet) -def add_parenthese_repeat(s): - return _add_parenthese_repeat(s, 0) +def add_parentheses_repeat(s): + return _add_parentheses_repeat(s, 0) -def _add_parenthese_repeat(s, index): +def _add_parentheses_repeat(s, index): if not s: return s @@ -198,28 +198,11 @@ def _add_parenthese_repeat(s, index): if new_r_index >= 2 and s[new_r_index - 1] != ')': return (s[0 : new_r_index - 1] + '(' + s[new_r_index - 1] + ')*' - + add_parenthese_repeat(s[new_r_index + 1:])) + + add_parentheses_repeat(s[new_r_index + 1:])) if new_r_index >= 1 and s[new_r_index - 1] != ')': return ('(' + s[0 : new_r_index] + ')*' -<<<<<<< Updated upstream - + add_parathese_repeat(s[new_r_index + 1:])) - -if __name__ == '__main__': - # alphabet = ['a', 'b'] - - # regualar_string = '(b)* | a' - regular_string = 'aaaa | b*' - print('before add parethese : {}'.format(regular_string)) - print('after adding parethese : {}'.format(add_parathese_repeat(regular_string))) - alphabet = list(set([word for word in regular_string - if word.isalpha() or word.isdigit()])) - re = RE(alphabet, add_parathese_repeat(regular_string)) - - nfa = trans_RE_to_NFA(re) - print(nfa) -======= - + add_parenthese_repeat(s[new_r_index + 1:])) + + add_parentheses_repeat(s[new_r_index + 1:])) return s @@ -229,22 +212,14 @@ def _add_parenthese_repeat(s, index): for line in f.readlines(): regular_string = line.replace('\n', '') print('test {}'.format(str(count))) - print('before add parenthese : {}'.format(regular_string)) - print('after adding parenthese : {}'.format(add_parenthese_repeat(regular_string))) + print('before add parethese : {}'.format(regular_string)) + print('after adding parethese : {}'.format(add_parentheses_repeat(regular_string))) alphabet = list(set([word for word in regular_string if word.isalpha() or word.isdigit()])) - re = RE(alphabet, add_parenthese_repeat(regular_string)) + re = RE(alphabet, add_parentheses_repeat(regular_string)) nfa = trans_RE_to_NFA(re) - print('the nfa of {}'.format(add_parenthese_repeat(regular_string))) + print('the nfa of {}'.format(add_parentheses_repeat(regular_string))) print(nfa) - - # dot = Digraph() - # for key in nfa.t_function.keys(): - # dot.node('%s'%key, shape="circle") - # for action,node in nfa.t_function[key].keys(): - # dot.edges('%s'%action, '%s%s'%key%node) - # dot.view() - count += 1 ->>>>>>> Stashed changes + count += 1 \ No newline at end of file diff --git a/project01/test_ip.py b/project01/test_ip.py index 6800f34..cd552b2 100644 --- a/project01/test_ip.py +++ b/project01/test_ip.py @@ -17,7 +17,7 @@ def ip_match(input_string): Raises: """ - pattern_string = '(([1-9])\.|([1-9][0-9])\.|(1\d\d)\.|(2[0-4]\d)\.|(25[0-5])\.)(([1-9]?\d)\.|(1\d\d)\.|(2[0-4]\d)\.|(25[0-5])\.){2}(([1-9]?\d)|(1\d\d)|(2[0-4]\d)|(25[0-5]))$' + pattern_string ='(([1-9])\.|([1-9][0-9])\.|(1\d\d)\.|(2[0-4]\d)\.|(25[0-5])\.)(([1-9]?\d)\.|(1\d\d)\.|(2[0-4]\d)\.|(25[0-5])\.){2}(([1-9]?\d)|(1\d\d)|(2[0-4]\d)|(25[0-5]))$' match_ret = re.match(pattern_string, input_string) return match_ret is not None diff --git a/project01/test_retonfa.txt b/project01/test_retonfa.txt index 02e7180..9bf1233 100644 --- a/project01/test_retonfa.txt +++ b/project01/test_retonfa.txt @@ -1 +1,5 @@ +a +b +ab +ab|b (ab|b)* \ No newline at end of file diff --git a/project01/test_run_re.py b/project01/test_run_re.py new file mode 100644 index 0000000..c43aacf --- /dev/null +++ b/project01/test_run_re.py @@ -0,0 +1,15 @@ +from regular_expression import RE +from test_REtoNFA import trans_RE_to_NFA, add_parentheses_repeat + +if __name__ == '__main__': + regular_string = '(ab|a)*' + alphabet = list(set([word for word in regular_string + if word.isalpha() or word.isdigit()])) + re = RE(alphabet, add_parentheses_repeat(regular_string)) + nfa = trans_RE_to_NFA(re) + + with open('test_run_re.txt') as file: + for line in file.readlines(): + line = line.replace('\n', '') + if (nfa.run(line)): + print('matched and matched result {}'.format(line.replace('\n', ''))) \ No newline at end of file diff --git a/project01/test_run_re.txt b/project01/test_run_re.txt new file mode 100644 index 0000000..4c67a0e --- /dev/null +++ b/project01/test_run_re.txt @@ -0,0 +1,5 @@ +a +ab +aba +abbbbb +abaabababa \ No newline at end of file diff --git a/project01/visualize_nfa.py b/project01/visualize_nfa.py index 9f327ae..e2b4cce 100644 --- a/project01/visualize_nfa.py +++ b/project01/visualize_nfa.py @@ -1,39 +1,37 @@ -# -*- coding:utf-8 -*- from nfa import EMPTY_STRING from regular_expression import RE from test_REtoNFA import trans_RE_to_NFA, add_parentheses_repeat from graphviz import Digraph if __name__ == '__main__': - regular_string = '(ab|a)*' + regular_string = 'aa*|ab(ab)*' alphabet = list(set([word for word in regular_string if word.isalpha() or word.isdigit()])) re = RE(alphabet, add_parentheses_repeat(regular_string)) nfa = trans_RE_to_NFA(re) + print(nfa) graph = Digraph() - s_node = nfa.get_start_state() - graph.node('%s'%s_node, shape="doublecircle") + _s_node = '' + graph.node(_s_node, shape="circle", color='white') for f_node in nfa.get_f_states(): - if f_node != s_node: - graph.node('%s'%f_node, shape="doublecircle") + graph.node('%s'%f_node, shape="doublecircle") for node in nfa.t_function.keys(): # if node == nfa.s_state or node in nfa.f_states: - if node != s_node and node not in nfa.get_f_states(): + if node not in nfa.get_f_states(): graph.node('%s'%node, shape="circle") for action in nfa.t_function[node].keys(): for to_node in nfa.t_function[node][action]: if action == EMPTY_STRING: - graph.edge('%s'%node, '%s'%to_node, '%s'%'EMPTY_STRING') + graph.edge('%s'%node, '%s'%to_node, 'ε') else: - graph.edge('%s'%node, '%s'%to_node, '%s'%graph) - - _s_node = '' - graph.node(_s_node, shape="circle", color='white') - graph.edge(_s_node, '%s'%nfa.get_start_state()) + graph.edge('%s'%node, '%s'%to_node, '%s'%action) + + graph.edge(_s_node, '%s'%s_node) + graph.graph_attr['rankdir'] = 'LR' graph.view() # graph.format = 'png' # graph.render('output-graph.gv', view=True) \ No newline at end of file