def _read_type_usage(self): '''Read a type identifier, or array of type, etc. and return a SGType''' if self._match_lookahead('id', 'array', True): #found an array dimensions = [] # array [0..n,0..m] of if self._match_lookahead('symbol', '[', True): while True: low_idx = self._match_token('number')[1] self._match_token('symbol', '.') self._match_token('symbol', '.') high_idx = self._match_token('number')[1] dimensions.append((low_idx, high_idx)) if self._match_lookahead('symbol', ']', True): break self._match_token('symbol', ',') else: dimensions.append((0, 'n - 1')) # of type... self._match_token('id', 'of') nested_type = self._read_type_usage() #recursive call name = nested_type.name + ''.join([ '[%s..%s]' % (low_idx, high_idx) for low_idx, high_idx in dimensions ]) was_new = not name in all_types() result = find_or_add_type(name) if was_new: result.dimensions = dimensions result.nested_type = nested_type return result elif self._match_lookahead('symbol', '^', True): other_id = self._match_token('id')[1] other_type = find_or_add_type(other_id) name = '^' + other_type.name was_new = not name in all_types() result = find_or_add_type(name) if was_new: result.is_pointer = True result.related_type = other_type return result else: id_tok = self._match_token('id') return find_or_add_type(id_tok[1])
def _read_type_usage(self): '''Read a type identifier, or array of type, etc. and return a SGType''' if self._match_lookahead('id', 'array', True): #found an array dimensions = [] # array [0..n,0..m] of if self._match_lookahead('symbol', '[', True): while True: low_idx = self._match_token('number')[1] self._match_token('symbol', '.') self._match_token('symbol', '.') high_idx = self._match_token('number')[1] dimensions.append((low_idx,high_idx)) if self._match_lookahead('symbol', ']', True): break self._match_token('symbol', ',') else: dimensions.append((0,'n - 1')) # of type... self._match_token('id', 'of') nested_type = self._read_type_usage() #recursive call name = nested_type.name + ''.join(['[%s..%s]' % (low_idx, high_idx) for low_idx, high_idx in dimensions]) was_new = not name in all_types() result = find_or_add_type(name) if was_new: result.dimensions = dimensions result.nested_type = nested_type return result elif self._match_lookahead('symbol', '^', True): other_id = self._match_token('id')[1] other_type = find_or_add_type(other_id) name = '^' + other_type.name was_new = not name in all_types() result = find_or_add_type(name) if was_new: result.is_pointer = True result.related_type = other_type return result else: id_tok = self._match_token('id') return find_or_add_type(id_tok[1])
def process_block_types(self, block, token): '''Reads the types within a type declaration''' logger.info(' Parser : Processing types') logger.info('-' * 70) self.process_meta_comments() #following type... in pascal while True: type_name = self._match_token('id')[1] #read the types name self._match_token('operator', '=') #read the = the_type = find_or_add_type(type_name) the_type.file_line_details = self._tokeniser.line_details() the_type.meta_comment_line_details = self._tokeniser.meta_comment_line_details( ) self._parse_type_declaration(the_type) if 'type' or 'class' or 'struct' in the_type.keys(): self._add_class(the_type) self.process_meta_comments() tok1, tok2 = self._lookahead(2) #looking for... type_name = if tok2[0] != 'operator' or tok2[1] != '=' or tok1[0] != 'id': logger.info('-' * 70) logger.debug('Parser : At end of block types') break
def _parse_type_declaration(self, the_type): ''' Parse a type from the next token, add details to the_type. this is called for each type declaration... type_name = BLAH Need to process BLAH and add details to the_type ''' #check what kind of type it is... if self._match_lookahead('symbol', '(', True): values = [] while not self._match_lookahead('symbol',')'): temp = self._match_token('id')[1] if self._match_lookahead('operator', '=', True) or self._match_lookahead('operator', ':=', True): #assigned value values.append('%s = %s' % (temp, self._match_token('number')[1])) else: values.append(temp) self._match_lookahead('symbol', ',', True) #consume commas self._match_token('symbol',')') #read close bracket the_type.values = tuple(values) elif (self._match_lookahead('id', 'packed', True) and self._match_lookahead('id', 'record', True)) or self._match_lookahead('id', 'record', True): #packed record field: Type end; while not self._match_lookahead('id', 'end', True): #read field variables = self._read_variable_list() self._match_token('symbol', ';') for name, data_type in variables: field = SGField(name) field.data_type = data_type the_type.fields.append(field) elif self._match_lookahead('id', 'array') or self._match_lookahead('symbol', '^'): #is pointer or array the_type.clone(self._read_type_usage()) elif self._match_lookahead('id', 'procedure', True): #procedure type: read ( params ); self._match_token('symbol', '(') m = SGMethod(the_type.name) m.in_file = self._current_file self._read_params(m) the_type.is_procedure = True the_type.method = m if self._lookahead(2)[1][1] == 'cdecl': self._match_token('symbol', ';') self._match_token('id', 'cdecl') elif self._match_lookahead('id'): other_id = self._match_token('id')[1] other_type = find_or_add_type(other_id) the_type.related_type = other_type else: tok = self._next_token() logger.error('Parser Error %s: unknown type %s(%s)', self._tokeniser.line_details(), tok[0], tok[1]) assert False if the_type.related_type != None: logger.info(' Parser : Setup type %s = %s', the_type, the_type.related_type) elif the_type.is_enum: logger.info(' Parser : Setup type %s = %s', the_type, the_type.values) else: logger.info(' Parser : Setup type %s = %s', the_type, the_type.fields) self._apply_attributes_to(the_type) self._match_token('symbol', ';')
def process_block_types(self, block, token): '''Reads the types within a type declaration''' logger.info(' Parser : Processing types') logger.info('-' * 70) self.process_meta_comments() #following type... in pascal while True: type_name = self._match_token('id')[1] #read the types name self._match_token('operator','=') #read the = the_type = find_or_add_type(type_name) the_type.file_line_details = self._tokeniser.line_details() the_type.meta_comment_line_details = self._tokeniser.meta_comment_line_details() self._parse_type_declaration(the_type) if 'type' or 'class' or 'struct'in the_type.keys(): self._add_class(the_type) self.process_meta_comments() tok1, tok2 = self._lookahead(2) #looking for... type_name = if tok2[0] != 'operator' or tok2[1] != '=' or tok1[0] != 'id': logger.info('-' * 70) logger.debug('Parser : At end of block types') break
def to_keyed_dict(self, doc_transform = None, type_visitor = None, array_idx_sep = ', ', param_visitor = None, map_data_value = None): """Export a keyed dictionary of the class for template matching""" import wrapper_helper result = dict() result['name'] = self.name result['name_lower'] = wrapper_helper.lower_name(self.name) result['camel_name'] = self.name.lower()[0] + self.name[1:] result['doc'] = doc_transform(self.doc) if doc_transform != None else self.doc result['static'] = 'static ' if self.is_static else '' result['sealed'] = 'sealed ' if self.is_module else '' if self.wraps_array: # add accessor methods main_type = self.data_type.related_type dim = main_type.dimensions data_type = find_or_add_type('longint') idx_type = type_visitor(data_type) if type_visitor != None else 'int' result['element.type'] = type_visitor(main_type.nested_type) if param_visitor == None: result['element.idx.params'] = ', '.join([idx_type + ' idx%s' % i for i,d in enumerate(dim)]) else: result['element.idx.params'] = ''.join([param_visitor(SGParameter('idx%s' % i, data_type), i + 1 == len(dim)) for i,d in enumerate(dim)]) result['element.idx.expr'] = array_idx_sep.join(['idx%s' % i for i,d in enumerate(dim)]) result['element.access'] = map_data_value('return_val', main_type.nested_type, 'data[%(element.idx.expr)s]' % result) result['element.value'] = map_data_value('arg_val', main_type.nested_type, 'value') return result
def method_process_visitor(the_method, other): '''Process a method prior to rendering. This does all of the transformations that go into the functions and procedures of the SGSDK unit.''' # Change functions with string or array return type to have a result parameter if the_method.return_type != None and ( the_method.return_type.wraps_array or the_method.return_type.name.lower() in ['string']): #print 'PARS RUN PARAMS', [p.name for p in the_method.params] result_param = SGParameter('result') for param in the_method.params: if 'result' == param.name: logger.error('PARSER RUN: Error adding result parameter to %s', the_method.name) assert False _add_parameter(the_method, result_param) result_param.maps_result = True result_param.modifier = 'result' result_param.data_type = the_method.return_type the_method.return_type = None the_method.was_function = True #print 'PARS RUN PARAMS', [p.name for p in the_method.params] #Replace any variable length arrays orig_params = the_method.params for param in orig_params: #does it wrap a variable length array if param.data_type.array_wrapper: the_method.has_length_params = True logger.debug( 'PARSER RUN: Altering variable length array of %s\'s parameter %s', the_method.name, param.name) # old_type = param.data_type #param.data_type = param.data_type #.fields[0].data_type len_param = SGParameter('%s_len' % param.name) len_param.is_length_param = True len_param.data_type = find_or_add_type('Longint') len_param.modifier = param.modifier if param.modifier is [ 'out', 'var' ] else None len_param.length_of = param param.has_length_param = True param.length_idx = _add_parameter(the_method, len_param) return other
def add_length_local(to_method, for_param): var_name = for_param.local_var_name() + '_len' local_var = SGParameter(var_name) local_var.is_length_param = True local_var.local_for = for_param local_var.data_type = find_or_add_type('Longint') local_var.modifier = for_param.modifier local_var.length_of = for_param for_param.length_param = local_var for_param.has_length_param = True to_method.local_vars.append(local_var) to_method.args.append(local_var.name) return local_var
def method_process_visitor(the_method, other): '''Process a method prior to rendering. This does all of the transformations that go into the functions and procedures of the SGSDK unit.''' # Change functions with string or array return type to have a result parameter if the_method.return_type != None and (the_method.return_type.wraps_array or the_method.return_type.name.lower() in ['string']): #print 'PARS RUN PARAMS', [p.name for p in the_method.params] result_param = SGParameter('result') for param in the_method.params: if 'result' == param.name: logger.error('PARSER RUN: Error adding result parameter to %s', the_method.name) assert False _add_parameter(the_method, result_param) result_param.maps_result = True result_param.modifier = 'result' result_param.data_type = the_method.return_type the_method.return_type = None the_method.was_function = True #print 'PARS RUN PARAMS', [p.name for p in the_method.params] #Replace any variable length arrays orig_params = the_method.params for param in orig_params: #does it wrap a variable length array if param.data_type.array_wrapper: the_method.has_length_params = True logger.debug('PARSER RUN: Altering variable length array of %s\'s parameter %s', the_method.name, param.name) # old_type = param.data_type #param.data_type = param.data_type #.fields[0].data_type len_param = SGParameter('%s_len' % param.name) len_param.is_length_param = True len_param.data_type = find_or_add_type('Longint') len_param.modifier = param.modifier if param.modifier is ['out', 'var'] else None len_param.length_of = param param.has_length_param = True param.length_idx = _add_parameter(the_method, len_param) return other
def _parse_type_declaration(self, the_type): ''' Parse a type from the next token, add details to the_type. this is called for each type declaration... type_name = BLAH Need to process BLAH and add details to the_type ''' #check what kind of type it is... if self._match_lookahead('symbol', '(', True): values = [] while not self._match_lookahead('symbol', ')'): temp = self._match_token('id')[1] if self._match_lookahead( 'operator', '=', True) or self._match_lookahead( 'operator', ':=', True): #assigned value values.append('%s = %s' % (temp, self._match_token('number')[1])) else: values.append(temp) self._match_lookahead('symbol', ',', True) #consume commas self._match_token('symbol', ')') #read close bracket the_type.values = tuple(values) elif (self._match_lookahead('id', 'packed', True) and self._match_lookahead('id', 'record', True)) or self._match_lookahead( 'id', 'record', True): #packed record field: Type end; while not self._match_lookahead('id', 'end', True): #read field variables = self._read_variable_list() self._match_token('symbol', ';') for name, data_type in variables: field = SGField(name) field.data_type = data_type the_type.fields.append(field) elif self._match_lookahead('id', 'array') or self._match_lookahead( 'symbol', '^'): #is pointer or array the_type.clone(self._read_type_usage()) elif self._match_lookahead('id', 'procedure', True): #procedure type: read ( params ); self._match_token('symbol', '(') m = SGMethod(the_type.name) m.in_file = self._current_file self._read_params(m) the_type.is_procedure = True the_type.method = m if self._lookahead(2)[1][1] == 'cdecl': self._match_token('symbol', ';') self._match_token('id', 'cdecl') elif self._match_lookahead('id'): other_id = self._match_token('id')[1] other_type = find_or_add_type(other_id) the_type.related_type = other_type else: tok = self._next_token() logger.error('Parser Error %s: unknown type %s(%s)', self._tokeniser.line_details(), tok[0], tok[1]) assert False if the_type.related_type != None: logger.info(' Parser : Setup type %s = %s', the_type, the_type.related_type) elif the_type.is_enum: logger.info(' Parser : Setup type %s = %s', the_type, the_type.values) else: logger.info(' Parser : Setup type %s = %s', the_type, the_type.fields) self._apply_attributes_to(the_type) self._match_token('symbol', ';')