csv_plus_plus 0.0.2
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.
- checksums.yaml +7 -0
- data/lib/csv_plus_plus/cell.rb +51 -0
- data/lib/csv_plus_plus/code_section.rb +49 -0
- data/lib/csv_plus_plus/color.rb +22 -0
- data/lib/csv_plus_plus/expand.rb +18 -0
- data/lib/csv_plus_plus/google_options.rb +23 -0
- data/lib/csv_plus_plus/graph.rb +68 -0
- data/lib/csv_plus_plus/language/cell_value.tab.rb +333 -0
- data/lib/csv_plus_plus/language/code_section.tab.rb +443 -0
- data/lib/csv_plus_plus/language/compiler.rb +170 -0
- data/lib/csv_plus_plus/language/entities/boolean.rb +32 -0
- data/lib/csv_plus_plus/language/entities/cell_reference.rb +26 -0
- data/lib/csv_plus_plus/language/entities/entity.rb +70 -0
- data/lib/csv_plus_plus/language/entities/function.rb +33 -0
- data/lib/csv_plus_plus/language/entities/function_call.rb +25 -0
- data/lib/csv_plus_plus/language/entities/number.rb +34 -0
- data/lib/csv_plus_plus/language/entities/runtime_value.rb +27 -0
- data/lib/csv_plus_plus/language/entities/string.rb +29 -0
- data/lib/csv_plus_plus/language/entities/variable.rb +25 -0
- data/lib/csv_plus_plus/language/entities.rb +28 -0
- data/lib/csv_plus_plus/language/references.rb +53 -0
- data/lib/csv_plus_plus/language/runtime.rb +147 -0
- data/lib/csv_plus_plus/language/scope.rb +199 -0
- data/lib/csv_plus_plus/language/syntax_error.rb +61 -0
- data/lib/csv_plus_plus/lexer/lexer.rb +64 -0
- data/lib/csv_plus_plus/lexer/tokenizer.rb +65 -0
- data/lib/csv_plus_plus/lexer.rb +14 -0
- data/lib/csv_plus_plus/modifier.rb +124 -0
- data/lib/csv_plus_plus/modifier.tab.rb +921 -0
- data/lib/csv_plus_plus/options.rb +70 -0
- data/lib/csv_plus_plus/row.rb +42 -0
- data/lib/csv_plus_plus/template.rb +61 -0
- data/lib/csv_plus_plus/version.rb +6 -0
- data/lib/csv_plus_plus/writer/base_writer.rb +21 -0
- data/lib/csv_plus_plus/writer/csv.rb +31 -0
- data/lib/csv_plus_plus/writer/excel.rb +13 -0
- data/lib/csv_plus_plus/writer/google_sheet_builder.rb +173 -0
- data/lib/csv_plus_plus/writer/google_sheets.rb +139 -0
- data/lib/csv_plus_plus/writer/open_document.rb +14 -0
- data/lib/csv_plus_plus/writer.rb +25 -0
- data/lib/csv_plus_plus.rb +20 -0
- metadata +83 -0
@@ -0,0 +1,443 @@
|
|
1
|
+
#
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by Racc 1.6.2
|
4
|
+
# from Racc grammar file "".
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'racc/parser.rb'
|
8
|
+
|
9
|
+
require_relative '../lexer'
|
10
|
+
require_relative '../code_section'
|
11
|
+
|
12
|
+
module CSVPlusPlus
|
13
|
+
module Language
|
14
|
+
class CodeSectionParser < Racc::Parser
|
15
|
+
|
16
|
+
module_eval(<<'...end code_section.y/module_eval...', 'code_section.y', 67)
|
17
|
+
include ::CSVPlusPlus::Lexer
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
super
|
21
|
+
@code_section = CodeSection.new
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def anything_to_parse?(input)
|
27
|
+
@rest = input.strip
|
28
|
+
|
29
|
+
return !@rest.index(::CSVPlusPlus::Lexer::END_OF_CODE_SECTION).nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_subject
|
33
|
+
'code section'
|
34
|
+
end
|
35
|
+
|
36
|
+
def tokenizer(input)
|
37
|
+
::CSVPlusPlus::Lexer::Tokenizer.new(
|
38
|
+
catchall: /[\(\)\{\}\/\*\+\-,=&]/,
|
39
|
+
ignore: /\s+|\#[^\n]+\n/,
|
40
|
+
input:,
|
41
|
+
stop_fn: lambda do |scanner|
|
42
|
+
return false unless scanner.scan(/#{::CSVPlusPlus::Lexer::END_OF_CODE_SECTION}/)
|
43
|
+
|
44
|
+
@tokens << [:END_OF_CODE, scanner.matched]
|
45
|
+
@rest = scanner.rest.strip
|
46
|
+
true
|
47
|
+
end,
|
48
|
+
tokens: [
|
49
|
+
[/\n/, :EOL],
|
50
|
+
[/:=/, :ASSIGN],
|
51
|
+
[/\bdef\b/, :FN_DEF],
|
52
|
+
[/\bTRUE\b/i, :TRUE],
|
53
|
+
[/\bFALSE\b/i, :FALSE],
|
54
|
+
[/"(?:[^"\\]|\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4}))*"/, :STRING],
|
55
|
+
[/-?[\d.]+/, :NUMBER],
|
56
|
+
[/\$\$/, :VAR_REF],
|
57
|
+
[/[!:\w_]+/, :ID],
|
58
|
+
],
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def return_value
|
63
|
+
[@code_section, @rest]
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def e(type, *entity_args)
|
69
|
+
::CSVPlusPlus::Language::TYPES[type].new(*entity_args)
|
70
|
+
end
|
71
|
+
|
72
|
+
def def_function(id, arguments, body)
|
73
|
+
fn_def = e(:function, id, arguments, body)
|
74
|
+
@code_section.def_function(fn_def.id, fn_def)
|
75
|
+
end
|
76
|
+
|
77
|
+
def def_variable(id, ast)
|
78
|
+
@code_section.def_variable(id, ast)
|
79
|
+
end
|
80
|
+
...end code_section.y/module_eval...
|
81
|
+
##### State transition tables begin ###
|
82
|
+
|
83
|
+
racc_action_table = [
|
84
|
+
45, 27, 3, 37, 51, 7, 38, 52, 28, 9,
|
85
|
+
19, 8, 29, 30, 31, 32, 33, 24, 25, 22,
|
86
|
+
21, 23, 20, 19, 29, 30, 31, 32, 33, 19,
|
87
|
+
24, 25, 22, 21, 23, 20, 24, 25, 22, 21,
|
88
|
+
23, 20, 19, 29, 30, 31, 32, 33, 19, 24,
|
89
|
+
25, 22, 21, 23, 20, 24, 25, 22, 21, 23,
|
90
|
+
20, 19, 29, 30, 31, 32, 33, 19, 24, 25,
|
91
|
+
22, 21, 23, 20, 24, 25, 22, 21, 23, 20,
|
92
|
+
19, 29, 30, 31, 32, 33, 12, 24, 25, 22,
|
93
|
+
21, 23, 20, 19, 48, 13, 14, 15, 35, 19,
|
94
|
+
24, 25, 22, 21, 23, 20, 24, 25, 22, 21,
|
95
|
+
23, 20, 19, 29, 30, 31, 32, 33, 36, 24,
|
96
|
+
25, 22, 21, 23, 20, 10, 50, nil, 7, 29,
|
97
|
+
30, 31, 32, 33, 8, 29, 30, 31, 32, 33,
|
98
|
+
29, 30, 31, 32, 33, 29, 30, 31, 32, 33,
|
99
|
+
29, 30, 31, 32, 33 ]
|
100
|
+
|
101
|
+
racc_action_check = [
|
102
|
+
34, 15, 0, 26, 47, 0, 26, 47, 15, 1,
|
103
|
+
13, 0, 34, 34, 34, 34, 34, 13, 13, 13,
|
104
|
+
13, 13, 13, 19, 16, 16, 16, 16, 16, 27,
|
105
|
+
19, 19, 19, 19, 19, 19, 27, 27, 27, 27,
|
106
|
+
27, 27, 29, 39, 39, 39, 39, 39, 30, 29,
|
107
|
+
29, 29, 29, 29, 29, 30, 30, 30, 30, 30,
|
108
|
+
30, 31, 40, 40, 40, 40, 40, 32, 31, 31,
|
109
|
+
31, 31, 31, 31, 32, 32, 32, 32, 32, 32,
|
110
|
+
33, 41, 41, 41, 41, 41, 7, 33, 33, 33,
|
111
|
+
33, 33, 33, 36, 36, 8, 9, 12, 20, 37,
|
112
|
+
36, 36, 36, 36, 36, 36, 37, 37, 37, 37,
|
113
|
+
37, 37, 52, 42, 42, 42, 42, 42, 25, 52,
|
114
|
+
52, 52, 52, 52, 52, 2, 38, nil, 2, 43,
|
115
|
+
43, 43, 43, 43, 2, 44, 44, 44, 44, 44,
|
116
|
+
46, 46, 46, 46, 46, 49, 49, 49, 49, 49,
|
117
|
+
53, 53, 53, 53, 53 ]
|
118
|
+
|
119
|
+
racc_action_pointer = [
|
120
|
+
0, 9, 123, nil, nil, nil, nil, 75, 89, 96,
|
121
|
+
nil, nil, 94, 7, nil, -3, 8, nil, nil, 20,
|
122
|
+
87, nil, nil, nil, nil, 115, -1, 26, nil, 39,
|
123
|
+
45, 58, 64, 77, -4, nil, 90, 96, 115, 27,
|
124
|
+
46, 65, 97, 113, 119, nil, 124, 0, nil, 129,
|
125
|
+
nil, nil, 109, 134 ]
|
126
|
+
|
127
|
+
racc_action_default = [
|
128
|
+
-30, -30, -30, -2, -4, -5, -6, -30, -30, -30,
|
129
|
+
-1, -3, -30, -30, 54, -30, -11, -12, -13, -30,
|
130
|
+
-30, -16, -17, -18, -19, -20, -30, -30, -10, -30,
|
131
|
+
-30, -30, -30, -30, -30, -15, -30, -30, -30, -8,
|
132
|
+
-21, -22, -23, -24, -25, -14, -29, -30, -27, -7,
|
133
|
+
-9, -26, -30, -28 ]
|
134
|
+
|
135
|
+
racc_goto_table = [
|
136
|
+
16, 4, 1, 11, 2, 26, 34, 47, nil, nil,
|
137
|
+
nil, nil, nil, nil, 39, nil, 40, 41, 42, 43,
|
138
|
+
44, nil, nil, 46, 49, nil, nil, nil, nil, nil,
|
139
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, 53 ]
|
140
|
+
|
141
|
+
racc_goto_check = [
|
142
|
+
7, 3, 1, 3, 2, 6, 7, 10, nil, nil,
|
143
|
+
nil, nil, nil, nil, 7, nil, 7, 7, 7, 7,
|
144
|
+
7, nil, nil, 7, 7, nil, nil, nil, nil, nil,
|
145
|
+
nil, nil, nil, nil, nil, nil, nil, nil, nil, 7 ]
|
146
|
+
|
147
|
+
racc_goto_pointer = [
|
148
|
+
nil, 2, 4, 1, nil, nil, -10, -13, nil, nil,
|
149
|
+
-29 ]
|
150
|
+
|
151
|
+
racc_goto_default = [
|
152
|
+
nil, nil, nil, nil, 5, 6, nil, nil, 17, 18,
|
153
|
+
nil ]
|
154
|
+
|
155
|
+
racc_reduce_table = [
|
156
|
+
0, 0, :racc_error,
|
157
|
+
2, 22, :_reduce_none,
|
158
|
+
1, 22, :_reduce_none,
|
159
|
+
2, 23, :_reduce_none,
|
160
|
+
1, 23, :_reduce_none,
|
161
|
+
1, 24, :_reduce_none,
|
162
|
+
1, 24, :_reduce_none,
|
163
|
+
6, 25, :_reduce_7,
|
164
|
+
5, 25, :_reduce_8,
|
165
|
+
3, 27, :_reduce_9,
|
166
|
+
1, 27, :_reduce_10,
|
167
|
+
3, 26, :_reduce_11,
|
168
|
+
1, 28, :_reduce_none,
|
169
|
+
1, 28, :_reduce_none,
|
170
|
+
3, 28, :_reduce_14,
|
171
|
+
2, 28, :_reduce_15,
|
172
|
+
1, 28, :_reduce_16,
|
173
|
+
1, 28, :_reduce_17,
|
174
|
+
1, 28, :_reduce_18,
|
175
|
+
1, 28, :_reduce_19,
|
176
|
+
1, 28, :_reduce_20,
|
177
|
+
3, 30, :_reduce_21,
|
178
|
+
3, 30, :_reduce_22,
|
179
|
+
3, 30, :_reduce_23,
|
180
|
+
3, 30, :_reduce_24,
|
181
|
+
3, 30, :_reduce_25,
|
182
|
+
4, 29, :_reduce_26,
|
183
|
+
3, 29, :_reduce_27,
|
184
|
+
3, 31, :_reduce_28,
|
185
|
+
1, 31, :_reduce_29 ]
|
186
|
+
|
187
|
+
racc_reduce_n = 30
|
188
|
+
|
189
|
+
racc_shift_n = 54
|
190
|
+
|
191
|
+
racc_token_table = {
|
192
|
+
false => 0,
|
193
|
+
:error => 1,
|
194
|
+
:END_OF_CODE => 2,
|
195
|
+
"(" => 3,
|
196
|
+
")" => 4,
|
197
|
+
:FN_DEF => 5,
|
198
|
+
:ASSIGN => 6,
|
199
|
+
"," => 7,
|
200
|
+
:CELL_REF => 8,
|
201
|
+
:EOL => 9,
|
202
|
+
:FALSE => 10,
|
203
|
+
:ID => 11,
|
204
|
+
:NUMBER => 12,
|
205
|
+
:STRING => 13,
|
206
|
+
:TRUE => 14,
|
207
|
+
:VAR_REF => 15,
|
208
|
+
"&" => 16,
|
209
|
+
"*" => 17,
|
210
|
+
"+" => 18,
|
211
|
+
"-" => 19,
|
212
|
+
"/" => 20 }
|
213
|
+
|
214
|
+
racc_nt_base = 21
|
215
|
+
|
216
|
+
racc_use_result_var = true
|
217
|
+
|
218
|
+
Racc_arg = [
|
219
|
+
racc_action_table,
|
220
|
+
racc_action_check,
|
221
|
+
racc_action_default,
|
222
|
+
racc_action_pointer,
|
223
|
+
racc_goto_table,
|
224
|
+
racc_goto_check,
|
225
|
+
racc_goto_default,
|
226
|
+
racc_goto_pointer,
|
227
|
+
racc_nt_base,
|
228
|
+
racc_reduce_table,
|
229
|
+
racc_token_table,
|
230
|
+
racc_shift_n,
|
231
|
+
racc_reduce_n,
|
232
|
+
racc_use_result_var ]
|
233
|
+
|
234
|
+
Racc_token_to_s_table = [
|
235
|
+
"$end",
|
236
|
+
"error",
|
237
|
+
"END_OF_CODE",
|
238
|
+
"\"(\"",
|
239
|
+
"\")\"",
|
240
|
+
"FN_DEF",
|
241
|
+
"ASSIGN",
|
242
|
+
"\",\"",
|
243
|
+
"CELL_REF",
|
244
|
+
"EOL",
|
245
|
+
"FALSE",
|
246
|
+
"ID",
|
247
|
+
"NUMBER",
|
248
|
+
"STRING",
|
249
|
+
"TRUE",
|
250
|
+
"VAR_REF",
|
251
|
+
"\"&\"",
|
252
|
+
"\"*\"",
|
253
|
+
"\"+\"",
|
254
|
+
"\"-\"",
|
255
|
+
"\"/\"",
|
256
|
+
"$start",
|
257
|
+
"code_section",
|
258
|
+
"code",
|
259
|
+
"def",
|
260
|
+
"fn_def",
|
261
|
+
"var_def",
|
262
|
+
"fn_def_args",
|
263
|
+
"exp",
|
264
|
+
"fn_call",
|
265
|
+
"infix_fn_call",
|
266
|
+
"fn_call_args" ]
|
267
|
+
|
268
|
+
Racc_debug_parser = false
|
269
|
+
|
270
|
+
##### State transition tables end #####
|
271
|
+
|
272
|
+
# reduce 0 omitted
|
273
|
+
|
274
|
+
# reduce 1 omitted
|
275
|
+
|
276
|
+
# reduce 2 omitted
|
277
|
+
|
278
|
+
# reduce 3 omitted
|
279
|
+
|
280
|
+
# reduce 4 omitted
|
281
|
+
|
282
|
+
# reduce 5 omitted
|
283
|
+
|
284
|
+
# reduce 6 omitted
|
285
|
+
|
286
|
+
module_eval(<<'.,.,', 'code_section.y', 29)
|
287
|
+
def _reduce_7(val, _values, result)
|
288
|
+
def_function(val[1], val[3], val[5])
|
289
|
+
result
|
290
|
+
end
|
291
|
+
.,.,
|
292
|
+
|
293
|
+
module_eval(<<'.,.,', 'code_section.y', 30)
|
294
|
+
def _reduce_8(val, _values, result)
|
295
|
+
def_function(val[1], [], val[4])
|
296
|
+
result
|
297
|
+
end
|
298
|
+
.,.,
|
299
|
+
|
300
|
+
module_eval(<<'.,.,', 'code_section.y', 32)
|
301
|
+
def _reduce_9(val, _values, result)
|
302
|
+
result = val[0] << val[2]
|
303
|
+
result
|
304
|
+
end
|
305
|
+
.,.,
|
306
|
+
|
307
|
+
module_eval(<<'.,.,', 'code_section.y', 33)
|
308
|
+
def _reduce_10(val, _values, result)
|
309
|
+
result = [val[0]]
|
310
|
+
result
|
311
|
+
end
|
312
|
+
.,.,
|
313
|
+
|
314
|
+
module_eval(<<'.,.,', 'code_section.y', 35)
|
315
|
+
def _reduce_11(val, _values, result)
|
316
|
+
def_variable(val[0], val[2])
|
317
|
+
result
|
318
|
+
end
|
319
|
+
.,.,
|
320
|
+
|
321
|
+
# reduce 12 omitted
|
322
|
+
|
323
|
+
# reduce 13 omitted
|
324
|
+
|
325
|
+
module_eval(<<'.,.,', 'code_section.y', 39)
|
326
|
+
def _reduce_14(val, _values, result)
|
327
|
+
result = val[1]
|
328
|
+
result
|
329
|
+
end
|
330
|
+
.,.,
|
331
|
+
|
332
|
+
module_eval(<<'.,.,', 'code_section.y', 40)
|
333
|
+
def _reduce_15(val, _values, result)
|
334
|
+
result = e(:variable, val[1])
|
335
|
+
result
|
336
|
+
end
|
337
|
+
.,.,
|
338
|
+
|
339
|
+
module_eval(<<'.,.,', 'code_section.y', 41)
|
340
|
+
def _reduce_16(val, _values, result)
|
341
|
+
result = e(:string, val[0])
|
342
|
+
result
|
343
|
+
end
|
344
|
+
.,.,
|
345
|
+
|
346
|
+
module_eval(<<'.,.,', 'code_section.y', 42)
|
347
|
+
def _reduce_17(val, _values, result)
|
348
|
+
result = e(:number, val[0])
|
349
|
+
result
|
350
|
+
end
|
351
|
+
.,.,
|
352
|
+
|
353
|
+
module_eval(<<'.,.,', 'code_section.y', 43)
|
354
|
+
def _reduce_18(val, _values, result)
|
355
|
+
result = e(:boolean, true)
|
356
|
+
result
|
357
|
+
end
|
358
|
+
.,.,
|
359
|
+
|
360
|
+
module_eval(<<'.,.,', 'code_section.y', 44)
|
361
|
+
def _reduce_19(val, _values, result)
|
362
|
+
result = e(:boolean, false)
|
363
|
+
result
|
364
|
+
end
|
365
|
+
.,.,
|
366
|
+
|
367
|
+
module_eval(<<'.,.,', 'code_section.y', 45)
|
368
|
+
def _reduce_20(val, _values, result)
|
369
|
+
result = e(:cell_reference, val[0])
|
370
|
+
result
|
371
|
+
end
|
372
|
+
.,.,
|
373
|
+
|
374
|
+
module_eval(<<'.,.,', 'code_section.y', 47)
|
375
|
+
def _reduce_21(val, _values, result)
|
376
|
+
result = e(:function_call, :concat, [val[0], val[2]])
|
377
|
+
result
|
378
|
+
end
|
379
|
+
.,.,
|
380
|
+
|
381
|
+
module_eval(<<'.,.,', 'code_section.y', 48)
|
382
|
+
def _reduce_22(val, _values, result)
|
383
|
+
result = e(:function_call, :multiply, [val[0], val[2]])
|
384
|
+
result
|
385
|
+
end
|
386
|
+
.,.,
|
387
|
+
|
388
|
+
module_eval(<<'.,.,', 'code_section.y', 49)
|
389
|
+
def _reduce_23(val, _values, result)
|
390
|
+
result = e(:function_call, :add, [val[0], val[2]])
|
391
|
+
result
|
392
|
+
end
|
393
|
+
.,.,
|
394
|
+
|
395
|
+
module_eval(<<'.,.,', 'code_section.y', 50)
|
396
|
+
def _reduce_24(val, _values, result)
|
397
|
+
result = e(:function_call, :minus, [val[0], val[2]])
|
398
|
+
result
|
399
|
+
end
|
400
|
+
.,.,
|
401
|
+
|
402
|
+
module_eval(<<'.,.,', 'code_section.y', 51)
|
403
|
+
def _reduce_25(val, _values, result)
|
404
|
+
result = e(:function_call, :divide, [val[0], val[2]])
|
405
|
+
result
|
406
|
+
end
|
407
|
+
.,.,
|
408
|
+
|
409
|
+
module_eval(<<'.,.,', 'code_section.y', 53)
|
410
|
+
def _reduce_26(val, _values, result)
|
411
|
+
result = e(:function_call, val[0], val[2])
|
412
|
+
result
|
413
|
+
end
|
414
|
+
.,.,
|
415
|
+
|
416
|
+
module_eval(<<'.,.,', 'code_section.y', 54)
|
417
|
+
def _reduce_27(val, _values, result)
|
418
|
+
result = e(:function_call, val[0], [])
|
419
|
+
result
|
420
|
+
end
|
421
|
+
.,.,
|
422
|
+
|
423
|
+
module_eval(<<'.,.,', 'code_section.y', 56)
|
424
|
+
def _reduce_28(val, _values, result)
|
425
|
+
result = val[0] << val[2]
|
426
|
+
result
|
427
|
+
end
|
428
|
+
.,.,
|
429
|
+
|
430
|
+
module_eval(<<'.,.,', 'code_section.y', 57)
|
431
|
+
def _reduce_29(val, _values, result)
|
432
|
+
result = [val[0]]
|
433
|
+
result
|
434
|
+
end
|
435
|
+
.,.,
|
436
|
+
|
437
|
+
def _reduce_none(val, _values, result)
|
438
|
+
val[0]
|
439
|
+
end
|
440
|
+
|
441
|
+
end # class CodeSectionParser
|
442
|
+
end # module Language
|
443
|
+
end # module CSVPlusPlus
|
@@ -0,0 +1,170 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
require 'csv'
|
5
|
+
require_relative '../cell'
|
6
|
+
require_relative '../modifier'
|
7
|
+
require_relative '../modifier.tab'
|
8
|
+
require_relative '../row'
|
9
|
+
require_relative '../template'
|
10
|
+
require_relative 'code_section.tab'
|
11
|
+
require_relative 'entities'
|
12
|
+
require_relative 'runtime'
|
13
|
+
require_relative 'scope'
|
14
|
+
|
15
|
+
module CSVPlusPlus
|
16
|
+
module Language
|
17
|
+
##
|
18
|
+
# Encapsulates the parsing and building of objects (+Template+ -> +Row+ -> +Cell+).
|
19
|
+
# Variable resolution is delegated to the +Scope+
|
20
|
+
# rubocop:disable Metrics/ClassLength
|
21
|
+
class Compiler
|
22
|
+
attr_reader :timings, :benchmark, :options, :runtime, :scope
|
23
|
+
|
24
|
+
# Create a compiler and make sure it gets cleaned up
|
25
|
+
def self.with_compiler(input:, filename:, options:, &block)
|
26
|
+
runtime = ::CSVPlusPlus::Language::Runtime.new(filename:, input:)
|
27
|
+
|
28
|
+
if options.verbose
|
29
|
+
compiler_with_timings(runtime:, options:) do |c|
|
30
|
+
block.call(c)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
yield(new(runtime:, options:))
|
34
|
+
end
|
35
|
+
ensure
|
36
|
+
runtime.cleanup!
|
37
|
+
end
|
38
|
+
|
39
|
+
# Create a compiler that can time each of it's stages
|
40
|
+
def self.compiler_with_timings(options:, runtime:, &block)
|
41
|
+
::Benchmark.benchmark(::Benchmark::CAPTION, 25, ::Benchmark::FORMAT, '> Total') do |x|
|
42
|
+
compiler = new(options:, runtime:, benchmark: x)
|
43
|
+
block.call(compiler)
|
44
|
+
[compiler.timings.reduce(:+)]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# initialize
|
49
|
+
def initialize(runtime:, options:, scope: nil, benchmark: nil)
|
50
|
+
@options = options
|
51
|
+
@runtime = runtime
|
52
|
+
@scope = scope || ::CSVPlusPlus::Language::Scope.new(runtime:)
|
53
|
+
@benchmark = benchmark
|
54
|
+
@timings = [] if benchmark
|
55
|
+
end
|
56
|
+
|
57
|
+
# Parse an entire template and return a +::CSVPlusPlus::Template+ instance
|
58
|
+
def parse_template
|
59
|
+
parse_code_section!
|
60
|
+
rows = parse_csv_section!
|
61
|
+
|
62
|
+
::CSVPlusPlus::Template.new(rows:, scope: @scope).tap do |t|
|
63
|
+
t.validate_infinite_expands(@runtime)
|
64
|
+
expanding { t.expand_rows! }
|
65
|
+
resolve_all_cells!(t)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# parses the input file and returns a +CodeSection+
|
70
|
+
def parse_code_section!
|
71
|
+
parsing_code_section do |input|
|
72
|
+
code_section, csv_section = ::CSVPlusPlus::Language::CodeSectionParser.new.parse(input, self)
|
73
|
+
# TODO: infer a type
|
74
|
+
# allow user-supplied key/values to override anything global or from the code section
|
75
|
+
code_section.def_variables(
|
76
|
+
options.key_values.transform_values { |v| ::CSVPlusPlus::Language::Entities::String.new(v.to_s) }
|
77
|
+
)
|
78
|
+
@scope.code_section = code_section
|
79
|
+
|
80
|
+
# return the csv_section to the caller because they're gonna re-write input with it
|
81
|
+
next csv_section
|
82
|
+
end
|
83
|
+
@scope.code_section
|
84
|
+
end
|
85
|
+
|
86
|
+
# workflow when parsing csv
|
87
|
+
def parse_csv_section!
|
88
|
+
workflow(stage: 'Parsing CSV section') do
|
89
|
+
@runtime.map_rows(::CSV.new(runtime.input)) do |csv_row|
|
90
|
+
parse_row(csv_row)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
ensure
|
94
|
+
# we're done with the file and everything is in memory
|
95
|
+
@runtime.cleanup!
|
96
|
+
end
|
97
|
+
|
98
|
+
# Using the current +@runtime+ and the given +csv_row+ parse it into a +Row+ of +Cell+s
|
99
|
+
# +csv_row+ should have already been run through a CSV parser and is an array of strings
|
100
|
+
def parse_row(csv_row)
|
101
|
+
row_modifier = ::CSVPlusPlus::Modifier.new(row_level: true)
|
102
|
+
|
103
|
+
cells =
|
104
|
+
@runtime.map_row(csv_row) do |value, _cell_index|
|
105
|
+
cell_modifier = ::CSVPlusPlus::Modifier.new
|
106
|
+
parsed_value = ::CSVPlusPlus::ModifierParser.new(row_modifier:, cell_modifier:).parse(value, @runtime)
|
107
|
+
|
108
|
+
::CSVPlusPlus::Cell.parse(parsed_value, runtime:, modifier: cell_modifier)
|
109
|
+
end
|
110
|
+
|
111
|
+
::CSVPlusPlus::Row.new(@runtime.row_index, cells, row_modifier)
|
112
|
+
end
|
113
|
+
|
114
|
+
# workflow when resolving the values of all cells
|
115
|
+
def resolve_all_cells!(template)
|
116
|
+
workflow(stage: 'Resolving each cell') do
|
117
|
+
@runtime.map_rows(template.rows, cells_too: true) do |cell|
|
118
|
+
cell.ast = @scope.resolve_cell_value if cell.ast
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# workflow when writing results
|
124
|
+
def outputting!(&block)
|
125
|
+
workflow(stage: 'Writing the spreadsheet') do
|
126
|
+
block.call
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# to_s
|
131
|
+
def to_s
|
132
|
+
"Compiler(options: #{@options}, runtime: #{@runtime}, scope: #{@scope})"
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
# workflow when parsing the code section
|
138
|
+
def parsing_code_section(&block)
|
139
|
+
workflow(
|
140
|
+
stage: 'Parsing code section',
|
141
|
+
processing_code_section: true
|
142
|
+
) do
|
143
|
+
csv_section = block.call(@runtime.input.read)
|
144
|
+
@runtime.rewrite_input!(csv_section)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# workflow when expanding rows
|
149
|
+
def expanding(&block)
|
150
|
+
workflow(stage: 'Expanding rows') do
|
151
|
+
block.call
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def workflow(stage:, processing_code_section: false, &block)
|
156
|
+
@runtime.init!(processing_code_section ? 1 : (@runtime.length_of_code_section || 1))
|
157
|
+
|
158
|
+
ret = nil
|
159
|
+
if @benchmark
|
160
|
+
@timings << @benchmark.report(stage) { ret = block.call }
|
161
|
+
else
|
162
|
+
ret = block.call
|
163
|
+
end
|
164
|
+
|
165
|
+
ret
|
166
|
+
end
|
167
|
+
end
|
168
|
+
# rubocop:enable Metrics/ClassLength
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './entity'
|
4
|
+
|
5
|
+
module CSVPlusPlus
|
6
|
+
module Language
|
7
|
+
module Entities
|
8
|
+
##
|
9
|
+
# A boolean value
|
10
|
+
class Boolean < Entity
|
11
|
+
attr_reader :value
|
12
|
+
|
13
|
+
# initialize
|
14
|
+
def initialize(value)
|
15
|
+
super(:boolean)
|
16
|
+
# TODO: probably can do a lot better in general on type validation
|
17
|
+
@value = value.is_a?(::String) ? (value.downcase == 'true') : value
|
18
|
+
end
|
19
|
+
|
20
|
+
# to_s
|
21
|
+
def to_s
|
22
|
+
@value.to_s.upcase
|
23
|
+
end
|
24
|
+
|
25
|
+
# ==
|
26
|
+
def ==(other)
|
27
|
+
super && value == other.value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './entity'
|
4
|
+
|
5
|
+
module CSVPlusPlus
|
6
|
+
module Language
|
7
|
+
module Entities
|
8
|
+
##
|
9
|
+
# A reference to a cell
|
10
|
+
class CellReference < Entity
|
11
|
+
attr_reader :cell_reference
|
12
|
+
|
13
|
+
# initialize
|
14
|
+
def initialize(cell_reference)
|
15
|
+
super(:cell_reference)
|
16
|
+
@cell_reference = cell_reference
|
17
|
+
end
|
18
|
+
|
19
|
+
# to_s
|
20
|
+
def to_s
|
21
|
+
@cell_reference
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|