nexus_parser 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|