nexus_parser 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/lexer.rb +4 -4
- data/lib/{nexus_file.rb → nexus_parser.rb} +20 -21
- data/lib/parser.rb +92 -92
- data/lib/tokens.rb +40 -40
- data/nexus_parser.gemspec +61 -0
- data/test/MX_test_03.nex +234 -234
- data/test/test_nexus_parser.rb +210 -213
- metadata +5 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.1.0
|
data/lib/lexer.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
|
2
2
|
|
3
|
-
class
|
3
|
+
class NexusParser::Lexer
|
4
4
|
|
5
5
|
def initialize(input)
|
6
6
|
@input = input
|
@@ -21,7 +21,7 @@ class NexusFile::Lexer
|
|
21
21
|
token = read_next_token(token_class)
|
22
22
|
@next_token = nil
|
23
23
|
if token.class != token_class
|
24
|
-
raise(
|
24
|
+
raise(NexusParser::ParseError,"expected #{token_class.to_s} but received #{token.class.to_s} at #{@input[0..10]}...", caller)
|
25
25
|
else
|
26
26
|
return token
|
27
27
|
end
|
@@ -38,13 +38,13 @@ class NexusFile::Lexer
|
|
38
38
|
return @next_token
|
39
39
|
else
|
40
40
|
# now check all the tokens for a match
|
41
|
-
|
41
|
+
NexusParser::Tokens.nexus_file_token_list.each {|t|
|
42
42
|
return @next_token if match(t)
|
43
43
|
}
|
44
44
|
end
|
45
45
|
# no match, either end of string or lex-error
|
46
46
|
if @input != ''
|
47
|
-
raise(
|
47
|
+
raise( NexusParser::ParseError, "Lex Error, unknown token at #{@input[0..10]}...", caller)
|
48
48
|
else
|
49
49
|
return nil
|
50
50
|
end
|
@@ -7,13 +7,13 @@
|
|
7
7
|
# outstanding issues:
|
8
8
|
## need to resolve Tokens Labels, ValuePair, IDs
|
9
9
|
|
10
|
-
module
|
10
|
+
module NexusParser
|
11
11
|
|
12
12
|
require File.expand_path(File.join(File.dirname(__FILE__), 'tokens'))
|
13
13
|
require File.expand_path(File.join(File.dirname(__FILE__), 'parser'))
|
14
14
|
require File.expand_path(File.join(File.dirname(__FILE__), 'lexer'))
|
15
15
|
|
16
|
-
class
|
16
|
+
class NexusParser
|
17
17
|
|
18
18
|
attr_accessor :taxa, :characters, :sets, :codings, :vars, :notes
|
19
19
|
|
@@ -117,20 +117,20 @@ class NexusFile
|
|
117
117
|
end
|
118
118
|
|
119
119
|
|
120
|
-
# constructs the
|
120
|
+
# constructs the NexusParser
|
121
121
|
class Builder
|
122
122
|
|
123
123
|
def initialize
|
124
|
-
@nf =
|
124
|
+
@nf = NexusParser.new
|
125
125
|
end
|
126
126
|
|
127
127
|
def stub_taxon
|
128
|
-
@nf.taxa.push(
|
128
|
+
@nf.taxa.push(NexusParser::Taxon.new)
|
129
129
|
return @nf.taxa.size
|
130
130
|
end
|
131
131
|
|
132
132
|
def stub_chr
|
133
|
-
@nf.characters.push(
|
133
|
+
@nf.characters.push(NexusParser::Character.new)
|
134
134
|
return @nf.characters.size
|
135
135
|
end
|
136
136
|
|
@@ -138,7 +138,7 @@ class Builder
|
|
138
138
|
|
139
139
|
@nf.characters.each_with_index do |c, i|
|
140
140
|
@nf.codings[taxon_index.to_i] = [] if !@nf.codings[taxon_index.to_i]
|
141
|
-
@nf.codings[taxon_index.to_i][i] =
|
141
|
+
@nf.codings[taxon_index.to_i][i] = NexusParser::Coding.new(:states => rowvector[i])
|
142
142
|
|
143
143
|
# !! we must update states for a given character if the state isn't found (not all states are referenced in description !!
|
144
144
|
|
@@ -183,7 +183,7 @@ class Builder
|
|
183
183
|
|
184
184
|
# need to create the characters
|
185
185
|
|
186
|
-
raise(
|
186
|
+
raise(NexusParser::ParseError, "Can't update character of index #{@index}, it doesn't exist! This is a problem parsing the character state labels. Check the indices. It may be for this character \"#{@opt[:name]}\".") if !@nf.characters[@index]
|
187
187
|
|
188
188
|
(@nf.characters[@index].name = @opt[:name]) if @opt[:name]
|
189
189
|
|
@@ -223,28 +223,28 @@ class Builder
|
|
223
223
|
# Why does mesquite differentiate b/w footnotes and annotations?!, apparently same data structure?
|
224
224
|
when 'TEXT' # a footnote
|
225
225
|
if @opt[:file]
|
226
|
-
@nf.notes <<
|
226
|
+
@nf.notes << NexusParser::Note.new(@opt)
|
227
227
|
|
228
228
|
elsif @opt[:taxon] && @opt[:character] # its a cell, parse this case
|
229
229
|
@nf.codings[@opt[:taxon].to_i - 1][@opt[:character].to_i - 1].notes = [] if !@nf.codings[@opt[:taxon].to_i - 1][@opt[:character].to_i - 1].notes
|
230
|
-
@nf.codings[@opt[:taxon].to_i - 1][@opt[:character].to_i - 1].notes <<
|
230
|
+
@nf.codings[@opt[:taxon].to_i - 1][@opt[:character].to_i - 1].notes << NexusParser::Note.new(@opt)
|
231
231
|
|
232
232
|
elsif @opt[:taxon] && !@opt[:character]
|
233
|
-
@nf.taxa[@opt[:taxon].to_i - 1].notes <<
|
233
|
+
@nf.taxa[@opt[:taxon].to_i - 1].notes << NexusParser::Note.new(@opt)
|
234
234
|
|
235
235
|
elsif @opt[:character] && !@opt[:taxon]
|
236
236
|
|
237
|
-
@nf.characters[@opt[:character].to_i - 1].notes <<
|
237
|
+
@nf.characters[@opt[:character].to_i - 1].notes << NexusParser::Note.new(@opt)
|
238
238
|
end
|
239
239
|
|
240
240
|
when 'AN' # an annotation, rather than a footnote, same dif
|
241
241
|
if @opt[:t] && @opt[:c]
|
242
242
|
@nf.codings[@opt[:t].to_i - 1][@opt[:c].to_i - 1].notes = [] if !@nf.codings[@opt[:t].to_i - 1][@opt[:c].to_i - 1].notes
|
243
|
-
@nf.codings[@opt[:t].to_i - 1][@opt[:c].to_i - 1].notes <<
|
243
|
+
@nf.codings[@opt[:t].to_i - 1][@opt[:c].to_i - 1].notes << NexusParser::Note.new(@opt)
|
244
244
|
elsif @opt[:t]
|
245
|
-
@nf.taxa[@opt[:t].to_i - 1].notes <<
|
245
|
+
@nf.taxa[@opt[:t].to_i - 1].notes << NexusParser::Note.new(@opt)
|
246
246
|
elsif @opt[:c]
|
247
|
-
@nf.characters[@opt[:c].to_i - 1].notes <<
|
247
|
+
@nf.characters[@opt[:c].to_i - 1].notes << NexusParser::Note.new(@opt)
|
248
248
|
end
|
249
249
|
end
|
250
250
|
|
@@ -256,7 +256,7 @@ class Builder
|
|
256
256
|
|
257
257
|
end # end file
|
258
258
|
|
259
|
-
#
|
259
|
+
# NexusParser::ParseError
|
260
260
|
class ParseError < StandardError
|
261
261
|
end
|
262
262
|
|
@@ -267,15 +267,14 @@ end # end module
|
|
267
267
|
def parse_nexus_file(input)
|
268
268
|
@input = input
|
269
269
|
@input.gsub!(/\[[^\]]*\]/,'') # strip out all comments BEFORE we parse the file
|
270
|
-
|
271
270
|
# quickly peek at the input, does this look like a Nexus file?
|
272
271
|
if !(@input =~ /\#Nexus/i) || !(@input =~ /Begin/i) || !(@input =~ /Matrix/i) || !(@input =~ /end\;/i)
|
273
|
-
raise(
|
272
|
+
raise(NexusParser::ParseError, "File is missing at least some required headers, check formatting.", caller)
|
274
273
|
end
|
275
274
|
|
276
|
-
builder =
|
277
|
-
lexer =
|
278
|
-
|
275
|
+
builder = NexusParser::Builder.new
|
276
|
+
lexer = NexusParser::Lexer.new(@input)
|
277
|
+
NexusParser::Parser.new(lexer, builder).parse_file
|
279
278
|
|
280
279
|
return builder.nexus_file
|
281
280
|
end
|
data/lib/parser.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
class
|
2
|
+
class NexusParser::Parser
|
3
3
|
|
4
4
|
def initialize(lexer, builder)
|
5
5
|
@lexer = lexer
|
@@ -7,50 +7,50 @@ class NexusFile::Parser
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def parse_file
|
10
|
-
# nf = @builder.new_nexus_file # create new local
|
10
|
+
# nf = @builder.new_nexus_file # create new local NexusParser instance, nf
|
11
11
|
blks = []
|
12
|
-
@lexer.pop(
|
12
|
+
@lexer.pop(NexusParser::Tokens::NexusStart)
|
13
13
|
|
14
|
-
while @lexer.peek(
|
14
|
+
while @lexer.peek(NexusParser::Tokens::BeginBlk)
|
15
15
|
|
16
|
-
@lexer.pop(
|
16
|
+
@lexer.pop(NexusParser::Tokens::BeginBlk) # pop it
|
17
17
|
|
18
|
-
if @lexer.peek(
|
18
|
+
if @lexer.peek(NexusParser::Tokens::AuthorsBlk)
|
19
19
|
parse_authors_blk
|
20
20
|
|
21
21
|
# we parse these below
|
22
|
-
elsif @lexer.peek(
|
22
|
+
elsif @lexer.peek(NexusParser::Tokens::TaxaBlk)
|
23
23
|
|
24
|
-
@lexer.pop(
|
24
|
+
@lexer.pop(NexusParser::Tokens::TaxaBlk )
|
25
25
|
parse_taxa_blk
|
26
26
|
|
27
|
-
elsif @lexer.peek(
|
28
|
-
@lexer.pop(
|
27
|
+
elsif @lexer.peek(NexusParser::Tokens::ChrsBlk)
|
28
|
+
@lexer.pop(NexusParser::Tokens::ChrsBlk)
|
29
29
|
parse_characters_blk
|
30
30
|
|
31
|
-
elsif @lexer.peek(
|
32
|
-
@lexer.pop(
|
31
|
+
elsif @lexer.peek(NexusParser::Tokens::NotesBlk)
|
32
|
+
@lexer.pop(NexusParser::Tokens::NotesBlk)
|
33
33
|
parse_notes_blk
|
34
34
|
|
35
35
|
# we should parse this
|
36
|
-
elsif @lexer.peek(
|
37
|
-
@lexer.pop(
|
36
|
+
elsif @lexer.peek(NexusParser::Tokens::SetsBlk)
|
37
|
+
@lexer.pop(NexusParser::Tokens::SetsBlk)
|
38
38
|
|
39
39
|
# we don't parse these
|
40
|
-
elsif @lexer.peek(
|
41
|
-
@foo = @lexer.pop(
|
40
|
+
elsif @lexer.peek(NexusParser::Tokens::TreesBlk)
|
41
|
+
@foo = @lexer.pop(NexusParser::Tokens::TreesBlk).value
|
42
42
|
|
43
|
-
elsif @lexer.peek(
|
44
|
-
@lexer.pop(
|
43
|
+
elsif @lexer.peek(NexusParser::Tokens::LabelsBlk)
|
44
|
+
@lexer.pop(NexusParser::Tokens::LabelsBlk)
|
45
45
|
|
46
|
-
elsif @lexer.peek(
|
47
|
-
@lexer.pop(
|
46
|
+
elsif @lexer.peek(NexusParser::Tokens::MqCharModelsBlk)
|
47
|
+
@lexer.pop(NexusParser::Tokens::MqCharModelsBlk)
|
48
48
|
|
49
|
-
elsif @lexer.peek(
|
50
|
-
@lexer.pop(
|
49
|
+
elsif @lexer.peek(NexusParser::Tokens::AssumptionsBlk)
|
50
|
+
@lexer.pop(NexusParser::Tokens::AssumptionsBlk)
|
51
51
|
|
52
|
-
elsif @lexer.peek(
|
53
|
-
@lexer.pop(
|
52
|
+
elsif @lexer.peek(NexusParser::Tokens::CodonsBlk)
|
53
|
+
@lexer.pop(NexusParser::Tokens::CodonsBlk)
|
54
54
|
end
|
55
55
|
|
56
56
|
end
|
@@ -60,50 +60,50 @@ class NexusFile::Parser
|
|
60
60
|
def parse_authors_blk
|
61
61
|
# thing has non single word key/value pairs, like "AUTHOR NAME", SIGH
|
62
62
|
# for now just slurp it all up.
|
63
|
-
@lexer.pop(
|
63
|
+
@lexer.pop(NexusParser::Tokens::AuthorsBlk )
|
64
64
|
|
65
65
|
#while true
|
66
|
-
# if @lexer.peek(
|
67
|
-
# @lexer.pop(
|
66
|
+
# if @lexer.peek(NexusParser::Tokens::EndBlk)
|
67
|
+
# @lexer.pop(NexusParser::Tokens::EndBlk)
|
68
68
|
# break
|
69
69
|
# else
|
70
70
|
|
71
|
-
# while @lexer.peek(
|
71
|
+
# while @lexer.peek(NexusParser::Tokens::ValuePair)
|
72
72
|
# # IMPORTANT, these are going to a general hash, there may ultimately be overlap of keys used in different blocks, this is ignored at present
|
73
|
-
# @builder.add_var(@lexer.pop(
|
73
|
+
# @builder.add_var(@lexer.pop(NexusParser::Tokens::ValuePair).value)
|
74
74
|
# end
|
75
75
|
|
76
|
-
#@lexer.pop(
|
76
|
+
#@lexer.pop(NexusParser::Tokens::ID) if @lexer.peek(NexusParser::Tokens::ID)
|
77
77
|
# end
|
78
78
|
#end
|
79
79
|
end
|
80
80
|
|
81
81
|
def parse_taxa_blk
|
82
|
-
@lexer.pop(
|
82
|
+
@lexer.pop(NexusParser::Tokens::Title) if @lexer.peek(NexusParser::Tokens::Title)
|
83
83
|
|
84
84
|
# need to not ignore to test against
|
85
|
-
parse_dimensions if @lexer.peek(
|
85
|
+
parse_dimensions if @lexer.peek(NexusParser::Tokens::Dimensions)
|
86
86
|
|
87
87
|
while true
|
88
|
-
if @lexer.peek(
|
89
|
-
@lexer.pop(
|
88
|
+
if @lexer.peek(NexusParser::Tokens::EndBlk)
|
89
|
+
@lexer.pop(NexusParser::Tokens::EndBlk)
|
90
90
|
break
|
91
91
|
else
|
92
92
|
|
93
|
-
if @lexer.peek(
|
94
|
-
@lexer.pop(
|
93
|
+
if @lexer.peek(NexusParser::Tokens::Taxlabels)
|
94
|
+
@lexer.pop(NexusParser::Tokens::Taxlabels) if @lexer.peek(NexusParser::Tokens::Taxlabels)
|
95
95
|
i = 0
|
96
|
-
while @lexer.peek(
|
97
|
-
@builder.update_taxon(:index => i, :name => @lexer.pop(
|
96
|
+
while @lexer.peek(NexusParser::Tokens::Label)
|
97
|
+
@builder.update_taxon(:index => i, :name => @lexer.pop(NexusParser::Tokens::Label).value)
|
98
98
|
i += 1
|
99
99
|
end
|
100
|
-
@lexer.pop(
|
100
|
+
@lexer.pop(NexusParser::Tokens::SemiColon) if @lexer.peek(NexusParser::Tokens::SemiColon) # close of tax labels, placement of this seems dubious... but tests are working
|
101
101
|
|
102
|
-
elsif @lexer.peek(
|
102
|
+
elsif @lexer.peek(NexusParser::Tokens::MesquiteIDs)
|
103
103
|
|
104
|
-
@lexer.pop(
|
105
|
-
elsif @lexer.peek(
|
106
|
-
@lexer.pop(
|
104
|
+
@lexer.pop(NexusParser::Tokens::MesquiteIDs) # trashing these for now
|
105
|
+
elsif @lexer.peek(NexusParser::Tokens::MesquiteBlockID)
|
106
|
+
@lexer.pop(NexusParser::Tokens::MesquiteBlockID)
|
107
107
|
end
|
108
108
|
|
109
109
|
end
|
@@ -114,43 +114,43 @@ class NexusFile::Parser
|
|
114
114
|
|
115
115
|
def parse_characters_blk
|
116
116
|
while true
|
117
|
-
if @lexer.peek(
|
117
|
+
if @lexer.peek(NexusParser::Tokens::EndBlk) # we're at the end of the block, exit after geting rid of the semi-colon
|
118
118
|
break
|
119
119
|
else
|
120
|
-
@lexer.pop(
|
120
|
+
@lexer.pop(NexusParser::Tokens::Title) if @lexer.peek(NexusParser::Tokens::Title) # not used at present
|
121
121
|
|
122
|
-
parse_dimensions if @lexer.peek(
|
123
|
-
parse_format if @lexer.peek(
|
122
|
+
parse_dimensions if @lexer.peek(NexusParser::Tokens::Dimensions)
|
123
|
+
parse_format if @lexer.peek(NexusParser::Tokens::Format)
|
124
124
|
|
125
|
-
parse_chr_state_labels if @lexer.peek(
|
125
|
+
parse_chr_state_labels if @lexer.peek(NexusParser::Tokens::CharStateLabels)
|
126
126
|
|
127
|
-
parse_matrix if @lexer.peek(
|
127
|
+
parse_matrix if @lexer.peek(NexusParser::Tokens::Matrix)
|
128
128
|
|
129
129
|
# handle "\s*OPTIONS MSTAXA = UNCERTAIN;\s\n" within a characters block (sticks in an infinite loop right now)
|
130
130
|
|
131
|
-
@lexer.pop(
|
132
|
-
@lexer.pop(
|
131
|
+
@lexer.pop(NexusParser::Tokens::MesquiteIDs) if @lexer.peek(NexusParser::Tokens::MesquiteIDs) # trashing these for now
|
132
|
+
@lexer.pop(NexusParser::Tokens::MesquiteBlockID) if @lexer.peek(NexusParser::Tokens::MesquiteBlockID) # trashing these for now
|
133
133
|
|
134
134
|
false
|
135
135
|
end
|
136
136
|
end
|
137
|
-
@lexer.pop(
|
137
|
+
@lexer.pop(NexusParser::Tokens::EndBlk)
|
138
138
|
end
|
139
139
|
|
140
140
|
# prolly pop header then fuse with parse_dimensions
|
141
141
|
def parse_format
|
142
|
-
@lexer.pop(
|
143
|
-
while @lexer.peek(
|
144
|
-
@builder.add_var(@lexer.pop(
|
142
|
+
@lexer.pop(NexusParser::Tokens::Format)
|
143
|
+
while @lexer.peek(NexusParser::Tokens::ValuePair)
|
144
|
+
@builder.add_var(@lexer.pop(NexusParser::Tokens::ValuePair).value)
|
145
145
|
end
|
146
146
|
|
147
147
|
check_initialization_of_ntax_nchar
|
148
148
|
end
|
149
149
|
|
150
150
|
def parse_dimensions
|
151
|
-
@lexer.pop(
|
152
|
-
while @lexer.peek(
|
153
|
-
@builder.add_var(@lexer.pop(
|
151
|
+
@lexer.pop(NexusParser::Tokens::Dimensions)
|
152
|
+
while @lexer.peek(NexusParser::Tokens::ValuePair)
|
153
|
+
@builder.add_var(@lexer.pop(NexusParser::Tokens::ValuePair).value)
|
154
154
|
end
|
155
155
|
# the last value pair with a ; is automagically handled, don't try popping it again
|
156
156
|
|
@@ -170,33 +170,33 @@ class NexusFile::Parser
|
|
170
170
|
end
|
171
171
|
|
172
172
|
def parse_chr_state_labels
|
173
|
-
@lexer.pop(
|
173
|
+
@lexer.pop(NexusParser::Tokens::CharStateLabels)
|
174
174
|
|
175
175
|
while true
|
176
|
-
if @lexer.peek(
|
176
|
+
if @lexer.peek(NexusParser::Tokens::SemiColon)
|
177
177
|
break
|
178
178
|
else
|
179
179
|
opts = {}
|
180
180
|
|
181
181
|
name = ""
|
182
|
-
index = @lexer.pop(
|
183
|
-
(name = @lexer.pop(
|
182
|
+
index = @lexer.pop(NexusParser::Tokens::Number).value.to_i
|
183
|
+
(name = @lexer.pop(NexusParser::Tokens::Label).value) if @lexer.peek(NexusParser::Tokens::Label) # not always given a letter
|
184
184
|
|
185
|
-
@lexer.pop(
|
185
|
+
@lexer.pop(NexusParser::Tokens::BckSlash) if @lexer.peek(NexusParser::Tokens::BckSlash)
|
186
186
|
|
187
|
-
if !@lexer.peek(
|
187
|
+
if !@lexer.peek(NexusParser::Tokens::Comma) || !@lexer.peek(NexusParser::Tokens::SemiColon)
|
188
188
|
i = 0
|
189
189
|
|
190
190
|
# three kludge lines, need to figure out the label/number priority, could be issue in list order w/in tokens
|
191
|
-
while @lexer.peek(
|
192
|
-
opts.update({i.to_s => @lexer.pop(
|
193
|
-
opts.update({i.to_s => @lexer.pop(
|
191
|
+
while @lexer.peek(NexusParser::Tokens::Label) || @lexer.peek(NexusParser::Tokens::Number)
|
192
|
+
opts.update({i.to_s => @lexer.pop(NexusParser::Tokens::Label).value}) if @lexer.peek(NexusParser::Tokens::Label)
|
193
|
+
opts.update({i.to_s => @lexer.pop(NexusParser::Tokens::Number).value.to_s}) if @lexer.peek(NexusParser::Tokens::Number)
|
194
194
|
|
195
195
|
i += 1
|
196
196
|
end
|
197
197
|
end
|
198
198
|
|
199
|
-
@lexer.pop(
|
199
|
+
@lexer.pop(NexusParser::Tokens::Comma) if @lexer.peek(NexusParser::Tokens::Comma) # we may also have hit semicolon
|
200
200
|
|
201
201
|
opts.update({:index => (index - 1), :name => name})
|
202
202
|
|
@@ -205,56 +205,56 @@ class NexusFile::Parser
|
|
205
205
|
end
|
206
206
|
|
207
207
|
end
|
208
|
-
@lexer.pop(
|
208
|
+
@lexer.pop(NexusParser::Tokens::SemiColon)
|
209
209
|
end
|
210
210
|
|
211
211
|
def parse_matrix
|
212
|
-
@lexer.pop(
|
212
|
+
@lexer.pop(NexusParser::Tokens::Matrix)
|
213
213
|
i = 0
|
214
214
|
while true
|
215
|
-
if @lexer.peek(
|
215
|
+
if @lexer.peek(NexusParser::Tokens::SemiColon)
|
216
216
|
break
|
217
217
|
else
|
218
|
-
t = @lexer.pop(
|
218
|
+
t = @lexer.pop(NexusParser::Tokens::Label).value
|
219
219
|
|
220
220
|
@builder.update_taxon(:index => i, :name => t) # if it exists its not re-added
|
221
221
|
|
222
|
-
@builder.code_row(i, @lexer.pop(
|
222
|
+
@builder.code_row(i, @lexer.pop(NexusParser::Tokens::RowVec).value)
|
223
223
|
|
224
224
|
i += 1
|
225
225
|
end
|
226
226
|
end
|
227
|
-
@lexer.pop(
|
227
|
+
@lexer.pop(NexusParser::Tokens::SemiColon) # pop the semicolon
|
228
228
|
end
|
229
229
|
|
230
230
|
# this suck(s/ed), it needs work when a better API for Mesquite comes out
|
231
231
|
def parse_notes_blk
|
232
|
-
# IMPORTANT - we don't parse the (CM <note>), we just strip the "(CM" ... ")" bit for now in
|
232
|
+
# IMPORTANT - we don't parse the (CM <note>), we just strip the "(CM" ... ")" bit for now in NexusParser::Note
|
233
233
|
|
234
234
|
@vars = {}
|
235
235
|
inf = 0
|
236
236
|
while true
|
237
237
|
inf += 1
|
238
238
|
raise "Either you have a gazillion notes or more likely parser is caught in an infinite loop inside parse_notes_block" if inf > 100000
|
239
|
-
if @lexer.peek(
|
240
|
-
@lexer.pop(
|
239
|
+
if @lexer.peek(NexusParser::Tokens::EndBlk)
|
240
|
+
@lexer.pop(NexusParser::Tokens::EndBlk)
|
241
241
|
@builder.add_note(@vars) # one still left to add
|
242
242
|
break
|
243
243
|
else
|
244
244
|
|
245
|
-
if @lexer.peek(
|
246
|
-
@vars.update(@lexer.pop(
|
245
|
+
if @lexer.peek(NexusParser::Tokens::ValuePair)
|
246
|
+
@vars.update(@lexer.pop(NexusParser::Tokens::ValuePair).value)
|
247
247
|
|
248
|
-
elsif @lexer.peek(
|
248
|
+
elsif @lexer.peek(NexusParser::Tokens::Label)
|
249
249
|
if @vars[:type] # we have the data for this row write it, and start a new one
|
250
250
|
|
251
251
|
@builder.add_note(@vars)
|
252
252
|
@vars = {}
|
253
253
|
else
|
254
|
-
@vars.update(:type => @lexer.pop(
|
254
|
+
@vars.update(:type => @lexer.pop(NexusParser::Tokens::Label).value)
|
255
255
|
end
|
256
|
-
elsif @lexer.peek(
|
257
|
-
@lexer.pop(
|
256
|
+
elsif @lexer.peek(NexusParser::Tokens::FileLbl)
|
257
|
+
@lexer.pop(NexusParser::Tokens::FileLbl)
|
258
258
|
@vars.update(:file => 'file') # we check for whether :file key is present and handle conditionally
|
259
259
|
end
|
260
260
|
end
|
@@ -264,27 +264,27 @@ class NexusFile::Parser
|
|
264
264
|
#@vars = {}
|
265
265
|
#while true
|
266
266
|
|
267
|
-
# break if @lexer.peek(
|
267
|
+
# break if @lexer.peek(NexusParser::Tokens::EndBlk)
|
268
268
|
|
269
|
-
# @vars.update(:type => @lexer.pop(
|
269
|
+
# @vars.update(:type => @lexer.pop(NexusParser::Tokens::Label).value)
|
270
270
|
|
271
271
|
# kludge to get around the funny construct that references file
|
272
|
-
# if @lexer.peek(
|
273
|
-
# @lexer.pop(
|
272
|
+
# if @lexer.peek(NexusParser::Tokens::FileLbl)
|
273
|
+
# @lexer.pop(NexusParser::Tokens::FileLbl)
|
274
274
|
# vars.update(:file => 'file') # we check for whether :file key is present and handle conditionally
|
275
275
|
# end
|
276
276
|
|
277
277
|
# while true
|
278
278
|
|
279
|
-
# meh = @lexer.pop(
|
279
|
+
# meh = @lexer.pop(NexusParser::Tokens::ValuePair)
|
280
280
|
# @vars.update(meh.value)
|
281
|
-
# break if !@lexer.peek(
|
281
|
+
# break if !@lexer.peek(NexusParser::Tokens::ValuePair)
|
282
282
|
# end
|
283
283
|
#
|
284
284
|
# @builder.add_note(@vars)
|
285
285
|
# @vars = {}
|
286
286
|
#end
|
287
|
-
# @lexer.pop(
|
287
|
+
# @lexer.pop(NexusParser::Tokens::EndBlk)
|
288
288
|
|
289
289
|
|
290
290
|
def parse_trees_blk
|
@@ -320,8 +320,8 @@ class NexusFile::Parser
|
|
320
320
|
# parse a comma-separated list of nodes
|
321
321
|
# while true
|
322
322
|
# parse_node(parent)
|
323
|
-
# if @lexer.peek(
|
324
|
-
# @lexer.pop(
|
323
|
+
# if @lexer.peek(NexusParser::Tokens::Comma)
|
324
|
+
# @lexer.pop(NexusParser::Tokens::Comma)
|
325
325
|
# else
|
326
326
|
# break
|
327
327
|
# end
|