rison 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|