Skip to content

Instantly share code, notes, and snippets.

@Nemo157
Created February 20, 2011 12:10
Show Gist options
  • Save Nemo157/835931 to your computer and use it in GitHub Desktop.
Save Nemo157/835931 to your computer and use it in GitHub Desktop.
A JSON validator written in Befunge

This gist is going to contain a JSON validator written in Befunge-93. So far there is a working ruby "pseudocode" version that should be able to be directly translated to Befunge.

The architecture of this program is to have one central dispatcher, and use continuation passing style via the stack to determine which functions to call. The biggest problem with this is that by using the stack as the function call information it cannot be used for arguments. The solution to this is to minimize the number of arguments that have to be used. This has been almost perfectly accomplished, only the number related functions require arguments. This means that one cell can be set aside to be used for storing this argument when they return.

s = []
f0,f1,f2,f3,f4,f5,f6,f7,f8,f9,fa,fb,fc,fd,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23 = nil
cell = nil
n =->{}
eval %Q|
f0 =->{
puts "Invalid"
exit
}
f1 =->{
puts "Valid"
exit
}
f2 =->{
case STDIN.getc
$'"'
s<<fb
s<<f8
$'}'
n[]
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
f3 =->{
case STDIN.getc
$'"'
s<<f4
s<<f8
$'0'
s<<f14
s<<f18
$'-', /[1-9]/
s<<f14
s<<f15
$'{'
s<<f4
s<<f2
$'['
s<<f4
s<<f3
$'t'
s<<f4
s<<f6
$'f'
s<<f4
s<<f7
$'n'
s<<f4
s<<f5
$']'
n[]
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
f21 =->{
case STDIN.getc
$'"'
s<<f4
s<<f8
$'0'
s<<f14
s<<f18
$'-', /[1-9]/
s<<f14
s<<f15
$'{'
s<<f4
s<<f2
$'['
s<<f4
s<<f3
$'t'
s<<f4
s<<f6
$'f'
s<<f4
s<<f7
$'n'
s<<f4
s<<f5
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
f4 =->{
case STDIN.getc
$','
s<<f21
$']'
n[]
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
f5 =->{
if STDIN.getc == 'u' and STDIN.getc == 'l' and STDIN.getc == 'l'
n[]
else
s<<f0
end
}
f6 =->{
if STDIN.getc == 'r' and STDIN.getc == 'u' and STDIN.getc == 'e'
n[]
else
s<<f0
end
}
f7 =->{
if STDIN.getc == 'a' and STDIN.getc == 'l' and STDIN.getc == 's' and STDIN.getc == 'e'
n[]
else
s<<f0
end
}
f8 =->{
case STDIN.getc
$"\\\\"
s<<f8
s<<f9
$'"'
n[]
$/[^\\x00-\\x1F]/
redo
else
s<<f0
end
}
f9 =->{ # Decode escaped part of string
case STDIN.getc
$'"', "\\\\", '/', 'b', 'f', 'n', 'r', 't'
n[]
$'u'
s<<fa
else
s<<f0
end
}
fa =->{ # Decode unicode hex character
if /[a-z\\d]/i =~ STDIN.getc and /[a-z\\d]/i =~ STDIN.getc and /[a-z\\d]/i =~ STDIN.getc and /[a-z\\d]/i =~ STDIN.getc
n[]
else
s<<f0
end
}
fb =->{ # Decode the key-value joiner
case STDIN.getc
$':'
s<<fc
$' '
redo
else
s<<f0
end
}
fc =->{ # Decode second half of object value
case STDIN.getc
$'"'
s<<fd
s<<f8 # string
$'0'
s<<f19
s<<f18 # zero starting number
$'-', /[1-9]/
s<<f19
s<<f15 # number
$'{'
s<<fd
s<<f2 # object
$'['
s<<fd
s<<f3 # array
$'t'
s<<fd
s<<f6 # true
$'f'
s<<fd
s<<f7 # false
$'n'
s<<fd
s<<f5 # null
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
fd =->{ # Continuation for object
case STDIN.getc
$','
s<<f22
$' ', "\\n", "\\t"
redo
$'}'
n[]
else
s<<f0
end
}
f14 =->{ # Continuation for array from number
case cell
$' ', "\\n", "\\t"
s<<f4
$','
s<<f21
$']'
n[]
else
s<<f0
end
}
f18 =->{
case c = STDIN.getc
$'.'
s<<f16
else
cell = c
end
}
f15 =->{
case c = STDIN.getc
$/\\d/
redo
$'.'
s<<f16
$'e', 'E'
s<<f17
else
cell = c
end
}
f16 =->{
if /\\d/ =~ STDIN.getc
n[] while /\\d/ =~ (c = STDIN.getc)
if c == 'e' or c == 'E'
s<<f17
else
cell = c
end
else
s<<f0
end
}
f17 =->{
case STDIN.getc
$'+', '-'
s<<f0 unless /\\d/ =~ STDIN.getc
$/\\d/
n[]
else
s<<f0
end
n[] while /\\d/ =~ (c = STDIN.getc)
cell = c
}
f19 =->{
case cell
$' ', "\\n", "\\t";s<<fd
$',';s<<f22
$'}';n[]
else;s<<f0
end
}
f20 =->{
case STDIN.getc
$' ', "\\n", "\\t"
redo
$nil
n[]
else
s<<f0
end
}
f22 =->{
case STDIN.getc
$'"'
s<<fb
s<<f8
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
s<<f1
s<<f20
start =->{ case STDIN.getc $'{'
s<<f2 $'['
s<<f3
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
start[]
s.pop[]while true
|.gsub('$','when ')
s = []
f0,f1,f2,f3,f4,f5,f6,f7,f8,f9,fa,fb,fc,fd,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23 = nil
cell = nil
n =->{}
eval %Q|
f0 =->{
puts "Invalid"
exit
}
f1 =->{
puts "Valid"
exit
}
f2 =->{
case STDIN.getc
$'"'
s<<fb
s<<f8
$'}'
n[]
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
f3 =->{
case STDIN.getc
$'"'
s<<f4
s<<f8
$'0'
s<<f14
s<<f18
$'-', /[1-9]/
s<<f14
s<<f15
$'{'
s<<f4
s<<f2
$'['
s<<f4
s<<f3
$'t'
s<<f4
s<<f6
$'f'
s<<f4
s<<f7
$'n'
s<<f4
s<<f5
$']'
n[]
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
f21 =->{
case STDIN.getc
$'"'
s<<f4
s<<f8
$'0'
s<<f14
s<<f18
$'-', /[1-9]/
s<<f14
s<<f15
$'{'
s<<f4
s<<f2
$'['
s<<f4
s<<f3
$'t'
s<<f4
s<<f6
$'f'
s<<f4
s<<f7
$'n'
s<<f4
s<<f5
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
f4 =->{
case STDIN.getc
$','
s<<f21
$']'
n[]
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
f5 =->{
if STDIN.getc == 'u' and STDIN.getc == 'l' and STDIN.getc == 'l'
n[]
else
s<<f0
end
}
f6 =->{
if STDIN.getc == 'r' and STDIN.getc == 'u' and STDIN.getc == 'e'
n[]
else
s<<f0
end
}
f7 =->{
if STDIN.getc == 'a' and STDIN.getc == 'l' and STDIN.getc == 's' and STDIN.getc == 'e'
n[]
else
s<<f0
end
}
f8 =->{
case STDIN.getc
$"\\\\"
s<<f8
s<<f9
$'"'
n[]
$/[^\\x00-\\x1F]/
redo
else
s<<f0
end
}
f9 =->{ # Decode escaped part of string
case STDIN.getc
$'"', "\\\\", '/', 'b', 'f', 'n', 'r', 't'
n[]
$'u'
s<<fa
else
s<<f0
end
}
fa =->{ # Decode unicode hex character
if /[a-z\\d]/i =~ STDIN.getc and /[a-z\\d]/i =~ STDIN.getc and /[a-z\\d]/i =~ STDIN.getc and /[a-z\\d]/i =~ STDIN.getc
n[]
else
s<<f0
end
}
fb =->{ # Decode the key-value joiner
case STDIN.getc
$':'
s<<fc
$' '
redo
else
s<<f0
end
}
fc =->{ # Decode second half of object value
case STDIN.getc
$'"'
s<<fd
s<<f8 # string
$'0'
s<<f19
s<<f18 # zero starting number
$'-', /[1-9]/
s<<f19
s<<f15 # number
$'{'
s<<fd
s<<f2 # object
$'['
s<<fd
s<<f3 # array
$'t'
s<<fd
s<<f6 # true
$'f'
s<<fd
s<<f7 # false
$'n'
s<<fd
s<<f5 # null
$' ', "\\n", "\\t"
redo
else
s<<f0
end
}
fd =->{ # Continuation for object
case STDIN.getc
$','
s<<f22
$' ', "\\n", "\\t"
redo
$'}'
n[]
else
s<<f0
end
}
f14 =->{ # Continuation for array from number
case cell
$' ', "\\n", "\\t"
s<<f4
$','
s<<f21
$']'
n[]
else
s<<f0
end
}
f18 =->{
case c = STDIN.getc
$'.'
s<<f16
else
cell = c
end
}
f15 =->{
case c = STDIN.getc
$/\\d/
redo
$'.'
s<<f16
$'e', 'E'
s<<f17
else
cell = c
end
}
f16 =->{
if /\\d/ =~ STDIN.getc
n[] while /\\d/ =~ (c = STDIN.getc)
if c == 'e' or c == 'E'
s<<f17
else
cell = c
end
else;s<<f0
end
}
f17 =->{
case STDIN.getc
$'+', '-';s<<f0 unless /\\d/ =~ STDIN.getc
$/\\d/;n[]
else;s<<f0
end
n[] while /\\d/ =~ (c = STDIN.getc)
cell = c
}
f19 =->{
case cell
$' ', "\\n", "\\t";s<<fd
$',';s<<f22
$'}';n[]
else;s<<f0
end
}
f20 =->{
case STDIN.getc
$' ', "\\n", "\\t";redo
$nil;n[]
else;s<<f0
end
}
f22 =->{
case STDIN.getc
$'"';s<<fb;s<<f8
$' ', "\\n", "\\t";redo
else;s<<f0
end
}
s<<f1
s<<f20
start =->{ case STDIN.getc $'{'
s<<f2
$'[';s<<f3
$' ', "\\n", "\\t";redo
else;s<<f0
end
}
start[]
s.pop[]while true
|.gsub('$','when ')
#!/bin/bash
if [ $# -lt 1 ] ; then
echo "Usage: $0 ./command" >& 2
exit 1
fi
if [ $# -eq 1 ] ; then
if [ ! -f "$(which "$1" 2>/dev/null)" ] ; then
if [ -f "./$1" ] ; then
echo "$1 not found. Perhaps you meant:" >& 2
echo >& 2
printf '\t'
echo "$0 ./$1" >& 2
echo >& 2
else
echo "$1 not found." >& 2
fi
exit 1
fi
fi
command="$@"
score=0
total=0
function expect {
out="$(echo -n "$2" | $command)"
if [ "$out" = "$1" ] ; then
: $((score++))
else
echo "fail: should be $(echo "$1" | tr A-Z a-z): $2" >& 2
fi
: $((total++))
}
function expect_printf {
expected="$1"
shift
out="$(printf "$@" | $command)"
if [ "$out" = "$expected" ] ; then
: $((score++))
else
echo "fail: should be $(echo "$expected" | tr A-Z a-z): E'$@'" >& 2
fi
: $((total++))
}
expect_printf Valid '[\n]'
expect_printf Invalid '["\n"]'
expect_printf Valid '["\\n"]'
expect_printf Invalid '["\t"]'
expect_printf Valid '["\\t"]'
expect_printf Invalid '["\\a"]'
expect_printf Valid '["\\b"]'
expect_printf Valid '\t\n [\n\t 1 \t\n, \n\t2 ]\t'
expect_printf Invalid '[\f]'
expect_printf Invalid '[\v]'
expect_printf Invalid '["\t"]'
expect_printf Invalid '["\v"]'
expect_printf Invalid '["\f"]'
expect_printf Invalid '["\n"]'
expect_printf Invalid '["\r"]'
expect_printf Valid '[" "]'
expect_printf Valid '[" "] '
expect_printf Valid ' [" "]'
expect_printf Invalid ' [" "]]'
expect_printf Invalid '[]\x00'
expect_printf Valid '[]\n'
expect_printf Invalid '["""]'
expect_printf Invalid '["\\"]'
expect_printf Invalid '["\x00"]'
expect_printf Invalid '["\x01"]'
expect_printf Invalid '["\x02"]'
expect_printf Invalid '["\x03"]'
expect_printf Invalid '["\x04"]'
expect_printf Invalid '["\x05"]'
expect_printf Invalid '["\x06"]'
expect_printf Invalid '["\x07"]'
expect_printf Invalid '["\x08"]'
expect_printf Invalid '["\x09"]'
expect_printf Invalid '["\x0A"]'
expect_printf Invalid '["\x0B"]'
expect_printf Invalid '["\x0C"]'
expect_printf Invalid '["\x0D"]'
expect_printf Invalid '["\x0E"]'
expect_printf Invalid '["\x0F"]'
expect_printf Invalid '["\x10"]'
expect_printf Invalid '["\x11"]'
expect_printf Invalid '["\x12"]'
expect_printf Invalid '["\x13"]'
expect_printf Invalid '["\x14"]'
expect_printf Invalid '["\x15"]'
expect_printf Invalid '["\x16"]'
expect_printf Invalid '["\x17"]'
expect_printf Invalid '["\x18"]'
expect_printf Invalid '["\x19"]'
expect_printf Invalid '["\x1A"]'
expect_printf Invalid '["\x1B"]'
expect_printf Invalid '["\x1C"]'
expect_printf Invalid '["\x1D"]'
expect_printf Invalid '["\x1E"]'
expect_printf Invalid '["\x1F"]'
expect Valid '["\\"]'
expect Valid '["\/"]'
expect Valid '["\""]'
expect Valid ' [ -1 ] '
expect Invalid '-1'
expect Invalid ' [ - 1 ] '
expect Valid ' [ 1 ] '
expect Valid ' [ 12 ] '
expect Valid ' [ 123 ] '
expect Invalid ' [ 1 23 ] '
expect Valid ' [ 0 ] '
expect Invalid ' [ 01 ] '
expect Invalid ' [ \x12 ] '
expect Valid ' [ 0.1 ] '
expect Invalid ' [ 01.2 ] '
expect Valid ' [ 1.1 ] '
expect Invalid ' [ .1 ] '
expect Valid ' [ 0.01 ] '
expect Valid ' [ 0.10 ] '
expect Valid ' [ 0.1e0 ] '
expect Valid ' [ 0.1e012 ] '
expect Invalid ' [ 0.1e ] '
expect Invalid ' [ 0.e1 ] '
expect Valid ' [ 0.1e+1 ] '
expect Valid ' [ 0.1e-1 ] '
expect Invalid ' [ 0.1e+-1 ] '
expect Invalid ' [ 0.1e-+1 ] '
expect Valid '[1,2,3]'
expect Valid '[1 , 2 , 3 ]'
expect Valid '[0.1,2]'
expect Valid '[0.1e2,3]'
expect Invalid ''
expect Invalid ' '
expect Invalid '"'
expect Invalid '[,]'
expect Invalid '[)'
expect Invalid '[]]'
expect Invalid '[}'
expect Invalid '{,}'
expect Invalid '{]'
expect Invalid '["1":2]'
expect Invalid '[1,2,]'
expect Invalid '[1:2}'
expect Invalid '{"1":2,}'
expect Invalid '{1:2}'
expect Invalid '{"1":2, "2.5" : [3, 4, {}, {"5": ["6"], [7 ]}]}'
expect Invalid '{"1":2, "2.5" : [3, 4, {}, {"5": ["6"], [7]}]}'
expect Invalid '{"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]'
expect Invalid '{"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]]'
expect Invalid '{"1":2, "3":4'
expect Invalid '["1\u2"]'
expect Invalid '[,2]'
expect Invalid '["3]'
expect Invalid '["3" "4"]'
expect Invalid '[3[4]'
expect Invalid '[3[4]]'
expect Invalid '[3, [4, [5], 6] 7, 8 9]'
expect Invalid '[3, [4, [5], 6] 7, 8, 9]'
expect Invalid '[3, [4, [5], 6], 7, 8 9]'
expect Invalid '{"hello":true, "bye":false, null}'
expect Invalid '{"hello":true, "bye":false, null:null}'
expect Invalid '["hi]'
expect Invalid '["hi"""]'
expect Invalid '{"hi": "bye"]'
expect Valid '["\uFFFE"]'
expect Valid '["\uFFFF"]'
expect Invalid '[.]'
expect Valid '[""]'
expect Valid '[]'
expect Valid '{}'
expect Invalid '[+.]'
expect Valid '[0.5]'
expect Valid '[0.5 ]'
expect Valid '[ 0.5]'
expect Invalid '[0 .5]'
expect Invalid '[0. 5]'
expect Invalid '0.e1'
expect Valid '{"1":{}}'
expect Valid '{"1":2}'
expect Valid '{"1":2, "2.5" : [3, 4, {}, {"5": ["6"]}]}'
expect Valid '{"1":2, "2.5" : [3, 4, {}, {"5": ["6"], "7" :[8 ]}]}'
expect Valid '[1234]'
expect Valid '[-1234]'
expect Valid '{"1":2, "3":4}'
expect Invalid '[+1234]'
expect Invalid '[++1234]'
expect Valid '[123.456e14234]'
expect Valid '[123.456e-14234]'
expect Valid '[123.456e+14234]'
expect Invalid '[123.e-14234]'
expect Valid '["1\u2000"]'
expect Valid '["1\u20001"]'
expect Valid '[2]'
expect Invalid '[.246e-14234]'
expect Invalid '[.2e-14234]'
expect Valid '[3]'
expect Invalid '[.3]'
expect Valid '["3"]'
expect Valid '[3]'
expect Invalid '[+3.]'
expect Valid '[3.2e+1]'
expect Valid '[3, [4]]'
expect Valid '[3, [4, [5]]]'
expect Valid '[3, [4, [5], 6]]'
expect Valid '[3, [4, [5], 6], 7]'
expect Valid '[3, [4, [5], 6], 7, 8]'
expect Valid '[3, [4, [5], 6], 7, 8, 9]'
expect Invalid '[+3.5]'
expect Invalid '[.3e]'
expect Invalid '[.3e1]'
expect Invalid '[.3e-1]'
expect Invalid '[.3e+1]'
expect Invalid '[3.e1]'
expect Invalid '[3.e+1]'
expect Valid '[3e+1]'
expect Invalid '[.5]'
expect Invalid '[+.5]'
expect Invalid '[.5e+1]'
expect Valid '[ 7]'
expect Valid '[7 ]'
expect Valid '[7]'
expect Invalid '[.e-14234]'
expect Valid '["hello"]'
expect Valid '["hello"]'
expect Valid '["hello", "bye"]'
expect Valid '["hello", "bye\n"]'
expect Valid '["hello", "bye\n\r\t"]'
expect Valid '["hello", "bye\n\r\t\b"]'
expect Valid '["hello", "bye\n\r\t\b",true]'
expect Valid '["hello", "bye\n\r\t\b",true , false]'
expect Valid '["hello", "bye\n\r\t\b",true , false, null]'
expect Invalid '["hello", "bye\n\r\t\v"]'
expect Valid '{"hello":true}'
expect Valid '{"hello":true, "bye":false}'
expect Valid '{"hello":true, "bye":false, "foo":["one","two","three"]}'
expect Valid '["hi"]'
expect Valid '["hi"]'
expect Valid '["hi", "bye"]'
expect Valid '{"hi": "bye"}'
expect Valid '["hi", "bye", 3]'
expect Valid '["hi", "bye[", 3]'
expect Valid '["\u0007"]'
expect Valid '["\u0008"]'
expect Valid '["\u0009"]'
expect Valid '["\u0010"]'
expect Valid '["\u0020"]'
expect Valid '["\u10000"]'
expect Valid '["\u1234"]'
expect Valid '["\u99999"]'
expect Valid '["\ud800\udc00"]'
expect Valid '["\uD800\uDC00"]'
expect Valid '["\uD834\uDD1E"]'
expect Valid '["\uDBFF\uDFFF"]'
expect Valid '["\uFFFD"]'
expect Valid '["\uFFFF"]'
expect Invalid '[hello]'
expect Valid '[32, 1]'
expect Invalid '[32, '
expect Valid '["\uD800\uDC00"]'
expect Valid '["\n"]'
expect Valid '["hello"]'
expect Valid '["hello\u0009world"]'
expect Valid '["hello"]'
expect Valid '["hello\n"]'
expect Valid '["hello"]'
expect Valid '[3]'
expect Invalid '[3.]'
expect Invalid '[.3]'
expect Valid '[0.3]'
expect Invalid '[0.3e]'
expect Invalid '[0.3e+]'
expect Valid '[0.3e+5]'
expect Valid '[0.3e-5]'
expect Valid '[0.3e5]'
expect Valid '["hello"]'
expect Invalid '[+3]'
expect Valid '[-3]'
expect Invalid '[-3.]'
expect Valid '[-3.1]'
expect Invalid '[.5]'
expect Invalid '[5.]'
expect Invalid '[5.e1]'
expect Valid '[0.5]'
expect Invalid '[.3e1]'
expect Invalid '[.3e+1]'
expect Invalid '[.3e-1]'
expect Invalid '[.3e-1 .5]'
expect Invalid '[.3e-1.5]'
expect Invalid '[.3e+1.5]'
expect Invalid '[.3e+.]'
expect Invalid '[.3e+.5]'
expect Invalid '[.3e+1.5]'
expect Invalid '[9.3e+1.5]'
expect Invalid '[9.e+1.5]'
expect Invalid '[9.e+]'
expect Invalid '[9.e+1]'
expect Valid '["\""]'
expect Valid '["\"3.5"]'
expect Valid '["\"."]'
expect Invalid '["\".".]'
expect Valid '["\"....."]'
expect Invalid '["\"\"\"\"""]'
expect Invalid '["\"\"\"\"", .5]'
expect Invalid '[.5]'
expect Valid '["\"\"\"\"", 0.5]'
expect Invalid '["\"\"\"\"", .5]'
expect Invalid '["\"\"\"\"",.5]'
expect Invalid '["\"",.5]'
expect Invalid '["\".5",.5]'
expect Invalid '["\".5",".5\"".5]'
expect Invalid '["\".5",".5\"", .5]'
expect Invalid '["\".5",".5\"",.5]'
expect Valid '["\".5",".5\"",0.5]'
expect Invalid '{"key":/*comment*/"value"}'
expect Invalid '{"key":/*comment"value"}'
expect Invalid '{"key":"value"}/*'
expect Invalid '{"key":"value"}/**/'
expect Invalid '{"key":"value"}/***/'
expect Invalid '{"key":"value"}/**//'
expect Invalid '{"key":"value"}/**///'
expect Invalid '{"key":"value"}/**///----'
expect Invalid '{"key":"value"}#'
expect Invalid '{"key":"value"}#{'
expect Invalid '{"key":"value"}#{}'
expect Invalid '{"key":"value"}#,'
expect Invalid '{"key":"value"/**/, "k2":"v2"}'
expect Valid '["\u0027"]'
expect Invalid '["hello\'"'"'"]'
expect Invalid '['"'"'hello\'"'"''"'"']'
expect Invalid '['"'"'hello'"'"']'
expect Invalid '['"'"'hell\'"'"'o'"'"']'
expect Invalid '['"'"'\'"'"'hello'"'"']'
expect Invalid '['"'"'\'"'"'hello\'"'"''"'"']'
expect Invalid '[\'"'"'hello\'"'"']'
expect Invalid '['"'"'hello\'"'"']'
expect Invalid '['"'"'hello\'"'"']'
expect Invalid '['"'"'hello\'"'"''"'"']'
expect Invalid '['"'"'hello"'"'"']'
expect Invalid '['"'"'hello\"'"'"']'
expect Invalid '['"'"'hello"o'"'"']'
expect Invalid '['"'"'"'"'"']'
expect Invalid '['"'"'"'"'"']'
expect Invalid '['"'"'"hello"'"'"']'
expect Invalid '['"'"'"hello'"'"']'
expect Invalid '['"'"'"hi"'"'"']'
echo "score: $score/$total"
stack = []
f0,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23 = nil
cell = nil
noop = proc {}
f0 = proc do
puts "Invalid"
exit
end
f1 = proc do
puts "Valid"
exit
end
f2 = proc do # Start of object
case STDIN.getc
when '"'
stack << f11
stack << f8 # string
when '}'
noop[]
when "\x00".." "
redo
else
stack << f0
end
end
f3 = proc do # Start of an array element
case STDIN.getc
when '"'
stack << f4
stack << f8 # string
when '0'
stack << f14
stack << f18 # zero starting number
when '-', /[1-9]/
stack << f14
stack << f15 # number
when '{'
stack << f4
stack << f2 # object
when '['
stack << f4
stack << f3 # array
when 't'
stack << f4
stack << f6 # true
when 'f'
stack << f4
stack << f7 # false
when 'n'
stack << f4
stack << f5 # null
when ']'
noop[]
when "\x00".." "
redo
else
stack << f0
end
end
f21 = proc do
case STDIN.getc
when '"'
stack << f4
stack << f8 # string
when '0'
stack << f14
stack << f18 # zero starting number
when '-', /[1-9]/
stack << f14
stack << f15 # number
when '{'
stack << f4
stack << f2 # object
when '['
stack << f4
stack << f3 # array
when 't'
stack << f4
stack << f6 # true
when 'f'
stack << f4
stack << f7 # false
when 'n'
stack << f4
stack << f5 # null
when "\x00".." "
redo
else
stack << f0
end
end
f4 = proc do # Continuation after array element
case STDIN.getc
when ','
stack << f21
when ']'
noop[]
when "\x00".." "
redo
else
stack << f0
end
end
f5 = proc do # Decode null
if STDIN.getc == 'u' and STDIN.getc == 'l' and STDIN.getc == 'l'
noop[]
else
stack << f0
end
end
f6 = proc do # Decode true
if STDIN.getc == 'r' and STDIN.getc == 'u' and STDIN.getc == 'e'
noop[]
else
stack << f0
end
end
f7 = proc do # Decode false
if STDIN.getc == 'a' and STDIN.getc == 'l' and STDIN.getc == 's' and STDIN.getc == 'e'
noop[]
else
stack << f0
end
end
f8 = proc do # Decode string
case STDIN.getc
when "\\"
stack << f8
stack << f9
when '"'
noop[]
when /[^\x00-\x1F]/
redo
else
stack << f0
end
end
f9 = proc do # Decode escaped part of string
case STDIN.getc
when '"', "\\", '/', 'b', 'f', 'n', 'r', 't'
noop[]
when 'u'
stack << f10
else
stack << f0
end
end
f10 = proc do # Decode unicode hex character
if /[a-z\d]/i =~ STDIN.getc and /[a-z\d]/i =~ STDIN.getc and /[a-z\d]/i =~ STDIN.getc and /[a-z\d]/i =~ STDIN.getc
noop[]
else
stack << f0
end
end
f11 = proc do # Decode the key-value joiner
case STDIN.getc
when ':'
stack << f12
when ' '
redo
else
stack << f0
end
end
f12 = proc do # Decode second half of object value
case STDIN.getc
when '"'
stack << f13
stack << f8 # string
when '0'
stack << f19
stack << f18 # zero starting number
when '-', /[1-9]/
stack << f19
stack << f15 # number
when '{'
stack << f13
stack << f2 # object
when '['
stack << f13
stack << f3 # array
when 't'
stack << f13
stack << f6 # true
when 'f'
stack << f13
stack << f7 # false
when 'n'
stack << f13
stack << f5 # null
when "\x00".." "
redo
else
stack << f0
end
end
f13 = proc do # Continuation for object
case STDIN.getc
when ','
stack << f22
when "\x00".." "
redo
when '}'
noop[]
else
stack << f0
end
end
f14 = proc do # Continuation for array from number
case cell
when "\x00".." "
stack << f4
when ','
stack << f21
when ']'
noop[]
else
stack << f0
end
end
f18 = proc do # Decode number starting with '0'
case c = STDIN.getc
when '.'
stack << f16
else
cell = c
end
end
f15 = proc do # Decode number
case c = STDIN.getc
when /\d/
redo
when '.'
stack << f16
when 'e', 'E'
stack << f17
else
cell = c
end
end
f16 = proc do # Decode frac
if /\d/ =~ STDIN.getc
noop[] while /\d/ =~ (c = STDIN.getc)
if c == 'e' or c == 'E'
stack << f17
else
cell = c
end
else
stack << f0
end
end
f17 = proc do # Decode exp
case STDIN.getc
when '+', '-'
stack << f0 unless /\d/ =~ STDIN.getc
when /\d/
noop[]
else
stack << f0
end
noop[] while /\d/ =~ (c = STDIN.getc)
cell = c
end
f19 = proc do # Continuation for object after number
case cell
when "\x00".." "
stack << f13
when ','
stack << f22
when '}'
noop[]
else
stack << f0
end
end
f20 = proc do
case STDIN.getc
when "\x00".." "
redo
when nil
noop[]
else
stack << f0
end
end
f22 = proc do
case STDIN.getc
when '"'
stack << f11
stack << f8 # string
when "\x00".." "
redo
else
stack << f0
end
end
stack << f1
stack << f20
start = proc do
case STDIN.getc
when '{'
stack << f2
when '['
stack << f3
when "\x00".." "
redo
else
stack << f0
end
end
start[]
while true
stack.pop.call
end
tr '"' '\5' | ruby ./ruby.rb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment