JSON

I have a bunch of coping mechanisms. And the bigger one is coding. It might be a problem. I'm the equivalent to that woman that knits a lot because it calms her, and when you open her wardrobe a veritable flood of scarves, both completed and not, fall on you.

And one of the things that relaxes me is writing parsers of many kinds. And of all the parsers I've written the language I have parsed the most is JSON.

At this point I have gone over it so many times that I have generated tables for FSM that make up a scanner and parser of the language. By hand. Several times.

So this is a language-independent JSON parser. These tables can be used to build a parser on anything, as long as you implement a couple snippets of pseudocode.

For those not in the know, these tables are what many parser generators will automatically build for you given an input grammar. I just ran the process by hand. Artisanal code at its best.

Scanner

The pseudo code for the scanner is as follows:

state = 0
while True:
    next = trans[state][group[peek()]]
    if next == Error:
        # syntax error
    elif next == Accept:
        return rval[state]
    state = next
    consume()

The group table returns a group for every possible input character. Most groups are named by the characters they hold, but there are also the o and x groups representing "other characters" that are valid and not valid in the input stream respectively.

x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
0x eof x x x x x x x x ws ws x x ws x x
1x x x x x x x x x x x x x x x x x
2x ws o " o o o o o o o o + , - . /
3x 0 19 19 19 19 19 19 19 19 19 : o o o o o
4x o AF AF AF AF E AF o o o o o o o o o
5x o o o o o o o o o o o [ \ ] o o
6x o a b cd cd e f o o o o o l o n o
7x o o r s t u o o o o o { o } o o
8x o o o o o o o o o o o o o o o o
9x o o o o o o o o o o o o o o o o
Ax o o o o o o o o o o o o o o o o
Bx o o o o o o o o o o o o o o o o
Cx o o o o o o o o o o o o o o o o
Dx o o o o o o o o o o o o o o o o
Ex o o o o o o o o o o o o o o o o
Fx o o o o o o o o o o o o o o o o

The trans table determines where to go from each state according to the group of the next character in the input. Errors are indicated with a period (.) and accept states are labeled ac.

state [ ] { } , : " \ / a b cd e f l n r s t u 0 19 - + . E AF * ws eof returns
lb le ob oe cm cl s0 . . . . . . f0 . u0 . . t0 . n1 n2 n0 . . . . . ws en eof
t0 . . . . . . . . . . . . . . . . t1 . . . . . . . . . . . . .
t1 . . . . . . . . . . . . . . . . . . . t2 . . . . . . . . . .
t2 . . . . . . . . . . . . t3 . . . . . . . . . . . . . . . . .
t3 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac true
f0 . . . . . . . . . f1 . . . . . . . . . . . . . . . . . . . .
f1 . . . . . . . . . . . . . . f2 . . . . . . . . . . . . . . .
f2 . . . . . . . . . . . . . . . . . f3 . . . . . . . . . . . .
f3 . . . . . . . . . . . . f4 . . . . . . . . . . . . . . . . .
f4 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac false
u0 . . . . . . . . . . . . . . . . . . . u1 . . . . . . . . . .
u1 . . . . . . . . . . . . . . u2 . . . . . . . . . . . . . . .
u2 . . . . . . . . . . . . . . u3 . . . . . . . . . . . . . . .
u3 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac null
n0 . . . . . . . . . . . . . . . . . . . . n1 n2 . . . . . . . .
n1 ac ac ac ac ac ac ac ac ac ac ac ac n5 ac ac ac ac ac ac ac ac ac ac ac n3 n5 ac ac ac ac number
n2 ac ac ac ac ac ac ac ac ac ac ac ac n5 ac ac ac ac ac ac ac n2 n2 ac ac n3 n5 ac ac ac ac number
n3 . . . . . . . . . . . . . . . . . . . . n4 n4 . . . . . . . .
n4 ac ac ac ac ac ac ac ac ac ac ac ac n5 ac ac ac ac ac ac ac n4 n4 ac ac ac n5 ac ac ac ac number
n5 . . . . . . . . . . . . . . . . . . . . n7 n7 n6 n6 . . . . . .
n6 . . . . . . . . . . . . . . . . . . . . n7 n7 . . . . . . . .
n7 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac n7 n7 ac ac ac ac ac ac ac ac number
s0 s0 s0 s0 s0 s0 s0 s6 s1 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 s0
s1 . . . . . . s0 s0 s0 . s0 . . s0 . s0 s0 . s0 s2 . . . . . . . . . .
s2 . . . . . . . . . s3 s3 s3 s3 s3 . . . . . . s3 s3 . . . . s3 . . .
s3 . . . . . . . . . s4 s4 s4 s4 s4 . . . . . . s4 s4 . . . . s4 . . .
s4 . . . . . . . . . s5 s5 s5 s5 s5 . . . . . . s5 s5 . . . . s5 . . .
s5 . . . . . . . . . s0 s0 s0 s0 s0 . . . . . . s0 s0 . . . . s0 . . .
s6 ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac string
lb ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac [
le ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ]
ob ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac {
oe ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac }
cm ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ,
cl ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac :
ws ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ac ws ac whitespace

Parser

The pseudo code for the parser is as follows:

state = [0]
while t = next token:
    tr = trans[state[-1]][t]
    if tr == Error:
        # bad input
    elif tr == Accept:
        # this is a JSON document
    elif tr == Pop:
        pop(state)
    elif tr < 0:
        state[-1] = action[~tr][0]
        state += action[~tr][1]
    else:
        state[-1] = tr

The trans table determines which action to take on each state,token pair. Regular states are named, whereas extended actions are marked as ~N, where N is a number that refers to the action table below.

state end nul tru fal num str [ ] { } , : wsp
t0 . t1 t1 t1 t1 t1 ~0 . ~1 . . . t0
t1 t2 . . . . . . . . . . . t1
t2 ac ac ac ac ac ac ac ac ac ac ac ac ac
l0 . l1 l1 l1 l1 l1 ~2 pop ~3 . . . l0
l1 . . . . . . . pop . . l2 . l1
l2 . l1 l1 l1 l1 l1 ~2 . ~3 . . . l2
o0 . . . . . o1 . . . pop . . o0
o1 . . . . . . . . . . . o2 o1
o2 . o3 o3 o3 o3 o3 ~4 . ~5 . . . o2
o3 . . . . . . . . . pop o4 . o3
o4 . . . . . o1 . . . . . . o4

The action table determines what to do when a transition requires to both set the next state and push another in the stack.

transition next state push state
0 t1 l0
1 t1 o0
2 l1 l0
3 l1 o0
4 o3 l0
5 o3 o0