csv_plus_plus 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +18 -63
  3. data/{CHANGELOG.md → docs/CHANGELOG.md} +17 -0
  4. data/lib/csv_plus_plus/benchmarked_compiler.rb +112 -0
  5. data/lib/csv_plus_plus/cell.rb +46 -24
  6. data/lib/csv_plus_plus/cli.rb +44 -17
  7. data/lib/csv_plus_plus/cli_flag.rb +1 -2
  8. data/lib/csv_plus_plus/color.rb +42 -11
  9. data/lib/csv_plus_plus/compiler.rb +178 -0
  10. data/lib/csv_plus_plus/entities/ast_builder.rb +50 -0
  11. data/lib/csv_plus_plus/entities/boolean.rb +40 -0
  12. data/lib/csv_plus_plus/entities/builtins.rb +58 -0
  13. data/lib/csv_plus_plus/entities/cell_reference.rb +231 -0
  14. data/lib/csv_plus_plus/entities/date.rb +63 -0
  15. data/lib/csv_plus_plus/entities/entity.rb +50 -0
  16. data/lib/csv_plus_plus/entities/entity_with_arguments.rb +57 -0
  17. data/lib/csv_plus_plus/entities/function.rb +45 -0
  18. data/lib/csv_plus_plus/entities/function_call.rb +50 -0
  19. data/lib/csv_plus_plus/entities/number.rb +48 -0
  20. data/lib/csv_plus_plus/entities/runtime_value.rb +43 -0
  21. data/lib/csv_plus_plus/entities/string.rb +42 -0
  22. data/lib/csv_plus_plus/entities/variable.rb +37 -0
  23. data/lib/csv_plus_plus/entities.rb +40 -0
  24. data/lib/csv_plus_plus/error/error.rb +20 -0
  25. data/lib/csv_plus_plus/error/formula_syntax_error.rb +37 -0
  26. data/lib/csv_plus_plus/error/modifier_syntax_error.rb +75 -0
  27. data/lib/csv_plus_plus/error/modifier_validation_error.rb +69 -0
  28. data/lib/csv_plus_plus/error/syntax_error.rb +71 -0
  29. data/lib/csv_plus_plus/error/writer_error.rb +17 -0
  30. data/lib/csv_plus_plus/error.rb +10 -2
  31. data/lib/csv_plus_plus/google_api_client.rb +11 -2
  32. data/lib/csv_plus_plus/google_options.rb +23 -18
  33. data/lib/csv_plus_plus/lexer/lexer.rb +17 -6
  34. data/lib/csv_plus_plus/lexer/tokenizer.rb +6 -1
  35. data/lib/csv_plus_plus/lexer.rb +24 -0
  36. data/lib/csv_plus_plus/modifier/conditional_formatting.rb +18 -0
  37. data/lib/csv_plus_plus/modifier/data_validation.rb +138 -0
  38. data/lib/csv_plus_plus/modifier/expand.rb +61 -0
  39. data/lib/csv_plus_plus/modifier/google_sheet_modifier.rb +133 -0
  40. data/lib/csv_plus_plus/modifier/modifier.rb +222 -0
  41. data/lib/csv_plus_plus/modifier/modifier_validator.rb +243 -0
  42. data/lib/csv_plus_plus/modifier/rubyxl_modifier.rb +84 -0
  43. data/lib/csv_plus_plus/modifier.rb +82 -150
  44. data/lib/csv_plus_plus/options.rb +64 -19
  45. data/lib/csv_plus_plus/{language → parser}/cell_value.tab.rb +25 -25
  46. data/lib/csv_plus_plus/{language → parser}/code_section.tab.rb +86 -95
  47. data/lib/csv_plus_plus/parser/modifier.tab.rb +478 -0
  48. data/lib/csv_plus_plus/row.rb +53 -15
  49. data/lib/csv_plus_plus/runtime/can_define_references.rb +87 -0
  50. data/lib/csv_plus_plus/runtime/can_resolve_references.rb +209 -0
  51. data/lib/csv_plus_plus/runtime/graph.rb +68 -0
  52. data/lib/csv_plus_plus/runtime/position_tracker.rb +231 -0
  53. data/lib/csv_plus_plus/runtime/references.rb +110 -0
  54. data/lib/csv_plus_plus/runtime/runtime.rb +126 -0
  55. data/lib/csv_plus_plus/runtime.rb +42 -0
  56. data/lib/csv_plus_plus/source_code.rb +66 -0
  57. data/lib/csv_plus_plus/template.rb +63 -36
  58. data/lib/csv_plus_plus/version.rb +2 -1
  59. data/lib/csv_plus_plus/writer/base_writer.rb +30 -5
  60. data/lib/csv_plus_plus/writer/csv.rb +11 -9
  61. data/lib/csv_plus_plus/writer/excel.rb +9 -2
  62. data/lib/csv_plus_plus/writer/file_backer_upper.rb +7 -4
  63. data/lib/csv_plus_plus/writer/google_sheet_builder.rb +88 -45
  64. data/lib/csv_plus_plus/writer/google_sheets.rb +79 -29
  65. data/lib/csv_plus_plus/writer/open_document.rb +6 -1
  66. data/lib/csv_plus_plus/writer/rubyxl_builder.rb +103 -33
  67. data/lib/csv_plus_plus/writer.rb +39 -9
  68. data/lib/csv_plus_plus.rb +41 -15
  69. metadata +44 -30
  70. data/lib/csv_plus_plus/code_section.rb +0 -101
  71. data/lib/csv_plus_plus/expand.rb +0 -18
  72. data/lib/csv_plus_plus/graph.rb +0 -62
  73. data/lib/csv_plus_plus/language/ast_builder.rb +0 -68
  74. data/lib/csv_plus_plus/language/benchmarked_compiler.rb +0 -65
  75. data/lib/csv_plus_plus/language/builtins.rb +0 -46
  76. data/lib/csv_plus_plus/language/compiler.rb +0 -152
  77. data/lib/csv_plus_plus/language/entities/boolean.rb +0 -33
  78. data/lib/csv_plus_plus/language/entities/cell_reference.rb +0 -33
  79. data/lib/csv_plus_plus/language/entities/entity.rb +0 -86
  80. data/lib/csv_plus_plus/language/entities/function.rb +0 -35
  81. data/lib/csv_plus_plus/language/entities/function_call.rb +0 -37
  82. data/lib/csv_plus_plus/language/entities/number.rb +0 -36
  83. data/lib/csv_plus_plus/language/entities/runtime_value.rb +0 -28
  84. data/lib/csv_plus_plus/language/entities/string.rb +0 -31
  85. data/lib/csv_plus_plus/language/entities/variable.rb +0 -25
  86. data/lib/csv_plus_plus/language/entities.rb +0 -28
  87. data/lib/csv_plus_plus/language/references.rb +0 -70
  88. data/lib/csv_plus_plus/language/runtime.rb +0 -205
  89. data/lib/csv_plus_plus/language/scope.rb +0 -192
  90. data/lib/csv_plus_plus/language/syntax_error.rb +0 -66
  91. data/lib/csv_plus_plus/modifier.tab.rb +0 -907
  92. data/lib/csv_plus_plus/writer/google_sheet_modifier.rb +0 -56
  93. data/lib/csv_plus_plus/writer/rubyxl_modifier.rb +0 -59
@@ -0,0 +1,478 @@
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
+
10
+ require_relative '../lexer'
11
+
12
+ module CSVPlusPlus
13
+ module Parser
14
+ class Modifier < Racc::Parser
15
+
16
+ module_eval(<<'...end modifier.y/module_eval...', 'modifier.y', 60)
17
+ attr_reader :return_value
18
+
19
+ include ::CSVPlusPlus::Lexer
20
+
21
+ # @param cell_modifier [Modifier]
22
+ # @param row_modifier [Modifier]
23
+ def initialize(cell_modifier:, row_modifier:)
24
+ super()
25
+
26
+ @parsing_row = false
27
+ @cell_modifier = ::CSVPlusPlus::Modifier::ModifierValidator.new(cell_modifier)
28
+ @row_modifier = ::CSVPlusPlus::Modifier::ModifierValidator.new(row_modifier)
29
+ end
30
+
31
+ protected
32
+
33
+ def anything_to_parse?(input)
34
+ @modifiers_to_parse = input.scan(/!?\[\[/).count
35
+
36
+ if @modifiers_to_parse == 0
37
+ assign_defaults!
38
+ @return_value = input
39
+ end
40
+
41
+ @modifiers_to_parse > 0
42
+ end
43
+
44
+ def parse_subject
45
+ 'modifier'
46
+ end
47
+
48
+ def tokenizer
49
+ ::CSVPlusPlus::Lexer::Tokenizer.new(
50
+ ignore: /\s+/,
51
+ stop_fn: lambda do |scanner|
52
+ return false unless scanner.scan(/\]\]/)
53
+
54
+ @tokens << [:END_MODIFIERS, scanner.matched]
55
+ @return_value = scanner.rest
56
+
57
+ @modifiers_to_parse -= 1
58
+ @modifiers_to_parse == 0
59
+ end,
60
+ tokens: [
61
+ [/\bborder\b/, 'border'],
62
+ [/\bbordercolor\b/, 'bordercolor'],
63
+ [/\bborderstyle\b/, 'borderstyle'],
64
+ [/\bcolor\b/, 'color'],
65
+ [/\bexpand\b/, 'expand'],
66
+ [/\bfontcolor\b/, 'fontcolor'],
67
+ [/\bfontfamily\b/, 'fontfamily'],
68
+ [/\bfontsize\b/, 'fontsize'],
69
+ [/\bformat\b/, 'format'],
70
+ [/\bfreeze\b/, 'freeze'],
71
+ [/\bhalign\b/, 'halign'],
72
+ [/\bnote\b/, 'note'],
73
+ [/\bnumberformat\b/, 'numberformat'],
74
+ [/\bvalidate\b/, 'validate'],
75
+ [/\bvalign\b/, 'valign'],
76
+ [/\bvar\b/, 'var'],
77
+ [/-?[\d.]+/, :NUMBER],
78
+ TOKEN_LIBRARY[:HEX_COLOR],
79
+ [
80
+ /
81
+ (?:
82
+ \w+\s*:\s*'([^'\\]|\\.)*') # allow for a single-quoted string which can accept any input and also allow
83
+ # for escaping via backslash (i.e., 'ain\\'t won\\'t something' is valid)
84
+ | # - or -
85
+ (?:'([^'\\]|\\.)*') # allow for a single-quoted string which can accept any input and also allow
86
+ |
87
+ (?:
88
+ [\w,_:-] # something that accepts most basic input if it doesn't need to be quoted
89
+ [\w\s,_:-]+ # same thing but allow spaces in the middle
90
+ [\w,_:-] # no spaces at the end
91
+ )
92
+ /x,
93
+ :RIGHT_SIDE,
94
+ ],
95
+ [/\[\[/, :START_CELL_MODIFIERS],
96
+ [/!\[\[/, :START_ROW_MODIFIERS],
97
+ [/\//, :MODIFIER_SEPARATOR],
98
+ [/=/, :EQ],
99
+ ],
100
+ alter_matches: {
101
+ STRING: ->(s) { s.gsub(/^'|'$/, '') }
102
+ },
103
+ )
104
+ end
105
+
106
+ private
107
+
108
+ def assign_defaults!
109
+ @cell_modifier.modifier.take_defaults_from!(@row_modifier.modifier)
110
+ end
111
+
112
+ def parsing_row!
113
+ @parsing_row = true
114
+ end
115
+
116
+ def finished_row!
117
+ parsing_cell!
118
+ end
119
+
120
+ def parsing_cell!
121
+ @parsing_row = false
122
+ assign_defaults!
123
+ end
124
+
125
+ def modifier
126
+ @parsing_row ? @row_modifier : @cell_modifier
127
+ end
128
+ ...end modifier.y/module_eval...
129
+ ##### State transition tables begin ###
130
+
131
+ racc_action_table = [
132
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
133
+ 23, 24, 25, 26, 27, 28, 13, 14, 15, 16,
134
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
135
+ 27, 28, 13, 14, 15, 16, 17, 18, 19, 20,
136
+ 21, 22, 23, 24, 25, 26, 27, 28, 30, 47,
137
+ 5, 4, 6, 31, 31, 5, 10, 32, 33, 34,
138
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
139
+ 45, 46, 49, 50, 51, 52, 53, 54, 55, 56,
140
+ 57, 58, 59, 60, 61, 62, 63 ]
141
+
142
+ racc_action_check = [
143
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
144
+ 8, 8, 8, 8, 8, 8, 9, 9, 9, 9,
145
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
146
+ 9, 9, 31, 31, 31, 31, 31, 31, 31, 31,
147
+ 31, 31, 31, 31, 31, 31, 31, 31, 11, 29,
148
+ 0, 0, 1, 11, 29, 2, 6, 13, 14, 15,
149
+ 16, 17, 18, 19, 20, 21, 23, 24, 25, 26,
150
+ 27, 28, 32, 33, 34, 35, 36, 37, 38, 39,
151
+ 40, 41, 42, 43, 44, 45, 46 ]
152
+
153
+ racc_action_pointer = [
154
+ 36, 52, 41, nil, nil, nil, 56, nil, -17, -1,
155
+ nil, 41, nil, 49, 50, 51, 52, 53, 54, 55,
156
+ 56, 57, nil, 58, 59, 60, 61, 62, 63, 42,
157
+ nil, 15, 59, 64, 61, 66, 66, 68, 65, 69,
158
+ 67, 68, 69, 70, 71, 72, 73, nil, nil, nil,
159
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
160
+ nil, nil, nil, nil ]
161
+
162
+ racc_action_default = [
163
+ -27, -27, -2, -3, -4, -6, -27, -1, -27, -27,
164
+ 64, -27, -9, -27, -27, -27, -27, -15, -27, -27,
165
+ -27, -27, -20, -27, -27, -27, -27, -27, -27, -27,
166
+ -5, -27, -27, -27, -27, -27, -27, -27, -27, -27,
167
+ -27, -27, -27, -27, -27, -27, -27, -7, -8, -10,
168
+ -11, -12, -13, -14, -16, -17, -18, -19, -21, -22,
169
+ -23, -24, -25, -26 ]
170
+
171
+ racc_goto_table = [
172
+ 3, 1, 7, 11, 29, 2, 8, 9, 48 ]
173
+
174
+ racc_goto_check = [
175
+ 3, 1, 3, 4, 4, 2, 5, 6, 7 ]
176
+
177
+ racc_goto_pointer = [
178
+ nil, 1, 5, 0, -5, 2, 2, -23 ]
179
+
180
+ racc_goto_default = [
181
+ nil, nil, nil, nil, nil, nil, nil, 12 ]
182
+
183
+ racc_reduce_table = [
184
+ 0, 0, :racc_error,
185
+ 2, 34, :_reduce_none,
186
+ 1, 34, :_reduce_none,
187
+ 1, 34, :_reduce_none,
188
+ 0, 38, :_reduce_4,
189
+ 4, 35, :_reduce_5,
190
+ 0, 39, :_reduce_6,
191
+ 4, 36, :_reduce_none,
192
+ 3, 37, :_reduce_none,
193
+ 1, 37, :_reduce_none,
194
+ 3, 40, :_reduce_10,
195
+ 3, 40, :_reduce_11,
196
+ 3, 40, :_reduce_12,
197
+ 3, 40, :_reduce_13,
198
+ 3, 40, :_reduce_14,
199
+ 1, 40, :_reduce_15,
200
+ 3, 40, :_reduce_16,
201
+ 3, 40, :_reduce_17,
202
+ 3, 40, :_reduce_18,
203
+ 3, 40, :_reduce_19,
204
+ 1, 40, :_reduce_20,
205
+ 3, 40, :_reduce_21,
206
+ 3, 40, :_reduce_22,
207
+ 3, 40, :_reduce_23,
208
+ 3, 40, :_reduce_24,
209
+ 3, 40, :_reduce_25,
210
+ 3, 40, :_reduce_26 ]
211
+
212
+ racc_reduce_n = 27
213
+
214
+ racc_shift_n = 64
215
+
216
+ racc_token_table = {
217
+ false => 0,
218
+ :error => 1,
219
+ "![[" => 2,
220
+ "[[" => 3,
221
+ "]]" => 4,
222
+ "=" => 5,
223
+ "/" => 6,
224
+ :END_MODIFIERS => 7,
225
+ :EQ => 8,
226
+ :HEX_COLOR => 9,
227
+ :NUMBER => 10,
228
+ :MODIFIER => 11,
229
+ :MODIFIER_SEPARATOR => 12,
230
+ :RIGHT_SIDE => 13,
231
+ :START_CELL_MODIFIERS => 14,
232
+ :START_ROW_MODIFIERS => 15,
233
+ :STRING => 16,
234
+ "border" => 17,
235
+ "bordercolor" => 18,
236
+ "borderstyle" => 19,
237
+ "color" => 20,
238
+ "expand" => 21,
239
+ "fontcolor" => 22,
240
+ "fontfamily" => 23,
241
+ "fontsize" => 24,
242
+ "format" => 25,
243
+ "freeze" => 26,
244
+ "halign" => 27,
245
+ "note" => 28,
246
+ "numberformat" => 29,
247
+ "validate" => 30,
248
+ "valign" => 31,
249
+ "var" => 32 }
250
+
251
+ racc_nt_base = 33
252
+
253
+ racc_use_result_var = true
254
+
255
+ Racc_arg = [
256
+ racc_action_table,
257
+ racc_action_check,
258
+ racc_action_default,
259
+ racc_action_pointer,
260
+ racc_goto_table,
261
+ racc_goto_check,
262
+ racc_goto_default,
263
+ racc_goto_pointer,
264
+ racc_nt_base,
265
+ racc_reduce_table,
266
+ racc_token_table,
267
+ racc_shift_n,
268
+ racc_reduce_n,
269
+ racc_use_result_var ]
270
+
271
+ Racc_token_to_s_table = [
272
+ "$end",
273
+ "error",
274
+ "\"![[\"",
275
+ "\"[[\"",
276
+ "\"]]\"",
277
+ "\"=\"",
278
+ "\"/\"",
279
+ "END_MODIFIERS",
280
+ "EQ",
281
+ "HEX_COLOR",
282
+ "NUMBER",
283
+ "MODIFIER",
284
+ "MODIFIER_SEPARATOR",
285
+ "RIGHT_SIDE",
286
+ "START_CELL_MODIFIERS",
287
+ "START_ROW_MODIFIERS",
288
+ "STRING",
289
+ "\"border\"",
290
+ "\"bordercolor\"",
291
+ "\"borderstyle\"",
292
+ "\"color\"",
293
+ "\"expand\"",
294
+ "\"fontcolor\"",
295
+ "\"fontfamily\"",
296
+ "\"fontsize\"",
297
+ "\"format\"",
298
+ "\"freeze\"",
299
+ "\"halign\"",
300
+ "\"note\"",
301
+ "\"numberformat\"",
302
+ "\"validate\"",
303
+ "\"valign\"",
304
+ "\"var\"",
305
+ "$start",
306
+ "modifiers_definition",
307
+ "row_modifiers",
308
+ "cell_modifiers",
309
+ "modifiers",
310
+ "@1",
311
+ "@2",
312
+ "modifier" ]
313
+
314
+ Racc_debug_parser = false
315
+
316
+ ##### State transition tables end #####
317
+
318
+ # reduce 0 omitted
319
+
320
+ # reduce 1 omitted
321
+
322
+ # reduce 2 omitted
323
+
324
+ # reduce 3 omitted
325
+
326
+ module_eval(<<'.,.,', 'modifier.y', 25)
327
+ def _reduce_4(val, _values, result)
328
+ parsing_row!
329
+ result
330
+ end
331
+ .,.,
332
+
333
+ module_eval(<<'.,.,', 'modifier.y', 27)
334
+ def _reduce_5(val, _values, result)
335
+ finished_row!
336
+ result
337
+ end
338
+ .,.,
339
+
340
+ module_eval(<<'.,.,', 'modifier.y', 29)
341
+ def _reduce_6(val, _values, result)
342
+ parsing_cell!
343
+ result
344
+ end
345
+ .,.,
346
+
347
+ # reduce 7 omitted
348
+
349
+ # reduce 8 omitted
350
+
351
+ # reduce 9 omitted
352
+
353
+ module_eval(<<'.,.,', 'modifier.y', 35)
354
+ def _reduce_10(val, _values, result)
355
+ modifier.border = val[2]
356
+ result
357
+ end
358
+ .,.,
359
+
360
+ module_eval(<<'.,.,', 'modifier.y', 36)
361
+ def _reduce_11(val, _values, result)
362
+ modifier.bordercolor = val[2]
363
+ result
364
+ end
365
+ .,.,
366
+
367
+ module_eval(<<'.,.,', 'modifier.y', 37)
368
+ def _reduce_12(val, _values, result)
369
+ modifier.borderstyle = val[2]
370
+ result
371
+ end
372
+ .,.,
373
+
374
+ module_eval(<<'.,.,', 'modifier.y', 38)
375
+ def _reduce_13(val, _values, result)
376
+ modifier.color = val[2]
377
+ result
378
+ end
379
+ .,.,
380
+
381
+ module_eval(<<'.,.,', 'modifier.y', 39)
382
+ def _reduce_14(val, _values, result)
383
+ modifier.expand = val[2]
384
+ result
385
+ end
386
+ .,.,
387
+
388
+ module_eval(<<'.,.,', 'modifier.y', 40)
389
+ def _reduce_15(val, _values, result)
390
+ modifier.infinite_expand!
391
+ result
392
+ end
393
+ .,.,
394
+
395
+ module_eval(<<'.,.,', 'modifier.y', 41)
396
+ def _reduce_16(val, _values, result)
397
+ modifier.fontcolor = val[2]
398
+ result
399
+ end
400
+ .,.,
401
+
402
+ module_eval(<<'.,.,', 'modifier.y', 42)
403
+ def _reduce_17(val, _values, result)
404
+ modifier.fontfamily = val[2]
405
+ result
406
+ end
407
+ .,.,
408
+
409
+ module_eval(<<'.,.,', 'modifier.y', 43)
410
+ def _reduce_18(val, _values, result)
411
+ modifier.fontsize = val[2]
412
+ result
413
+ end
414
+ .,.,
415
+
416
+ module_eval(<<'.,.,', 'modifier.y', 44)
417
+ def _reduce_19(val, _values, result)
418
+ modifier.format = val[2]
419
+ result
420
+ end
421
+ .,.,
422
+
423
+ module_eval(<<'.,.,', 'modifier.y', 45)
424
+ def _reduce_20(val, _values, result)
425
+ modifier.freeze!
426
+ result
427
+ end
428
+ .,.,
429
+
430
+ module_eval(<<'.,.,', 'modifier.y', 46)
431
+ def _reduce_21(val, _values, result)
432
+ modifier.halign = val[2]
433
+ result
434
+ end
435
+ .,.,
436
+
437
+ module_eval(<<'.,.,', 'modifier.y', 47)
438
+ def _reduce_22(val, _values, result)
439
+ modifier.note = val[2]
440
+ result
441
+ end
442
+ .,.,
443
+
444
+ module_eval(<<'.,.,', 'modifier.y', 48)
445
+ def _reduce_23(val, _values, result)
446
+ modifier.numberformat = val[2]
447
+ result
448
+ end
449
+ .,.,
450
+
451
+ module_eval(<<'.,.,', 'modifier.y', 49)
452
+ def _reduce_24(val, _values, result)
453
+ modifier.validate = val[2]
454
+ result
455
+ end
456
+ .,.,
457
+
458
+ module_eval(<<'.,.,', 'modifier.y', 50)
459
+ def _reduce_25(val, _values, result)
460
+ modifier.valign = val[2]
461
+ result
462
+ end
463
+ .,.,
464
+
465
+ module_eval(<<'.,.,', 'modifier.y', 51)
466
+ def _reduce_26(val, _values, result)
467
+ modifier.var = val[2]
468
+ result
469
+ end
470
+ .,.,
471
+
472
+ def _reduce_none(val, _values, result)
473
+ val[0]
474
+ end
475
+
476
+ end # class Modifier
477
+ end # module Parser
478
+ end # module CSVPlusPlus
@@ -1,26 +1,37 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
- require_relative 'cell'
4
- require_relative 'modifier.tab'
5
-
6
4
  module CSVPlusPlus
7
- # A row of a template
5
+ # A row of a template. A row contains an +Array+ of +Cell+s and possibly a row-level +Modifier+.
8
6
  #
9
- # @attr_reader cells [Array<Cell>]
10
- # @attr_reader index [Integer] The index of this row
7
+ # @attr_reader cells [Array<Cell>] The cells contained by this row.
8
+ # @attr_reader index [Integer] The index of this row. Starts at 0.
11
9
  # @attr_reader modifier [Modifier] The modifier to apply to all cells in this row
12
10
  class Row
13
- attr_reader :cells, :index, :modifier
11
+ extend ::T::Sig
14
12
 
15
- # @param index [Integer] The index of this row (starts at 0)
13
+ sig { returns(::T::Array[::CSVPlusPlus::Cell]) }
14
+ attr_reader :cells
15
+
16
+ sig { returns(::Integer) }
17
+ attr_reader :index
18
+
19
+ sig { returns(::CSVPlusPlus::Modifier::Modifier) }
20
+ attr_reader :modifier
21
+
22
+ sig do
23
+ params(cells: ::T::Array[::CSVPlusPlus::Cell], index: ::Integer, modifier: ::CSVPlusPlus::Modifier::Modifier).void
24
+ end
16
25
  # @param cells [Array<Cell>] The cells belonging to this row
26
+ # @param index [Integer] The index of this row (starts at 0)
17
27
  # @param modifier [Modifier] The modifier to apply to all cells in this row
18
- def initialize(index, cells, modifier)
28
+ def initialize(cells:, index:, modifier:)
19
29
  @cells = cells
20
30
  @modifier = modifier
21
31
  @index = index
22
32
  end
23
33
 
34
+ sig { params(index: ::Integer).void }
24
35
  # Set the row's +index+ and update the +row_index+ of all affected cells
25
36
  #
26
37
  # @param index [Integer] The index of this row (starts at 0)
@@ -29,25 +40,52 @@ module CSVPlusPlus
29
40
  @cells.each { |cell| cell.row_index = index }
30
41
  end
31
42
 
43
+ sig { returns(::Integer) }
32
44
  # How much this row will expand itself, if at all (0)
33
45
  #
34
46
  # @return [Integer]
35
47
  def expand_amount
36
- return 0 unless @modifier.expand
48
+ return 0 if @modifier.expand.nil?
49
+
50
+ ::T.must(@modifier.expand).repetitions || (1000 - @index)
51
+ end
52
+
53
+ sig { params(starts_at: ::Integer, into: ::T::Array[::CSVPlusPlus::Row]).returns(::T::Array[::CSVPlusPlus::Row]) }
54
+ # Starting at +starts_at+, do a deep copy of this row into the +Array+ referenced by +into+.
55
+ #
56
+ # @param starts_at [Integer] The +row_index+ where this row was expanded.
57
+ # @param into [Array<Row>] An array where the expanded rows will be accumulated.
58
+ #
59
+ # @return [Array<Row>] The rows expanded
60
+ def expand_rows(starts_at:, into: [])
61
+ return into if @modifier.expand.nil?
37
62
 
38
- @modifier.expand.repetitions || (1000 - @index)
63
+ ::T.must(@modifier.expand).starts_at = starts_at
64
+
65
+ starts_at.upto(expand_amount + starts_at - 1) do |row_index|
66
+ into << deep_clone.tap { |c| c.index = row_index }
67
+ end
68
+ into
39
69
  end
40
70
 
41
- # @return [String]
42
- def to_s
43
- "Row(index: #{index}, modifier: #{modifier}, cells: #{cells})"
71
+ sig { returns(::T::Boolean) }
72
+ # Does the row have an ![[expand]] modifier but is yet to be expanded?
73
+ #
74
+ # @return [T::Boolean]
75
+ def unexpanded?
76
+ return false if @modifier.expand.nil?
77
+
78
+ !::T.must(@modifier.expand).expanded?
44
79
  end
45
80
 
81
+ private
82
+
83
+ sig { returns(::CSVPlusPlus::Row) }
46
84
  # Return a deep copy of this row
47
85
  #
48
86
  # @return [Row]
49
87
  def deep_clone
50
- ::Marshal.load(::Marshal.dump(self))
88
+ ::T.cast(::Marshal.load(::Marshal.dump(self)), ::CSVPlusPlus::Row)
51
89
  end
52
90
  end
53
91
  end
@@ -0,0 +1,87 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module CSVPlusPlus
5
+ module Runtime
6
+ # Methods for classes that need to manage +@variables+ and +@functions+
7
+ module CanDefineReferences
8
+ # Define a (or re-define an existing) variable
9
+ #
10
+ # @param id [String, Symbol] The identifier for the variable
11
+ # @param entity [Entity] The value (entity) the variable holds
12
+ #
13
+ # @return [Entity] The value of the variable (+entity+)
14
+ def def_variable(id, entity)
15
+ @variables[id.to_sym] = entity
16
+ end
17
+
18
+ # Define (or re-define existing) variables
19
+ #
20
+ # @param vars [Hash<Symbol, Variable>] Variables to define
21
+ def def_variables(vars)
22
+ vars.each { |id, entity| def_variable(id, entity) }
23
+ end
24
+
25
+ # Define a (or re-define an existing) function
26
+ #
27
+ # @param id [String, Symbol] The identifier for the function
28
+ # @param entity [Entities::Function] The defined function
29
+ #
30
+ # @return [Entities::Function] The defined function
31
+ def def_function(id, entity)
32
+ @functions[id.to_sym] = entity
33
+ end
34
+
35
+ # Is the variable defined?
36
+ #
37
+ # @param var_id [Symbol, String] The identifier of the variable
38
+ #
39
+ # @return [boolean]
40
+ def defined_variable?(var_id)
41
+ @variables.key?(var_id.to_sym)
42
+ end
43
+
44
+ # Is the function defined?
45
+ #
46
+ # @param fn_id [Symbol, String] The identifier of the function
47
+ #
48
+ # @return [boolean]
49
+ def defined_function?(fn_id)
50
+ @functions.key?(fn_id.to_sym)
51
+ end
52
+
53
+ # Provide a summary of the functions and variables compiled (to show in verbose mode)
54
+ #
55
+ # @return [String]
56
+ def verbose_summary
57
+ <<~SUMMARY
58
+ # Code Section Summary
59
+
60
+ ## Resolved Variables
61
+
62
+ #{variable_summary}
63
+
64
+ ## Functions
65
+
66
+ #{function_summary}
67
+ SUMMARY
68
+ end
69
+
70
+ private
71
+
72
+ def variable_summary
73
+ return '(no variables defined)' if @variables.empty?
74
+
75
+ @variables.map { |k, v| "#{k} := #{v}" }
76
+ .join("\n")
77
+ end
78
+
79
+ def function_summary
80
+ return '(no functions defined)' if @functions.empty?
81
+
82
+ @functions.map { |k, f| "#{k}: #{f}" }
83
+ .join("\n")
84
+ end
85
+ end
86
+ end
87
+ end