Last active
December 21, 2015 18:59
-
-
Save v2e4lisp/6350775 to your computer and use it in GitHub Desktop.
parsing json-like data. Designed for cli use. It's far from effient. The funny thing is you can customize the special mark of the json-like data.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module Fakeit | |
| extend self | |
| attr_accessor :array_mark, :hash_mark | |
| @array_mark = '[ ]' | |
| @hash_mark = '{:,}' | |
| # Not effient way to parse json-like structure | |
| # The problem is `split` is called too many times. | |
| # The better way to do it, is something like the original js json parser . | |
| # It's done by using only one pass. | |
| def parse str='' | |
| str = str.strip | |
| case str[0] | |
| when '"', "'" | |
| string str[1..-1] | |
| when array_mark[0] | |
| array str[1..-1] | |
| when hash_mark[0] | |
| hash str[1..-1] | |
| else | |
| str | |
| end | |
| end | |
| def string str | |
| raise 'String parse error !' unless ["'", '"'].include?(str[-1]) | |
| return str[0...-1] | |
| end | |
| def array str | |
| raise 'Array parse error !' if str[-1] != array_mark[-1] | |
| split(str, :array).map { |x| parse(x) } | |
| end | |
| def hash str | |
| raise 'Hash parse error !' if str[-1] != hash_mark[-1] | |
| Hash[split(str, :hash).map { |e| key_value e.strip }] | |
| end | |
| def key_value str | |
| key, value = str.split(hash_mark[1], 2) | |
| return [key, parse(value)] | |
| end | |
| def split str, init_state | |
| target = if init_state == :array | |
| array_mark[1] | |
| elsif init_state == :hash | |
| hash_mark[2] | |
| end | |
| state = [init_state] | |
| state.instance_eval { def lookup; self.last; end } | |
| ret = [] | |
| last = 0 | |
| str.split("").each_with_index do |x, i| | |
| case x | |
| when "'" | |
| case state.lookup | |
| when :str1; state.pop | |
| when :str2; next | |
| else; state.push :str1 | |
| end | |
| when '"' | |
| case state.lookup | |
| when :str2; state.pop | |
| when :str1; next | |
| else; state.push :str2 | |
| end | |
| when array_mark[0] | |
| case state.lookup | |
| when :str1, :str2; next | |
| else; state.push :array | |
| end | |
| when array_mark[-1] | |
| case state.lookup | |
| when :str1, :str2; next | |
| when :array; state.pop | |
| else; raise 'error' | |
| end | |
| when hash_mark[0] | |
| case state.lookup | |
| when :str1, :str2; next | |
| else; state.push :hash | |
| end | |
| when hash_mark[-1] | |
| case state.lookup | |
| when :str1, :str2; next | |
| when :hash; state.pop | |
| else; raise 'error' | |
| end | |
| when target | |
| if state.lookup == init_state | |
| ret << str[last...i] | |
| last = i+1 | |
| end | |
| end | |
| end | |
| raise 'error state' if state.any? | |
| ret << str[last...-1] | |
| return ret | |
| end | |
| end | |
| Fakeit.array_mark = '(,)' | |
| Fakeit.hash_mark = '{:,}' | |
| p Fakeit.parse(ARGV.first) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment