'JSON PARSING
'10/02/2025
'CP

uses console
'
'INPUT
'
string s=quote
~~~

{
"employees":[
    {"firstName":"John", "lastName":"Doe", value:30.5 },
    {"firstName":"Anna", "lastName":"Smith"},
    {"firstName":"Peter", "lastName":"Jones"}
]
}

~~~

interface
=========
'
's source strung
'
'outputs:
'
string name[1000] 'names of objects
string  dat[1000] 'data of objects
int    dmap[1000] 'location of name:object
int    dlvl[1000] 'nesting level of objects
int    je         'count of all objects
'
====================
subroutine JsonParse
====================
'
indexbase 1 'arrays lbound
int i,j
int gf,bf,be,cc,sc,db,ty,dm
int qc,qf,qe,td,tf,te,sa,sd,nc
byte*b
@b=strptr(s)-1 'byte overlay
i=0            'char iterator
j=0            'index items
sa=0           'array capture flag
sd=0           'array items flag
nc=0           'nesting depth
'
'
===================================
NextItem: 'clear flags and counters
===================================
'
j++            'increment name / dat index
qf=0           'quote flag start
qe=0           'quote end
qc=0           'quote toggle
tf=0           'text flag
bf=0           'object flag
gf=0           'array fkag stt
cc=0           '{} object depth
sc=0           '[] array depth
td=0           'end of text flag
ty=0           'type of direct data
dm=0           'dmap assigned flag
ty=0           'raw data flgs
db=sa          'data flag

================
do 'parsing loop
================
'
@b++
i++
td=0 'assume delimiting char
'
select b 'byte pointer
'
=========
case   0 ' ' end of string
=========
  '
  exit do
  '
=========
case 1 to 32 ' ' white space
=========
  '
  continue do
  '
=========
case  "\" 'escape char
=========
  @b++ : i++ : td=1
  'itr edit out '\'
  if b=0 then exit do
=========
case  34 '"' quote flag toggle
=========
  qc xor=1
  if qc then
    qf=i
  else
    qe=i
    if gf+bf=0
      if db
        dat(j)=mid(s,qf+1,qe-qf-1)
        if dm=0
          dmap[j]=qf+1
          dlvl[j]=nc
        endif
        goto nextitem
      else
        name(j)=mid(s,qf+1,qe-qf-1)
        dmap[j]=qf+1
        dlvl[j]=nc
        dm=1
        tf=0 'text flag
        db=1 'data flag (expecting)
        continue do
      endif
    endif
  endif
==========
case qc<>0 
==========
  '
  continue do 'till the quote ends
  '
=========
case ","
=========
  'capture unquoted data
  gosub captData
  if ty
    goto nextitem
  endif
=========
case  ":"
=========
  if gf+bf=0
    if qf=0 then 
      name[j]=mid(s,tf,te-tf+1) 'raw name
      dmap[j]=tf
      dlvl[j]=nc
      dm=1
    endif
    qf=0 'clear quote flag
    tf=0 'text flag
    db=1 'data flag (expecting)
    continue do
  endif
=========
case  "["
=========
  nc++
  if db
    sc++
    if gf+bf=0
      if sc=1 'start array
        bf=i
        sa=1 'array capture flag
      endif
    endif
  else 'db=0
    'splitting array into separate items
    'no name assigned
    name(j)=""
    sd=1
  endif
=========
case  "]"
=========
  nc--
  sc--
  gosub CaptData
  if sc=0 'end inner array
    sa=0
    if ty=0
      dat[j]=mid(s,bf,i-bf+1)   'brackets included
      if dm=0
        dmap[j]=bf
        dlvl[j]=nc
      endif
    endif
    goto nextitem
  elseif sc<0
    sc=0
    sa=0
    sd=0
    if nc<=0
      if ty
        j++
      endif
      exit do 'splitting array complete
    else
      goto nextitem
    endif
  endif
=========
case "{"
=========
  nc++
  if sa+sd
    db=1 'objects inside an array
  endif
  if db
    cc++
    if cc=1 'inner object
      gf=i  'start of {} block
    endif
  else 'db=0
    'splitting an object into parts
  endif
=========
case "}"
=========
  nc--
  cc--
  gosub CaptData
  if cc=0 'end inner object
    if sa=0 'not inside array
      dat[j]=mid(s,gf,i-gf+1) 'brackets included
      if dm=0
        dmap[j]=gf
        dlvl[j]=nc
      endif
      goto nextitem
    endif
  elseif cc<0
    cc=0
    if nc<=0
      if ty
        j++
      endif
      exit do 'splitting array complete
    else
      goto nextitem
    endif
  endif
=========
case else 'covers all other ascii
=========
  td=1
  if gf+bf=0
    if tf=0
      tf=i 
      'start of unquoted /
      'name/number/true/flse/null
    endif
    te=i
  endif
end select
'
'
end do 'parsing loop


SubRoutine CaptData 'internal
=============================
'
ty=0
if gf+bf+td+qf=0
  if tf
    if db
      'unquoted data
      dat[j]=mid(s,tf,te-tf+1)
      if dm=0
        dmap[j]=tf
        dlvl[j]=nc
      endif
      'numbers/true/falsr/null
      ty=1
    endif
  endif
endif
end subroutine 'CaptData


je=j-1 'set end of data

end subroutine 'JsonParse
'
'===========
'TEST OUTPUT
'===========
'
int i
print cr
gosub JsonParse
for i=1 to je
  print i " NAME: " name[i] cr
  print i " DATA: " dat[i] cr
next
print cr cr
'
print "split array" cr
s=dat(1)
gosub JsonParse
for i=1 to je
  print i " NAME: " name[i] cr
  print i " DATA: " dat[i] cr
next
print cr

print "split object" cr
s=dat(1)
gosub JsonParse
for i=1 to je
  print i " NAME: " name[i] cr
  print i " DATA: " dat[i] cr
next
print cr

wait(100000)
