sgfparser 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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