def _add_class(self, the_type): logger.info(' Parser : Adding class %s', the_type.name) new_class = find_or_add_class(the_type.name) new_class.in_file = self._current_file if new_class not in self._current_file.members: self._current_file.members.append(new_class) new_class.setup_from(the_type)
def process_variable_decl(self, block, token): ''' ''' while True: names = [self._match_token('id')[1]] #the name of the var while self._match_lookahead('symbol', ',', True): #separated by ,'s names.append(self._match_token('id')[1]) #add next name. self._match_token('symbol',':') # ... : type the_type = self._read_type_usage() self._match_token('symbol', ';') #apply type to all names, and add to block as field for name in names: field = SGField(name) self._apply_attributes_to(field) field.is_static = True #these are globals field.data_type = the_type if not field.is_ignored: block.add_member(field) else: logger.info('Parser : Ignoring field %s', name) #read the next batch of comments self.process_meta_comments() #variable list is ended by ... tok = self._lookahead(1)[0] if tok[1].lower() in ['function', 'procedure', 'type', 'var', 'const', 'implementation']: break
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 complete_method_processing(self): ''' This is called on methods that are read by the parser from the Pascal file. Set up the call from the library to this method if marked. Check the call's validity Steps: 1: Get other methods related to this one 2: Set parameters on library method (if called) ''' logger.info(' Method : Completing processing of %s', self) #This is 'the' method it has its params self.params = self.params #Find the length method if it exists if self.length_call != None: self.length_call = self.in_class.find_method(self.length_call) #Convert args to appropriate values... self._process_args() self._check_args_match_params() #Get other methods lib_method = self.method_called class_method = self.class_method #check rules if lib_method == None and not self.is_operator: logger.error('Method : Found method %s without lib', self) assert False if lib_method != None: #set up library method self.setup_lib_method(lib_method) logger.info(' Method : %s calls %s', self.name, lib_method.name) lib_method.called_by.append(self) #set up class method if class_method != None: logger.debug(' Method : %s is also %s', self.name, class_method) self._setup_class_method(class_method) logger.info(' Method : %s calls %s', class_method.name, lib_method.name) lib_method.called_by.append(class_method) #library is also called by class elif self.is_operator: assert self.other_class != None self.name = 'operator ' + self.name self.other_method = self.in_class.find_method(self['calls'].other) self.doc = self.other_method.doc self.method_called = self.other_method.method_called self.method_called.called_by.append(self) #library is also called by operator self.is_static = True self.in_class.operators[self.signature] = None self.in_class = self.other_class self.in_class.add_member(self) self.args = list(self.params) # operators must match directly
def process_variable_decl(self, block, token): ''' ''' while True: names = [self._match_token('id')[1]] #the name of the var while self._match_lookahead('symbol', ',', True): #separated by ,'s names.append(self._match_token('id')[1]) #add next name. self._match_token('symbol', ':') # ... : type the_type = self._read_type_usage() self._match_token('symbol', ';') #apply type to all names, and add to block as field for name in names: field = SGField(name) self._apply_attributes_to(field) field.is_static = True #these are globals field.data_type = the_type if not field.is_ignored: block.add_member(field) else: logger.info('Parser : Ignoring field %s', name) #read the next batch of comments self.process_meta_comments() #variable list is ended by ... tok = self._lookahead(1)[0] if tok[1].lower() in [ 'function', 'procedure', 'type', 'var', 'const', 'implementation' ]: 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_unit(self, token): tok = self._match_token('id') unit_name = tok[1] name = self._get_attribute('module', unit_name) self._add_attribute('name', name) logger.info('-' * 70) logger.info(' Parser : Processing unit: %s', unit_name) logger.info('-' * 70) #self._check_attributes(['class','static'],'unit ' + unit_name) self._check_meta_comments(1, 'unit ' + unit_name + '\'s declaration') #Create the unit unit = self._create_model_element(SGCodeModule) unit.module_kind = 'module' unit.is_static = True logger.info(' Parser : Creating class %s', unit.name) self._apply_attributes_to(unit) #unit name; tok = self._match_token('symbol', ';') #interface - ignore comments #self._skip_comments('unit ' + unit_name + '\'s interface') self._match_token('id', 'interface') #check 'uses' tok = self._lookahead()[0] if tok[0] == 'id' and tok[1] == 'uses': tok = self._next_token() self.process_uses_clause(tok) logger.info('-' * 70) while True: logger.debug( 'Parser : At start of loop to process elements in unit') #read comments if they follow this position, otherwise leave # attributes as they are if self._match_lookahead('meta comment'): self.process_meta_comments() #Process the body of the unit's interface tok = self._lookahead()[0] #check the next token if tok[0] == 'id' and tok[1] == 'implementation': logger.info(' Parser : Found end of unit\'s interface') logger.info('-' * 70) break #interface contains types, functions, procedures, var, const, operator tok = self._match_one_token([['id', 'type'], ['id', 'function'], ['id', 'procedure'], ['id', 'const'], ['id', 'operator'], ['id', 'var']]) self._block_header_processors[tok[1]](unit, tok) logger.info( ' Parser : Finished processing unit. Resulting class is:\n%s', str(unit))
def process_unit(self, token): tok = self._match_token('id') unit_name = tok[1] name = self._get_attribute('module', unit_name) self._add_attribute('name',name) logger.info('-' * 70) logger.info(' Parser : Processing unit: %s', unit_name) logger.info('-' * 70) #self._check_attributes(['class','static'],'unit ' + unit_name) self._check_meta_comments(1, 'unit ' + unit_name + '\'s declaration') #Create the unit unit = self._create_model_element(SGCodeModule) unit.module_kind = 'module' unit.is_static = True logger.info(' Parser : Creating class %s', unit.name) self._apply_attributes_to(unit) #unit name; tok = self._match_token('symbol', ';') #interface - ignore comments #self._skip_comments('unit ' + unit_name + '\'s interface') self._match_token('id', 'interface') #check 'uses' tok = self._lookahead()[0] if tok[0] == 'id' and tok[1] == 'uses': tok = self._next_token() self.process_uses_clause(tok) logger.info('-' * 70) while True: logger.debug('Parser : At start of loop to process elements in unit') #read comments if they follow this position, otherwise leave # attributes as they are if self._match_lookahead('meta comment'): self.process_meta_comments() #Process the body of the unit's interface tok = self._lookahead()[0] #check the next token if tok[0] == 'id' and tok[1] == 'implementation': logger.info(' Parser : Found end of unit\'s interface') logger.info('-' * 70) break #interface contains types, functions, procedures, var, const, operator tok = self._match_one_token([['id','type'], ['id','function'], ['id','procedure'], ['id','const'], ['id','operator'], ['id','var']]) self._block_header_processors[tok[1]](unit, tok); logger.info(' Parser : Finished processing unit. Resulting class is:\n%s', str(unit))
def complete_method_processing(self): ''' This is called on methods that are read by the parser from the Pascal file. Set up the call from the library to this method if marked. Check the call's validity Steps: 1: Get other methods related to this one 2: Set parameters on library method (if called) ''' logger.info(' Method : Completing processing of %s', self) #This is 'the' method it has its params self.params = self.params #Find the length method if it exists if self.length_call != None: self.length_call = self.in_class.find_method(self.length_call) #Convert args to appropriate values... self._process_args() self._check_args_match_params() #Get other methods lib_method = self.method_called class_method = self.class_method #check rules if lib_method == None and not self.is_operator: logger.error('Method : Found method %s without lib', self) assert False if lib_method != None: #set up library method self.setup_lib_method(lib_method) logger.info(' Method : %s calls %s', self.name, lib_method.name) lib_method.called_by.append(self) #set up class method if class_method != None: logger.debug(' Method : %s is also %s', self.name, class_method) self._setup_class_method(class_method) logger.info(' Method : %s calls %s', class_method.name, lib_method.name) lib_method.called_by.append( class_method) #library is also called by class elif self.is_operator: assert self.other_class != None self.name = 'operator ' + self.name self.other_method = self.in_class.find_method(self['calls'].other) self.doc = self.other_method.doc self.method_called = self.other_method.method_called self.method_called.called_by.append( self) #library is also called by operator self.is_static = True self.in_class.operators[self.signature] = None self.in_class = self.other_class self.in_class.add_member(self) self.args = list(self.params) # operators must match directly
def post_parse_process(the_file): '''Create temporary variables for out/var string parameters, and string return types''' logger.info('Post parsing library') the_file.members[0].visit_methods(method_process_visitor, None)
def visit_all_units(file_visitor): logger.info('Processing files') files = [unit[0] for unit in all_units] + ['SGSDK'] for each_file in files: logger.debug('Visiting file %s', each_file) find_or_add_file(each_file).visit(file_visitor, None)
def visit_all_units(file_visitor): logger.info('Processing files') files = [ unit[0] for unit in all_units ] + ['SGSDK'] for each_file in files: logger.debug('Visiting file %s', each_file) find_or_add_file(each_file).visit(file_visitor, None)