scan_yaml Subroutine

private 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 "<<"

Arguments

Type IntentOptional 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

Calls

proc~~scan_yaml~~CallsGraph proc~scan_yaml scan_yaml proc~scan_yaml->proc~scan_yaml append append proc~scan_yaml->append get_dictionary get_dictionary proc~scan_yaml->get_dictionary get_list get_list proc~scan_yaml->get_list get_string get_string proc~scan_yaml->get_string set set proc~scan_yaml->set

Called by

proc~~scan_yaml~~CalledByGraph proc~scan_yaml scan_yaml proc~scan_yaml->proc~scan_yaml proc~input_open_yaml input_t%input_open_yaml proc~input_open_yaml->proc~scan_yaml

Source Code

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