Skip to content

Instantly share code, notes, and snippets.

@Twisol
Created May 16, 2011 20:13
Show Gist options
  • Save Twisol/975248 to your computer and use it in GitHub Desktop.
Save Twisol/975248 to your computer and use it in GitHub Desktop.
JSON parser in kpeg
module StringEscaper
def process_escapes (str)
str.gsub! /\\(u\d{4}|\D)/m do
seq = $1
case seq
when '/' then "\/"
when 'b' then "\b"
when 'f' then "\f"
when 'n' then "\n"
when 'r' then "\r"
when 't' then "\t"
when '"' then '"'
when '\\' then '\\'
when /u\d{4}/ then seq[1..-1].to_i.chr
else seq
end
end
str
end
end
%% name = JsonParser
%% {
require "./escaper"
include StringEscaper
attr_reader :result
}
value = object
| array
| string
| number
| "true" { true }
| "false" { false }
| "null" { nil }
object = "{" - "}" { {} }
| "{" - object-body:obj - "}" { obj }
object-body = object-pair:x (- "," - object-pair)*:xs { Hash[[x].concat(xs)] }
object-pair = string:k - ":" - value:v { [k, v] }
array = "[" - "]" { [] }
| "[" - array-body:arr - "]" { arr }
array-body = value:x (- "," - value)*:xs { [x].concat(xs) }
string = "\"" <string-char+> "\"" { process_escapes(text) }
string-char = !/["\\]/ .
| "\\" string-char-escape
string-char-escape = /[\/\"bfnrt]/
| "u" /\d{4}/
number = number-base:b number-exponent:e { b * (10 ** e) }
| number-base:b { b }
number-base = <number-base-whole number-base-frac> { text.to_f }
| <number-base-whole> { text.to_i }
number-base-whole = "0" | /-?[1-9]\d*/
number-base-frac = /\.\d+/
number-exponent = ("E"|"e") </[+-]?\d+/> { text.to_i }
- = /[ \t]*/
root = value:v { @result = v }
@Twisol
Copy link
Author

Twisol commented May 16, 2011

This version supports any value as the "root" rather than just objects and arrays, but it's common/useful enough that I did it anyways. To be strict about it, change the root= line to:

root = (object | array):v { @result = v }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment