Scanning all nodes in yaml tree and attaching to them external files It also implementing dictionary key marge operator "<<"
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(type_node), | intent(inout) | :: | me | |||
| character(len=*), | intent(inout) | :: | folder | |||
| class(type_key_value_pair), | intent(inout), | optional | :: | dict_item | ||
| class(type_list_item), | intent(inout), | optional | :: | list_item |
recursive subroutine scan_yaml(me,folder,dict_item,list_item) !! Scanning all nodes in yaml tree and attaching to them external files !! It also implementing dictionary key marge operator "<<" class(type_node), intent(inout) :: me character(*), intent(inout) :: folder class(type_key_value_pair), optional, intent(inout) :: dict_item class(type_list_item), optional, intent(inout) :: list_item ! TODO: think about having parent (dict_item or list_item) as type_node, ! maybe it will make this code nicer. character(:), allocatable :: path type(type_error), allocatable :: err type(type_key_value_pair), pointer :: pair type(type_list_item), pointer :: item type(type_dictionary), pointer :: dict type(type_list), pointer :: list type(type_list), target :: tmp_list type(input_t) :: file ! including files external files select type(dict_top=>me);class is(type_dictionary) path = dict_top%get_string('include','',err) if(path/='') then call file%open(folder//path,.true.) if (present(dict_item)) then dict_item%value => file%root endif if (present(list_item)) then list_item%node => file%root endif nullify(file%file%root) ! to avoid deallocation endif end select ! recursive scan through whole tree select type(me) class is(type_dictionary) pair => me%first do while (associated(pair)) select type (value=>pair%value) class is (type_dictionary) call scan_yaml(pair%value,folder,dict_item=pair) class is (type_list) call scan_yaml(pair%value,folder,dict_item=pair) class default;end select pair => pair%next end do class is(type_list) item => me%first do while (associated(item)) select type (value=>item%node) class is (type_dictionary) call scan_yaml(item%node,folder,list_item=item) class is (type_list) call scan_yaml(item%node,folder,list_item=item) class default;end select item => item%next end do end select ! key merge with operator "<<" merge: select type(dict_top=>me);class is(type_dictionary) dict => dict_top%get_dictionary('<<',.false.,error=err) if(associated(dict)) then call tmp_list%append(dict) list => tmp_list else list => dict_top%get_list('<<',.true.,error=err) endif if(allocated(err)) exit merge if(list%size()==0) exit merge select type(first_dict=>list%first%node);class is(type_dictionary) item => list%first item => item%next do while(associated(item)) select type(sub_dict=>item%node);class is(type_dictionary) pair => sub_dict%first do while (associated(pair)) call first_dict%set(pair%key,pair%value) pair => pair%next enddo end select item => item%next enddo pair => dict_top%first do while (associated(pair)) if(pair%key/='<<')then call first_dict%set(pair%key,pair%value) endif pair => pair%next enddo if (present(dict_item)) then dict_item%value => first_dict endif if (present(list_item)) then list_item%node => first_dict endif end select nullify(tmp_list%first) end select merge end subroutine scan_yaml