diff --git a/example.json b/example.json new file mode 100644 index 0000000..0d09c8b --- /dev/null +++ b/example.json @@ -0,0 +1,12 @@ +{ + "animals": { + "pig": { + "tail": "curly", + "nose": "adorable" + }, + "sheep": { + "tail": "short", + "nose": "ugly" + } + } +} diff --git a/json.sh b/json.sh index efa7d36..51c29fa 100644 --- a/json.sh +++ b/json.sh @@ -1,74 +1,101 @@ -#!/bin/sh +#!/bin/sh -ex +# WIP JSON parser -# OK, this is going to be a convoluted state machine based on the following states: -imov=0 # in middle of variable [ "variable" = "..." ] -imosv=0 # in middle of string value [ "..." = "value" ] -imoo=0 # in middle of object [ "object" {...} ] -imoas=0 # in middle of ambiguous string -# And using the following vars: -cv='' # current variable -lv='' # last variable -csv='' # current string value -lsv='' # last string value -co='' # current object -lo='' # last object -aco='' # all current objects -cas='' # current abiguous string +JGROUPS='' +GROUPORVAR=0 +NEWWORD=0 - -get_co() { - aco="$aco/$cas" - co=$(echo "$aco" | sed 's^.*/^^') +endword() { + NEWWORD=0 + if [ $GROUPORVAR -eq 1 ] + then + echo "${JGROUPS}/$LASTWORD = $CURWORD" + GROUPORVAR=0 + else + echo "${JGROUPS}/$CURWORD" + fi + LASTWORD=$CURWORD + CURWORD='' + TYPE='' } -get_lo() { - lo=$co - aco=$(echo "$aco" | sed 's^/'"$lo"'^^') +startword() { + NEWWORD=1 } +addword() { + CURWORD="${CURWORD}${1}" +} + + +json() { for char in $(cat $1 | sed 's/\(.\)/\1 /g') do - case $char in - "{") - imoas=0 - imoo=1 - get_co - ;; - "}") - imoo=0 - get_lo - ;; - "\"") - if [ $imosv -eq 1 ] - then - imosv=0 - echo "$cv: $csv" - elif [ $imoas -eq 1 ] - then - imoas=0 - imosv=1 - cv="$cas" - else - imoas=1 - fi - ;; - ":") - echo "Ignore" > /dev/null - ;; - ",") - echo "Ignore" > /dev/null - ;; - *) - if [ $imoas -eq 1 ] - then - cas="${cas}${char}" - elif [ $imosv -eq 1 ] - then - csv="${csv}${char}" - else - echo "Ignored: $char" - fi - ;; - esac - echo "$char | $imov $imosv $imoo $imoas" -done + case "$char" in + ' ') + if [ $NEWWORD -eq 1 ] && [ $TYPE == "string" ] + then + addword $char + fi + ;; +# Works in bash, not in sh. +# [[:alpha:]]) + [ABCDEFGHIJKLMNOPQRSTUVWXYZ]) + addword $char + ;; + [abcdefghijklmnopqrstuvwxyz]) + addword $char + ;; +# [[:digit:]]) + [0123456789]) + if [ $NEWWORD -eq 1 ] + then + addword $char + else + TYPE="number" + startword + addword $char + fi + ;; + [,]) + if [ $NEWWORD -eq 1 ] && [ $TYPE == "string" ] + then + addword $char + elif [ $NEWWORD -eq 1 ] && [ $TYPE == "number" ] + then + endword + fi + ;; + \") + if [ $NEWWORD -eq 1 ] + then + endword + else + TYPE="string" + startword + fi + ;; + ':') + GROUPORVAR=1 + ;; + '{') + if [ $GROUPORVAR -eq 1 ] + then + CURGROUP="${LASTWORD}" + JGROUPS="${JGROUPS}/${CURGROUP}" + GROUPORVAR=0 + fi + ;; + '}') + if [ $NEWWORD -eq 1 ] && [ $TYPE == "number" ] + then + endword + fi + JGROUPS=$(echo $JGROUPS | sed 's@/'$CURGROUP'$@@') + CURGROUP=$(echo $JGROUPS | grep -oE '[^/]+$') + ;; + esac +done < "$1" +} + +json $1