PageRenderTime 25ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/gems/json-1.1.6/lib/json/pure/parser.rb

https://github.com/jjuglans/Webiva
Ruby | 267 lines | 239 code | 8 blank | 20 comment | 10 complexity | 5a5915dd53014b805be99b9790229ef4 MD5 | raw file
  1. require 'strscan'
  2. module JSON
  3. module Pure
  4. # This class implements the JSON parser that is used to parse a JSON string
  5. # into a Ruby data structure.
  6. class Parser < StringScanner
  7. STRING = /" ((?:[^\x0-\x1f"\\] |
  8. \\["\\\/bfnrt] |
  9. \\u[0-9a-fA-F]{4} |
  10. \\[\x20-\xff])*)
  11. "/nx
  12. INTEGER = /(-?0|-?[1-9]\d*)/
  13. FLOAT = /(-?
  14. (?:0|[1-9]\d*)
  15. (?:
  16. \.\d+(?i:e[+-]?\d+) |
  17. \.\d+ |
  18. (?i:e[+-]?\d+)
  19. )
  20. )/x
  21. NAN = /NaN/
  22. INFINITY = /Infinity/
  23. MINUS_INFINITY = /-Infinity/
  24. OBJECT_OPEN = /\{/
  25. OBJECT_CLOSE = /\}/
  26. ARRAY_OPEN = /\[/
  27. ARRAY_CLOSE = /\]/
  28. PAIR_DELIMITER = /:/
  29. COLLECTION_DELIMITER = /,/
  30. TRUE = /true/
  31. FALSE = /false/
  32. NULL = /null/
  33. IGNORE = %r(
  34. (?:
  35. //[^\n\r]*[\n\r]| # line comments
  36. /\* # c-style comments
  37. (?:
  38. [^*/]| # normal chars
  39. /[^*]| # slashes that do not start a nested comment
  40. \*[^/]| # asterisks that do not end this comment
  41. /(?=\*/) # single slash before this comment's end
  42. )*
  43. \*/ # the End of this comment
  44. |[ \t\r\n]+ # whitespaces: space, horicontal tab, lf, cr
  45. )+
  46. )mx
  47. UNPARSED = Object.new
  48. # Creates a new JSON::Pure::Parser instance for the string _source_.
  49. #
  50. # It will be configured by the _opts_ hash. _opts_ can have the following
  51. # keys:
  52. # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
  53. # structures. Disable depth checking with :max_nesting => false|nil|0,
  54. # it defaults to 19.
  55. # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
  56. # defiance of RFC 4627 to be parsed by the Parser. This option defaults
  57. # to false.
  58. # * *create_additions*: If set to false, the Parser doesn't create
  59. # additions even if a matchin class and create_id was found. This option
  60. # defaults to true.
  61. # * *object_class*: Defaults to Hash
  62. # * *array_class*: Defaults to Array
  63. def initialize(source, opts = {})
  64. super
  65. if !opts.key?(:max_nesting) # defaults to 19
  66. @max_nesting = 19
  67. elsif opts[:max_nesting]
  68. @max_nesting = opts[:max_nesting]
  69. else
  70. @max_nesting = 0
  71. end
  72. @allow_nan = !!opts[:allow_nan]
  73. ca = true
  74. ca = opts[:create_additions] if opts.key?(:create_additions)
  75. @create_id = ca ? JSON.create_id : nil
  76. @object_class = opts[:object_class] || Hash
  77. @array_class = opts[:array_class] || Array
  78. end
  79. alias source string
  80. # Parses the current JSON string _source_ and returns the complete data
  81. # structure as a result.
  82. def parse
  83. reset
  84. obj = nil
  85. until eos?
  86. case
  87. when scan(OBJECT_OPEN)
  88. obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
  89. @current_nesting = 1
  90. obj = parse_object
  91. when scan(ARRAY_OPEN)
  92. obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
  93. @current_nesting = 1
  94. obj = parse_array
  95. when skip(IGNORE)
  96. ;
  97. else
  98. raise ParserError, "source '#{peek(20)}' not in JSON!"
  99. end
  100. end
  101. obj or raise ParserError, "source did not contain any JSON!"
  102. obj
  103. end
  104. private
  105. # Unescape characters in strings.
  106. UNESCAPE_MAP = Hash.new { |h, k| h[k] = k.chr }
  107. UNESCAPE_MAP.update({
  108. ?" => '"',
  109. ?\\ => '\\',
  110. ?/ => '/',
  111. ?b => "\b",
  112. ?f => "\f",
  113. ?n => "\n",
  114. ?r => "\r",
  115. ?t => "\t",
  116. ?u => nil,
  117. })
  118. def parse_string
  119. if scan(STRING)
  120. return '' if self[1].empty?
  121. string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
  122. if u = UNESCAPE_MAP[$&[1]]
  123. u
  124. else # \uXXXX
  125. bytes = ''
  126. i = 0
  127. while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
  128. bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
  129. i += 1
  130. end
  131. JSON::UTF16toUTF8.iconv(bytes)
  132. end
  133. end
  134. if string.respond_to?(:force_encoding)
  135. string.force_encoding(Encoding::UTF_8)
  136. end
  137. string
  138. else
  139. UNPARSED
  140. end
  141. rescue Iconv::Failure => e
  142. raise GeneratorError, "Caught #{e.class}: #{e}"
  143. end
  144. def parse_value
  145. case
  146. when scan(FLOAT)
  147. Float(self[1])
  148. when scan(INTEGER)
  149. Integer(self[1])
  150. when scan(TRUE)
  151. true
  152. when scan(FALSE)
  153. false
  154. when scan(NULL)
  155. nil
  156. when (string = parse_string) != UNPARSED
  157. string
  158. when scan(ARRAY_OPEN)
  159. @current_nesting += 1
  160. ary = parse_array
  161. @current_nesting -= 1
  162. ary
  163. when scan(OBJECT_OPEN)
  164. @current_nesting += 1
  165. obj = parse_object
  166. @current_nesting -= 1
  167. obj
  168. when @allow_nan && scan(NAN)
  169. NaN
  170. when @allow_nan && scan(INFINITY)
  171. Infinity
  172. when @allow_nan && scan(MINUS_INFINITY)
  173. MinusInfinity
  174. else
  175. UNPARSED
  176. end
  177. end
  178. def parse_array
  179. raise NestingError, "nesting of #@current_nesting is to deep" if
  180. @max_nesting.nonzero? && @current_nesting > @max_nesting
  181. result = @array_class.new
  182. delim = false
  183. until eos?
  184. case
  185. when (value = parse_value) != UNPARSED
  186. delim = false
  187. result << value
  188. skip(IGNORE)
  189. if scan(COLLECTION_DELIMITER)
  190. delim = true
  191. elsif match?(ARRAY_CLOSE)
  192. ;
  193. else
  194. raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
  195. end
  196. when scan(ARRAY_CLOSE)
  197. if delim
  198. raise ParserError, "expected next element in array at '#{peek(20)}'!"
  199. end
  200. break
  201. when skip(IGNORE)
  202. ;
  203. else
  204. raise ParserError, "unexpected token in array at '#{peek(20)}'!"
  205. end
  206. end
  207. result
  208. end
  209. def parse_object
  210. raise NestingError, "nesting of #@current_nesting is to deep" if
  211. @max_nesting.nonzero? && @current_nesting > @max_nesting
  212. result = @object_class.new
  213. delim = false
  214. until eos?
  215. case
  216. when (string = parse_string) != UNPARSED
  217. skip(IGNORE)
  218. unless scan(PAIR_DELIMITER)
  219. raise ParserError, "expected ':' in object at '#{peek(20)}'!"
  220. end
  221. skip(IGNORE)
  222. unless (value = parse_value).equal? UNPARSED
  223. result[string] = value
  224. delim = false
  225. skip(IGNORE)
  226. if scan(COLLECTION_DELIMITER)
  227. delim = true
  228. elsif match?(OBJECT_CLOSE)
  229. ;
  230. else
  231. raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!"
  232. end
  233. else
  234. raise ParserError, "expected value in object at '#{peek(20)}'!"
  235. end
  236. when scan(OBJECT_CLOSE)
  237. if delim
  238. raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
  239. end
  240. if @create_id and klassname = result[@create_id]
  241. klass = JSON.deep_const_get klassname
  242. break unless klass and klass.json_creatable?
  243. result = klass.json_create(result)
  244. end
  245. break
  246. when skip(IGNORE)
  247. ;
  248. else
  249. raise ParserError, "unexpected token in object at '#{peek(20)}'!"
  250. end
  251. end
  252. result
  253. end
  254. end
  255. end
  256. end