1# Copyright (C) 2010, 2011 Apple Inc. All rights reserved. 2# 3# Redistribution and use in source and binary forms, with or without 4# modification, are permitted provided that the following conditions 5# are met: 6# 1. Redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer. 8# 2. Redistributions in binary form must reproduce the above copyright 9# notice, this list of conditions and the following disclaimer in the 10# documentation and/or other materials provided with the distribution. 11# 12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND 13# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR 16# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 18# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 19# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 20# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 21# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 23import re 24 25from webkit2 import model 26 27 28def parse(file): 29 receiver_attributes = None 30 destination = None 31 messages = [] 32 condition = None 33 master_condition = None 34 for line in file: 35 match = re.search(r'messages -> (?P<destination>[A-Za-z_0-9]+) \s*(?:(?P<attributes>.*?)\s+)?{', line) 36 if match: 37 receiver_attributes = parse_attributes_string(match.group('attributes')) 38 39 if condition: 40 master_condition = condition 41 condition = None 42 destination = match.group('destination') 43 continue 44 if line.startswith('#'): 45 if line.startswith('#if '): 46 condition = line.rstrip()[4:] 47 elif line.startswith('#endif'): 48 condition = None 49 continue 50 match = re.search(r'([A-Za-z_0-9]+)\((.*?)\)(?:(?:\s+->\s+)\((.*?)\))?(?:\s+(.*))?', line) 51 if match: 52 name, parameters_string, reply_parameters_string, attributes_string = match.groups() 53 if parameters_string: 54 parameters = parse_parameters_string(parameters_string) 55 for parameter in parameters: 56 parameter.condition = condition 57 else: 58 parameters = [] 59 60 attributes = parse_attributes_string(attributes_string) 61 62 if reply_parameters_string: 63 reply_parameters = parse_parameters_string(reply_parameters_string) 64 for reply_parameter in reply_parameters: 65 reply_parameter.condition = condition 66 elif reply_parameters_string == '': 67 reply_parameters = [] 68 else: 69 reply_parameters = None 70 71 messages.append(model.Message(name, parameters, reply_parameters, attributes, condition)) 72 return model.MessageReceiver(destination, receiver_attributes, messages, master_condition) 73 74 75def parse_attributes_string(attributes_string): 76 if not attributes_string: 77 return None 78 return attributes_string.split() 79 80 81def split_parameters_string(parameters_string): 82 parameters = [] 83 current_parameter_string = '' 84 85 nest_level = 0 86 for character in parameters_string: 87 if character == ',' and nest_level == 0: 88 parameters.append(current_parameter_string) 89 current_parameter_string = '' 90 continue 91 92 if character == '<': 93 nest_level += 1 94 elif character == '>': 95 nest_level -= 1 96 97 current_parameter_string += character 98 99 parameters.append(current_parameter_string) 100 return parameters 101 102def parse_parameters_string(parameters_string): 103 parameters = [] 104 105 for parameter_string in split_parameters_string(parameters_string): 106 match = re.search(r'\s*(?:\[(?P<attributes>.*?)\]\s+)?(?P<type_and_name>.*)', parameter_string) 107 attributes_string, type_and_name_string = match.group('attributes', 'type_and_name') 108 parameter_type, parameter_name = type_and_name_string.rsplit(' ', 1) 109 parameters.append(model.Parameter(type=parameter_type, name=parameter_name, attributes=parse_attributes_string(attributes_string))) 110 return parameters 111