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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/lib/csv_plus_plus/cell.rb +51 -0
  3. data/lib/csv_plus_plus/code_section.rb +49 -0
  4. data/lib/csv_plus_plus/color.rb +22 -0
  5. data/lib/csv_plus_plus/expand.rb +18 -0
  6. data/lib/csv_plus_plus/google_options.rb +23 -0
  7. data/lib/csv_plus_plus/graph.rb +68 -0
  8. data/lib/csv_plus_plus/language/cell_value.tab.rb +333 -0
  9. data/lib/csv_plus_plus/language/code_section.tab.rb +443 -0
  10. data/lib/csv_plus_plus/language/compiler.rb +170 -0
  11. data/lib/csv_plus_plus/language/entities/boolean.rb +32 -0
  12. data/lib/csv_plus_plus/language/entities/cell_reference.rb +26 -0
  13. data/lib/csv_plus_plus/language/entities/entity.rb +70 -0
  14. data/lib/csv_plus_plus/language/entities/function.rb +33 -0
  15. data/lib/csv_plus_plus/language/entities/function_call.rb +25 -0
  16. data/lib/csv_plus_plus/language/entities/number.rb +34 -0
  17. data/lib/csv_plus_plus/language/entities/runtime_value.rb +27 -0
  18. data/lib/csv_plus_plus/language/entities/string.rb +29 -0
  19. data/lib/csv_plus_plus/language/entities/variable.rb +25 -0
  20. data/lib/csv_plus_plus/language/entities.rb +28 -0
  21. data/lib/csv_plus_plus/language/references.rb +53 -0
  22. data/lib/csv_plus_plus/language/runtime.rb +147 -0
  23. data/lib/csv_plus_plus/language/scope.rb +199 -0
  24. data/lib/csv_plus_plus/language/syntax_error.rb +61 -0
  25. data/lib/csv_plus_plus/lexer/lexer.rb +64 -0
  26. data/lib/csv_plus_plus/lexer/tokenizer.rb +65 -0
  27. data/lib/csv_plus_plus/lexer.rb +14 -0
  28. data/lib/csv_plus_plus/modifier.rb +124 -0
  29. data/lib/csv_plus_plus/modifier.tab.rb +921 -0
  30. data/lib/csv_plus_plus/options.rb +70 -0
  31. data/lib/csv_plus_plus/row.rb +42 -0
  32. data/lib/csv_plus_plus/template.rb +61 -0
  33. data/lib/csv_plus_plus/version.rb +6 -0
  34. data/lib/csv_plus_plus/writer/base_writer.rb +21 -0
  35. data/lib/csv_plus_plus/writer/csv.rb +31 -0
  36. data/lib/csv_plus_plus/writer/excel.rb +13 -0
  37. data/lib/csv_plus_plus/writer/google_sheet_builder.rb +173 -0
  38. data/lib/csv_plus_plus/writer/google_sheets.rb +139 -0
  39. data/lib/csv_plus_plus/writer/open_document.rb +14 -0
  40. data/lib/csv_plus_plus/writer.rb +25 -0
  41. data/lib/csv_plus_plus.rb +20 -0
  42. 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