csv_plus_plus 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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