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 91 92 93 94
|
class JsonParser
rule
json: value { result = val[0] }
array: "[" valueList "]" { result = val[1] }
| "[" "]" { result = [] }
valueList: value { result = [ val[0] ] }
| value "," valueList { result = [ val[0] ] + val[2] }
object: "{" memberList "}" { result = @instantiator.createObject(val[1]) }
| "{" "}" { result = nil }
memberList: member { result = val[0] }
| member "," memberList { result = val[0].merge(val[2]) }
member: STRING ":" value { result = {val[0].value => val[2]} }
value: array { result = val[0] }
| object { result = val[0] }
| STRING { result = val[0].value }
| INTEGER { result = val[0].value.to_i }
| FLOAT { result = val[0].value.to_f }
| "true" { result = true }
| "false" { result = false }
end
---- header
module RGen
module Instantiator
---- inner
ParserToken = Struct.new(:line, :file, :value)
def initialize(instantiator)
@instantiator = instantiator
end
def parse(str, file=nil)
@q = []
line = 1
until str.empty?
case str
when /\A\n/
str = $'
line +=1
when /\A\s+/
str = $'
when /\A([-+]?\d+\.\d+)/
str = $'
@q << [:FLOAT, ParserToken.new(line, file, $1)]
when /\A([-+]?\d+)/
str = $'
@q << [:INTEGER, ParserToken.new(line, file, $1)]
when /\A"((?:[^"\\]|\\"|\\\\|\\[^"\\])*)"/
str = $'
sval = $1
sval.gsub!('\\\\','\\')
sval.gsub!('\\"','"')
sval.gsub!('\\n',"\n")
sval.gsub!('\\r',"\r")
sval.gsub!('\\t',"\t")
sval.gsub!('\\f',"\f")
sval.gsub!('\\b',"\b")
@q << [:STRING, ParserToken.new(line, file, sval)]
when /\A(\{|\}|\[|\]|,|:|true|false)/
str = $'
@q << [$1, ParserToken.new(line, file, $1)]
else
raise "parse error in line #{line} on "+str[0..20].inspect+"..."
end
end
@q.push [false, ParserToken.new(line, file, '$end')]
do_parse
end
def next_token
r = @q.shift
r
end
---- footer
end
end
|