rison 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING.txt +22 -0
- data/README.html +43 -0
- data/Rakefile.rb +73 -0
- data/lib/rison/evaluator.rb +169 -0
- data/lib/rison/grammar.rb +112 -0
- data/lib/rison/lexer.rb +30 -0
- data/lib/rison/parser.rb +340 -0
- data/lib/rison.rb +29 -0
- data/test/test_rison.rb +122 -0
- metadata +70 -0
data/COPYING.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2007 Tim Fletcher <tfletcher.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.html
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>rison.rubyforge.org</title>
|
4
|
+
<style type="text/css" media="screen">
|
5
|
+
html {
|
6
|
+
height: 100%; margin-bottom: 1px;
|
7
|
+
}
|
8
|
+
body {
|
9
|
+
margin: 0; padding: 30px;
|
10
|
+
}
|
11
|
+
h1, h2 {
|
12
|
+
font-family: garamond;
|
13
|
+
}
|
14
|
+
code {
|
15
|
+
font-family: "Panic Sans", "Bitstream Vera Sans Mono", Consolas, Monaco, monospace;
|
16
|
+
}
|
17
|
+
</style>
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
|
21
|
+
|
22
|
+
<h1>rison<span style="color:#F99">.rb</span></h1>
|
23
|
+
|
24
|
+
<h2>Examples</h2>
|
25
|
+
|
26
|
+
<pre><code> require 'rison'
|
27
|
+
|
28
|
+
Rison.load('!t') # => true
|
29
|
+
|
30
|
+
Rison.load('!(1,2,3)') # => [1, 2, 3]
|
31
|
+
|
32
|
+
Rison.load('(a:0)') # => {'a' => 0}
|
33
|
+
</code></pre>
|
34
|
+
|
35
|
+
<h2>Links</h2>
|
36
|
+
|
37
|
+
<p><a href="http://mjtemplate.org/examples/rison.html">Rison - Compact Data in URIs</a></p>
|
38
|
+
|
39
|
+
<p><a href="http://dhaka.rubyforge.org/">Dhaka</a></p>
|
40
|
+
|
41
|
+
|
42
|
+
</body>
|
43
|
+
</html>
|
data/Rakefile.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
|
6
|
+
GEMSPEC = Gem::Specification.new do |s|
|
7
|
+
s.name = 'rison'
|
8
|
+
s.version = '1.0.0'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.has_rdoc = false
|
11
|
+
s.summary = 'Pure Ruby parser for Rison (http://mjtemplate.org/examples/rison.html)'
|
12
|
+
s.description = s.summary
|
13
|
+
s.author = 'Tim Fletcher'
|
14
|
+
s.email = 'twoggle@gmail.com'
|
15
|
+
s.homepage = 'http://rison.rubyforge.org/'
|
16
|
+
s.files = Dir.glob('{lib,test}/**/*') + %w( COPYING.txt Rakefile.rb README.html )
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
s.add_dependency 'dhaka'
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
Rake::GemPackageTask.new(GEMSPEC) { }
|
23
|
+
|
24
|
+
|
25
|
+
Rake::PackageTask.new(GEMSPEC.name, GEMSPEC.version) do |p|
|
26
|
+
p.need_tar_gz = true
|
27
|
+
p.package_files.include GEMSPEC.files
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
desc 'Run all the tests'
|
32
|
+
Rake::TestTask.new do |t|
|
33
|
+
t.verbose = true
|
34
|
+
t.ruby_opts = ['-rubygems']
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
task :parse_stdin do
|
39
|
+
$:.unshift 'lib'
|
40
|
+
|
41
|
+
require 'rison'
|
42
|
+
require 'pp'
|
43
|
+
|
44
|
+
pp Rison.load($stdin.read.chomp)
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
task :reinstall do
|
49
|
+
sh 'sudo gem uninstall rison dhaka'
|
50
|
+
sh 'sudo gem install pkg/rison-%s.gem' % GEMSPEC.version
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
desc 'Regenerate the compiled parser'
|
55
|
+
task :regen do
|
56
|
+
$:.unshift 'lib'
|
57
|
+
|
58
|
+
require 'rison/grammar'
|
59
|
+
require 'dhaka'
|
60
|
+
|
61
|
+
parser = Dhaka::Parser.new(Rison::Grammar)
|
62
|
+
|
63
|
+
source = [
|
64
|
+
"require 'dhaka'",
|
65
|
+
"require 'rison/grammar'",
|
66
|
+
'',
|
67
|
+
'module Rison',
|
68
|
+
parser.compile_to_ruby_source_as(:Parser).gsub(/^/, ' '),
|
69
|
+
'end'
|
70
|
+
]
|
71
|
+
|
72
|
+
File.open('lib/rison/parser.rb', 'w+') { |f| f.puts source * "\n" }
|
73
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'dhaka'
|
2
|
+
require 'rison/grammar'
|
3
|
+
|
4
|
+
module Rison
|
5
|
+
class Evaluator < Dhaka::Evaluator
|
6
|
+
|
7
|
+
self.grammar = Grammar
|
8
|
+
|
9
|
+
define_evaluation_rules do
|
10
|
+
|
11
|
+
for_empty_object do
|
12
|
+
{}
|
13
|
+
end
|
14
|
+
|
15
|
+
for_non_empty_object do
|
16
|
+
evaluate(child_nodes[1])
|
17
|
+
end
|
18
|
+
|
19
|
+
for_member_pair do
|
20
|
+
evaluate(child_nodes[0])
|
21
|
+
end
|
22
|
+
|
23
|
+
for_member_pairs do
|
24
|
+
evaluate(child_nodes[2]).merge(evaluate(child_nodes[0]))
|
25
|
+
end
|
26
|
+
|
27
|
+
for_pair_key_value do
|
28
|
+
{ evaluate(child_nodes[0]) => evaluate(child_nodes[2]) }
|
29
|
+
end
|
30
|
+
|
31
|
+
for_empty_array do
|
32
|
+
[]
|
33
|
+
end
|
34
|
+
|
35
|
+
for_non_empty_array do
|
36
|
+
evaluate(child_nodes[2])
|
37
|
+
end
|
38
|
+
|
39
|
+
for_element_value do
|
40
|
+
[ evaluate(child_nodes[0]) ]
|
41
|
+
end
|
42
|
+
|
43
|
+
for_element_values do
|
44
|
+
[ evaluate(child_nodes[0]) ] + evaluate(child_nodes[2])
|
45
|
+
end
|
46
|
+
|
47
|
+
# for_key_id do
|
48
|
+
|
49
|
+
# for_key_string do
|
50
|
+
|
51
|
+
# for_value_id do
|
52
|
+
|
53
|
+
# for_value_string
|
54
|
+
|
55
|
+
# for_value_number do
|
56
|
+
|
57
|
+
# for_value_object do
|
58
|
+
|
59
|
+
# for_value_array do
|
60
|
+
|
61
|
+
for_value_true do
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
for_value_false do
|
66
|
+
false
|
67
|
+
end
|
68
|
+
|
69
|
+
for_value_null do
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
|
73
|
+
# for_id_idstart
|
74
|
+
|
75
|
+
for_id_idstart_idchars do
|
76
|
+
evaluate(child_nodes[0]) + evaluate(child_nodes[1])
|
77
|
+
end
|
78
|
+
|
79
|
+
# for_idchars_idchar
|
80
|
+
|
81
|
+
for_idchars_idchars do
|
82
|
+
evaluate(child_nodes[0]) + evaluate(child_nodes[1])
|
83
|
+
end
|
84
|
+
|
85
|
+
for_idchars_int do
|
86
|
+
evaluate(child_nodes[0]).to_s
|
87
|
+
end
|
88
|
+
|
89
|
+
for_idchar_char do
|
90
|
+
child_nodes[0].token.value
|
91
|
+
end
|
92
|
+
|
93
|
+
for_idstart_char do
|
94
|
+
child_nodes[0].token.value
|
95
|
+
end
|
96
|
+
|
97
|
+
for_empty_string do
|
98
|
+
''
|
99
|
+
end
|
100
|
+
|
101
|
+
for_non_empty_string do
|
102
|
+
evaluate(child_nodes[1]).inject { |s, c| s + c }
|
103
|
+
end
|
104
|
+
|
105
|
+
for_strchars_char do
|
106
|
+
[ evaluate(child_nodes[0]) ]
|
107
|
+
end
|
108
|
+
|
109
|
+
for_strchars_chars do
|
110
|
+
[ evaluate(child_nodes[0]) ] + evaluate(child_nodes[1])
|
111
|
+
end
|
112
|
+
|
113
|
+
for_strchar_char do
|
114
|
+
child_nodes[0].token.value
|
115
|
+
end
|
116
|
+
|
117
|
+
for_strchar_quoted_exclamation do
|
118
|
+
'!'
|
119
|
+
end
|
120
|
+
|
121
|
+
for_strchar_quoted_single_quote do
|
122
|
+
"'"
|
123
|
+
end
|
124
|
+
|
125
|
+
for_strchar_num do
|
126
|
+
evaluate(child_nodes[0]).to_s
|
127
|
+
end
|
128
|
+
|
129
|
+
for_number_int do
|
130
|
+
evaluate(child_nodes[0])
|
131
|
+
end
|
132
|
+
|
133
|
+
for_number_int_frac do
|
134
|
+
evaluate(child_nodes[0]) + evaluate(child_nodes[1])
|
135
|
+
end
|
136
|
+
|
137
|
+
for_number_int_exp do
|
138
|
+
evaluate(child_nodes[0]) * evaluate(child_nodes[1])
|
139
|
+
end
|
140
|
+
|
141
|
+
for_number_int_frac_exp do
|
142
|
+
(evaluate(child_nodes[0]) + evaluate(child_nodes[1])) * evaluate(child_nodes[2])
|
143
|
+
end
|
144
|
+
|
145
|
+
for_integer_literal do
|
146
|
+
token = child_nodes[0].token.value
|
147
|
+
token =~ /^(-?)(\d+?)$/
|
148
|
+
|
149
|
+
$1.empty?? $2.to_i : - $2.to_i
|
150
|
+
end
|
151
|
+
|
152
|
+
for_frac_literal do
|
153
|
+
token = child_nodes[0].token.value
|
154
|
+
token =~ /^\.(\d+?)$/
|
155
|
+
|
156
|
+
Rational($1.to_i, 10 ** $1.length)
|
157
|
+
end
|
158
|
+
|
159
|
+
for_exponent_literal do
|
160
|
+
token = child_nodes[0].token.value
|
161
|
+
token =~ /^e(-?)(\d+?)$/
|
162
|
+
|
163
|
+
10 ** ($1.empty?? $2.to_i : - $2.to_i)
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'dhaka'
|
2
|
+
|
3
|
+
module Rison
|
4
|
+
class Grammar < Dhaka::Grammar
|
5
|
+
|
6
|
+
for_symbol(Dhaka::START_SYMBOL_NAME) do
|
7
|
+
start %w| value |
|
8
|
+
end
|
9
|
+
|
10
|
+
for_symbol 'object' do
|
11
|
+
empty_object %w| ( ) |
|
12
|
+
non_empty_object %w| ( members ) |
|
13
|
+
end
|
14
|
+
|
15
|
+
for_symbol 'members' do
|
16
|
+
member_pair %w| pair |
|
17
|
+
member_pairs %w| pair , members |
|
18
|
+
end
|
19
|
+
|
20
|
+
for_symbol 'pair' do
|
21
|
+
pair_key_value %w| key : value |
|
22
|
+
end
|
23
|
+
|
24
|
+
for_symbol 'array' do
|
25
|
+
empty_array %w| ! ( ) |
|
26
|
+
non_empty_array %w| ! ( elements ) |
|
27
|
+
end
|
28
|
+
|
29
|
+
for_symbol 'elements' do
|
30
|
+
element_value %w| value |
|
31
|
+
element_values %w| value , elements |
|
32
|
+
end
|
33
|
+
|
34
|
+
for_symbol 'key' do
|
35
|
+
key_id %w| id |
|
36
|
+
key_string %w| string |
|
37
|
+
end
|
38
|
+
|
39
|
+
for_symbol 'value' do
|
40
|
+
value_id %w| id |
|
41
|
+
value_string %w| string |
|
42
|
+
value_number %w| number |
|
43
|
+
value_object %w| object |
|
44
|
+
value_array %w| array |
|
45
|
+
value_true %w| !t |
|
46
|
+
value_false %w| !f |
|
47
|
+
value_null %w| !n |
|
48
|
+
end
|
49
|
+
|
50
|
+
for_symbol 'id' do
|
51
|
+
id_idstart %w| idstart |
|
52
|
+
id_idstart_idchars %w| idstart idchars |
|
53
|
+
end
|
54
|
+
|
55
|
+
for_symbol 'idchars' do
|
56
|
+
idchars_idchar %w| idchar |
|
57
|
+
idchars_idchars %w| idchar idchars |
|
58
|
+
idchars_int %w| int |
|
59
|
+
end
|
60
|
+
|
61
|
+
for_symbol 'idchar' do
|
62
|
+
# any Unicode character not in '!:(),*@$
|
63
|
+
idchar_char %w| char_token |
|
64
|
+
end
|
65
|
+
|
66
|
+
for_symbol 'idstart' do
|
67
|
+
# any Unicode character not in -, digit, or idchar
|
68
|
+
idstart_char %w| char_token |
|
69
|
+
end
|
70
|
+
|
71
|
+
for_symbol 'string' do
|
72
|
+
empty_string %w| ' ' |
|
73
|
+
non_empty_string %w| ' strchars ' |
|
74
|
+
end
|
75
|
+
|
76
|
+
for_symbol 'strchars' do
|
77
|
+
strchars_char %w| strchar |
|
78
|
+
strchars_chars %w| strchar strchars |
|
79
|
+
end
|
80
|
+
|
81
|
+
for_symbol 'strchar' do
|
82
|
+
# any Unicode character not in ' or !
|
83
|
+
# !!
|
84
|
+
# !'
|
85
|
+
strchar_char %w| char_token |
|
86
|
+
strchar_quoted_exclamation %w| !! |
|
87
|
+
strchar_quoted_single_quote %w| !' |
|
88
|
+
strchar_num %w| number |
|
89
|
+
end
|
90
|
+
|
91
|
+
for_symbol 'number' do
|
92
|
+
number_int %w| int |
|
93
|
+
number_int_frac %w| int frac |
|
94
|
+
number_int_exp %w| int exp |
|
95
|
+
number_int_frac_exp %w| int frac exp |
|
96
|
+
end
|
97
|
+
|
98
|
+
for_symbol 'int' do
|
99
|
+
integer_literal %w| integer_token |
|
100
|
+
end
|
101
|
+
|
102
|
+
for_symbol 'frac' do
|
103
|
+
frac_literal %w| frac_token |
|
104
|
+
end
|
105
|
+
|
106
|
+
for_symbol 'exp' do
|
107
|
+
exponent_literal %w| exponent_token |
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
data/lib/rison/lexer.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'dhaka'
|
2
|
+
|
3
|
+
module Rison
|
4
|
+
class LexerSpec < Dhaka::LexerSpecification
|
5
|
+
|
6
|
+
[ ['!!', nil],
|
7
|
+
["!'", nil],
|
8
|
+
['!t', nil],
|
9
|
+
['!f', nil],
|
10
|
+
['!n', nil],
|
11
|
+
|
12
|
+
['\(', '('],
|
13
|
+
['\)', ')'],
|
14
|
+
['!', '!'],
|
15
|
+
|
16
|
+
[',', nil],
|
17
|
+
[':', nil],
|
18
|
+
["'", nil],
|
19
|
+
|
20
|
+
['e-?\d+', 'exponent_token'],
|
21
|
+
['\.\d+', 'frac_token'],
|
22
|
+
['-?\d+', 'integer_token'],
|
23
|
+
['.', 'char_token']
|
24
|
+
|
25
|
+
].each do |(pattern, token)|
|
26
|
+
for_pattern(pattern) { create_token(token || pattern) }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/lib/rison/parser.rb
ADDED
@@ -0,0 +1,340 @@
|
|
1
|
+
require 'dhaka'
|
2
|
+
require 'rison/grammar'
|
3
|
+
|
4
|
+
module Rison
|
5
|
+
class Parser < Dhaka::CompiledParser
|
6
|
+
|
7
|
+
self.grammar = Rison::Grammar
|
8
|
+
|
9
|
+
start_with 0
|
10
|
+
|
11
|
+
at_state(44) {
|
12
|
+
for_symbols(",", "_End_", ")") { reduce_with "value_false" }
|
13
|
+
}
|
14
|
+
|
15
|
+
at_state(31) {
|
16
|
+
for_symbols("integer_token") { shift_to 6 }
|
17
|
+
for_symbols("!") { shift_to 11 }
|
18
|
+
for_symbols("!t") { shift_to 33 }
|
19
|
+
for_symbols("array") { shift_to 10 }
|
20
|
+
for_symbols("number") { shift_to 45 }
|
21
|
+
for_symbols("'") { shift_to 34 }
|
22
|
+
for_symbols("string") { shift_to 9 }
|
23
|
+
for_symbols("object") { shift_to 46 }
|
24
|
+
for_symbols("id") { shift_to 15 }
|
25
|
+
for_symbols("!f") { shift_to 44 }
|
26
|
+
for_symbols("!n") { shift_to 1 }
|
27
|
+
for_symbols("char_token") { shift_to 16 }
|
28
|
+
for_symbols("idstart") { shift_to 2 }
|
29
|
+
for_symbols("int") { shift_to 18 }
|
30
|
+
for_symbols("value") { shift_to 32 }
|
31
|
+
for_symbols("(") { shift_to 24 }
|
32
|
+
}
|
33
|
+
|
34
|
+
at_state(19) {
|
35
|
+
for_symbols("!!", ",", "integer_token", "!'", "'", "_End_", ")", "char_token") { reduce_with "exponent_literal" }
|
36
|
+
}
|
37
|
+
|
38
|
+
at_state(7) {
|
39
|
+
for_symbols(",", ":", "_End_", ")") { reduce_with "idchars_idchars" }
|
40
|
+
}
|
41
|
+
|
42
|
+
at_state(3) {
|
43
|
+
for_symbols("idchar") { shift_to 3 }
|
44
|
+
for_symbols("integer_token") { shift_to 6 }
|
45
|
+
for_symbols("idchars") { shift_to 7 }
|
46
|
+
for_symbols("int") { shift_to 5 }
|
47
|
+
for_symbols("char_token") { shift_to 4 }
|
48
|
+
for_symbols(",", ":", "_End_", ")") { reduce_with "idchars_idchar" }
|
49
|
+
}
|
50
|
+
|
51
|
+
at_state(50) {
|
52
|
+
for_symbols(",", "_End_", ")") { reduce_with "empty_array" }
|
53
|
+
}
|
54
|
+
|
55
|
+
at_state(49) {
|
56
|
+
for_symbols(",", "_End_", ")") { reduce_with "empty_object" }
|
57
|
+
}
|
58
|
+
|
59
|
+
at_state(48) {
|
60
|
+
for_symbols(",", "_End_", ")") { reduce_with "non_empty_object" }
|
61
|
+
}
|
62
|
+
|
63
|
+
at_state(45) {
|
64
|
+
for_symbols(",", "_End_", ")") { reduce_with "value_number" }
|
65
|
+
}
|
66
|
+
|
67
|
+
at_state(40) {
|
68
|
+
for_symbols("!!", "integer_token", "!'", "'", "char_token") { reduce_with "strchar_num" }
|
69
|
+
}
|
70
|
+
|
71
|
+
at_state(27) {
|
72
|
+
for_symbols("id") { shift_to 29 }
|
73
|
+
for_symbols("key") { shift_to 30 }
|
74
|
+
for_symbols("'") { shift_to 34 }
|
75
|
+
for_symbols("members") { shift_to 28 }
|
76
|
+
for_symbols("char_token") { shift_to 16 }
|
77
|
+
for_symbols("pair") { shift_to 26 }
|
78
|
+
for_symbols("idstart") { shift_to 2 }
|
79
|
+
for_symbols("string") { shift_to 25 }
|
80
|
+
}
|
81
|
+
|
82
|
+
at_state(24) {
|
83
|
+
for_symbols(")") { shift_to 49 }
|
84
|
+
for_symbols("id") { shift_to 29 }
|
85
|
+
for_symbols("members") { shift_to 47 }
|
86
|
+
for_symbols("key") { shift_to 30 }
|
87
|
+
for_symbols("'") { shift_to 34 }
|
88
|
+
for_symbols("char_token") { shift_to 16 }
|
89
|
+
for_symbols("pair") { shift_to 26 }
|
90
|
+
for_symbols("idstart") { shift_to 2 }
|
91
|
+
for_symbols("string") { shift_to 25 }
|
92
|
+
}
|
93
|
+
|
94
|
+
at_state(18) {
|
95
|
+
for_symbols("exponent_token") { shift_to 19 }
|
96
|
+
for_symbols("exp") { shift_to 23 }
|
97
|
+
for_symbols("frac") { shift_to 21 }
|
98
|
+
for_symbols("!!", ",", "integer_token", "!'", "'", "_End_", "char_token", ")") { reduce_with "number_int" }
|
99
|
+
for_symbols("frac_token") { shift_to 20 }
|
100
|
+
}
|
101
|
+
|
102
|
+
at_state(8) {
|
103
|
+
for_symbols(",", ":", "_End_", ")") { reduce_with "id_idstart_idchars" }
|
104
|
+
}
|
105
|
+
|
106
|
+
at_state(4) {
|
107
|
+
for_symbols(",", "integer_token", ":", "_End_", "char_token", ")") { reduce_with "idchar_char" }
|
108
|
+
}
|
109
|
+
|
110
|
+
at_state(32) {
|
111
|
+
for_symbols(",", ")") { reduce_with "pair_key_value" }
|
112
|
+
}
|
113
|
+
|
114
|
+
at_state(14) {
|
115
|
+
for_symbols("value") { shift_to 13 }
|
116
|
+
for_symbols("integer_token") { shift_to 6 }
|
117
|
+
for_symbols("!") { shift_to 11 }
|
118
|
+
for_symbols("!t") { shift_to 33 }
|
119
|
+
for_symbols("array") { shift_to 10 }
|
120
|
+
for_symbols("number") { shift_to 45 }
|
121
|
+
for_symbols("'") { shift_to 34 }
|
122
|
+
for_symbols("string") { shift_to 9 }
|
123
|
+
for_symbols("object") { shift_to 46 }
|
124
|
+
for_symbols("id") { shift_to 15 }
|
125
|
+
for_symbols("!f") { shift_to 44 }
|
126
|
+
for_symbols("!n") { shift_to 1 }
|
127
|
+
for_symbols("char_token") { shift_to 16 }
|
128
|
+
for_symbols("idstart") { shift_to 2 }
|
129
|
+
for_symbols("int") { shift_to 18 }
|
130
|
+
for_symbols("elements") { shift_to 17 }
|
131
|
+
for_symbols("(") { shift_to 24 }
|
132
|
+
}
|
133
|
+
|
134
|
+
at_state(2) {
|
135
|
+
for_symbols("idchar") { shift_to 3 }
|
136
|
+
for_symbols("integer_token") { shift_to 6 }
|
137
|
+
for_symbols("int") { shift_to 5 }
|
138
|
+
for_symbols(",", ":", "_End_", ")") { reduce_with "id_idstart" }
|
139
|
+
for_symbols("char_token") { shift_to 4 }
|
140
|
+
for_symbols("idchars") { shift_to 8 }
|
141
|
+
}
|
142
|
+
|
143
|
+
at_state(47) {
|
144
|
+
for_symbols(")") { shift_to 48 }
|
145
|
+
}
|
146
|
+
|
147
|
+
at_state(35) {
|
148
|
+
for_symbols("!!", "integer_token", "!'", "'", "char_token") { reduce_with "strchar_quoted_single_quote" }
|
149
|
+
}
|
150
|
+
|
151
|
+
at_state(29) {
|
152
|
+
for_symbols(":") { reduce_with "key_id" }
|
153
|
+
}
|
154
|
+
|
155
|
+
at_state(21) {
|
156
|
+
for_symbols("exp") { shift_to 22 }
|
157
|
+
for_symbols("exponent_token") { shift_to 19 }
|
158
|
+
for_symbols("!!", ",", "integer_token", "!'", "'", "_End_", "char_token", ")") { reduce_with "number_int_frac" }
|
159
|
+
}
|
160
|
+
|
161
|
+
at_state(16) {
|
162
|
+
for_symbols(",", "integer_token", ":", "_End_", "char_token", ")") { reduce_with "idstart_char" }
|
163
|
+
}
|
164
|
+
|
165
|
+
at_state(10) {
|
166
|
+
for_symbols(",", "_End_", ")") { reduce_with "value_array" }
|
167
|
+
}
|
168
|
+
|
169
|
+
at_state(9) {
|
170
|
+
for_symbols(",", "_End_", ")") { reduce_with "value_string" }
|
171
|
+
}
|
172
|
+
|
173
|
+
at_state(17) {
|
174
|
+
for_symbols(")") { reduce_with "element_values" }
|
175
|
+
}
|
176
|
+
|
177
|
+
at_state(0) {
|
178
|
+
for_symbols("integer_token") { shift_to 6 }
|
179
|
+
for_symbols("!") { shift_to 11 }
|
180
|
+
for_symbols("!t") { shift_to 33 }
|
181
|
+
for_symbols("array") { shift_to 10 }
|
182
|
+
for_symbols("number") { shift_to 45 }
|
183
|
+
for_symbols("'") { shift_to 34 }
|
184
|
+
for_symbols("string") { shift_to 9 }
|
185
|
+
for_symbols("object") { shift_to 46 }
|
186
|
+
for_symbols("id") { shift_to 15 }
|
187
|
+
for_symbols("!f") { shift_to 44 }
|
188
|
+
for_symbols("!n") { shift_to 1 }
|
189
|
+
for_symbols("char_token") { shift_to 16 }
|
190
|
+
for_symbols("idstart") { shift_to 2 }
|
191
|
+
for_symbols("int") { shift_to 18 }
|
192
|
+
for_symbols("(") { shift_to 24 }
|
193
|
+
for_symbols("value") { shift_to 53 }
|
194
|
+
}
|
195
|
+
|
196
|
+
at_state(38) {
|
197
|
+
for_symbols("'") { reduce_with "strchars_chars" }
|
198
|
+
}
|
199
|
+
|
200
|
+
at_state(34) {
|
201
|
+
for_symbols("integer_token") { shift_to 6 }
|
202
|
+
for_symbols("char_token") { shift_to 39 }
|
203
|
+
for_symbols("strchar") { shift_to 36 }
|
204
|
+
for_symbols("number") { shift_to 40 }
|
205
|
+
for_symbols("!'") { shift_to 35 }
|
206
|
+
for_symbols("'") { shift_to 43 }
|
207
|
+
for_symbols("int") { shift_to 18 }
|
208
|
+
for_symbols("!!") { shift_to 37 }
|
209
|
+
for_symbols("strchars") { shift_to 41 }
|
210
|
+
}
|
211
|
+
|
212
|
+
at_state(26) {
|
213
|
+
for_symbols(")") { reduce_with "member_pair" }
|
214
|
+
for_symbols(",") { shift_to 27 }
|
215
|
+
}
|
216
|
+
|
217
|
+
at_state(5) {
|
218
|
+
for_symbols(",", ":", "_End_", ")") { reduce_with "idchars_int" }
|
219
|
+
}
|
220
|
+
|
221
|
+
at_state(53) {
|
222
|
+
for_symbols("_End_") { reduce_with "start" }
|
223
|
+
}
|
224
|
+
|
225
|
+
at_state(52) {
|
226
|
+
for_symbols(",", "_End_", ")") { reduce_with "non_empty_array" }
|
227
|
+
}
|
228
|
+
|
229
|
+
at_state(46) {
|
230
|
+
for_symbols(",", "_End_", ")") { reduce_with "value_object" }
|
231
|
+
}
|
232
|
+
|
233
|
+
at_state(41) {
|
234
|
+
for_symbols("'") { shift_to 42 }
|
235
|
+
}
|
236
|
+
|
237
|
+
at_state(37) {
|
238
|
+
for_symbols("!!", "integer_token", "!'", "'", "char_token") { reduce_with "strchar_quoted_exclamation" }
|
239
|
+
}
|
240
|
+
|
241
|
+
at_state(25) {
|
242
|
+
for_symbols(":") { reduce_with "key_string" }
|
243
|
+
}
|
244
|
+
|
245
|
+
at_state(22) {
|
246
|
+
for_symbols("!!", ",", "integer_token", "!'", "'", "_End_", "char_token", ")") { reduce_with "number_int_frac_exp" }
|
247
|
+
}
|
248
|
+
|
249
|
+
at_state(13) {
|
250
|
+
for_symbols(")") { reduce_with "element_value" }
|
251
|
+
for_symbols(",") { shift_to 14 }
|
252
|
+
}
|
253
|
+
|
254
|
+
at_state(51) {
|
255
|
+
for_symbols(")") { shift_to 52 }
|
256
|
+
}
|
257
|
+
|
258
|
+
at_state(43) {
|
259
|
+
for_symbols(",", ":", "_End_", ")") { reduce_with "empty_string" }
|
260
|
+
}
|
261
|
+
|
262
|
+
at_state(42) {
|
263
|
+
for_symbols(",", ":", "_End_", ")") { reduce_with "non_empty_string" }
|
264
|
+
}
|
265
|
+
|
266
|
+
at_state(39) {
|
267
|
+
for_symbols("!!", "integer_token", "!'", "'", "char_token") { reduce_with "strchar_char" }
|
268
|
+
}
|
269
|
+
|
270
|
+
at_state(33) {
|
271
|
+
for_symbols(",", "_End_", ")") { reduce_with "value_true" }
|
272
|
+
}
|
273
|
+
|
274
|
+
at_state(36) {
|
275
|
+
for_symbols("integer_token") { shift_to 6 }
|
276
|
+
for_symbols("char_token") { shift_to 39 }
|
277
|
+
for_symbols("'") { reduce_with "strchars_char" }
|
278
|
+
for_symbols("strchar") { shift_to 36 }
|
279
|
+
for_symbols("number") { shift_to 40 }
|
280
|
+
for_symbols("!'") { shift_to 35 }
|
281
|
+
for_symbols("int") { shift_to 18 }
|
282
|
+
for_symbols("!!") { shift_to 37 }
|
283
|
+
for_symbols("strchars") { shift_to 38 }
|
284
|
+
}
|
285
|
+
|
286
|
+
at_state(30) {
|
287
|
+
for_symbols(":") { shift_to 31 }
|
288
|
+
}
|
289
|
+
|
290
|
+
at_state(12) {
|
291
|
+
for_symbols("value") { shift_to 13 }
|
292
|
+
for_symbols("elements") { shift_to 51 }
|
293
|
+
for_symbols("integer_token") { shift_to 6 }
|
294
|
+
for_symbols("!") { shift_to 11 }
|
295
|
+
for_symbols("!t") { shift_to 33 }
|
296
|
+
for_symbols("array") { shift_to 10 }
|
297
|
+
for_symbols("number") { shift_to 45 }
|
298
|
+
for_symbols("'") { shift_to 34 }
|
299
|
+
for_symbols("string") { shift_to 9 }
|
300
|
+
for_symbols("object") { shift_to 46 }
|
301
|
+
for_symbols("id") { shift_to 15 }
|
302
|
+
for_symbols("!f") { shift_to 44 }
|
303
|
+
for_symbols("!n") { shift_to 1 }
|
304
|
+
for_symbols("char_token") { shift_to 16 }
|
305
|
+
for_symbols("idstart") { shift_to 2 }
|
306
|
+
for_symbols("int") { shift_to 18 }
|
307
|
+
for_symbols(")") { shift_to 50 }
|
308
|
+
for_symbols("(") { shift_to 24 }
|
309
|
+
}
|
310
|
+
|
311
|
+
at_state(11) {
|
312
|
+
for_symbols("(") { shift_to 12 }
|
313
|
+
}
|
314
|
+
|
315
|
+
at_state(6) {
|
316
|
+
for_symbols("!!", "frac_token", ",", "integer_token", ":", "!'", "'", "_End_", "char_token", ")", "exponent_token") { reduce_with "integer_literal" }
|
317
|
+
}
|
318
|
+
|
319
|
+
at_state(1) {
|
320
|
+
for_symbols(",", "_End_", ")") { reduce_with "value_null" }
|
321
|
+
}
|
322
|
+
|
323
|
+
at_state(28) {
|
324
|
+
for_symbols(")") { reduce_with "member_pairs" }
|
325
|
+
}
|
326
|
+
|
327
|
+
at_state(23) {
|
328
|
+
for_symbols("!!", ",", "integer_token", "!'", "'", "_End_", ")", "char_token") { reduce_with "number_int_exp" }
|
329
|
+
}
|
330
|
+
|
331
|
+
at_state(20) {
|
332
|
+
for_symbols("!!", ",", "integer_token", "!'", "'", "_End_", "char_token", ")", "exponent_token") { reduce_with "frac_literal" }
|
333
|
+
}
|
334
|
+
|
335
|
+
at_state(15) {
|
336
|
+
for_symbols(",", "_End_", ")") { reduce_with "value_id" }
|
337
|
+
}
|
338
|
+
|
339
|
+
end
|
340
|
+
end
|
data/lib/rison.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'dhaka'
|
2
|
+
require 'rison/lexer'
|
3
|
+
require 'rison/parser'
|
4
|
+
require 'rison/evaluator'
|
5
|
+
|
6
|
+
module Rison
|
7
|
+
|
8
|
+
def self.load(data)
|
9
|
+
evaluate(parse(lex(data)))
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
LEXER = Dhaka::Lexer.new(LexerSpec)
|
14
|
+
|
15
|
+
EVALUATOR = Evaluator.new
|
16
|
+
|
17
|
+
def self.lex(data)
|
18
|
+
LEXER.lex(data.to_s)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.parse(lexed)
|
22
|
+
Parser.parse(lexed)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.evaluate(parsed)
|
26
|
+
EVALUATOR.evaluate(parsed)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/test/test_rison.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rison'
|
3
|
+
|
4
|
+
class RisonTests < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def rison(string)
|
7
|
+
parsed = Rison.parse(Rison.lex(string))
|
8
|
+
|
9
|
+
if parsed.has_error?
|
10
|
+
p parsed
|
11
|
+
end
|
12
|
+
|
13
|
+
Rison.evaluate(parsed)
|
14
|
+
end
|
15
|
+
|
16
|
+
# cf. http://mjtemplate.org/examples/rison.html
|
17
|
+
|
18
|
+
def test_true
|
19
|
+
assert_equal true, rison('!t')
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_false
|
23
|
+
assert_equal false, rison('!f')
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_null
|
27
|
+
assert_equal nil, rison('!n')
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_empty_string
|
31
|
+
assert_equal '', rison(%{''})
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_zero
|
35
|
+
assert_equal 0, rison('0')
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_positive_integer
|
39
|
+
assert_equal 1, rison('1')
|
40
|
+
assert_equal 12, rison('12')
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_negative_integer
|
44
|
+
assert_equal -3, rison('-3')
|
45
|
+
assert_equal -33, rison('-33')
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_rational
|
49
|
+
assert_equal Rational(3, 2), rison('1.5')
|
50
|
+
assert_equal Rational(9999, 100), rison('99.99')
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_positive_exponent
|
54
|
+
assert_equal 10**30, rison('1e30')
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_negative_exponent
|
58
|
+
assert_equal 10**-30, rison('1e-30')
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_fraction_and_exponent
|
62
|
+
assert_equal 150, rison('1.5e2')
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_single_character
|
66
|
+
assert_equal 'a', rison('a')
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_string_with_leading_digit
|
70
|
+
assert_equal '0a', rison("'0a'")
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_unquoted_string
|
74
|
+
assert_equal 'abc def', rison('abc def')
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_empty_object
|
78
|
+
assert_equal Hash.new, rison('()')
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_non_empty_objects
|
82
|
+
expected = {'a' => 0}
|
83
|
+
assert_equal expected, rison('(a:0)')
|
84
|
+
|
85
|
+
expected = {'id' => nil, 'type' => '/common/document'}
|
86
|
+
assert_equal expected, rison('(id:!n,type:/common/document)')
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_empty_array
|
90
|
+
assert_equal [], rison('!()')
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_array
|
94
|
+
assert_equal [ true, false, nil, '' ], rison(%{!(!t,!f,!n,'')})
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_unquoted_string_with_leading_minus
|
98
|
+
assert_equal '-h', rison('-h')
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_unquoted_string_with_minus
|
102
|
+
assert_equal 'a-z', rison('a-z')
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_domain_name
|
106
|
+
assert_equal 'domain.com', rison('domain.com')
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_email
|
110
|
+
assert_equal 'user@domain.com', rison('user@domain.com')
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_money
|
114
|
+
assert_equal 'US $10', rison('US $10')
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_quoting
|
118
|
+
assert_equal "can't", rison("'can!'t'")
|
119
|
+
assert_equal 'wow!', rison("'wow!!'")
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.4.7
|
3
|
+
specification_version: 2
|
4
|
+
name: rison
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2007-11-18 00:00:00 +00:00
|
8
|
+
summary: Pure Ruby parser for Rison (http://mjtemplate.org/examples/rison.html)
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: twoggle@gmail.com
|
12
|
+
homepage: http://rison.rubyforge.org/
|
13
|
+
rubyforge_project:
|
14
|
+
description: Pure Ruby parser for Rison (http://mjtemplate.org/examples/rison.html)
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: "0"
|
30
|
+
version:
|
31
|
+
platform: ruby
|
32
|
+
signing_key:
|
33
|
+
cert_chain: []
|
34
|
+
|
35
|
+
post_install_message:
|
36
|
+
authors:
|
37
|
+
- Tim Fletcher
|
38
|
+
files:
|
39
|
+
- lib/rison
|
40
|
+
- lib/rison/evaluator.rb
|
41
|
+
- lib/rison/grammar.rb
|
42
|
+
- lib/rison/lexer.rb
|
43
|
+
- lib/rison/parser.rb
|
44
|
+
- lib/rison.rb
|
45
|
+
- test/test_rison.rb
|
46
|
+
- COPYING.txt
|
47
|
+
- Rakefile.rb
|
48
|
+
- README.html
|
49
|
+
test_files: []
|
50
|
+
|
51
|
+
rdoc_options: []
|
52
|
+
|
53
|
+
extra_rdoc_files: []
|
54
|
+
|
55
|
+
executables: []
|
56
|
+
|
57
|
+
extensions: []
|
58
|
+
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
dependencies:
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: dhaka
|
64
|
+
version_requirement:
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0"
|
70
|
+
version:
|