dimus-biodiversity 0.0.18 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,98 +1,123 @@
1
- grammar ScientificNameDirty
2
- include ScientificNameClean
3
-
4
- rule composite_scientific_name
5
- super
6
- end
7
-
8
- # rule original_authors_names_full
9
- # super
10
- # end
11
- #
12
- # rule incorrect_original_authors_names
13
- # "[" space a:authors_names_full space "]" {
14
- # def value
15
- # "(" + a.value + ")"
16
- # end
17
- # def details
18
- # {:orig_authors => a.details[:authors]}
19
- # end
20
- # }
21
- # end
22
-
23
- rule year
24
- a:[\d]+ space b:approximate_year {
25
- def value
26
- a.text_value + " " + b.text_value
27
- end
28
- def pos
29
- {a.interval.begin => ['year', a.interval.end]}.merge(b.pos)
30
- end
31
- def details
32
- {:ambiguous_year => value}
33
- end
34
- }
35
- /
36
- a:[\d]+ page_number
37
- {
38
- def value
39
- a.text_value
40
- end
41
-
42
- def pos
43
- {a.interval.begin => ['year', a.interval.end]}
44
- end
45
-
46
- def details
47
- {:year => value}
48
- end
49
- }
50
- /
51
- double_year
52
- /
53
- approximate_year
54
- /
55
- super
56
- end
57
-
58
- rule approximate_year
59
- "[" space a:([\d] [\d] [\d] [\d\?]+) space "]"+ {
60
- def value
61
- "(" + a.text_value + ")"
62
- end
63
-
64
- def pos
65
- {a.interval.begin => ['year', a.interval.end]}
66
- end
67
-
68
- def details
69
- {:approximate_year => value}
70
- end
71
- }
72
- end
73
-
74
- rule double_year
75
- [0-9] [0-9A-Za-z\?\-]+ {
76
- def value
77
- text_value
78
- end
79
-
80
- def pos
81
- {interval.begin => ['year', interval.end]}
82
- end
83
-
84
- def details
85
- {:year => value}
86
- end
87
- }
88
- end
89
-
90
- rule page_number
91
- ":" space [\d]+
92
- {
93
- def value
94
- end
95
- }
96
- end
97
-
98
- end
1
+ # encoding: UTF-8
2
+ grammar ScientificNameDirty
3
+ include ScientificNameClean
4
+
5
+ rule root
6
+ super
7
+ end
8
+
9
+ rule species
10
+ a:species_epitheton space b:year {
11
+ def value
12
+ a.value + " " + b.value
13
+ end
14
+
15
+ def canonical
16
+ a.canonical
17
+ end
18
+
19
+ def pos
20
+ a.pos.merge(b.pos)
21
+ end
22
+
23
+ def details
24
+ {:species => a.details[:species].merge(b.details)}
25
+ end
26
+ }
27
+ /
28
+ super
29
+ end
30
+
31
+ rule right_paren
32
+ ")" space ")"
33
+ /
34
+ super
35
+ end
36
+
37
+
38
+
39
+ rule left_paren
40
+ "(" space "("
41
+ /
42
+ super
43
+ end
44
+
45
+ rule year
46
+ a:year_number space b:approximate_year {
47
+ def value
48
+ a.value + " " + b.value
49
+ end
50
+
51
+ def pos
52
+ a.pos.merge(b.pos)
53
+ end
54
+
55
+ def details
56
+ {:year => a.value, :approximate_year => b.value}
57
+ end
58
+ }
59
+ /
60
+ a:year_number space page_number {
61
+ def value
62
+ a.text_value
63
+ end
64
+
65
+ def pos
66
+ {a.interval.begin => ['year', a.interval.end]}
67
+ end
68
+
69
+ def details
70
+ {:year => value}
71
+ end
72
+ }
73
+ /
74
+ approximate_year
75
+ /
76
+ double_year
77
+ /
78
+ super
79
+ end
80
+
81
+ rule approximate_year
82
+ "[" space a:year_number space "]"+ {
83
+ def value
84
+ "(" + a.text_value + ")"
85
+ end
86
+
87
+ def pos
88
+ {a.interval.begin => ['year', a.interval.end]}
89
+ end
90
+
91
+ def details
92
+ {:approximate_year => value}
93
+ end
94
+ }
95
+ end
96
+
97
+
98
+ rule double_year
99
+ year_number "-" [0-9]+ [A-Za-z]? [\?]? {
100
+ def value
101
+ text_value
102
+ end
103
+
104
+ def pos
105
+ {interval.begin => ['year', interval.end]}
106
+ end
107
+
108
+ def details
109
+ {:year => value}
110
+ end
111
+ }
112
+ end
113
+
114
+ rule page_number
115
+ ":" space [\d]+
116
+ {
117
+ def value
118
+ end
119
+ }
120
+ end
121
+
122
+
123
+ end
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  require 'rubygems'
3
2
  require 'spec'
4
3
  require 'treetop'
@@ -37,33 +36,13 @@ describe ScientificNameClean do
37
36
  parse(input).to_json
38
37
  end
39
38
 
40
- it 'should parse accurate name' do
41
- sn = 'Pseudocercospora dendrobii'
42
- parse(sn).should_not be_nil
43
- value(sn).should == 'Pseudocercospora dendrobii'
44
- canonical(sn).should == 'Pseudocercospora dendrobii'
45
- details(sn).should == {:species=>"dendrobii", :genus=>"Pseudocercospora"}
46
- pos(sn).should == {0=>["genus", 16], 21=>["species", 30]}
47
- canonical('Quoyula').should == 'Quoyula'
48
- parse('Perissandra laotica').should_not be_nil
49
- end
50
-
51
- it 'should parse inaccurate name' do
52
- parse("Tridentella tangeroae Bruce, 198?").should_not be_nil
53
- end
54
-
55
- it 'should parse name that cannot be fully parsed' do
56
- parse("Plantago major ESEFDSlj sdafsladjfasd fd ;asldfjasfas#&^&*^*^&}}").should_not be_nil
57
- canonical('Plantago major ESEFDSlj sdafsladjfasd fd ;asldfjasfas#&^&*^*^&}}').should == 'Plantago major'
58
- end
59
-
60
- it 'should generate pos_json output' do
61
- parse("Plantago major").pos_to_json.should == '{"0":["genus",8],"9":["species",14]}'
62
- end
63
-
64
- it 'should generate json output' do
65
- parse("Stagonospora polyspora M.T. Lucas & Sousa da Câmara 1934").to_json.should == "{\"scientificName\":{\"parsed\":true,\"verbatim\":\"Stagonospora polyspora M.T. Lucas & Sousa da C\\u00e2mara 1934\",\"normalized\":\"Stagonospora polyspora M.T. Lucas et Sousa da C\\u00e2mara 1934\",\"canonical\":\"Stagonospora polyspora\",\"genus\":\"Stagonospora\",\"species\":\"polyspora\",\"authors\":{\"names\":[\"M.T. Lucas\",\"Sousa da C\\u00e2mara\"],\"year\":\"1934\"},\"name_part_verbatim\":\"Stagonospora polyspora\",\"auth_part_verbatim\":\"M.T. Lucas & Sousa da C\\u00e2mara 1934\"}}"
66
- parse("something very wrong да?").to_json.should == "{\"parsed\":false,\"verbatim\":\"something very wrong \\u0434\\u0430?\"}"
39
+ it 'should generate standardized json' do
40
+ f = open(File.expand_path(dir + "../../spec/parser/test_data.txt"))
41
+ f.each do |line|
42
+ name, jsn, notes = line.split("|")
43
+ next unless line.match(/^\s*#/) == nil && name && jsn
44
+ JSON.load(json(name)).should == JSON.load(jsn)
45
+ end
67
46
  end
68
47
 
69
48
  end
@@ -36,15 +36,16 @@ describe ScientificNameCanonical do
36
36
 
37
37
  it 'should parse names with valid name part and unparseable rest' do
38
38
  [
39
- ['Moraea spathulata ( (L. f. Klatt','Moraea spathulata','Moraea spathulata',{:genus=>"Moraea", :species=>"spathulata", :name_part_verbatim=>"Moraea spathulata", :auth_part_verbatim=>"( (L. f. Klatt"}, {0=>["genus", 6], 7=>["species", 17]} ],
40
- ['Verpericola megasoma ""Dall" Pils.','Verpericola megasoma','Verpericola megasoma',{:genus=>"Verpericola", :species=>"megasoma", :name_part_verbatim=>"Verpericola megasoma", :auth_part_verbatim=>"\"\"Dall\" Pils."}, {0=>["genus", 11], 12=>["species", 20]}],
41
- ['Nesticus cellulanus affinis Kulczynski, in Chyzer & Kulczynski, 1894','Nesticus cellulanus affinis','Nesticus cellulanus affinis',{:genus=>"Nesticus", :species=>"cellulanus", :subspecies=>{:rank=>"n/a", :value=>"affinis"}, :name_part_verbatim=>"Nesticus cellulanus", :auth_part_verbatim=>"Kulczynski, in Chyzer & Kulczynski, 1894"},{0=>["genus", 8], 9=>["species", 19], 20=>["subspecies", 27]}]
39
+ ['Morea ssjjlajajaj324$33 234243242','Morea', {:uninomial=>{:epitheton=>"Morea"}}, {0=>["uninomial", 5]}],
40
+ ['Morea (Morea) Burt 2342343242 23424322342 23424234', 'Morea (Morea)', {:genus=>{:epitheton=>"Morea"}, :subgenus=>{:epitheton=>"Morea"}}, {0=>["genus", 5], 7=>["subgenus", 12]}],
41
+ ['Morea (Morea) burtius 2342343242 23424322342 23424234', 'Morea (Morea) burtius', {:genus=>{:epitheton=>"Morea"}, :subgenus=>{:epitheton=>"Morea"}, :species=>{:epitheton=>"burtius"}}, {0=>["genus", 5], 7=>["subgenus", 12], 14=>["species", 21]}],
42
+ ['Moraea spathulata ( (L. f. Klatt','Moraea spathulata',{:genus=>{:epitheton=>"Moraea"}, :species=>{:epitheton=>"spathulata"}}, {0=>["genus", 6], 7=>["species", 17]} ],
43
+ ['Verpericola megasoma ""Dall" Pils.','Verpericola megasoma',{:genus=>{:epitheton=>"Verpericola"}, :species=>{:epitheton=>"megasoma"}}, {0=>["genus", 11], 12=>["species", 20]}]
42
44
  ].each do |n|
43
45
  parse(n[0]).should_not be_nil
44
46
  value(n[0]).should == n[1]
45
- canonical(n[0]).should == n[2]
46
- details(n[0]).should == n[3]
47
- pos(n[0]).should == n[4]
47
+ details(n[0]).should == n[2]
48
+ pos(n[0]).should == n[3]
48
49
  end
49
50
  end
50
51
  end
@@ -2,6 +2,7 @@
2
2
  dir = File.dirname("__FILE__")
3
3
  require 'rubygems'
4
4
  require 'spec'
5
+ require 'yaml'
5
6
  require 'treetop'
6
7
 
7
8
  Treetop.load(File.expand_path(dir + '../../lib/biodiversity/parser/scientific_name_clean'))
@@ -36,57 +37,20 @@ describe ScientificNameClean do
36
37
  parse(sn).should_not be_nil
37
38
  value(sn).should == 'Pseudocercospora'
38
39
  canonical(sn).should == 'Pseudocercospora'
39
- details(sn).should == {:uninomial=>"Pseudocercospora"}
40
+ details(sn).should == {:uninomial=>{:epitheton=>"Pseudocercospora"}}
40
41
  pos(sn).should == {0=>["uninomial", 16]}
41
42
  end
42
43
 
43
44
  it 'should parse uninomial with author and year' do
44
- sn = 'Pseudocercospora Dow 1913'
45
+ sn = 'Pseudocercospora Speg.'
45
46
  parse(sn).should_not be_nil
46
- value(sn).should == 'Pseudocercospora Dow 1913'
47
- details(sn).should == {:authors=>{:year=>"1913", :names=>["Dow"]}, :name_part_verbatim=>"Pseudocercospora", :auth_part_verbatim=>"Dow 1913", :uninomial=>"Pseudocercospora"}
48
- pos(sn).should == {0=>["uninomial", 16], 17=>["author_word", 20], 21=>["year", 25]}
49
- end
50
-
51
- it 'should parse canonical' do
52
- sn = 'Pseudocercospora dendrobii'
53
- parse(sn).should_not be_nil
54
- value(sn).should == 'Pseudocercospora dendrobii'
55
- canonical(sn).should == 'Pseudocercospora dendrobii'
56
- details(sn).should == {:species=>"dendrobii", :genus=>"Pseudocercospora"}
57
- pos(sn).should == {0=>["genus", 16], 21=>["species", 30]}
58
- end
59
-
60
- it 'should parse subgenus ZOOLOGICAL' do
61
- sn = "Doriteuthis (Amerigo) pealeii Author 1999"
47
+ details(sn).should == {:uninomial=>{:epitheton=>"Pseudocercospora", :authorship=>"Speg.", :basionymAuthorTeam=>{:authorTeam=>"Speg.", :author=>["Speg."]}}}
48
+ pos(sn).should == {0=>["uninomial", 16], 17=>["author_word", 22]}
49
+ sn = 'Pseudocercospora Spegazzini, 1910'
62
50
  parse(sn).should_not be_nil
63
- value(sn).should == "Doriteuthis (Amerigo) pealeii Author 1999"
64
- canonical(sn).should == "Doriteuthis pealeii"
65
- details(sn).should == {:genus=>"Doriteuthis", :subgenus=>"Amerigo", :species=>"pealeii", :authors=>{:names=>["Author"], :year=>"1999"}, :name_part_verbatim=>"Doriteuthis (Amerigo) pealeii", :auth_part_verbatim=>"Author 1999"}
66
- pos(sn).should == {0=>["genus", 11], 13=>["subgenus", 20], 22=>["subspecies", 29], 30=>["author_word", 36], 37=>["year", 41]}
67
- end
68
-
69
- it 'should parse æ in the name' do
70
- names = [
71
- ["Læptura laetifica Dow, 1913", "Laeptura laetifica Dow 1913"],
72
- ["Leptura lætifica Dow, 1913", "Leptura laetifica Dow 1913"],
73
- ["Leptura leætifica Dow, 1913", "Leptura leaetifica Dow 1913"],
74
- ["Leæptura laetifica Dow, 1913", "Leaeptura laetifica Dow 1913"],
75
- ["Leœptura laetifica Dow, 1913", "Leoeptura laetifica Dow 1913"],
76
- ['Ærenea cognata Lacordaire, 1872', 'Aerenea cognata Lacordaire 1872'],
77
- ['Œdicnemus capensis ehrenbergi', 'Oedicnemus capensis ehrenbergi'],
78
- ['Œnanthe œnanthe œnanthe','Oenanthe oenanthe oenanthe']
79
- ]
80
- names.each do |name_pair|
81
- parse(name_pair[0]).should_not be_nil
82
- value(name_pair[0]).should == name_pair[1]
83
- end
84
- end
85
-
86
- it 'should parse names with "common" utf-8 charactes' do
87
- names = ["Rühlella","Sténométope laevissimus Bibron 1855"].each do |name|
88
- parse(name).should_not be_nil
89
- end
51
+ value(sn).should == 'Pseudocercospora Spegazzini 1910'
52
+ details(sn).should == {:uninomial=>{:epitheton=>"Pseudocercospora", :authorship=>"Spegazzini, 1910", :basionymAuthorTeam=>{:authorTeam=>"Spegazzini", :author=>["Spegazzini"], :year=>"1910"}}}
53
+ pos(sn).should == {0=>["uninomial", 16], 17=>["author_word", 27], 29=>["year", 33]}
90
54
  end
91
55
 
92
56
  it 'should parse names with a valid 2 letter genus' do
@@ -103,7 +67,6 @@ describe ScientificNameClean do
103
67
  "Ty Bory de St. Vincent 1827",
104
68
  "Ua Girault 1929",
105
69
  "Aa Baker 1940",
106
- #"Mc",
107
70
  "Ja Uéno 1955",
108
71
  "Zu Walters & Fitch 1960",
109
72
  "La Bleszynski 1966",
@@ -114,34 +77,86 @@ describe ScientificNameClean do
114
77
  end
115
78
  canonical('Quoyula').should == 'Quoyula'
116
79
  end
117
-
118
- it 'should parse year' do
80
+
81
+ it 'should parse canonical' do
82
+ sn = 'Pseudocercospora dendrobii'
83
+ parse(sn).should_not be_nil
84
+ value(sn).should == 'Pseudocercospora dendrobii'
85
+ canonical(sn).should == 'Pseudocercospora dendrobii'
86
+ details(sn).should == {:genus=>{:epitheton=>"Pseudocercospora"}, :species=>{:epitheton=>"dendrobii"}}
87
+ pos(sn).should == {0=>["genus", 16], 21=>["species", 30]}
88
+ end
89
+
90
+
91
+ it 'should parse species name with author and year' do
119
92
  sn = "Platypus bicaudatulus Schedl 1935"
120
93
  parse(sn).should_not be_nil
121
94
  value(sn).should == "Platypus bicaudatulus Schedl 1935"
122
95
  sn = "Platypus bicaudatulus Schedl, 1935h"
123
96
  parse(sn).should_not be_nil
124
97
  value(sn).should == "Platypus bicaudatulus Schedl 1935"
125
- details(sn).should == {:genus=>"Platypus", :species=>"bicaudatulus", :authors=>{:names=>["Schedl"], :year=>"1935"}, :name_part_verbatim=>"Platypus bicaudatulus", :auth_part_verbatim=>"Schedl, 1935h"}
98
+ details(sn).should == {:genus=>{:epitheton=>"Platypus"}, :species=>{:epitheton=>"bicaudatulus", :authorship=>"Schedl, 1935h", :basionymAuthorTeam=>{:authorTeam=>"Schedl", :author=>["Schedl"], :year=>"1935"}}}
126
99
  pos(sn).should == {0=>["genus", 8], 9=>["species", 21], 22=>["author_word", 28], 30=>["year", 35]}
127
100
  parse("Platypus bicaudatulus Schedl, 1935B").should_not be_nil
101
+ sn = "Platypus bicaudatulus Schedl (1935h)"
102
+ parse(sn).should_not be_nil
103
+ details(sn).should == {:genus=>{:epitheton=>"Platypus"}, :species=>{:epitheton=>"bicaudatulus", :authorship=>"Schedl (1935h)", :basionymAuthorTeam=>{:authorTeam=>"Schedl", :author=>["Schedl"], :year=>"1935"}}}
104
+ parse("Platypus bicaudatulus Schedl 1935").should_not be_nil
128
105
  end
129
106
 
130
- it 'should parse species autonym for complex subspecies authorships' do
131
- parse("Aus bus Linn. var. bus").should_not be_nil
132
- details("Aus bus Linn. var. bus").should == {:genus=>"Aus", :species=>"bus", :subspecies=>[{:rank=>"var.", :value=>"bus"}], :species_authors=>{:authors=>{:names=>["Linn."]}}, :name_part_verbatim=>"Aus bus", :auth_part_verbatim=>"Linn. var. bus"}
133
- sn = "Agalinis purpurea (L.) Briton var. borealis (Berg.) Peterson 1987"
107
+ it 'should parse genus with "?"' do
108
+ sn = "Ferganoconcha? oblonga"
134
109
  parse(sn).should_not be_nil
135
- details(sn).should == {:genus=>"Agalinis", :species=>"purpurea", :subspecies=>[{:rank=>"var.", :value=>"borealis"}], :species_authors=>{:orig_authors=>{:names=>["L."]}, :authors=>{:names=>["Briton"]}}, :subspecies_authors=>{:orig_authors=>{:names=>["Berg."]}, :authors=>{:names=>["Peterson"], :year=>"1987"}}, :name_part_verbatim=>"Agalinis purpurea", :auth_part_verbatim=>"(L.) Briton var. borealis (Berg.) Peterson 1987"}
136
- pos(sn).should == {0=>["genus", 8], 9=>["species", 17], 19=>["author_word", 21], 23=>["author_word", 29], 35=>["subspecies", 43], 45=>["author_word", 50], 52=>["author_word", 60], 61=>["year", 65]}
110
+ value(sn).should == "Ferganoconcha oblonga"
111
+ details(sn).should == {:genus=>{:epitheton=>"Ferganoconcha"}, :species=>{:epitheton=>"oblonga"}}
112
+ pos(sn).should == {0=>["genus", 14], 15=>["species", 22]}
137
113
  end
138
114
 
139
- it 'should parse several authors' do
115
+ it 'should parse æ in the name' do
116
+ names = [
117
+ ["Læptura laetifica Dow, 1913", "Laeptura laetifica Dow 1913"],
118
+ ["Leptura lætifica Dow, 1913", "Leptura laetifica Dow 1913"],
119
+ ["Leptura leætifica Dow, 1913", "Leptura leaetifica Dow 1913"],
120
+ ["Leæptura laetifica Dow, 1913", "Leaeptura laetifica Dow 1913"],
121
+ ["Leœptura laetifica Dow, 1913", "Leoeptura laetifica Dow 1913"],
122
+ ['Ærenea cognata Lacordaire, 1872', 'Aerenea cognata Lacordaire 1872'],
123
+ ['Œdicnemus capensis', 'Oedicnemus capensis'],
124
+ ['Œnanthe œnanthe','Oenanthe oenanthe']
125
+ ]
126
+ names.each do |name_pair|
127
+ parse(name_pair[0]).should_not be_nil
128
+ value(name_pair[0]).should == name_pair[1]
129
+ end
130
+ end
131
+
132
+ it 'should parse names with "common" utf-8 charactes' do
133
+ names = ["Rühlella","Sténométope laevissimus Bibron 1855"].each do |name|
134
+ parse(name).should_not be_nil
135
+ end
136
+ sn = "Trematosphaeria phaeospora (E. Müll.) L. Holm 1957"
137
+ parse(sn).should_not be_nil
138
+ value(sn).should == "Trematosphaeria phaeospora (E. Müll.) L. Holm 1957"
139
+ canonical(sn).should == "Trematosphaeria phaeospora"
140
+ details(sn).should == {:genus=>{:epitheton=>"Trematosphaeria"}, :species=>{:epitheton=>"phaeospora", :authorship=>"(E. Müll.) L. Holm 1957", :combinationAuthorTeam=>{:authorTeam=>"L. Holm", :author=>["L. Holm"], :year=>"1957"}, :basionymAuthorTeam=>{:authorTeam=>"E. Müll.", :author=>["E. Müll."]}}}
141
+ pos(sn).should == {0=>["genus", 15], 16=>["species", 26], 28=>["author_word", 30], 31=>["author_word", 36], 46=>["author_word", 48], 61=>["author_word", 65], 66=>["year", 70]}
142
+
143
+ end
144
+
145
+ it 'should parse subgenus (ICZN code)' do
146
+ sn = "Hegeter (Hegeter) intercedens Lindberg H 1950"
147
+ parse(sn).should_not be_nil
148
+ value(sn).should == "Hegeter (Hegeter) intercedens Lindberg H 1950"
149
+ canonical(sn).should == "Hegeter intercedens"
150
+ details(sn).should == {:genus=>{:epitheton=>"Hegeter"}, :subgenus=>{:epitheton=>"Hegeter"}, :species=>{:epitheton=>"intercedens", :authorship=>"Lindberg H 1950", :basionymAuthorTeam=>{:authorTeam=>"Lindberg H", :author=>["Lindberg H"], :year=>"1950"}}}
151
+ pos(sn).should == {0=>["genus", 7], 9=>["subgenus", 16], 18=>["species", 29], 30=>["author_word", 38], 39=>["author_word", 40], 41=>["year", 45]}
152
+ end
153
+
154
+ it 'should parse several authors without a year' do
140
155
  sn = "Pseudocercospora dendrobii U. Braun & Crous"
141
156
  parse(sn).should_not be_nil
142
157
  value(sn).should == "Pseudocercospora dendrobii U. Braun et Crous"
143
158
  canonical(sn).should == "Pseudocercospora dendrobii"
144
- details(sn).should == {:genus=>"Pseudocercospora", :species=>"dendrobii", :authors=>{:names=>["U. Braun", "Crous"]}, :name_part_verbatim=>"Pseudocercospora dendrobii", :auth_part_verbatim=>"U. Braun & Crous"}
159
+ details(sn).should == {:genus=>{:epitheton=>"Pseudocercospora"}, :species=>{:epitheton=>"dendrobii", :authorship=>"U. Braun & Crous", :basionymAuthorTeam=>{:authorTeam=>"U. Braun & Crous", :author=>["U. Braun", "Crous"]}}}
145
160
  pos(sn).should == {0=>["genus", 16], 17=>["species", 26], 27=>["author_word", 29], 30=>["author_word", 35], 38=>["author_word", 43]}
146
161
  sn = "Pseudocercospora dendrobii U. Braun and Crous"
147
162
  parse(sn).should_not be_nil
@@ -150,46 +165,120 @@ describe ScientificNameClean do
150
165
  sn = "Pseudocercospora dendrobii U. Braun et Crous"
151
166
  parse(sn).should_not be_nil
152
167
  value(sn).should == "Pseudocercospora dendrobii U. Braun et Crous"
168
+ sn = "Arthopyrenia hyalospora(Nyl.)R.C. Harris"
169
+ parse(sn).should_not be_nil
170
+ value(sn).should == "Arthopyrenia hyalospora (Nyl.) R.C. Harris"
171
+ canonical(sn).should == "Arthopyrenia hyalospora"
172
+ details(sn).should == {:genus=>{:epitheton=>"Arthopyrenia"}, :species=>{:epitheton=>"hyalospora", :authorship=>"(Nyl.)R.C. Harris", :combinationAuthorTeam=>{:authorTeam=>"R.C. Harris", :author=>["R.C. Harris"]}, :basionymAuthorTeam=>{:authorTeam=>"Nyl.", :author=>["Nyl."]}}}
153
173
  end
174
+
175
+
154
176
 
155
177
  it 'should parse several authors with a year' do
156
178
  sn = "Pseudocercospora dendrobii U. Braun & Crous 2003"
157
179
  parse(sn).should_not be_nil
158
180
  value(sn).should == "Pseudocercospora dendrobii U. Braun et Crous 2003"
159
181
  canonical(sn).should == "Pseudocercospora dendrobii"
160
- details(sn).should == {:genus=>"Pseudocercospora", :species=>"dendrobii", :authors=>{:names=>["U. Braun", "Crous"], :year=>"2003"}, :name_part_verbatim=>"Pseudocercospora dendrobii", :auth_part_verbatim=>"U. Braun & Crous 2003"}
182
+ details(sn).should == {:genus=>{:epitheton=>"Pseudocercospora"}, :species=>{:epitheton=>"dendrobii", :authorship=>"U. Braun & Crous 2003", :basionymAuthorTeam=>{:authorTeam=>"U. Braun & Crous", :author=>["U. Braun", "Crous"], :year=>"2003"}}}
161
183
  pos(sn).should == {0=>["genus", 16], 17=>["species", 26], 27=>["author_word", 29], 30=>["author_word", 35], 38=>["author_word", 43], 44=>["year", 48]}
162
184
  sn = "Pseudocercospora dendrobii Crous, 2003"
163
185
  parse(sn).should_not be_nil
164
- parse("Zophosis persis (Chatanay, 1914)").should_not be_nil
165
- parse("Zophosis persis (Chatanay 1914)").should_not be_nil
186
+ end
187
+
188
+ it 'should parse basionym authors in parenthesis' do
189
+ sn = "Zophosis persis (Chatanay, 1914)"
190
+ parse(sn).should_not be_nil
191
+ details(sn).should == {:genus=>{:epitheton=>"Zophosis"}, :species=>{:epitheton=>"persis", :authorship=>"(Chatanay, 1914)", :basionymAuthorTeam=>{:authorTeam=>"Chatanay", :author=>["Chatanay"], :year=>"1914"}}}
192
+ sn = "Zophosis persis (Chatanay 1914)"
193
+ parse(sn).should_not be_nil
194
+ details(sn).should == {:genus=>{:epitheton=>"Zophosis"}, :species=>{:epitheton=>"persis", :authorship=>"(Chatanay 1914)", :basionymAuthorTeam=>{:authorTeam=>"Chatanay", :author=>["Chatanay"], :year=>"1914"}}}
166
195
  sn = "Zophosis persis (Chatanay), 1914"
167
196
  parse(sn).should_not be_nil
168
197
  value(sn).should == "Zophosis persis (Chatanay 1914)"
169
- details(sn).should == {:genus=>"Zophosis", :species=>"persis", :orig_authors=>{:names=>["Chatanay"]}, :year=>"1914", :name_part_verbatim=>"Zophosis persis", :auth_part_verbatim=>"(Chatanay), 1914"}
198
+ details(sn).should == {:genus=>{:epitheton=>"Zophosis"}, :species=>{:epitheton=>"persis", :authorship=>"(Chatanay), 1914", :basionymAuthorTeam=>{:author_team=>"(Chatanay), 1914", :author=>["Chatanay"], :year=>"1914"}}}
170
199
  pos(sn).should == {0=>["genus", 8], 9=>["species", 15], 17=>["author_word", 25], 28=>["year", 32]}
171
200
  parse("Zophosis persis (Chatanay) 1914").should_not be_nil
172
201
  #parse("Zophosis persis Chatanay (1914)").should_not be_nil
173
202
  end
174
203
 
175
204
  it 'should parse scientific name' do
176
- sn = "Abacetus laevicollis de Chaudoir, 1869"
205
+ sn = "Pseudocercospora dendrobii(H.C. Burnett)U. Braun & Crous 2003"
177
206
  parse(sn).should_not be_nil
178
- canonical(sn).should == 'Abacetus laevicollis'
179
- parse("Pseudocercospora dendrobii (H.C. Burnett) U. Braun & Crous 2003").should_not be_nil
180
- value("Pseudocercospora dendrobii(H.C. Burnett)U. Braun & Crous 2003").should == "Pseudocercospora dendrobii (H.C. Burnett) U. Braun et Crous 2003"
181
- canonical("Pseudocercospora dendrobii(H.C. Burnett)U. Braun & Crous 2003").should == "Pseudocercospora dendrobii"
207
+ value(sn).should == "Pseudocercospora dendrobii (H.C. Burnett) U. Braun et Crous 2003"
208
+ canonical(sn).should == "Pseudocercospora dendrobii"
209
+ details(sn).should == {:genus=>{:epitheton=>"Pseudocercospora"}, :species=>{:epitheton=>"dendrobii", :authorship=>"(H.C. Burnett)U. Braun & Crous 2003", :combinationAuthorTeam=>{:authorTeam=>"U. Braun & Crous", :author=>["U. Braun", "Crous"], :year=>"2003"}, :basionymAuthorTeam=>{:authorTeam=>"H.C. Burnett", :author=>["H.C. Burnett"]}}}
210
+ sn = "Pseudocercospora dendrobii(H.C. Burnett,1873)U. Braun & Crous 2003"
211
+ parse(sn).should_not be_nil
212
+ value(sn).should == "Pseudocercospora dendrobii (H.C. Burnett 1873) U. Braun et Crous 2003"
213
+ details(sn).should == {:genus=>{:epitheton=>"Pseudocercospora"}, :species=>{:epitheton=>"dendrobii", :authorship=>"(H.C. Burnett,1873)U. Braun & Crous 2003", :combinationAuthorTeam=>{:authorTeam=>"U. Braun & Crous", :author=>["U. Braun", "Crous"], :year=>"2003"}, :basionymAuthorTeam=>{:authorTeam=>"H.C. Burnett", :author=>["H.C. Burnett"], :year=>"1873"}}}
214
+ end
215
+
216
+ it 'should parse several authors with several years' do
217
+ sn = "Pseudocercospora dendrobii (H.C. Burnett 1883) U. Braun & Crous 2003"
218
+ parse(sn).should_not be_nil
219
+ value(sn).should == "Pseudocercospora dendrobii (H.C. Burnett 1883) U. Braun et Crous 2003"
220
+ canonical(sn).should == "Pseudocercospora dendrobii"
221
+ details(sn).should == {:genus=>{:epitheton=>"Pseudocercospora"}, :species=>{:epitheton=>"dendrobii", :authorship=>"(H.C. Burnett 1883) U. Braun & Crous 2003", :combinationAuthorTeam=>{:authorTeam=>"U. Braun & Crous", :author=>["U. Braun", "Crous"], :year=>"2003"}, :basionymAuthorTeam=>{:authorTeam=>"H.C. Burnett", :author=>["H.C. Burnett"], :year=>"1883"}}}
222
+ pos(sn).should == {0=>["genus", 16], 17=>["species", 26], 28=>["author_word", 32], 33=>["author_word", 40], 41=>["year", 45], 47=>["author_word", 49], 50=>["author_word", 55], 58=>["author_word", 63], 64=>["year", 68]}
223
+ end
224
+
225
+ it "should parse name with subspecies without rank Zoological Code" do
226
+ sn = "Hydnellum scrobiculatum zonatum (Banker) D. Hall & D.E. Stuntz 1972"
227
+ parse(sn).should_not be_nil
228
+ value(sn).should == "Hydnellum scrobiculatum zonatum (Banker) D. Hall et D.E. Stuntz 1972"
229
+ canonical(sn).should == "Hydnellum scrobiculatum zonatum"
230
+ details(sn).should == {:genus=>{:epitheton=>"Hydnellum"}, :species=>{:epitheton=>"scrobiculatum"}, :infraspecies=>{:epitheton=>"zonatum", :rank=>"n/a", :authorship=>"(Banker) D. Hall & D.E. Stuntz 1972", :combinationAuthorTeam=>{:authorTeam=>"D. Hall & D.E. Stuntz", :author=>["D. Hall", "D.E. Stuntz"], :year=>"1972"}, :basionymAuthorTeam=>{:authorTeam=>"Banker", :author=>["Banker"]}}}
231
+ pos(sn).should == {0=>["genus", 9], 10=>["species", 23], 24=>["infraspecies", 31], 33=>["author_word", 39], 41=>["author_word", 43], 44=>["author_word", 48], 51=>["author_word", 55], 56=>["author_word", 62], 63=>["year", 67]}
232
+ sn = "Begonia pingbienensis angustior"
233
+ parse(sn).should_not be_nil
234
+ details(sn).should == {:genus=>{:epitheton=>"Begonia"}, :species=>{:epitheton=>"pingbienensis"}, :infraspecies=>{:epitheton=>"angustior", :rank=>"n/a"}}
235
+ pos(sn).should == {0=>["genus", 7], 8=>["species", 21], 22=>["infraspecies", 31]}
236
+ end
182
237
 
238
+ it 'should parse infraspecies with rank' do
239
+ sn = "Aus bus Linn. var. bus"
240
+ parse(sn).should_not be_nil
241
+ details(sn).should == {:genus=>{:epitheton=>"Aus"}, :species=>{:epitheton=>"bus", :authorship=>"Linn.", :basionymAuthorTeam=>{:authorTeam=>"Linn.", :author=>["Linn."]}}, :infraspecies=>{:epitheton=>"bus", :rank=>"var."}}
242
+ sn = "Agalinis purpurea (L.) Briton var. borealis (Berg.) Peterson 1987"
243
+ parse(sn).should_not be_nil
244
+ details(sn).should == {:genus=>{:epitheton=>"Agalinis"}, :species=>{:epitheton=>"purpurea", :authorship=>"(L.) Briton", :combinationAuthorTeam=>{:authorTeam=>"Briton", :author=>["Briton"]}, :basionymAuthorTeam=>{:authorTeam=>"L.", :author=>["L."]}}, :infraspecies=>{:epitheton=>"borealis", :rank=>"var.", :authorship=>"(Berg.) Peterson 1987", :combinationAuthorTeam=>{:authorTeam=>"Peterson", :author=>["Peterson"], :year=>"1987"}, :basionymAuthorTeam=>{:authorTeam=>"Berg.", :author=>["Berg."]}}}
245
+ pos(sn).should == {0=>["genus", 8], 9=>["species", 17], 19=>["author_word", 21], 23=>["author_word", 29], 35=>["infraspecies", 43], 45=>["author_word", 50], 52=>["author_word", 60], 61=>["year", 65]}
246
+ sn = "Phaeographis inusta var. macularis(Leight.) A.L. Sm. 1861"
247
+ parse(sn).should_not be_nil
248
+ value(sn).should == "Phaeographis inusta var. macularis (Leight.) A.L. Sm. 1861"
249
+ canonical(sn).should == "Phaeographis inusta macularis"
250
+ pos(sn).should == {0=>["genus", 12], 13=>["species", 19], 25=>["infraspecies", 34], 35=>["author_word", 42], 44=>["author_word", 48], 49=>["author_word", 52], 53=>["year", 57]}
251
+ end
252
+
253
+ it 'should parse unknown original authors (auct.)/(hort.)/(?)' do
254
+ sn = "Tragacantha leporina (?) Kuntze"
255
+ parse(sn).should_not be_nil
256
+ value(sn).should == "Tragacantha leporina (?) Kuntze"
257
+ details(sn).should == {:genus=>{:epitheton=>"Tragacantha"}, :species=>{:epitheton=>"leporina", :authorship=>"(?) Kuntze", :combinationAuthorTeam=>{:authorTeam=>"Kuntze", :author=>["Kuntze"]}, :basionymAuthorTeam=>{:authorTeam=>"(?)", :author=>["?"]}}}
258
+ sn = "Lachenalia tricolor var. nelsonii (auct.) Baker"
259
+ parse(sn).should_not be_nil
260
+ value(sn).should == "Lachenalia tricolor var. nelsonii (auct.) Baker"
261
+ details(sn).should == {:genus=>{:epitheton=>"Lachenalia"}, :species=>{:epitheton=>"tricolor"}, :infraspecies=>{:epitheton=>"nelsonii", :rank=>"var.", :authorship=>"(auct.) Baker", :combinationAuthorTeam=>{:authorTeam=>"Baker", :author=>["Baker"]}, :basionymAuthorTeam=>{:authorTeam=>"auct.", :author=>["unknown"]}}}
262
+ pos(sn).should == {0=>["genus", 10], 11=>["species", 19], 25=>["infraspecies", 33], 35=>["unknown_author", 40], 42=>["author_word", 47]}
263
+ end
264
+
265
+ it 'should parse unknown authors auct./anon./hort./ht.' do
266
+ sn = "Puya acris ht."
267
+ parse(sn).should_not be_nil
268
+ pos(sn).should == {0=>["genus", 4], 5=>["species", 10], 11=>["unknown_author", 14]}
269
+ end
270
+
271
+ it 'shuould parse real world examples' do
183
272
  sn = "Stagonospora polyspora M.T. Lucas & Sousa da Câmara 1934"
184
273
  parse(sn).should_not be_nil
185
274
  value(sn).should == "Stagonospora polyspora M.T. Lucas et Sousa da Câmara 1934"
186
- details(sn).should == {:genus=>"Stagonospora", :species=>"polyspora", :authors=>{:names=>["M.T. Lucas", "Sousa da Câmara"], :year=>"1934"}, :name_part_verbatim=>"Stagonospora polyspora", :auth_part_verbatim=>"M.T. Lucas & Sousa da Câmara 1934"}
275
+ details(sn).should == {:genus=>{:epitheton=>"Stagonospora"}, :species=>{:epitheton=>"polyspora", :authorship=>"M.T. Lucas & Sousa da Câmara 1934", :basionymAuthorTeam=>{:authorTeam=>"M.T. Lucas & Sousa da Câmara", :author=>["M.T. Lucas", "Sousa da Câmara"], :year=>"1934"}}}
187
276
  pos(sn).should == {0=>["genus", 12], 13=>["species", 22], 23=>["author_word", 27], 28=>["author_word", 33], 36=>["author_word", 41], 42=>["author_word", 44], 45=>["author_word", 51], 52=>["year", 56]}
188
277
  parse("Cladoniicola staurospora Diederich, van den Boom & Aptroot 2001").should_not be_nil
189
278
  sn = "Yarrowia lipolytica var. lipolytica (Wick., Kurtzman & E.A. Herrm.) Van der Walt & Arx 1981"
190
279
  parse(sn).should_not be_nil
191
280
  value(sn).should == "Yarrowia lipolytica var. lipolytica (Wick., Kurtzman et E.A. Herrm.) Van der Walt et Arx 1981"
192
- pos(sn).should == {0=>["genus", 8], 9=>["species", 19], 25=>["subspecies", 35], 37=>["author_word", 42], 44=>["author_word", 52], 55=>["author_word", 59], 60=>["author_word", 66], 68=>["author_word", 71], 72=>["author_word", 75], 76=>["author_word", 80], 83=>["author_word", 86], 87=>["year", 91]}
281
+ pos(sn).should == {0=>["genus", 8], 9=>["species", 19], 25=>["infraspecies", 35], 37=>["author_word", 42], 44=>["author_word", 52], 55=>["author_word", 59], 60=>["author_word", 66], 68=>["author_word", 71], 72=>["author_word", 75], 76=>["author_word", 80], 83=>["author_word", 86], 87=>["year", 91]}
193
282
  parse("Physalospora rubiginosa (Fr.) anon.").should_not be_nil
194
283
  parse("Pleurotus ëous (Berk.) Sacc. 1887").should_not be_nil
195
284
  parse("Lecanora wetmorei Śliwa 2004").should_not be_nil
@@ -206,293 +295,200 @@ describe ScientificNameClean do
206
295
  # author is exception
207
296
  sn = "Tuber liui A S. Xu 1999"
208
297
  parse(sn).should_not be_nil
209
- details(sn).should == {:genus=>"Tuber", :species=>"liui", :authors=>{:names=>["A S. Xu"], :year=>"1999"}, :name_part_verbatim=>"Tuber liui", :auth_part_verbatim=>"A S. Xu 1999"}
210
- pos(sn).should == {0=>["genus", 5], 6=>["species", 10], 11=>["author_word", 1], 13=>["author_word", 2], 16=>["author_word", 2], 19=>["year", 23]}
298
+ details(sn).should == {:genus=>{:epitheton=>"Tuber"}, :species=>{:epitheton=>"liui", :authorship=>"A S. Xu 1999", :basionymAuthorTeam=>{:authorTeam=>"A S. Xu", :author=>["A S. Xu"], :year=>"1999"}}}
211
299
  parse('Xylaria potentillae A S. Xu').should_not be_nil
212
300
  parse("Agaricus squamula Berk. & M.A. Curtis 1860").should_not be_nil
213
301
  parse("Peltula coriacea Büdel, Henssen & Wessels 1986").should_not be_nil
214
302
  #had to add no dot rule for trinomials without a rank to make it to work
215
303
  sn = "Saccharomyces drosophilae anon."
216
304
  parse(sn).should_not be_nil
217
- details(sn).should == {:genus=>"Saccharomyces", :species=>"drosophilae", :authors=>{:names=>["anon."]}, :name_part_verbatim=>"Saccharomyces drosophilae", :auth_part_verbatim=>"anon."}
218
- pos(sn).should == {0=>["genus", 13], 14=>["species", 25], 26=>["author_word", 31]}
219
- end
220
-
221
- it 'should parse several authors with several years' do
222
- sn = "Pseudocercospora dendrobii (H.C. Burnett 1883) U. Braun & Crous 2003"
223
- parse(sn).should_not be_nil
224
- value(sn).should == "Pseudocercospora dendrobii (H.C. Burnett 1883) U. Braun et Crous 2003"
225
- canonical(sn).should == "Pseudocercospora dendrobii"
226
- details(sn).should == {:genus=>"Pseudocercospora", :species=>"dendrobii", :orig_authors=>{:names=>["H.C. Burnett"], :year=>"1883"}, :authors=>{:names=>["U. Braun", "Crous"], :year=>"2003"}, :name_part_verbatim=>"Pseudocercospora dendrobii", :auth_part_verbatim=>"(H.C. Burnett 1883) U. Braun & Crous 2003"}
227
- pos(sn).should == {0=>["genus", 16], 17=>["species", 26], 28=>["author_word", 32], 33=>["author_word", 40], 41=>["year", 45], 47=>["author_word", 49], 50=>["author_word", 55], 58=>["author_word", 63], 64=>["year", 68]}
228
- end
229
-
230
- it 'should parse unknown original authors (auct.)/(hort.)/(?)' do
231
- parse("Tragacantha leporina (?) Kuntze").should_not be_nil
232
- value("Tragacantha leporina ( ? ) Kuntze").should == "Tragacantha leporina (?) Kuntze"
233
- sn = "Lachenalia tricolor var. nelsonii (auct.) Baker"
234
- parse(sn).should_not be_nil
235
- value(sn).should == "Lachenalia tricolor var. nelsonii (auct.) Baker"
236
- details(sn).should == {:genus=>"Lachenalia", :species=>"tricolor", :subspecies=>[{:rank=>"var.", :value=>"nelsonii"}], :orig_authors=>"unknown", :authors=>{:names=>["Baker"]}, :name_part_verbatim=>"Lachenalia tricolor var. nelsonii", :auth_part_verbatim=>"(auct.) Baker"}
237
- pos(sn).should == {0=>["genus", 10], 11=>["species", 19], 25=>["subspecies", 33], 35=>["unknown_author", 40], 42=>["author_word", 47]}
238
- end
239
-
240
- it 'should parse unknown authors auct./anon./hort./ht.' do
241
- sn = "Puya acris ht. ex Gentil"
242
- parse(sn).should_not be_nil
243
- pos(sn).should == {0=>["genus", 4], 5=>["species", 10], 11=>["unknown_author", 14], 18=>["author_word", 24]}
244
- end
245
-
246
-
247
- it 'should not parse serveral authors groups with several years NOT CORRECT' do
248
- parse("Pseudocercospora dendrobii (H.C. Burnett 1883) (Leight.) (Movss. 1967) U. Braun & Crous 2003").should be_nil
249
- end
250
-
251
- it 'should parse names with taxon concept sec. part' do
252
- sn = "Sténométope laevissimus sec. Eschmeyer 2004"
253
- parse(sn).should_not be_nil
254
- details(sn).should == {:genus=>"Sténométope", :species=>"laevissimus", :taxon_concept=>{:authors=>{:names=>["Eschmeyer"], :year=>"2004"}}, :name_part_verbatim=>"Sténométope laevissimus", :auth_part_verbatim=>"sec. Eschmeyer 2004"}
255
- pos(sn).should == {0=>["genus", 11], 12=>["species", 23], 29=>["author_word", 38], 39=>["year", 43]}
256
- sn = "Sténométope laevissimus Bibron 1855 sec. Eschmeyer 2004"
305
+ details(sn).should == {:genus=>{:epitheton=>"Saccharomyces"}, :species=>{:epitheton=>"drosophilae", :authorship=>"anon.", :basionymAuthorTeam=>{:authorTeam=>"anon.", :author=>["unknown"]}}}
306
+ pos(sn).should == {0=>["genus", 13], 14=>["species", 25], 26=>["unknown_author", 31]}
307
+ sn = "Abacetus laevicollis de Chaudoir, 1869"
257
308
  parse(sn).should_not be_nil
258
- details(sn).should == {:genus=>"Sténométope", :species=>"laevissimus", :authors=>{:names=>["Bibron"], :year=>"1855"}, :taxon_concept=>{:authors=>{:names=>["Eschmeyer"], :year=>"2004"}}, :name_part_verbatim=>"Sténométope laevissimus", :auth_part_verbatim=>"Bibron 1855 sec. Eschmeyer 2004"}
259
- pos(sn).should == {0=>["genus", 11], 12=>["species", 23], 24=>["author_word", 30], 31=>["year", 35], 41=>["author_word", 50], 51=>["year", 55]}
260
- #
261
- # puts "<pre>"
262
- # puts @parser.failure_reason
263
- # #puts @parser.public_methods.select{|r| r.match /fail/}
264
- # puts "</pre>"
309
+ canonical(sn).should == 'Abacetus laevicollis'
310
+ sn = "Gastrosericus eremorum van Beaumont 1955"
311
+ canonical(sn).should == 'Gastrosericus eremorum'
312
+ sn = "Gastrosericus eremorum von Beaumont 1955"
313
+ canonical(sn).should == 'Gastrosericus eremorum'
314
+ sn = "Cypraeovula (Luponia) amphithales perdentata"
315
+ canonical(sn).should == 'Cypraeovula amphithales perdentata'
316
+ details(sn).should == {:genus=>{:epitheton=>"Cypraeovula"}, :subgenus=>{:epitheton=>"Luponia"}, :species=>{:epitheton=>"amphithales"}, :infraspecies=>{:epitheton=>"perdentata", :rank=>"n/a"}}
317
+ sn = "Polyrhachis orsyllus nat musculus Forel 1901"
318
+ canonical(sn).should == "Polyrhachis orsyllus musculus"
319
+ sn = 'Latrodectus 13-guttatus Thorell, 1875'
320
+ canonical(sn).should == 'Latrodectus 13-guttatus'
321
+ value(sn).should == 'Latrodectus 13-guttatus Thorell 1875'
322
+ sn = 'Latrodectus 3guttatus Thorell, 1875'
323
+ canonical(sn).should == 'Latrodectus 3-guttatus'
324
+ value(sn).should == 'Latrodectus 3-guttatus Thorell 1875'
265
325
  end
266
326
 
267
-
268
- it 'should parse utf-8 name' do
269
- sn = "Trematosphaeria phaeospora (E. Müll.) L. Holm 1957"
327
+ it "should parse name with morph." do
328
+ sn = "Callideriphus flavicollis morph. reductus Fuchs 1961"
270
329
  parse(sn).should_not be_nil
271
- value(sn).should == "Trematosphaeria phaeospora (E. Müll.) L. Holm 1957"
272
- canonical(sn).should == "Trematosphaeria phaeospora"
273
- details(sn).should == {:genus=>"Trematosphaeria", :species=>"phaeospora", :orig_authors=>{:names=>["E. Müll."]}, :authors=>{:names=>["L. Holm"], :year=>"1957"}, :name_part_verbatim=>"Trematosphaeria phaeospora", :auth_part_verbatim=>"(E. Müll.) L. Holm 1957"}
274
- pos(sn).should == {0=>["genus", 15], 16=>["species", 26], 28=>["author_word", 30], 31=>["author_word", 36], 46=>["author_word", 48], 61=>["author_word", 65], 66=>["year", 70]}
330
+ value(sn).should == "Callideriphus flavicollis morph. reductus Fuchs 1961"
331
+ canonical(sn).should == "Callideriphus flavicollis reductus"
332
+ details(sn).should == {:genus=>{:epitheton=>"Callideriphus"}, :species=>{:epitheton=>"flavicollis"}, :infraspecies=>{:epitheton=>"reductus", :rank=>"morph.", :authorship=>"Fuchs 1961", :basionymAuthorTeam=>{:authorTeam=>"Fuchs", :author=>["Fuchs"], :year=>"1961"}}}
333
+ pos(sn).should == {0=>["genus", 13], 14=>["species", 25], 33=>["infraspecies", 41], 42=>["author_word", 47], 48=>["year", 52]}
275
334
  end
276
-
277
- it "should parse name with var." do
278
- sn = "Phaeographis inusta var. macularis(Leight.) A.L. Sm. 1861"
279
- parse(sn).should_not be_nil
280
- value(sn).should == "Phaeographis inusta var. macularis (Leight.) A.L. Sm. 1861"
281
- canonical(sn).should == "Phaeographis inusta macularis"
282
- pos(sn).should == {0=>["genus", 12], 13=>["species", 19], 25=>["subspecies", 34], 35=>["author_word", 42], 44=>["author_word", 48], 49=>["author_word", 52], 53=>["year", 57]}
283
- end
284
-
285
- it "should parse name with morph." do
286
- sn = "Callideriphus flavicollis morph. reductus Fuchs 1961"
287
- parse(sn).should_not be_nil
288
- value(sn).should == "Callideriphus flavicollis morph. reductus Fuchs 1961"
289
- canonical(sn).should == "Callideriphus flavicollis reductus"
290
- details(sn).should == {:genus=>"Callideriphus", :species=>"flavicollis", :subspecies=>[{:rank=>"morph.", :value=>"reductus"}], :authors=>{:names=>["Fuchs"], :year=>"1961"}, :name_part_verbatim=>"Callideriphus flavicollis morph. reductus", :auth_part_verbatim=>"Fuchs 1961"}
291
- pos(sn).should == {0=>["genus", 13], 14=>["species", 25], 33=>["subspecies", 41], 42=>["author_word", 47], 48=>["year", 52]}
292
- end
293
-
294
- # "subsect."/"subtrib."/"subgen."/"trib."/
295
- #Stipa Speg. subgen. Leptostipa
296
- #Sporobolus subgen. Sporobolus R.Br.
297
335
 
298
- # it 'should parse name with "subsect."/"subtrib."/"subgen."/"trib."' do
299
- # val = "Sporobolus subgen. Sporobolus R.Br."
300
- # parse(val).should_not be_nil
301
- # # value(val).should == val
302
- # # canonical(val).should == "Callideriphus flavicollis reductus"
303
- # # details(val).should == {}
304
- # end
305
336
 
306
337
  it "should parse name with forma/fo./form./f." do
307
338
  sn = "Caulerpa cupressoides forma nuda"
308
339
  parse(sn).should_not be_nil
309
340
  value(sn).should == "Caulerpa cupressoides f. nuda"
310
341
  canonical(sn).should == "Caulerpa cupressoides nuda"
311
- details(sn).should == {:genus=>"Caulerpa", :species=>"cupressoides", :subspecies=>[{:rank=>"f.", :value=>"nuda"}]}
312
- pos(sn).should == {0=>["genus", 8], 9=>["species", 21], 28=>["subspecies", 32]}
342
+ details(sn).should == {:genus=>{:epitheton=>"Caulerpa"}, :species=>{:epitheton=>"cupressoides"}, :infraspecies=>{:epitheton=>"nuda", :rank=>"f."}}
343
+ pos(sn).should == {0=>["genus", 8], 9=>["species", 21], 28=>["infraspecies", 32]}
313
344
  sn = "Chlorocyperus glaber form. fasciculariforme (Lojac.) Soó"
314
345
  parse(sn).should_not be_nil
315
346
  value("Chlorocyperus glaber form. fasciculariforme (Lojac.) Soó").should == "Chlorocyperus glaber f. fasciculariforme (Lojac.) Soó"
316
347
  canonical(sn).should == "Chlorocyperus glaber fasciculariforme"
317
- details(sn).should == {:genus=>"Chlorocyperus", :species=>"glaber", :subspecies=>[{:rank=>"f.", :value=>"fasciculariforme"}], :orig_authors=>{:names=>["Lojac."]}, :authors=>{:names=>["Soó"]}, :name_part_verbatim=>"Chlorocyperus glaber form. fasciculariforme", :auth_part_verbatim=>"(Lojac.) Soó"}
318
- pos(sn).should == {0=>["genus", 13], 14=>["species", 20], 27=>["subspecies", 43], 45=>["author_word", 51], 53=>["author_word", 56]}
348
+ details(sn).should == {:genus=>{:epitheton=>"Chlorocyperus"}, :species=>{:epitheton=>"glaber"}, :infraspecies=>{:epitheton=>"fasciculariforme", :rank=>"f.", :authorship=>"(Lojac.) Soó", :combinationAuthorTeam=>{:authorTeam=>"Soó", :author=>["Soó"]}, :basionymAuthorTeam=>{:authorTeam=>"Lojac.", :author=>["Lojac."]}}}
349
+ pos(sn).should == {0=>["genus", 13], 14=>["species", 20], 27=>["infraspecies", 43], 45=>["author_word", 51], 53=>["author_word", 56]}
319
350
  sn = "Bambusa nana Roxb. fo. alphonse-karri (Mitford ex Satow) Makino ex Shiros."
320
351
  parse(sn).should_not be_nil
321
352
  value(sn).should == "Bambusa nana Roxb. f. alphonse-karri (Mitford ex Satow) Makino ex Shiros."
322
353
  canonical(sn).should == "Bambusa nana alphonse-karri"
323
- details(sn).should == {:genus=>"Bambusa", :species=>"nana", :subspecies=>[{:rank=>"f.", :value=>"alphonse-karri"}], :species_authors=>{:authors=>{:names=>["Roxb."]}}, :subspecies_authors=>{:original_revised_name_authors=>{:revised_authors=>{:names=>["Mitford"]}, :authors=>{:names=>["Satow"]}}, :revised_name_authors=>{:revised_authors=>{:names=>["Makino"]}, :authors=>{:names=>["Shiros."]}}}, :name_part_verbatim=>"Bambusa nana", :auth_part_verbatim=>"Roxb. fo. alphonse-karri (Mitford ex Satow) Makino ex Shiros."}
324
- pos(sn).should == {0=>["genus", 7], 8=>["species", 12], 13=>["author_word", 18], 23=>["subspecies", 37], 39=>["author_word", 46], 50=>["author_word", 55], 57=>["author_word", 63], 67=>["author_word", 74]}
354
+ details(sn).should == {:genus=>{:epitheton=>"Bambusa"}, :species=>{:epitheton=>"nana", :authorship=>"Roxb.", :basionymAuthorTeam=>{:authorTeam=>"Roxb.", :author=>["Roxb."]}}, :infraspecies=>{:epitheton=>"alphonse-karri", :rank=>"f.", :authorship=>"(Mitford ex Satow) Makino ex Shiros.", :combinationAuthorTeam=>{:authorTeam=>"Makino", :author=>["Makino"], :exAuthorTeam=>{:authorTeam=>"Shiros.", :author=>["Shiros."]}}, :basionymAuthorTeam=>{:authorTeam=>"Mitford", :author=>["Mitford"], :exAuthorTeam=>{:authorTeam=>"Satow", :author=>["Satow"]}}}}
355
+ pos(sn).should == {0=>["genus", 7], 8=>["species", 12], 13=>["author_word", 18], 23=>["infraspecies", 37], 39=>["author_word", 46], 50=>["author_word", 55], 57=>["author_word", 63], 67=>["author_word", 74]}
325
356
  sn = " Sphaerotheca fuliginea f. dahliae Movss. 1967 "
357
+ sn = "Sphaerotheca fuliginea f. dahliae Movss. 1967"
326
358
  parse(sn).should_not be_nil
327
359
  value(sn).should == "Sphaerotheca fuliginea f. dahliae Movss. 1967"
328
360
  canonical(sn).should == "Sphaerotheca fuliginea dahliae"
329
- details(sn).should == {:genus=>"Sphaerotheca", :species=>"fuliginea", :subspecies=>[{:rank=>"f.", :value=>"dahliae"}], :authors=>{:names=>["Movss."], :year=>"1967"}, :name_part_verbatim=>"Sphaerotheca fuliginea f. dahliae", :auth_part_verbatim=>"Movss. 1967"}
330
- pos(sn).should == {3=>["genus", 15], 19=>["species", 28], 39=>["subspecies", 46], 50=>["author_word", 56], 59=>["year", 63]}
361
+ details(sn).should == {:genus=>{:epitheton=>"Sphaerotheca"}, :species=>{:epitheton=>"fuliginea"}, :infraspecies=>{:epitheton=>"dahliae", :rank=>"f.", :authorship=>"Movss. 1967", :basionymAuthorTeam=>{:authorTeam=>"Movss.", :author=>["Movss."], :year=>"1967"}}}
362
+ pos(sn).should == {0=>["genus", 12], 16=>["species", 25], 36=>["infraspecies", 43], 47=>["author_word", 53], 58=>["year", 62]}
363
+ parse('Polypodium vulgare nothosubsp. mantoniae (Rothm.) Schidlay').should_not be_nil
331
364
  end
332
365
 
333
366
  it "should parse name with several subspecies names NOT BOTANICAL CODE BUT NOT INFREQUENT" do
334
367
  sn = "Hydnellum scrobiculatum var. zonatum f. parvum (Banker) D. Hall & D.E. Stuntz 1972"
335
368
  parse(sn).should_not be_nil
336
369
  value(sn).should == "Hydnellum scrobiculatum var. zonatum f. parvum (Banker) D. Hall et D.E. Stuntz 1972"
337
- details(sn).should == {:genus=>"Hydnellum", :species=>"scrobiculatum", :subspecies=>[{:rank=>"var.", :value=>"zonatum"}, {:rank=>"f.", :value=>"parvum"}], :is_valid=>false, :orig_authors=>{:names=>["Banker"]}, :authors=>{:names=>["D. Hall", "D.E. Stuntz"], :year=>"1972"}, :name_part_verbatim=>"Hydnellum scrobiculatum var. zonatum f. parvum", :auth_part_verbatim=>"(Banker) D. Hall & D.E. Stuntz 1972"}
338
- pos(sn).should == {0=>["genus", 9], 10=>["species", 23], 29=>["subspecies", 36], 40=>["subspecies", 46], 48=>["author_word", 54], 56=>["author_word", 58], 59=>["author_word", 63], 66=>["author_word", 70], 71=>["author_word", 77], 78=>["year", 82]}
370
+ details(sn).should == {:genus=>{:epitheton=>"Hydnellum"}, :species=>{:epitheton=>"scrobiculatum"}, :infraspecies=>[{:epitheton=>"zonatum", :rank=>"var."}, {:epitheton=>"parvum", :rank=>"f.", :authorship=>"(Banker) D. Hall & D.E. Stuntz 1972", :combinationAuthorTeam=>{:authorTeam=>"D. Hall & D.E. Stuntz", :author=>["D. Hall", "D.E. Stuntz"], :year=>"1972"}, :basionymAuthorTeam=>{:authorTeam=>"Banker", :author=>["Banker"]}}]}
371
+ pos(sn).should == {0=>["genus", 9], 10=>["species", 23], 29=>["infraspecies", 36], 40=>["infraspecies", 46], 48=>["author_word", 54], 56=>["author_word", 58], 59=>["author_word", 63], 66=>["author_word", 70], 71=>["author_word", 77], 78=>["year", 82]}
372
+ parse('Senecio fuchsii C.C.Gmel. subsp. fuchsii var. expansus (Boiss. & Heldr.) Hayek').should_not be_nil
373
+ parse('Senecio fuchsii C.C.Gmel. subsp. fuchsii var. fuchsii').should_not be_nil
339
374
  end
340
375
 
376
+
341
377
  it "should parse status BOTANICAL RARE" do
342
378
  #it is always latin abbrev often 2 words
343
379
  sn = "Arthopyrenia hyalospora (Nyl.) R.C. Harris comb. nov."
344
380
  parse(sn).should_not be_nil
345
381
  value(sn).should == "Arthopyrenia hyalospora (Nyl.) R.C. Harris comb. nov."
346
382
  canonical(sn).should == "Arthopyrenia hyalospora"
347
- details(sn).should == {:genus=>"Arthopyrenia", :species=>"hyalospora", :orig_authors=>{:names=>["Nyl."]}, :authors=>{:names=>["R.C. Harris"]}, :status=>"comb. nov.", :name_part_verbatim=>"Arthopyrenia hyalospora", :auth_part_verbatim=>"(Nyl.) R.C. Harris comb. nov."}
383
+ details(sn).should == {:genus=>{:epitheton=>"Arthopyrenia"}, :species=>{:epitheton=>"hyalospora", :authorship=>"(Nyl.) R.C. Harris", :combinationAuthorTeam=>{:authorTeam=>"R.C. Harris ", :author=>["R.C. Harris"]}, :basionymAuthorTeam=>{:authorTeam=>"Nyl.", :author=>["Nyl."]}}, :status=>"comb. nov."}
348
384
  pos(sn).should == {0=>["genus", 12], 13=>["species", 23], 25=>["author_word", 29], 31=>["author_word", 35], 36=>["author_word", 42]}
349
385
  end
350
386
 
351
- it "should parse name without a year but with authors" do
352
- sn = "Arthopyrenia hyalospora(Nyl.)R.C. Harris"
353
- parse(sn).should_not be_nil
354
- value(sn).should == "Arthopyrenia hyalospora (Nyl.) R.C. Harris"
355
- canonical(sn).should == "Arthopyrenia hyalospora"
356
- pos(sn).should == {0=>["genus", 12], 13=>["species", 23], 24=>["author_word", 28], 29=>["author_word", 33], 38=>["author_word", 44]}
357
- end
358
-
359
387
  it "should parse revised (ex) names" do
360
388
  #invalidly published
361
389
  sn = "Arthopyrenia hyalospora (Nyl. ex Banker) R.C. Harris"
362
390
  parse(sn).should_not be_nil
363
391
  value(sn).should == "Arthopyrenia hyalospora (Nyl. ex Banker) R.C. Harris"
364
392
  canonical(sn).should == "Arthopyrenia hyalospora"
365
- details(sn).should == {:genus=>"Arthopyrenia", :species=>"hyalospora", :original_revised_name_authors=>{:revised_authors=>{:names=>["Nyl."]}, :authors=>{:names=>["Banker"]}}, :authors=>{:names=>["R.C. Harris"]}, :name_part_verbatim=>"Arthopyrenia hyalospora", :auth_part_verbatim=>"(Nyl. ex Banker) R.C. Harris"}
393
+ details(sn).should == {:genus=>{:epitheton=>"Arthopyrenia"}, :species=>{:epitheton=>"hyalospora", :authorship=>"(Nyl. ex Banker) R.C. Harris", :combinationAuthorTeam=>{:authorTeam=>"R.C. Harris", :author=>["R.C. Harris"]}, :basionymAuthorTeam=>{:authorTeam=>"Nyl.", :author=>["Nyl."], :exAuthorTeam=>{:authorTeam=>"Banker", :author=>["Banker"]}}}}
366
394
  pos(sn).should == {0=>["genus", 12], 13=>["species", 23], 25=>["author_word", 29], 33=>["author_word", 39], 41=>["author_word", 45], 46=>["author_word", 52]}
367
-
368
- parse("Arthopyrenia hyalospora Nyl. ex Banker").should_not be_nil
395
+ sn = "Arthopyrenia hyalospora Nyl. ex Banker"
396
+ parse(sn).should_not be_nil
397
+ details(sn).should == {:genus=>{:epitheton=>"Arthopyrenia"}, :species=>{:epitheton=>"hyalospora", :authorship=>"Nyl. ex Banker", :basionymAuthorTeam=>{:authorTeam=>"Nyl.", :author=>["Nyl."], :exAuthorTeam=>{:authorTeam=>"Banker", :author=>["Banker"]}}}}
369
398
  sn = "Glomopsis lonicerae Peck ex C.J. Gould 1945"
370
399
  parse(sn).should_not be_nil
371
- details(sn).should == {:genus=>"Glomopsis", :species=>"lonicerae", :revised_name_authors=>{:revised_authors=>{:names=>["Peck"]}, :authors=>{:names=>["C.J. Gould"], :year=>"1945"}}, :name_part_verbatim=>"Glomopsis lonicerae", :auth_part_verbatim=>"Peck ex C.J. Gould 1945"}
400
+ details(sn).should == {:genus=>{:epitheton=>"Glomopsis"}, :species=>{:epitheton=>"lonicerae", :authorship=>"Peck ex C.J. Gould 1945", :basionymAuthorTeam=>{:authorTeam=>"Peck", :author=>["Peck"], :exAuthorTeam=>{:authorTeam=>"C.J. Gould", :author=>["C.J. Gould"], :year=>"1945"}}}}
372
401
  pos(sn).should == {0=>["genus", 9], 10=>["species", 19], 20=>["author_word", 24], 28=>["author_word", 32], 33=>["author_word", 38], 39=>["year", 43]}
373
402
  parse("Acanthobasidium delicatum (Wakef.) Oberw. ex Jülich 1979").should_not be_nil
374
403
  sn = "Mycosphaerella eryngii (Fr. ex Duby) Johanson ex Oudem. 1897"
375
404
  parse(sn).should_not be_nil
376
- details(sn).should == {:genus=>"Mycosphaerella", :species=>"eryngii", :original_revised_name_authors=>{:revised_authors=>{:names=>["Fr."]}, :authors=>{:names=>["Duby"]}}, :revised_name_authors=>{:revised_authors=>{:names=>["Johanson"]}, :authors=>{:names=>["Oudem."], :year=>"1897"}}, :name_part_verbatim=>"Mycosphaerella eryngii", :auth_part_verbatim=>"(Fr. ex Duby) Johanson ex Oudem. 1897"}
405
+ details(sn).should == {:genus=>{:epitheton=>"Mycosphaerella"}, :species=>{:epitheton=>"eryngii", :authorship=>"(Fr. ex Duby) Johanson ex Oudem. 1897", :combinationAuthorTeam=>{:authorTeam=>"Johanson", :author=>["Johanson"], :exAuthorTeam=>{:authorTeam=>"Oudem.", :author=>["Oudem."], :year=>"1897"}}, :basionymAuthorTeam=>{:authorTeam=>"Fr.", :author=>["Fr."], :exAuthorTeam=>{:authorTeam=>"Duby", :author=>["Duby"]}}}}
377
406
  pos(sn).should == {0=>["genus", 14], 15=>["species", 22], 24=>["author_word", 27], 31=>["author_word", 35], 37=>["author_word", 45], 49=>["author_word", 55], 56=>["year", 60]}
378
407
  #invalid but happens
379
408
  parse("Mycosphaerella eryngii (Fr. Duby) ex Oudem. 1897").should_not be_nil
380
409
  parse("Mycosphaerella eryngii (Fr.ex Duby) ex Oudem. 1897").should_not be_nil
381
410
  sn = "Salmonella werahensis (Castellani) Hauduroy and Ehringer in Hauduroy 1937"
382
411
  parse(sn).should_not be_nil
412
+ details(sn).should == {:genus=>{:epitheton=>"Salmonella"}, :species=>{:epitheton=>"werahensis", :authorship=>"(Castellani) Hauduroy and Ehringer in Hauduroy 1937", :combinationAuthorTeam=>{:authorTeam=>"Hauduroy and Ehringer", :author=>["Hauduroy", "Ehringer"], :exAuthorTeam=>{:authorTeam=>"Hauduroy", :author=>["Hauduroy"], :year=>"1937"}}, :basionymAuthorTeam=>{:authorTeam=>"Castellani", :author=>["Castellani"]}}}
383
413
  pos(sn).should == {0=>["genus", 10], 11=>["species", 21], 23=>["author_word", 33], 35=>["author_word", 43], 48=>["author_word", 56], 60=>["author_word", 68], 69=>["year", 73]}
384
414
  end
385
-
386
- it "should parse multiplication sign" do
387
- sn = "Arthopyrenia x hyalospora (Nyl.) R.C. Harris"
388
- parse(sn).should_not be_nil
389
- details(sn).should == {:genus=>"Arthopyrenia", :species=>"hyalospora", :cross=>"inside", :orig_authors=>{:names=>["Nyl."]}, :authors=>{:names=>["R.C. Harris"]}, :name_part_verbatim=>"Arthopyrenia x hyalospora", :auth_part_verbatim=>"(Nyl.) R.C. Harris"}
390
- pos(sn).should == {0=>["genus", 12], 15=>["species", 25], 27=>["author_word", 31], 33=>["author_word", 37], 38=>["author_word", 44]}
391
- parse("Arthopyrenia X hyalospora(Nyl. ex Banker) R.C. Harris").should_not be_nil
392
- sn = "x Arthopyrenia hyalospora (Nyl. ex Banker) R.C. Harris"
393
- parse(sn).should_not be_nil
394
- details(sn).should == {:genus=>"Arthopyrenia", :species=>"hyalospora", :cross=>"before", :original_revised_name_authors=>{:revised_authors=>{:names=>["Nyl."]}, :authors=>{:names=>["Banker"]}}, :authors=>{:names=>["R.C. Harris"]}, :name_part_verbatim=>"x Arthopyrenia hyalospora", :auth_part_verbatim=>"(Nyl. ex Banker) R.C. Harris"}
395
- pos(sn).should == {2=>["genus", 14], 15=>["species", 25], 27=>["author_word", 31], 35=>["author_word", 41], 43=>["author_word", 47], 48=>["author_word", 54]}
396
- sn = "X Arthopyrenia (Nyl. ex Banker) R.C. Harris"
397
- parse(sn).should_not be_nil
398
- details(sn).should == {:uninomial=>"Arthopyrenia", :cross=>"before", :original_revised_name_authors=>{:revised_authors=>{:names=>["Nyl."]}, :authors=>{:names=>["Banker"]}}, :authors=>{:names=>["R.C. Harris"]}, :name_part_verbatim=>"X Arthopyrenia", :auth_part_verbatim=>"(Nyl. ex Banker) R.C. Harris"}
399
- pos(sn).should == {2=>["uninomial", 14], 16=>["author_word", 20], 24=>["author_word", 30], 32=>["author_word", 36], 37=>["author_word", 43]}
400
- #ascii for multiplication
401
- parse("Melampsora × columbiana G. Newc. 2000").should_not be_nil
415
+
416
+ it 'should parse named hybrids' do
417
+ [
418
+ ["×Agropogon P. Fourn. 1934", {:namedHybrid=>{:uninomial=>{:epitheton=>"Agropogon", :authorship=>"P. Fourn. 1934", :basionymAuthorTeam=>{:authorTeam=>"P. Fourn.", :author=>["P. Fourn."], :year=>"1934"}}}}],
419
+ ["xAgropogon P. Fourn.", {:namedHybrid=>{:uninomial=>{:epitheton=>"Agropogon", :authorship=>"P. Fourn.", :basionymAuthorTeam=>{:authorTeam=>"P. Fourn.", :author=>["P. Fourn."]}}}}],
420
+ ["XAgropogon P.Fourn.", {:namedHybrid=>{:uninomial=>{:epitheton=>"Agropogon", :authorship=>"P.Fourn.", :basionymAuthorTeam=>{:authorTeam=>"P.Fourn.", :author=>["P.Fourn."]}}}}],
421
+ ["× Agropogon", {:namedHybrid=>{:uninomial=>{:epitheton=>"Agropogon"}}}],
422
+ ["x Agropogon", {:namedHybrid=>{:uninomial=>{:epitheton=>"Agropogon"}}}],
423
+ ["X Agropogon", {:namedHybrid=>{:uninomial=>{:epitheton=>"Agropogon"}}}],
424
+ ["X Cupressocyparis leylandii", {:namedHybrid=>{:genus=>{:epitheton=>"Cupressocyparis"}, :species=>{:epitheton=>"leylandii"}}}],
425
+ ["×Heucherella tiarelloides", {:namedHybrid=>{:genus=>{:epitheton=>"Heucherella"}, :species=>{:epitheton=>"tiarelloides"}}}],
426
+ ["xHeucherella tiarelloides", {:namedHybrid=>{:genus=>{:epitheton=>"Heucherella"}, :species=>{:epitheton=>"tiarelloides"}}}],
427
+ ["x Heucherella tiarelloides", {:namedHybrid=>{:genus=>{:epitheton=>"Heucherella"}, :species=>{:epitheton=>"tiarelloides"}}}],
428
+ ["×Agropogon littoralis (Sm.) C. E. Hubb. 1946", {:namedHybrid=>{:genus=>{:epitheton=>"Agropogon"}, :species=>{:epitheton=>"littoralis", :authorship=>"(Sm.) C. E. Hubb. 1946", :combinationAuthorTeam=>{:authorTeam=>"C. E. Hubb.", :author=>["C. E. Hubb."], :year=>"1946"}, :basionymAuthorTeam=>{:authorTeam=>"Sm.", :author=>["Sm."]}}}}]
429
+ ].each do |res|
430
+ parse(res[0]).should_not be_nil
431
+ details(res[0]).should == res[1]
432
+ end
433
+ [
434
+ ['Asplenium X inexpectatum (E.L. Braun 1940) Morton (1956)',{:genus=>{:epitheton=>"Asplenium"}, :species=>{:epitheton=>"inexpectatum", :namedHybrid=>true, :authorship=>"(E.L. Braun 1940) Morton (1956)", :combinationAuthorTeam=>{:authorTeam=>"Morton", :author=>["Morton"], :year=>"1956"}, :basionymAuthorTeam=>{:authorTeam=>"E.L. Braun", :author=>["E.L. Braun"], :year=>"1940"}}}],
435
+ ['Mentha ×smithiana R. A. Graham 1949',{:genus=>{:epitheton=>"Mentha"}, :species=>{:epitheton=>"smithiana", :namedHybrid=>true, :authorship=>"R. A. Graham 1949", :basionymAuthorTeam=>{:authorTeam=>"R. A. Graham", :author=>["R. A. Graham"], :year=>"1949"}}}],
436
+ ['Salix ×capreola Andersson (1867)',{:genus=>{:epitheton=>"Salix"}, :species=>{:epitheton=>"capreola", :namedHybrid=>true, :authorship=>"Andersson (1867)", :basionymAuthorTeam=>{:authorTeam=>"Andersson", :author=>["Andersson"], :year=>"1867"}}}],
437
+ ['Salix x capreola Andersson',{:genus=>{:epitheton=>"Salix"}, :species=>{:epitheton=>"capreola", :namedHybrid=>true, :authorship=>"Andersson", :basionymAuthorTeam=>{:authorTeam=>"Andersson", :author=>["Andersson"]}}}]
438
+ ].each do |res|
439
+ parse(res[0]).should_not be_nil
440
+ details(res[0]).should == res[1]
441
+ end
402
442
  end
403
443
 
404
444
  it "should parse hybrid combination" do
405
445
  sn = "Arthopyrenia hyalospora X Hydnellum scrobiculatum"
406
- parse(sn).should_not be_nil
446
+ parse(sn).should_not be_nil
407
447
  value(sn).should == "Arthopyrenia hyalospora \303\227 Hydnellum scrobiculatum"
408
- canonical(sn).should == "Arthopyrenia hyalospora \303\227 Hydnellum scrobiculatum"
409
- details(sn).should == {:hybrid=>{:scientific_name1=>{:species=>"hyalospora", :genus=>"Arthopyrenia"}, :scientific_name2=>{:species=>"scrobiculatum", :genus=>"Hydnellum"}}}
448
+ canonical(sn).should == "Arthopyrenia hyalospora Hydnellum scrobiculatum"
449
+ details(sn).should == {:hybridFormula=>[{:genus=>{:epitheton=>"Arthopyrenia"}, :species=>{:epitheton=>"hyalospora"}}, {:genus=>{:epitheton=>"Hydnellum"}, :species=>{:epitheton=>"scrobiculatum"}}]}
410
450
  pos(sn).should == {0=>["genus", 12], 13=>["species", 23], 26=>["genus", 35], 36=>["species", 49]}
411
451
  sn = "Arthopyrenia hyalospora (Banker) D. Hall X Hydnellum scrobiculatum D.E. Stuntz"
412
452
  parse(sn).should_not be_nil
413
453
  value(sn).should == "Arthopyrenia hyalospora (Banker) D. Hall \303\227 Hydnellum scrobiculatum D.E. Stuntz"
414
- canonical(sn).should == "Arthopyrenia hyalospora \303\227 Hydnellum scrobiculatum"
454
+ canonical(sn).should == "Arthopyrenia hyalospora Hydnellum scrobiculatum"
415
455
  pos(sn).should == {0=>["genus", 12], 13=>["species", 23], 25=>["author_word", 31], 33=>["author_word", 35], 36=>["author_word", 40], 43=>["genus", 52], 53=>["species", 66], 67=>["author_word", 71], 72=>["author_word", 78]}
416
456
  value("Arthopyrenia hyalospora X").should == "Arthopyrenia hyalospora \303\227 ?"
417
457
  sn = "Arthopyrenia hyalospora x"
418
458
  parse(sn).should_not be_nil
419
459
  canonical(sn).should == "Arthopyrenia hyalospora"
420
- details(sn).should == {:hybrid=>{:scientific_name1=>{:species=>"hyalospora", :genus=>"Arthopyrenia"}, :scientific_name2=>"?"}}
460
+ details(sn).should == {:hybridFormula=>[{:genus=>{:epitheton=>"Arthopyrenia"}, :species=>{:epitheton=>"hyalospora"}}, "?"]}
421
461
  pos(sn).should == {0=>["genus", 12], 13=>["species", 23]}
422
462
  sn = "Arthopyrenia hyalospora × ?"
423
463
  parse(sn).should_not be_nil
424
- details(sn).should == {:hybrid=>{:scientific_name1=>{:species=>"hyalospora", :genus=>"Arthopyrenia"}, :scientific_name2=>"?"}}
464
+ details(sn).should == {:hybridFormula=>[{:genus=>{:epitheton=>"Arthopyrenia"}, :species=>{:epitheton=>"hyalospora"}}, "?"]}
425
465
  pos(sn).should == {0=>["genus", 12], 13=>["species", 23]}
426
466
  end
427
-
428
467
 
429
-
430
- it "should parse name with subspecies without rank NOT BOTANICAL" do
431
- sn = "Hydnellum scrobiculatum zonatum (Banker) D. Hall & D.E. Stuntz 1972"
432
- parse(sn).should_not be_nil
433
- value(sn).should == "Hydnellum scrobiculatum zonatum (Banker) D. Hall et D.E. Stuntz 1972"
434
- canonical(sn).should == "Hydnellum scrobiculatum zonatum"
435
- details(sn).should == {:genus=>"Hydnellum", :species=>"scrobiculatum", :subspecies=>{:rank=>"n/a", :value=>"zonatum"}, :orig_authors=>{:names=>["Banker"]}, :authors=>{:names=>["D. Hall", "D.E. Stuntz"], :year=>"1972"}, :name_part_verbatim=>"Hydnellum scrobiculatum zonatum", :auth_part_verbatim=>"(Banker) D. Hall & D.E. Stuntz 1972"}
436
- pos(sn).should == {0=>["genus", 9], 10=>["species", 23], 24=>["subspecies", 31], 33=>["author_word", 39], 41=>["author_word", 43], 44=>["author_word", 48], 51=>["author_word", 55], 56=>["author_word", 62], 63=>["year", 67]}
437
- sn = "Begonia pingbienensis angustior"
468
+ it 'should parse names with taxon concept' do
469
+ sn = "Sténométope laevissimus sec. Eschmeyer 2004"
470
+ val = @parser.failure_reason.to_s.match(/column [0-9]*/).to_s().gsub(/column /,'')
471
+ details(sn).should == {:genus=>{:epitheton=>"Sténométope"}, :species=>{:epitheton=>"laevissimus"}, :taxon_concept=>{:authorship=>"Eschmeyer 2004", :basionymAuthorTeam=>{:authorTeam=>"Eschmeyer", :author=>["Eschmeyer"], :year=>"2004"}}}
472
+ pos(sn).should == {0=>["genus", 11], 12=>["species", 23], 29=>["author_word", 38], 39=>["year", 43]}
473
+ sn = "Sténométope laevissimus Bibron 1855 sec. Eschmeyer 2004"
438
474
  parse(sn).should_not be_nil
439
- details(sn).should == {:genus=>"Begonia", :species=>"pingbienensis", :subspecies=>{:rank=>"n/a", :value=>"angustior"}}
440
- pos(sn).should == {0=>["genus", 7], 8=>["species", 21], 22=>["subspecies", 31]}
475
+ details(sn).should == {:genus=>{:epitheton=>"Sténométope"}, :species=>{:epitheton=>"laevissimus", :authorship=>"Bibron 1855", :basionymAuthorTeam=>{:authorTeam=>"Bibron", :author=>["Bibron"], :year=>"1855"}}, :taxon_concept=>{:authorship=>"Eschmeyer 2004", :basionymAuthorTeam=>{:authorTeam=>"Eschmeyer", :author=>["Eschmeyer"], :year=>"2004"}}}
476
+ pos(sn).should == {0=>["genus", 11], 12=>["species", 23], 24=>["author_word", 30], 31=>["year", 35], 41=>["author_word", 50], 51=>["year", 55]}
441
477
  end
442
478
 
443
- it "should not parse unallowed utf-8 chars in name part" do
444
- parse("Érematosphaeria phaespora").should be_nil
445
- parse("Trematosphaeria phaeáapora").should be_nil
446
- parse("Trematоsphaeria phaeáapora").should be_nil #cyrillic o
479
+ it 'should parse names with spaces inconsistencies at the start and the end and in the middle' do
480
+ parse(" Asplenium X inexpectatum (E.L. Braun 1940) Morton (1956) ").should_not be_nil
447
481
  end
448
482
 
449
- it "should parse some invalid names" do
450
- parse("Acarospora cratericola 1929").should_not be_nil
451
- parse("Agaricus acris var. (b.)").should_not be_nil
452
- value("Agaricus acris var. (b.)").should == "Agaricus acris var. (b.)"
453
- parse("Agaricus acris var. (b.)").should_not be_nil
454
- sn = "Agaricus acris var. (b.&c.)"
455
- value(sn).should == "Agaricus acris var. (b.c.)"
456
- details(sn).should == {:editorial_markup=>"(b.c.)", :subspecies=>[{:rank=>"var.", :value=>nil}], :species=>"acris", :genus=>"Agaricus", :is_valid=>false}
457
- pos(sn).should == {0=>["genus", 8], 9=>["species", 14]}
483
+ it 'should not parse serveral authors groups with several years NOT CORRECT' do
484
+ parse("Pseudocercospora dendrobii (H.C. Burnett 1883) (Leight.) (Movss. 1967) U. Braun & Crous 2003").should be_nil
458
485
  end
459
486
 
460
- it 'should parse double parenthesis' do
461
- sn = "Eichornia crassipes ( (Martius) ) Solms-Laub."
462
- parse(sn).should_not be_nil
463
- value(sn).should == "Eichornia crassipes (Martius) Solms-Laub."
464
- details(sn).should == {:genus=>"Eichornia", :species=>"crassipes", :orig_authors=>{:names=>["Martius"]}, :authors=>{:names=>["Solms-Laub."]}, :name_part_verbatim=>"Eichornia crassipes", :auth_part_verbatim=>"( (Martius) ) Solms-Laub."}
465
- pos(sn).should == {0=>["genus", 9], 10=>["species", 19], 23=>["author_word", 30], 34=>["author_word", 45]}
487
+ it "should not parse unallowed utf-8 chars in name part" do
488
+ parse("Érematosphaeria phaespora").should be_nil
489
+ parse("Trematosphaeria phaeáapora").should be_nil
490
+ parse("Trematоsphaeria phaeáapora").should be_nil #cyrillic o
466
491
  end
467
492
 
468
- # val = "Ferganoconcha? oblonga"
469
- it 'should parse genus?' do
470
- sn = "Ferganoconcha? oblonga"
471
- parse(sn).should_not be_nil
472
- value(sn).should == "Ferganoconcha oblonga"
473
- details(sn).should == {:genus=>"Ferganoconcha", :species=>"oblonga"}
474
- pos(sn).should == {0=>["genus", 14], 15=>["species", 22]}
475
- end
476
-
477
- it 'should parse new additions' do
478
- sn = "Abacetus laevicollis de Chaudoir, 1869"
479
- parse(sn).should_not be_nil
480
- canonical(sn).should == 'Abacetus laevicollis'
481
- sn = "Gastrosericus eremorum van Beaumont 1955"
482
- canonical(sn).should == 'Gastrosericus eremorum'
483
- sn = "Gastrosericus eremorum von Beaumont 1955"
484
- canonical(sn).should == 'Gastrosericus eremorum'
485
- sn = "Cypraeovula (Luponia) amphithales perdentata"
486
- canonical(sn).should == 'Cypraeovula amphithales perdentata'
487
- details(sn).should == {:genus=>"Cypraeovula", :subgenus=>"Luponia", :species=>"amphithales", :subspecies=>{:rank=>"n/a", :value=>"perdentata"}}
488
- sn = "Polyrhachis orsyllus nat musculus Forel 1901"
489
- canonical(sn).should == "Polyrhachis orsyllus musculus"
490
- sn = 'Latrodectus 13-guttatus Thorell, 1875'
491
- canonical(sn).should == 'Latrodectus 13-guttatus'
492
- value(sn).should == 'Latrodectus 13-guttatus Thorell 1875'
493
- sn = 'Latrodectus 3guttatus Thorell, 1875'
494
- canonical(sn).should == 'Latrodectus 3-guttatus'
495
- value(sn).should == 'Latrodectus 3-guttatus Thorell 1875'
496
- end
497
493
 
498
- end
494
+ end