Skip to content

Commit 3e2d053

Browse files
committed
Parse comments and multi-properties. Some bug remains, uncovered by the ff4_ex file.
1 parent 3044fa3 commit 3e2d053

5 files changed

Lines changed: 87 additions & 33 deletions

File tree

lib/sgf/node.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ def add_children *nodes
3030
#Takes a hash {identity => property} and adds those to the current node.
3131
#If a property already exists, it will append to it.
3232
def add_properties hash
33-
hash.each do |key, value|
34-
@properties[key] ||= ""
35-
@properties[key].concat value
33+
hash.each do |identity, property|
34+
@properties[identity] ||= property.class.new
35+
@properties[identity].concat property
3636
end
3737
end
3838

lib/sgf/parser.rb

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ class Parser
1111
BRANCHING = ["(", ")"]
1212
PROPERTY = ["[", "]"]
1313
NODE_DELIMITERS = [NEW_NODE].concat BRANCHING
14+
LIST_IDENTITIES = ["AW", "AB", "AE", "AR", "CR", "DD",
15+
"LB", "LN", "MA", "SL", "SQ", "TR", "VW",
16+
"TB", "TW"]
1417

1518
def initialize strict_parsing = true
1619
@strict_parsing = strict_parsing
@@ -31,12 +34,16 @@ def parse sgf
3134
@stream = streamable sgf
3235
until @stream.eof?
3336
case next_character
34-
when ";" then create_new_node
35-
when "(" then open_branch
36-
when ")" then close_branch
37+
when ";" then
38+
create_new_node
39+
parse_node_data
40+
add_properties_to_current_node
41+
when "(" then
42+
open_branch
43+
when ")" then
44+
close_branch
45+
else next
3746
end
38-
parse_node_data
39-
add_properties_to_current_node
4047
end
4148
@tree
4249
end
@@ -87,18 +94,56 @@ def still_inside_node?
8794
def parse_identity
8895
@identity = ""
8996
while char = next_character and char != "["
90-
@identity << char
97+
@identity << char unless char == "\n"
9198
end
9299
end
93100

94101
def parse_property
95102
@property = ""
103+
case @identity.upcase
104+
when "C" then
105+
parse_comment
106+
when *LIST_IDENTITIES then
107+
parse_multi_property
108+
else
109+
parse_generic_property
110+
end
111+
end
112+
113+
def parse_comment
114+
while char = next_character and still_inside_comment? char
115+
@property << char
116+
end
117+
@property.gsub! "\\]", "]"
118+
end
119+
120+
def parse_multi_property
121+
while char = next_character and still_inside_multi_property? char
122+
@property << char
123+
end
124+
@property = @property.gsub("][", ",").split(",")
125+
end
126+
127+
def parse_generic_property
96128
while char = next_character and char != "]"
97129
@property << char
98130
end
99131
end
100132

133+
def still_inside_comment? char
134+
char != "]" || (char == "]" && @property[-1..-1] == "\\")
135+
end
136+
137+
def still_inside_multi_property? char
138+
return true if char != "]"
139+
char = next_character
140+
@stream.pos -= 1
141+
return true if char == "["
142+
false
143+
end
144+
101145
def add_properties_to_current_node
146+
p @node_properties
102147
@current_node.add_properties @node_properties
103148
end
104149

spec/parser_spec.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,24 @@
5353
node.children[1].c.should == "branch"
5454
end
5555

56-
it "should parse a tricky comment well" do
56+
it "should parse a comment with a ] inside" do
5757
parser = strict_parser
58-
tree = parser.parse "(;C[Oh hi] there\\]"
58+
tree = parser.parse "(;C[Oh hi\\] there]"
5959
tree.root.children[0].c.should == "Oh hi] there"
6060
end
6161

6262
it "should parse a multi-property identity well" do
63-
pending "code me!"
63+
parser = strict_parser
64+
tree = parser.parse "(;FF[4];AW[bd][cc][qr])"
65+
tree.root.children[0].children[0].aw.should == ["bd", "cc", "qr"]
66+
end
67+
68+
it "should parse multiple trees" do
69+
parser = strict_parser
70+
tree = parser.parse "(;FF[4];AW[dd][cc])(;FF[4];PB[ad])"
71+
tree.root.children.size.should == 2
72+
tree.root.children[0].children[0].aw.should == ["dd", "cc"]
73+
tree.root.children[1].children[0].pb.should == "ad"
6474
end
6575

6676
private

spec/spec_helper.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,5 @@ def get_first_game_from file
1212

1313
def get_tree_from file
1414
parser = SGF::Parser.new
15-
p File.read file
1615
parser.parse File.read(file)
1716
end

spec/tree_spec.rb

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,26 @@
1111
FileUtils.rm_f 'spec/data/ff4_ex_saved.sgf'
1212
end
1313

14+
it "should have two gametrees" do
15+
@tree.games.size.should == 2
16+
end
17+
18+
it "should tell you the id of the object on inspect" do
19+
@tree.inspect.should match /#{@tree.object_id}/
20+
end
21+
22+
it "should tell you the class of the object on inspect" do
23+
@tree.inspect.should match /SGF::Tree/
24+
end
25+
26+
it "should tell you how many games it has on inspect" do
27+
@tree.inspect.should match /Games: 2/
28+
end
29+
30+
it "should tell you how many nodes it has on inspect" do
31+
@tree.inspect.should match /Nodes: 62/
32+
end
33+
1434
it "should use preorder traversal for each" do
1535
@tree = get_tree_from 'spec/data/example1.sgf'
1636
array = []
@@ -42,24 +62,4 @@
4262
tree2.should == @tree
4363
end
4464

45-
it "should have two gametrees" do
46-
@tree.games.size.should == 2
47-
end
48-
49-
it "should tell you the id of the object on inspect" do
50-
@tree.inspect.should match /#{@tree.object_id}/
51-
end
52-
53-
it "should tell you the class of the object on inspect" do
54-
@tree.inspect.should match /SGF::Tree/
55-
end
56-
57-
it "should tell you how many games it has on inspect" do
58-
@tree.inspect.should match /Games: 2/
59-
end
60-
61-
it "should tell you how many nodes it has on inspect" do
62-
@tree.inspect.should match /Nodes: 62/
63-
end
64-
6565
end

0 commit comments

Comments
 (0)