-
Notifications
You must be signed in to change notification settings - Fork 267
/
parse.sh
90 lines (84 loc) · 1.88 KB
/
parse.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
throw () {
echo "$*" >&2
exit 1
}
tokenize () {
local ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
local CHAR='[^[:cntrl:]"\\]'
local STRING="\"$CHAR*($ESCAPE$CHAR*)*\""
local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?'
local KEYWORD='null|false|true'
local SPACE='[[:space:]]+'
egrep -ao "$STRING|$NUMBER|$KEYWORD|$SPACE|." --color=never |
egrep -v "^$SPACE$" # eat whitespace
}
parse_array () {
local index=0
local ary=''
read -r token
while true;
do
case "$token" in
']') break ;;
esac
parse_value "$1" "$index"
let index=$index+1
ary="$ary""$value"
read -r token
case "$token" in
']') break ;;
',') ary="$ary", ;;
*) throw "EXPECTED ] or , GOT ${token:-EOF}" ;;
esac
read -r token
done
value=`printf '[%s]' $ary`
}
parse_object () {
local key
local obj=''
read -r token
while :
do
case "$token" in
'}') break ;;
'"'*'"') key=$token ;;
*) throw "EXPECTED STRING, GOT ${token:-EOF}" ;;
esac
read -r token
case "$token" in
':') ;;
*) throw "EXPECTED COLON, GOT ${token:-EOF}" ;;
esac
read -r token
parse_value "$1" "$key"
obj="$obj$key:$value"
read -r token
case "$token" in
'}') break;;
',') obj="$obj,"; read -r token ;;
*) throw "EXPECTED , or }, but got ${token:-EOF}" ;;
esac
done
value=`printf '{%s}' "$obj"`
}
parse_value () {
local jpath="${1:+$1,}$2"
case "$token" in
'{') parse_object "$jpath" ;;
'[') parse_array "$jpath" ;;
# At this point, the only valid single-character tokens are digits.
''|[^0-9]) throw "EXPECTED value, GOT ${token:-EOF}" ;;
*) value=$token ;;
esac
printf "[%s]\t%s\n" "$jpath" "$value"
}
parse () {
read -r token
parse_value
read -r token
case "$token" in
'') ;;
*) throw "EXPECTED EOF, GOT $token" ;;
esac
}