| OLD | NEW |
| 1 # Copyright 2013 the V8 project authors. All rights reserved. | 1 # Copyright 2013 the V8 project authors. All rights reserved. |
| 2 # Redistribution and use in source and binary forms, with or without | 2 # Redistribution and use in source and binary forms, with or without |
| 3 # modification, are permitted provided that the following conditions are | 3 # modification, are permitted provided that the following conditions are |
| 4 # met: | 4 # met: |
| 5 # | 5 # |
| 6 # * Redistributions of source code must retain the above copyright | 6 # * Redistributions of source code must retain the above copyright |
| 7 # notice, this list of conditions and the following disclaimer. | 7 # notice, this list of conditions and the following disclaimer. |
| 8 # * Redistributions in binary form must reproduce the above | 8 # * Redistributions in binary form must reproduce the above |
| 9 # copyright notice, this list of conditions and the following | 9 # copyright notice, this list of conditions and the following |
| 10 # disclaimer in the documentation and/or other materials provided | 10 # disclaimer in the documentation and/or other materials provided |
| 11 # with the distribution. | 11 # with the distribution. |
| 12 # * Neither the name of Google Inc. nor the names of its | 12 # * Neither the name of Google Inc. nor the names of its |
| 13 # contributors may be used to endorse or promote products derived | 13 # contributors may be used to endorse or promote products derived |
| 14 # from this software without specific prior written permission. | 14 # from this software without specific prior written permission. |
| 15 # | 15 # |
| 16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 import ply.yacc as yacc | 28 import ply.yacc as yacc |
| 29 from automaton import Action |
| 29 from rule_lexer import RuleLexer | 30 from rule_lexer import RuleLexer |
| 30 from regex_parser import RegexParser | 31 from regex_parser import RegexParser |
| 31 from nfa_builder import NfaBuilder | 32 from nfa_builder import NfaBuilder |
| 32 from dfa import Dfa | 33 from dfa import Dfa |
| 33 from transition_keys import TransitionKey | 34 from transition_keys import TransitionKey |
| 34 | 35 |
| 35 class RuleParserState: | 36 class RuleParserState: |
| 36 | 37 |
| 37 def __init__(self): | 38 def __init__(self): |
| 38 self.aliases = { | 39 self.aliases = { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 RuleParser.__rule_precedence_counter += 1 | 110 RuleParser.__rule_precedence_counter += 1 |
| 110 rules = self.__state.rules[self.__state.current_state] | 111 rules = self.__state.rules[self.__state.current_state] |
| 111 code = p[2] | 112 code = p[2] |
| 112 if p[1] == 'default_action': | 113 if p[1] == 'default_action': |
| 113 assert not rules['default_action'] | 114 assert not rules['default_action'] |
| 114 rules['default_action'] = code | 115 rules['default_action'] = code |
| 115 elif p[1] == 'catch_all': | 116 elif p[1] == 'catch_all': |
| 116 assert not rules['catch_all'] | 117 assert not rules['catch_all'] |
| 117 rules['catch_all'] = transition | 118 rules['catch_all'] = transition |
| 118 else: | 119 else: |
| 119 rule = (p[1], (RuleParser.__rule_precedence_counter, code, transition)) | 120 rule = (p[1], RuleParser.__rule_precedence_counter, code, transition) |
| 120 rules['regex'].append(rule) | 121 rules['regex'].append(rule) |
| 121 | 122 |
| 122 def p_action(self, p): | 123 def p_action(self, p): |
| 123 'action : ACTION_OPEN IDENTIFIER ACTION_CLOSE' | 124 'action : ACTION_OPEN IDENTIFIER ACTION_CLOSE' |
| 124 p[0] = p[2] | 125 p[0] = p[2] |
| 125 | 126 |
| 126 def p_composite_regex(self, p): | 127 def p_composite_regex(self, p): |
| 127 '''composite_regex : regex_parts OR regex_parts | 128 '''composite_regex : regex_parts OR regex_parts |
| 128 | regex_parts''' | 129 | regex_parts''' |
| 129 if len(p) == 2: | 130 if len(p) == 2: |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 return dfa.lex(string) | 238 return dfa.lex(string) |
| 238 | 239 |
| 239 def __process_parser_state(self, parser_state): | 240 def __process_parser_state(self, parser_state): |
| 240 rule_map = {} | 241 rule_map = {} |
| 241 builder = NfaBuilder() | 242 builder = NfaBuilder() |
| 242 builder.set_character_classes(parser_state.character_classes) | 243 builder.set_character_classes(parser_state.character_classes) |
| 243 assert 'default' in parser_state.rules | 244 assert 'default' in parser_state.rules |
| 244 def process(k, v): | 245 def process(k, v): |
| 245 graphs = [] | 246 graphs = [] |
| 246 continues = 0 | 247 continues = 0 |
| 247 for (graph, (precedence, code, transition)) in v['regex']: | 248 for (graph, precedence, code, transition) in v['regex']: |
| 248 default_code = v['default_action'] | 249 default_code = v['default_action'] |
| 249 action = code if code else default_code | 250 if code or default_code: |
| 250 if action: | 251 action = Action('code', code if code else default_code, precedence) |
| 251 graph = NfaBuilder.add_action(graph, (precedence, action)) | 252 graph = NfaBuilder.add_action(graph, action) |
| 252 if not transition or transition == 'break': | 253 if not transition or transition == 'break': |
| 253 pass | 254 pass |
| 254 elif transition == 'continue': | 255 elif transition == 'continue': |
| 255 assert not k == 'default' | 256 assert not k == 'default' |
| 256 continues += 1 | 257 continues += 1 |
| 257 graph = NfaBuilder.add_continue(graph) | 258 graph = NfaBuilder.add_continue(graph) |
| 258 elif (transition == 'terminate' or | 259 elif (transition == 'terminate' or |
| 259 transition == 'terminate_illegal'): | 260 transition == 'terminate_illegal'): |
| 260 assert not code | 261 assert not code |
| 261 graph = NfaBuilder.add_action(graph, (-1, transition)) | 262 graph = NfaBuilder.add_action(graph, Action(transition, None, -1)) |
| 262 else: | 263 else: |
| 263 assert k == 'default' | 264 assert k == 'default' |
| 264 subgraph_modifier = '*' if code else None | 265 subgraph_modifier = '*' if code else None |
| 265 graph = NfaBuilder.join_subgraph( | 266 graph = NfaBuilder.join_subgraph( |
| 266 graph, transition, rule_map[transition], subgraph_modifier) | 267 graph, transition, rule_map[transition], subgraph_modifier) |
| 267 graphs.append(graph) | 268 graphs.append(graph) |
| 268 if continues == len(graphs): | 269 if continues == len(graphs): |
| 269 graphs.append(NfaBuilder.epsilon()) | 270 graphs.append(NfaBuilder.epsilon()) |
| 270 if v['catch_all']: | 271 if v['catch_all']: |
| 271 assert v['catch_all'] == 'continue' | 272 assert v['catch_all'] == 'continue' |
| 272 graphs.append(NfaBuilder.add_continue(NfaBuilder.catch_all())) | 273 graphs.append(NfaBuilder.add_continue(NfaBuilder.catch_all())) |
| 273 graph = NfaBuilder.or_graphs(graphs) | 274 graph = NfaBuilder.or_graphs(graphs) |
| 274 rule_map[k] = graph | 275 rule_map[k] = graph |
| 275 # process first the subgraphs, then the default graph | 276 # process first the subgraphs, then the default graph |
| 276 for k, v in parser_state.rules.items(): | 277 for k, v in parser_state.rules.items(): |
| 277 if k == 'default': continue | 278 if k == 'default': continue |
| 278 process(k, v) | 279 process(k, v) |
| 279 process('default', parser_state.rules['default']) | 280 process('default', parser_state.rules['default']) |
| 280 # build the automata | 281 # build the automata |
| 281 for rule_name, graph in rule_map.items(): | 282 for rule_name, graph in rule_map.items(): |
| 282 nfa = builder.nfa(graph) | 283 nfa = builder.nfa(graph) |
| 283 (start, dfa_nodes) = nfa.compute_dfa() | 284 (start, dfa_nodes) = nfa.compute_dfa() |
| 284 dfa = Dfa(start, dfa_nodes) | 285 dfa = Dfa(start, dfa_nodes) |
| 285 self.__automata[rule_name] = (nfa, dfa) | 286 self.__automata[rule_name] = (nfa, dfa) |
| OLD | NEW |