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.
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 |
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 |