subroutine apply_one_pair(g, tokens, tok_line, n_tok, ti, path, errors, n_err)
!! Consume one `key = value [value...]` starting at token `ti`;
!! advance `ti` past the consumed tokens. Validates structure,
!! unknown keys, duplicate keys, and applies via parse_tokens.
type(nml_group_t), intent(inout) :: g
character(len=256), intent(in) :: tokens(:)
integer, intent(in) :: tok_line(:)
integer, intent(in) :: n_tok
integer, intent(inout) :: ti
character(len=*), intent(in) :: path
character(len=:), allocatable, intent(inout) :: errors(:)
integer, intent(inout) :: n_err
character(len=:), allocatable :: keyname, prefix
integer :: kidx, kline, vstart, vcount, j
character(len=256), allocatable :: vals(:)
! Skip stray separators.
do while (ti <= n_tok)
if (trim(tokens(ti)) == ",") then
ti = ti + 1
else
exit
end if
end do
if (ti > n_tok) return
keyname = trim(tokens(ti))
kline = tok_line(ti)
prefix = make_prefix(path, kline)
if (keyname == "=") then
call add_err(errors, n_err, prefix//"stray '=' with no key name")
ti = ti + 1
return
end if
! Expect '=' next.
if (ti + 1 > n_tok) then
call add_err(errors, n_err, prefix//"key '"//keyname//"' has no '=' assignment")
ti = ti + 1
return
end if
if (trim(tokens(ti + 1)) /= "=") then
call add_err(errors, n_err, prefix//"expected '=' after key '"//keyname// &
"', got '"//trim(tokens(ti + 1))//"'")
ti = ti + 1
return
end if
! Gather value tokens (skip commas) until next `ident =` or end.
vstart = ti + 2
vcount = 0
allocate (vals(0))
j = vstart
do while (j <= n_tok)
if (trim(tokens(j)) == ",") then
j = j + 1
cycle
end if
! Lookahead: is this token a key (followed by '=')?
if (j + 1 <= n_tok) then
if (trim(tokens(j + 1)) == "=") exit
end if
call append_val(vals, vcount, tokens(j))
j = j + 1
end do
ti = j
! Resolve and apply.
kidx = g%find_key(keyname)
if (kidx == 0) then
block
character(len=:), allocatable :: names(:)
character(len=:), allocatable :: sug
names = group_key_list(g)
sug = ""
if (size(names) > 0) sug = suggest(keyname, names)
call add_err(errors, n_err, prefix//"unknown key '"//keyname// &
"' in group '"//g%name//"'"//sug)
end block
return
end if
if (g%keys(kidx)%key%found) then
call add_err(errors, n_err, prefix//"duplicate key '"//keyname// &
"' in group '"//g%name//"'")
return
end if
g%keys(kidx)%key%found = .true.
if (vcount == 0) then
call add_err(errors, n_err, prefix//"key '"//keyname//"' has no value")
return
end if
block
character(len=:), allocatable :: emsg
call g%keys(kidx)%key%parse_tokens(vals(1:vcount), emsg)
if (allocated(emsg)) then
call add_err(errors, n_err, prefix//trim(emsg))
end if
end block
end subroutine apply_one_pair