fortio-namelist 1.0.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,91 +14,104 @@
14
14
 
15
15
  class FortIO::Namelist::Parser
16
16
 
17
- prechigh
18
- nonassoc COMMA
19
- nonassoc NL
20
- left ','
21
- left '='
22
- preclow
23
-
24
17
  rule
25
18
 
26
- namelist_all :
27
- | namelist
28
- | namelist namelist_all
29
-
30
19
  namelist :
31
- header tailer
20
+ namelist group
21
+ | group
22
+
23
+ group :
24
+ group_header separator varlist separator group_end
25
+ { @root[val[0]] = val[2]; @scan.in_namelist = nil }
26
+ | group_header separator group_end
32
27
  { @root[val[0]] = []; @scan.in_namelist = nil }
33
- | header paramlist tailer
34
- { @root[val[0]] = val[1]; @scan.in_namelist = nil }
35
28
 
36
- prefix : '&'
29
+ group_prefix :
30
+ '&'
37
31
  | '$'
38
32
 
39
- header :
40
- prefix IDENT { result = val[1].downcase; @scan.in_namelist = val[1].downcase }
41
- | header NL
33
+ group_header :
34
+ group_prefix IDENT
35
+ { result = val[1].downcase.intern; @scan.in_namelist = val[1].downcase.intern }
36
+
37
+ separator :
38
+ COMMA
39
+ | COMMA nls
40
+ | nls COMMA
41
+ | nls
42
+ | blank
43
+
44
+ nls :
45
+ NL
46
+ | nls NL
47
+
48
+ blank :
42
49
 
43
- tailer :
50
+ group_end :
44
51
  '/'
45
- | prefix IDENT { raise Racc::ParseError, "\nparse error (&)" unless val[1] =~ /\Aend\Z/i }
46
-
47
- separator: COMMA
48
- | NL
49
-
50
- paramlist:
51
- paramdef { result = [val[0]] }
52
- | paramlist paramdef
53
- { result = val[0] + [val[1]] }
54
- | paramlist separator
55
- { result = val[0] }
56
-
57
- paramdef:
58
- IDENT '=' separator
59
- { result = ParamDef.new(val[0].downcase, nil, "") }
60
- | IDENT '=' NIL
61
- { result = ParamDef.new(val[0].downcase, nil, "") }
62
- | IDENT '=' rvalues
63
- { result = ParamDef.new(val[0].downcase, nil, val[2]) }
64
- | IDENT '(' array_spec ')' '=' rvalues
65
- { result = ParamDef.new(val[0].downcase, val[2], val[5]) }
66
-
67
- rvalues :
68
- abbreb { result = val[0] }
69
- | rvalues abbreb
52
+ | group_prefix IDENT
53
+ { raise Racc::ParseError, "\nparse error (&)" unless val[1] =~ /\Aend\Z/i }
54
+
55
+ varlist :
56
+ vardef { result = [val[0]] }
57
+ | varlist separator vardef
58
+ { result = val[0] + [val[2]] }
59
+
60
+ vardef :
61
+ IDENT equal COMMA
62
+ { result = ParamDef.new(val[0].downcase.intern, nil, "") }
63
+ | IDENT equal rvalues
64
+ { result = ParamDef.new(val[0].downcase.intern, nil, val[2]) }
65
+ | IDENT '(' array_spec ')' equal rvalues
66
+ { result = ParamDef.new(val[0].downcase.intern, val[2], val[5]) }
67
+
68
+ equal :
69
+ '='
70
+ | '=' nls
71
+ | nls '='
72
+ | nls '=' nls
73
+
74
+ rvalues :
75
+ rlist
76
+ | ident_list
77
+
78
+ rlist :
79
+ element
80
+ | NIL { result = [nil, nil] }
81
+ | rlist element
70
82
  { result = val[0] + val[1] }
71
- | rvalues ',' abbreb
83
+ | rlist ',' element
72
84
  { result = val[0] + val[2] }
73
- | rvalues NL abbreb
74
- { result = val[0] + val[2] }
75
- | rvalues NIL
85
+ | rlist NIL
76
86
  { result = val[0] + [nil] }
77
- | NIL rvalues
78
- { result = [nil] + val[1] }
79
- | ',' rvalues
80
- { result = [nil] + val[1] }
81
- | rvalues NL
82
- { result = val[0] }
83
- | IDENT
84
- { result = val[0] }
85
-
86
- abbreb :
87
- constant { result = [val[0]] }
87
+
88
+ element :
89
+ constant { result = [val[0]] }
88
90
  | DIGITS '*' constant
89
- { result = [val[2]] * val[0] }
91
+ { result = [val[2]] * val[0] }
90
92
 
91
93
  constant :
92
94
  STRING
93
95
  | LOGICAL
94
- | DIGITS
95
- | FLOAT
96
+ | real
96
97
  | complex
97
98
 
98
- real : DIGITS
99
+ real :
100
+ DIGITS
99
101
  | FLOAT
100
102
 
101
- complex : '(' real ',' real ')' { result = Complex(val[1],val[3]) }
103
+ complex :
104
+ '(' real ',' real ')'
105
+ { result = Complex(val[1],val[3]) }
106
+
107
+ ident_list :
108
+ IDENT { result = [val[0]] }
109
+ | STRINGLIKE
110
+ { result = [val[0]] }
111
+ | ident_list ',' IDENT
112
+ { result = val[0] + [val[2]]}
113
+ | ident_list ',' STRINGLIKE
114
+ { result = val[0] + [val[2]]}
102
115
 
103
116
  array_spec :
104
117
  DIGITS { result = [val[0]-1] }
@@ -184,6 +197,21 @@ module FortIO::Namelist
184
197
  end
185
198
  else
186
199
  case
200
+ when @s.scan(/\A\(/)
201
+ return [
202
+ '(',
203
+ nil
204
+ ]
205
+ when @s.scan(/\A\)/)
206
+ return [
207
+ ')',
208
+ nil
209
+ ]
210
+ when @s.scan(/\A\:/)
211
+ return [
212
+ ':',
213
+ nil
214
+ ]
187
215
  when @s.scan(/\A[+-]?(\d+)\.(\d+)?([ED][+-]?(\d+))?/i) ### float
188
216
  return [ ### 1.2E+3, 1.E+3, 1.2E3
189
217
  :FLOAT, ### 1.2, 1.
@@ -199,9 +227,9 @@ module FortIO::Namelist
199
227
  :FLOAT,
200
228
  @s[0].sub(/D/i,'e').to_f
201
229
  ]
202
- when @s.scan(/\A\d+[a-z_]\w*/i) ### STRING
230
+ when @s.scan(/\A\d+[a-z_]\w*/i) ### STRING-Like
203
231
  return [
204
- :STRING,
232
+ :STRINGLIKE,
205
233
  @s[0]
206
234
  ]
207
235
  when @s.scan(/\A[\-\+]?\d+/) ### digits
@@ -229,6 +257,11 @@ module FortIO::Namelist
229
257
  ',',
230
258
  nil
231
259
  ]
260
+ elsif @s.match?(/\A[a-z]\w*\s*,/i)
261
+ return [
262
+ ',',
263
+ nil
264
+ ]
232
265
  elsif @s.match?(/\A[a-z]\w*/i) or @s.match?(/\A[\&\$\/\!]/)
233
266
  return [
234
267
  :COMMA,
@@ -252,17 +285,17 @@ module FortIO::Namelist
252
285
  @s[0],
253
286
  nil
254
287
  ]
255
- when @s.scan(/\A_\w*/i) ### STRING
288
+ when @s.scan(/\A_\w*/i) ### STRING-Like
256
289
  return [
257
- :STRING,
290
+ :STRINGLIKE,
258
291
  @s[0]
259
292
  ]
260
- when @s.scan(/\A\.t.*?\./i) ### LOGICAL true
293
+ when @s.scan(/\A\.t[\w\d_]*\.?/i) ### LOGICAL true
261
294
  return [
262
295
  :LOGICAL,
263
296
  true,
264
297
  ]
265
- when @s.scan(/\A\.f.*?\./i) ### LOGICAL false
298
+ when @s.scan(/\A\.f[\w\d_]*\.?/i) ### LOGICAL false
266
299
  return [
267
300
  :LOGICAL,
268
301
  false,
@@ -0,0 +1,160 @@
1
+ require "fortio-namelist"
2
+ require "rspec-power_assert"
3
+
4
+ describe "FortIO::Namelist" do
5
+
6
+ example "array stream" do
7
+ input = %{
8
+ &example
9
+ v1 = 1,2,3,4,5,
10
+ v2 = 6,7,8,9,10,
11
+ /
12
+ }
13
+ nml = FortIO::Namelist.parse(input)
14
+ is_asserted_by { nml.has_key? :example }
15
+ is_asserted_by { nml[:example].is_a? Hash }
16
+ is_asserted_by { nml[:example][:v1] == [1,2,3,4,5] }
17
+ is_asserted_by { nml[:example][:v2] == [6,7,8,9,10] }
18
+ end
19
+
20
+ example "array sequence" do
21
+ input = %{
22
+ &example v1 = 1,2,3,4,5, v2 = 6,7,8,9,10, /
23
+ }
24
+ nml = FortIO::Namelist.parse(input)
25
+ is_asserted_by { nml.has_key? :example }
26
+ is_asserted_by { nml[:example].is_a? Hash }
27
+ is_asserted_by { nml[:example][:v1] == [1,2,3,4,5] }
28
+ is_asserted_by { nml[:example][:v2] == [6,7,8,9,10] }
29
+ end
30
+
31
+ example "array index" do
32
+ input = %{
33
+ &example
34
+ v1(1) = 1
35
+ v1(2) = 2
36
+ v1(3) = 3
37
+ v1(4) = 4
38
+ v1(5) = 5
39
+ v2(1:2) = 6,7
40
+ v2(3:5) = 8,9,10,
41
+ /
42
+ }
43
+ nml = FortIO::Namelist.parse(input)
44
+ is_asserted_by { nml.has_key? :example }
45
+ is_asserted_by { nml[:example].is_a? Hash }
46
+ is_asserted_by { nml[:example][:v1] == [1,2,3,4,5] }
47
+ is_asserted_by { nml[:example][:v2] == [6,7,8,9,10] }
48
+ end
49
+
50
+ example "array partial" do
51
+ input = %{
52
+ &example
53
+ v1(2) = 2
54
+ v1(5) = 5
55
+ v2(3:5) = 8,9,10,
56
+ /
57
+ }
58
+ nml = FortIO::Namelist.parse(input)
59
+ is_asserted_by { nml.has_key? :example }
60
+ is_asserted_by { nml[:example].is_a? Hash }
61
+ is_asserted_by { nml[:example][:v1] == [nil,2,nil,nil,5] }
62
+ is_asserted_by { nml[:example][:v2] == [nil,nil,8,9,10] }
63
+ end
64
+
65
+ example "array extend" do
66
+ input = %{
67
+ &example
68
+ v1(2) = 2,3,4,5
69
+ /
70
+ }
71
+ nml = FortIO::Namelist.parse(input)
72
+ is_asserted_by { nml.has_key? :example }
73
+ is_asserted_by { nml[:example].is_a? Hash }
74
+ is_asserted_by { nml[:example][:v1] == [nil,2,3,4,5] }
75
+ end
76
+
77
+ example "array reputation" do
78
+ input = %{
79
+ &example
80
+ v1(1:5) = 2,4*2
81
+ v2(2) = 4*2
82
+ v3 = 5*.true.
83
+ v4 = 5 * f
84
+ /
85
+ }
86
+ nml = FortIO::Namelist.parse(input)
87
+ is_asserted_by { nml.has_key? :example }
88
+ is_asserted_by { nml[:example].is_a? Hash }
89
+ is_asserted_by { nml[:example][:v1] == [2,2,2,2,2] }
90
+ is_asserted_by { nml[:example][:v2] == [nil,2,2,2,2] }
91
+ is_asserted_by { nml[:example][:v3] == [true]*5 }
92
+ is_asserted_by { nml[:example][:v4] == [false]*5 }
93
+ end
94
+
95
+ example "array of string" do
96
+ input = %{
97
+ &example
98
+ v1 = "a",'b',"c"
99
+ /
100
+ }
101
+ nml = FortIO::Namelist.parse(input)
102
+ is_asserted_by { nml.has_key? :example }
103
+ is_asserted_by { nml[:example].is_a? Hash }
104
+ is_asserted_by { nml[:example][:v1] == ["a","b","c"] }
105
+ end
106
+
107
+ example "array of identifier" do
108
+ input = %{
109
+ &example
110
+ v1 = a, b, c
111
+ /
112
+ }
113
+ expect { FortIO::Namelist.parse(input) }.to raise_error(RuntimeError)
114
+ end
115
+
116
+ example "array of identifier 2" do
117
+ input = %{
118
+ &example
119
+ v1 = a, 0_b, _c
120
+ /
121
+ }
122
+ nml = FortIO::Namelist.parse(input)
123
+ is_asserted_by { nml.has_key? :example }
124
+ is_asserted_by { nml[:example].is_a? Hash }
125
+ is_asserted_by { nml[:example][:v1] == ["a","0_b","_c"] }
126
+ end
127
+
128
+ example "don't permit to mix identifier and string in array stream" do
129
+ input = %{
130
+ &example
131
+ v1 = "a", b, "c"
132
+ /
133
+ }
134
+ expect { FortIO::Namelist.parse(input) }.to raise_error(RuntimeError)
135
+ end
136
+
137
+ example "don't permit to mix identifier and string in array stream 2" do
138
+ input = %{
139
+ &example
140
+ v1 = a, "b", c
141
+ /
142
+ }
143
+ expect { FortIO::Namelist.parse(input) }.to raise_error(RuntimeError)
144
+ end
145
+
146
+ example "empty element" do
147
+ input = %{
148
+ &example
149
+ v1 = , , 3, , 5,
150
+ v2 = , , 3, , 5
151
+ /
152
+ }
153
+ nml = FortIO::Namelist.parse(input)
154
+ is_asserted_by { nml.has_key? :example }
155
+ is_asserted_by { nml[:example].is_a? Hash }
156
+ is_asserted_by { nml[:example][:v1] == [nil, nil, 3, nil, 5] }
157
+ is_asserted_by { nml[:example][:v2] == [nil, nil, 3, nil, 5] }
158
+ end
159
+
160
+ end
data/spec/dump_spec.rb ADDED
@@ -0,0 +1,51 @@
1
+ require "fortio-namelist"
2
+ require "rspec-power_assert"
3
+
4
+ describe "FortIO::Namelist" do
5
+
6
+ example "dumping float" do
7
+ root = {example: {v1: 1.234567890123456, v2: 0.123456789012345, v3: 1.234567890123456e10}}
8
+ output = FortIO::Namelist.dump(root)
9
+
10
+ answer = <<HERE
11
+ &example
12
+ v1 = 1.234567890123456,
13
+ v2 = 0.123456789012345,
14
+ v3 = 12345678901.23456
15
+ /
16
+ HERE
17
+
18
+ is_asserted_by { output == answer }
19
+ end
20
+
21
+ example "dumping float 'd0'" do
22
+ root = {example: {v1: 1.234567890123456, v2: 0.123456789012345, v3: 1.234567890123456e10}}
23
+ output = FortIO::Namelist.dump(root, float_format: 'd0')
24
+
25
+ answer = <<HERE
26
+ &example
27
+ v1 = 1.234567890123456d0,
28
+ v2 = 0.123456789012345d0,
29
+ v3 = 12345678901.23456d0
30
+ /
31
+ HERE
32
+
33
+ is_asserted_by { output == answer }
34
+ end
35
+
36
+ example "dumping float 'exp'" do
37
+ root = {example: {v1: 1.234567890123456, v2: 0.123456789012345, v3: 1.234567890123456e10}}
38
+ output = FortIO::Namelist.dump(root, float_format: 'exp')
39
+
40
+ answer = <<HERE
41
+ &example
42
+ v1 = 1.234567890123456d+00,
43
+ v2 = 1.23456789012345d-01,
44
+ v3 = 1.234567890123456d+10
45
+ /
46
+ HERE
47
+
48
+ is_asserted_by { output == answer }
49
+ end
50
+
51
+ end
@@ -0,0 +1,66 @@
1
+ require "fortio-namelist"
2
+ require "rspec-power_assert"
3
+
4
+ describe "FortIO::Namelist" do
5
+
6
+ example "namelist prefix &" do
7
+ input = %{
8
+ &example
9
+ &end
10
+ }
11
+ nml = FortIO::Namelist.parse(input)
12
+ is_asserted_by { nml.has_key? :example }
13
+ is_asserted_by { nml[:example].is_a? Hash }
14
+ is_asserted_by { nml[:example].empty? }
15
+ end
16
+
17
+ example "namelist prefix $" do
18
+ input = %{
19
+ $example
20
+ $end
21
+ }
22
+ nml = FortIO::Namelist.parse(input)
23
+ is_asserted_by { nml.has_key? :example }
24
+ end
25
+
26
+ example "end with /" do
27
+ input = %{
28
+ &example
29
+ /
30
+ }
31
+ nml = FortIO::Namelist.parse(input)
32
+ is_asserted_by { nml.has_key? :example }
33
+ end
34
+
35
+ example "only comment" do
36
+ input = %{
37
+ &example
38
+ ! this is comment
39
+ /
40
+ }
41
+ nml = FortIO::Namelist.parse(input)
42
+ is_asserted_by { nml.has_key? :example }
43
+ end
44
+
45
+
46
+ example "only newlines" do
47
+ input = %{
48
+ &example
49
+
50
+
51
+ /
52
+ }
53
+ nml = FortIO::Namelist.parse(input)
54
+ is_asserted_by { nml.has_key? :example }
55
+ end
56
+
57
+ example "one line" do
58
+ input = %{
59
+ &example /
60
+ }
61
+ nml = FortIO::Namelist.parse(input)
62
+ is_asserted_by { nml.has_key? :example }
63
+ end
64
+
65
+
66
+ end