| 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 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 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 rule_lexer import RuleLexer | 29 from rule_lexer import RuleLexer |
| 30 from regex_parser import RegexParser | 30 from regex_parser import RegexParser |
| 31 from nfa_builder import NfaBuilder | 31 from nfa_builder import NfaBuilder |
| 32 from dfa import Dfa |
| 32 from transition_keys import TransitionKey | 33 from transition_keys import TransitionKey |
| 33 | 34 |
| 34 class RuleParserState: | 35 class RuleParserState: |
| 35 | 36 |
| 36 def __init__(self): | 37 def __init__(self): |
| 37 self.aliases = { | 38 self.aliases = { |
| 38 'eof' : RegexParser.parse("[\\0]"), | 39 'eof' : RegexParser.parse("[\\0]"), |
| 39 } | 40 } |
| 40 self.character_classes = {} | 41 self.character_classes = {} |
| 41 self.current_state = None | 42 self.current_state = None |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 parser.build() | 206 parser.build() |
| 206 RuleParser.__static_instance = parser | 207 RuleParser.__static_instance = parser |
| 207 parser.__state = parser_state | 208 parser.__state = parser_state |
| 208 try: | 209 try: |
| 209 parser.parser.parse(data, lexer=parser.lexer.lexer) | 210 parser.parser.parse(data, lexer=parser.lexer.lexer) |
| 210 except Exception: | 211 except Exception: |
| 211 RuleParser.__static_instance = None | 212 RuleParser.__static_instance = None |
| 212 raise | 213 raise |
| 213 parser.__state = None | 214 parser.__state = None |
| 214 assert parser_state.transitions <= set(parser_state.rules.keys()) | 215 assert parser_state.transitions <= set(parser_state.rules.keys()) |
| 216 |
| 217 class RuleProcessor(object): |
| 218 |
| 219 def __init__(self, parser_state): |
| 220 self.__automata = {} |
| 221 self.__process_parser_state(parser_state) |
| 222 |
| 223 @staticmethod |
| 224 def parse(string): |
| 225 parser_state = RuleParserState() |
| 226 RuleParser.parse(string, parser_state) |
| 227 return RuleProcessor(parser_state) |
| 228 |
| 229 def automata_iter(self): |
| 230 return iter(self.__automata.items()) |
| 231 |
| 232 def default_automata(self): |
| 233 return self.__automata['default'] |
| 234 |
| 235 def lex(self, string): |
| 236 (nfa, dfa) = self.default_automata() |
| 237 return dfa.lex(string) |
| 238 |
| 239 def __process_parser_state(self, parser_state): |
| 240 rule_map = {} |
| 241 builder = NfaBuilder() |
| 242 builder.set_character_classes(parser_state.character_classes) |
| 243 assert 'default' in parser_state.rules |
| 244 def process(k, v): |
| 245 graphs = [] |
| 246 continues = 0 |
| 247 for (graph, (precedence, code, transition)) in v['regex']: |
| 248 default_code = v['default_action'] |
| 249 action = code if code else default_code |
| 250 if action: |
| 251 graph = NfaBuilder.add_action(graph, (precedence, action)) |
| 252 if not transition or transition == 'break': |
| 253 pass |
| 254 elif transition == 'continue': |
| 255 assert not k == 'default' |
| 256 continues += 1 |
| 257 graph = NfaBuilder.add_continue(graph) |
| 258 elif (transition == 'terminate' or |
| 259 transition == 'terminate_illegal'): |
| 260 assert not code |
| 261 graph = NfaBuilder.add_action(graph, (-1, transition)) |
| 262 else: |
| 263 assert k == 'default' |
| 264 subgraph_modifier = '*' if code else None |
| 265 graph = NfaBuilder.join_subgraph( |
| 266 graph, transition, rule_map[transition], subgraph_modifier) |
| 267 graphs.append(graph) |
| 268 if continues == len(graphs): |
| 269 graphs.append(NfaBuilder.epsilon()) |
| 270 if v['catch_all']: |
| 271 assert v['catch_all'] == 'continue' |
| 272 graphs.append(NfaBuilder.add_continue(NfaBuilder.catch_all())) |
| 273 graph = NfaBuilder.or_graphs(graphs) |
| 274 rule_map[k] = graph |
| 275 # process first the subgraphs, then the default graph |
| 276 for k, v in parser_state.rules.items(): |
| 277 if k == 'default': continue |
| 278 process(k, v) |
| 279 process('default', parser_state.rules['default']) |
| 280 # build the automata |
| 281 for rule_name, graph in rule_map.items(): |
| 282 nfa = builder.nfa(graph) |
| 283 (start, dfa_nodes) = nfa.compute_dfa() |
| 284 dfa = Dfa(start, dfa_nodes) |
| 285 self.__automata[rule_name] = (nfa, dfa) |
| OLD | NEW |