sgfparser 0.0.1

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/CHANGES ADDED
@@ -0,0 +1,4 @@
1
+ == Version 0.0.1 (sgf_parser) - 15-Dec-2007
2
+
3
+ * Initial revision
4
+
data/README ADDED
@@ -0,0 +1,5 @@
1
+ = SGF Tools - Ruby library to parse SGF files
2
+
3
+ For more information about the SGF format, see http://www.red-bean.com/sgf/
4
+
5
+
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ # Available options:
2
+ #
3
+ # rake test - Runs all test cases.
4
+ # rake package - Runs test cases and builds packages for distribution.
5
+ # rake rdoc - Builds API documentation in doc dir.
6
+
7
+ require 'rake'
8
+ require 'rspec/core/rake_task'
9
+ require 'rake/gempackagetask'
10
+
11
+ task :default => :spec
12
+
13
+ RSpec::Core::RakeTask.new do |rspec|
14
+ #rspec.ruby_opts="-w"
15
+ end
16
+
17
+ load(File.join(File.dirname(__FILE__), "sgftools.gemspec"))
18
+ Rake::GemPackageTask.new(SPEC) do |package|
19
+ # do nothing: I just need a gem but this block is required
20
+ end
21
+
22
+ file "lib/sgf_tools/parser.rb" => "lib/sgf_tools/parser.y" do
23
+ sh "racc -o lib/sgf_tools/parser.rb lib/sgf_tools/parser.y"
24
+ end
25
+
26
+ file "lib/sgf_tools/tokenizer.rb" => "lib/sgf_tools/tokenizer.rex" do
27
+ sh "rex -o lib/sgf_tools/tokenizer.rb lib/sgf_tools/tokenizer.rex"
28
+ end
29
+
30
+ task :build => ["lib/sgf_tools/parser.rb", "lib/sgf_tools/tokenizer.rb"]
31
+
@@ -0,0 +1,261 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.6
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require 'sgf_tools/tokenizer'
10
+
11
+ module SgfTools
12
+ class Node
13
+ attr_accessor :properties
14
+ attr_accessor :branches
15
+
16
+ def initialize(prop, branches)
17
+ @properties = prop
18
+ @branches = branches
19
+ end
20
+
21
+ def inspect
22
+ str = ""
23
+ str << @properties.inspect
24
+ if !@branches.nil? && @branches.size > 0
25
+ str << " (#{@branches.size} variation(s))"
26
+ end
27
+ str
28
+ end
29
+
30
+ def [](key)
31
+ @properties[key]
32
+ end
33
+ end
34
+
35
+ class Parser < Racc::Parser
36
+
37
+ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 58)
38
+
39
+ def parse_file(filename)
40
+ @tokenizer = SgfTokenizer.new
41
+ @tokenizer.load_file(filename)
42
+ do_parse
43
+ end
44
+
45
+ def parse_string(str)
46
+ @tokenizer = SgfTokenizer.new
47
+ @tokenizer.scan_evaluate(str)
48
+ do_parse
49
+ end
50
+
51
+ def next_token
52
+ @tokenizer.next_token
53
+ end
54
+
55
+ ...end parser.y/module_eval...
56
+ ##### State transition tables begin ###
57
+
58
+ racc_action_table = [
59
+ 4, 15, 3, 3, 11, 8, 3, 16, 8, 9,
60
+ 3, 15, 19, 20 ]
61
+
62
+ racc_action_check = [
63
+ 1, 8, 1, 6, 6, 6, 10, 10, 3, 4,
64
+ 0, 13, 15, 18 ]
65
+
66
+ racc_action_pointer = [
67
+ 8, 0, nil, 4, 9, nil, 1, nil, -4, nil,
68
+ 4, nil, nil, 6, nil, 6, nil, nil, 7, nil,
69
+ nil ]
70
+
71
+ racc_action_default = [
72
+ -14, -14, -1, -14, -14, -2, -14, -5, -7, 21,
73
+ -14, -3, -6, -8, -9, -14, -4, -10, -11, -12,
74
+ -13 ]
75
+
76
+ racc_goto_table = [
77
+ 5, 1, 7, 14, 13, 12, 6, 10, 17, 5,
78
+ 18 ]
79
+
80
+ racc_goto_check = [
81
+ 2, 1, 4, 6, 5, 4, 3, 1, 6, 2,
82
+ 7 ]
83
+
84
+ racc_goto_pointer = [
85
+ nil, 1, -1, 3, -1, -4, -5, -5 ]
86
+
87
+ racc_goto_default = [
88
+ nil, nil, 2, nil, nil, nil, nil, nil ]
89
+
90
+ racc_reduce_table = [
91
+ 0, 0, :racc_error,
92
+ 1, 8, :_reduce_1,
93
+ 2, 8, :_reduce_2,
94
+ 3, 9, :_reduce_3,
95
+ 4, 9, :_reduce_4,
96
+ 1, 10, :_reduce_5,
97
+ 2, 10, :_reduce_6,
98
+ 1, 11, :_reduce_7,
99
+ 2, 11, :_reduce_8,
100
+ 1, 12, :_reduce_9,
101
+ 2, 12, :_reduce_10,
102
+ 2, 13, :_reduce_11,
103
+ 1, 14, :_reduce_12,
104
+ 2, 14, :_reduce_13 ]
105
+
106
+ racc_reduce_n = 14
107
+
108
+ racc_shift_n = 21
109
+
110
+ racc_token_table = {
111
+ false => 0,
112
+ :error => 1,
113
+ "(" => 2,
114
+ ")" => 3,
115
+ ";" => 4,
116
+ :prop_ident => 5,
117
+ :prop_value => 6 }
118
+
119
+ racc_nt_base = 7
120
+
121
+ racc_use_result_var = true
122
+
123
+ Racc_arg = [
124
+ racc_action_table,
125
+ racc_action_check,
126
+ racc_action_default,
127
+ racc_action_pointer,
128
+ racc_goto_table,
129
+ racc_goto_check,
130
+ racc_goto_default,
131
+ racc_goto_pointer,
132
+ racc_nt_base,
133
+ racc_reduce_table,
134
+ racc_token_table,
135
+ racc_shift_n,
136
+ racc_reduce_n,
137
+ racc_use_result_var ]
138
+
139
+ Racc_token_to_s_table = [
140
+ "$end",
141
+ "error",
142
+ "\"(\"",
143
+ "\")\"",
144
+ "\";\"",
145
+ "prop_ident",
146
+ "prop_value",
147
+ "$start",
148
+ "collection",
149
+ "game_tree",
150
+ "sequence",
151
+ "node",
152
+ "properties",
153
+ "property",
154
+ "prop_list" ]
155
+
156
+ Racc_debug_parser = false
157
+
158
+ ##### State transition tables end #####
159
+
160
+ # reduce 0 omitted
161
+
162
+ module_eval(<<'.,.,', 'parser.y', 3)
163
+ def _reduce_1(val, _values, result)
164
+ result = val
165
+ result
166
+ end
167
+ .,.,
168
+
169
+ module_eval(<<'.,.,', 'parser.y', 4)
170
+ def _reduce_2(val, _values, result)
171
+ result.push val[1]
172
+ result
173
+ end
174
+ .,.,
175
+
176
+ module_eval(<<'.,.,', 'parser.y', 6)
177
+ def _reduce_3(val, _values, result)
178
+ result = val[1]
179
+ result
180
+ end
181
+ .,.,
182
+
183
+ module_eval(<<'.,.,', 'parser.y', 9)
184
+ def _reduce_4(val, _values, result)
185
+ val[2][0].first.branches = val[2][1..-1]
186
+ result = val[1] + val[2][0]
187
+
188
+ result
189
+ end
190
+ .,.,
191
+
192
+ module_eval(<<'.,.,', 'parser.y', 13)
193
+ def _reduce_5(val, _values, result)
194
+ result = val
195
+ result
196
+ end
197
+ .,.,
198
+
199
+ module_eval(<<'.,.,', 'parser.y', 14)
200
+ def _reduce_6(val, _values, result)
201
+ result.push val[1]
202
+ result
203
+ end
204
+ .,.,
205
+
206
+ module_eval(<<'.,.,', 'parser.y', 16)
207
+ def _reduce_7(val, _values, result)
208
+ result = {}
209
+ result
210
+ end
211
+ .,.,
212
+
213
+ module_eval(<<'.,.,', 'parser.y', 17)
214
+ def _reduce_8(val, _values, result)
215
+ result = Node.new(val[1], nil)
216
+ result
217
+ end
218
+ .,.,
219
+
220
+ module_eval(<<'.,.,', 'parser.y', 19)
221
+ def _reduce_9(val, _values, result)
222
+ result = val[0]
223
+ result
224
+ end
225
+ .,.,
226
+
227
+ module_eval(<<'.,.,', 'parser.y', 20)
228
+ def _reduce_10(val, _values, result)
229
+ result.merge!(val[1])
230
+ result
231
+ end
232
+ .,.,
233
+
234
+ module_eval(<<'.,.,', 'parser.y', 22)
235
+ def _reduce_11(val, _values, result)
236
+ result = {val[0] => val[1]}
237
+ result
238
+ end
239
+ .,.,
240
+
241
+ module_eval(<<'.,.,', 'parser.y', 24)
242
+ def _reduce_12(val, _values, result)
243
+ result = val
244
+ result
245
+ end
246
+ .,.,
247
+
248
+ module_eval(<<'.,.,', 'parser.y', 25)
249
+ def _reduce_13(val, _values, result)
250
+ result.push val[1]
251
+ result
252
+ end
253
+ .,.,
254
+
255
+ def _reduce_none(val, _values, result)
256
+ val[0]
257
+ end
258
+
259
+ end # class Parser
260
+
261
+ end
@@ -0,0 +1,76 @@
1
+
2
+ class Parser
3
+ rule
4
+ collection: game_tree { result = val }
5
+ | collection game_tree { result.push val[1] }
6
+
7
+ game_tree: '(' sequence ')' { result = val[1] }
8
+ | '(' sequence collection ')'
9
+ {
10
+ val[2][0].first.branches = val[2][1..-1]
11
+ result = val[1] + val[2][0]
12
+ }
13
+
14
+ sequence: node { result = val }
15
+ | sequence node { result.push val[1] }
16
+
17
+ node: ';' { result = {} }
18
+ | ';' properties { result = Node.new(val[1], nil) }
19
+
20
+ properties: property { result = val[0] }
21
+ | properties property { result.merge!(val[1]) }
22
+
23
+ property: prop_ident prop_list { result = {val[0] => val[1]} }
24
+
25
+ prop_list: prop_value { result = val }
26
+ | prop_list prop_value { result.push val[1] }
27
+
28
+ end
29
+
30
+ ---- header
31
+ require 'sgf_tools/tokenizer'
32
+
33
+ module SgfTools
34
+ class Node
35
+ attr_accessor :properties
36
+ attr_accessor :branches
37
+
38
+ def initialize(prop, branches)
39
+ @properties = prop
40
+ @branches = branches
41
+ end
42
+
43
+ def inspect
44
+ str = ""
45
+ str << @properties.inspect
46
+ if !@branches.nil? && @branches.size > 0
47
+ str << " (#{@branches.size} variation(s))"
48
+ end
49
+ str
50
+ end
51
+
52
+ def [](key)
53
+ @properties[key]
54
+ end
55
+ end
56
+
57
+ ---- inner
58
+
59
+ def parse_file(filename)
60
+ @tokenizer = SgfTokenizer.new
61
+ @tokenizer.load_file(filename)
62
+ do_parse
63
+ end
64
+
65
+ def parse_string(str)
66
+ @tokenizer = SgfTokenizer.new
67
+ @tokenizer.scan_evaluate(str)
68
+ do_parse
69
+ end
70
+
71
+ def next_token
72
+ @tokenizer.next_token
73
+ end
74
+
75
+ ---- footer
76
+ end
@@ -0,0 +1,87 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by rex 1.0.0
4
+ # from lexical definition file "lib/sgf_parser/tokenizer.rex".
5
+ #
6
+
7
+ require 'racc/parser'
8
+ #
9
+ # sgf.rex
10
+ # lexical definition for sgf
11
+ #
12
+ # usage
13
+ # rex sgf.rex
14
+ #
15
+
16
+ class SgfTokenizer < Racc::Parser
17
+ require 'strscan'
18
+
19
+ class ScanError < StandardError ; end
20
+
21
+ attr_reader :lineno
22
+ attr_reader :filename
23
+
24
+ def scan_setup ; end
25
+
26
+ def action &block
27
+ yield
28
+ end
29
+
30
+ def scan_str( str )
31
+ scan_evaluate str
32
+ do_parse
33
+ end
34
+
35
+ def load_file( filename )
36
+ @filename = filename
37
+ open(filename, "r") do |f|
38
+ scan_evaluate f.read
39
+ end
40
+ end
41
+
42
+ def scan_file( filename )
43
+ load_file filename
44
+ do_parse
45
+ end
46
+
47
+ def next_token
48
+ @rex_tokens.shift
49
+ end
50
+
51
+ def scan_evaluate( str )
52
+ scan_setup
53
+ @rex_tokens = []
54
+ @lineno = 1
55
+ ss = StringScanner.new(str)
56
+ state = nil
57
+ until ss.eos?
58
+ text = ss.peek(1)
59
+ @lineno += 1 if text == "\n"
60
+ case state
61
+ when nil
62
+ case
63
+ when (text = ss.scan(/[A-Z]+/))
64
+ @rex_tokens.push action { [:prop_ident, text] }
65
+
66
+ when (text = ss.scan(/\[[^\]]*\]/))
67
+ @rex_tokens.push action { [:prop_value, text[1..-2]] }
68
+
69
+ when (text = ss.scan(/\s+/))
70
+ ;
71
+
72
+ when (text = ss.scan(/./))
73
+ @rex_tokens.push action { [text, text] }
74
+
75
+ else
76
+ text = ss.string[ss.pos .. -1]
77
+ raise ScanError, "can not match: '" + text + "'"
78
+ end # if
79
+
80
+ else
81
+ raise ScanError, "undefined state: '" + state.to_s + "'"
82
+ end # case state
83
+ end # until ss
84
+ end # def scan_evaluate
85
+
86
+ end # class
87
+
@@ -0,0 +1,31 @@
1
+ #
2
+ # sgf.rex
3
+ # lexical definition for sgf
4
+ #
5
+ # usage
6
+ # rex sgf.rex
7
+ #
8
+
9
+ class SgfTokenizer
10
+
11
+ macro
12
+ BLANK \s+
13
+
14
+ rule
15
+
16
+ # [:state] pattern [actions]
17
+
18
+ # PropIdent
19
+ [A-Z]+ { [:prop_ident, text] }
20
+
21
+ # PropValue
22
+ \[[^\]]*\] { [:prop_value, text[1..-2]] }
23
+
24
+ # skip
25
+ {BLANK} # no action
26
+
27
+ # identifier
28
+ . { [text, text] }
29
+
30
+ end
31
+
data/lib/sgf_tools.rb ADDED
@@ -0,0 +1,6 @@
1
+ module SgfTools
2
+ VERSION = "0.0.1"
3
+ end
4
+
5
+ require 'sgf_tools/parser'
6
+
data/lib/sgftools.rb ADDED
@@ -0,0 +1,2 @@
1
+
2
+ require 'sgf_tools'
data/sgftools.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ DIR = File.dirname(__FILE__)
2
+ LIB = File.join(DIR, *%w[lib sgf_tools.rb])
3
+ VERSION = open(LIB) { |lib|
4
+ lib.each { |line|
5
+ if v = line[/^\s*VERSION\s*=\s*(['"])(\d\.\d\.\d)\1/, 2]
6
+ break v
7
+ end
8
+ }
9
+ }
10
+
11
+ SPEC = Gem::Specification.new do |s|
12
+ s.name = "sgfparser"
13
+ s.version = VERSION
14
+ s.platform = Gem::Platform::RUBY
15
+ s.authors = ["Pete Schwamb"]
16
+ s.email = ["pete@schwamb.net"]
17
+ s.homepage = "http://github.com/ps2/sgfparser"
18
+ s.summary = "A ruby library for working with SGF files"
19
+ s.description = <<-END_DESCRIPTION.gsub(/\s+/, " ").strip
20
+ This library reads sgf files, described at http://www.red-bean.com/sgf/
21
+ END_DESCRIPTION
22
+
23
+ s.required_rubygems_version = "~> 1.9.2"
24
+ s.required_rubygems_version = "~> 1.3.6"
25
+
26
+ s.add_development_dependency "rspec"
27
+
28
+ s.files = `git ls-files`.split("\n")
29
+ s.test_files = `git ls-files -- spec/*_spec.rb`.split("\n")
30
+ s.require_paths = %w[lib]
31
+ end
@@ -0,0 +1,21 @@
1
+ require 'sgftools'
2
+
3
+ describe SgfTools::Parser do
4
+
5
+ it "should parse sgf with single game with branches" do
6
+ @simple_sgf = <<-END_OF_SGF
7
+ (;FF[4]C[root](;C[a];C[b](;C[c])
8
+ (;C[d];C[e]))
9
+ (;C[f](;C[g];C[h];C[i])
10
+ (;C[j])))
11
+ END_OF_SGF
12
+ p = SgfTools::Parser.new
13
+ game = p.parse_string(@simple_sgf).first
14
+ game.size.should == 4
15
+ game[0].branches.should == nil
16
+ game[1].branches.size.should == 1
17
+ game[2].branches.should == nil
18
+ game[1].branches[0].size.should == 4
19
+ game[1].branches[0][1].branches.size.should == 1
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+
2
+ require 'test/unit'
3
+ require 'rubygems'
4
+ require 'sgf_parser'
5
+
6
+ class SgfParserTest < Test::Unit::TestCase
7
+
8
+ def test_parse_simple
9
+ p = SgfParser.new
10
+ simple_sgf = <<END_OF_SGF
11
+ (;FF[4]C[root](;C[a];C[b](;C[c])
12
+ (;C[d];C[e]))
13
+ (;C[f](;C[g];C[h];C[i])
14
+ (;C[j])))
15
+ END_OF_SGF
16
+ game = p.parse_string(simple_sgf).first
17
+ assert_equal(4, game.size)
18
+ assert_equal(nil, game[0].branches)
19
+ assert_equal(1, game[1].branches.size)
20
+ assert_equal(nil, game[2].branches)
21
+ assert_equal(4, game[1].branches[0].size)
22
+ assert_equal(1, game[1].branches[0][1].branches.size)
23
+ end
24
+
25
+ end
26
+
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sgfparser
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Pete Schwamb
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-22 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ description: This library reads sgf files, described at http://www.red-bean.com/sgf/
34
+ email:
35
+ - pete@schwamb.net
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - CHANGES
44
+ - README
45
+ - Rakefile
46
+ - lib/sgf_tools.rb
47
+ - lib/sgf_tools/parser.rb
48
+ - lib/sgf_tools/parser.y
49
+ - lib/sgf_tools/tokenizer.rb
50
+ - lib/sgf_tools/tokenizer.rex
51
+ - lib/sgftools.rb
52
+ - sgftools.gemspec
53
+ - spec/parser_spec.rb
54
+ - test/test_sgf_parse.rb
55
+ has_rdoc: true
56
+ homepage: http://github.com/ps2/sgfparser
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options: []
61
+
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ segments:
78
+ - 1
79
+ - 3
80
+ - 6
81
+ version: 1.3.6
82
+ requirements: []
83
+
84
+ rubyforge_project:
85
+ rubygems_version: 1.3.7
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: A ruby library for working with SGF files
89
+ test_files:
90
+ - spec/parser_spec.rb