csv_plus_plus 0.1.3 → 0.2.1
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 +4 -4
- data/README.md +13 -3
- data/docs/CHANGELOG.md +18 -0
- data/lib/csv_plus_plus/a1_reference.rb +202 -0
- data/lib/csv_plus_plus/benchmarked_compiler.rb +3 -3
- data/lib/csv_plus_plus/cell.rb +1 -35
- data/lib/csv_plus_plus/cli.rb +43 -80
- data/lib/csv_plus_plus/cli_flag.rb +77 -70
- data/lib/csv_plus_plus/color.rb +1 -1
- data/lib/csv_plus_plus/compiler.rb +31 -21
- data/lib/csv_plus_plus/entities/ast_builder.rb +11 -4
- data/lib/csv_plus_plus/entities/boolean.rb +16 -9
- data/lib/csv_plus_plus/entities/builtins.rb +68 -40
- data/lib/csv_plus_plus/entities/date.rb +14 -11
- data/lib/csv_plus_plus/entities/entity.rb +11 -29
- data/lib/csv_plus_plus/entities/entity_with_arguments.rb +18 -31
- data/lib/csv_plus_plus/entities/function.rb +22 -11
- data/lib/csv_plus_plus/entities/function_call.rb +35 -11
- data/lib/csv_plus_plus/entities/has_identifier.rb +19 -0
- data/lib/csv_plus_plus/entities/number.rb +15 -10
- data/lib/csv_plus_plus/entities/reference.rb +77 -0
- data/lib/csv_plus_plus/entities/runtime_value.rb +36 -23
- data/lib/csv_plus_plus/entities/string.rb +13 -10
- data/lib/csv_plus_plus/entities.rb +2 -18
- data/lib/csv_plus_plus/error/cli_error.rb +17 -0
- data/lib/csv_plus_plus/error/compiler_error.rb +17 -0
- data/lib/csv_plus_plus/error/error.rb +18 -5
- data/lib/csv_plus_plus/error/formula_syntax_error.rb +12 -13
- data/lib/csv_plus_plus/error/modifier_syntax_error.rb +10 -36
- data/lib/csv_plus_plus/error/modifier_validation_error.rb +6 -32
- data/lib/csv_plus_plus/error/positional_error.rb +15 -0
- data/lib/csv_plus_plus/error/writer_error.rb +1 -1
- data/lib/csv_plus_plus/error.rb +4 -1
- data/lib/csv_plus_plus/error_formatter.rb +111 -0
- data/lib/csv_plus_plus/google_api_client.rb +18 -8
- data/lib/csv_plus_plus/lexer/racc_lexer.rb +144 -0
- data/lib/csv_plus_plus/lexer/tokenizer.rb +53 -17
- data/lib/csv_plus_plus/lexer.rb +40 -1
- data/lib/csv_plus_plus/modifier/data_validation.rb +1 -1
- data/lib/csv_plus_plus/modifier/expand.rb +17 -0
- data/lib/csv_plus_plus/modifier.rb +6 -1
- data/lib/csv_plus_plus/options/file_options.rb +49 -0
- data/lib/csv_plus_plus/options/google_sheets_options.rb +42 -0
- data/lib/csv_plus_plus/options/options.rb +102 -0
- data/lib/csv_plus_plus/options.rb +22 -110
- data/lib/csv_plus_plus/parser/cell_value.tab.rb +65 -66
- data/lib/csv_plus_plus/parser/code_section.tab.rb +92 -84
- data/lib/csv_plus_plus/parser/modifier.tab.rb +40 -30
- data/lib/csv_plus_plus/reader/csv.rb +50 -0
- data/lib/csv_plus_plus/reader/google_sheets.rb +129 -0
- data/lib/csv_plus_plus/reader/reader.rb +27 -0
- data/lib/csv_plus_plus/reader/rubyxl.rb +37 -0
- data/lib/csv_plus_plus/reader.rb +14 -0
- data/lib/csv_plus_plus/runtime/graph.rb +6 -6
- data/lib/csv_plus_plus/runtime/{position_tracker.rb → position.rb} +16 -5
- data/lib/csv_plus_plus/runtime/references.rb +32 -27
- data/lib/csv_plus_plus/runtime/runtime.rb +73 -67
- data/lib/csv_plus_plus/runtime/scope.rb +280 -0
- data/lib/csv_plus_plus/runtime.rb +9 -9
- data/lib/csv_plus_plus/source_code.rb +14 -9
- data/lib/csv_plus_plus/template.rb +17 -12
- data/lib/csv_plus_plus/version.rb +1 -1
- data/lib/csv_plus_plus/writer/csv.rb +32 -5
- data/lib/csv_plus_plus/writer/excel.rb +19 -6
- data/lib/csv_plus_plus/writer/file_backer_upper.rb +27 -14
- data/lib/csv_plus_plus/writer/google_sheets.rb +23 -129
- data/lib/csv_plus_plus/writer/{google_sheet_builder.rb → google_sheets_builder.rb} +39 -55
- data/lib/csv_plus_plus/writer/merger.rb +56 -0
- data/lib/csv_plus_plus/writer/open_document.rb +16 -2
- data/lib/csv_plus_plus/writer/rubyxl_builder.rb +68 -43
- data/lib/csv_plus_plus/writer/writer.rb +42 -0
- data/lib/csv_plus_plus/writer.rb +58 -19
- data/lib/csv_plus_plus.rb +26 -14
- metadata +43 -18
- data/lib/csv_plus_plus/entities/cell_reference.rb +0 -231
- data/lib/csv_plus_plus/entities/variable.rb +0 -37
- data/lib/csv_plus_plus/error/syntax_error.rb +0 -71
- data/lib/csv_plus_plus/google_options.rb +0 -32
- data/lib/csv_plus_plus/lexer/lexer.rb +0 -89
- data/lib/csv_plus_plus/runtime/can_define_references.rb +0 -87
- data/lib/csv_plus_plus/runtime/can_resolve_references.rb +0 -209
- data/lib/csv_plus_plus/writer/base_writer.rb +0 -45
|
@@ -56,6 +56,23 @@ module CSVPlusPlus
|
|
|
56
56
|
@starts_at = row_index
|
|
57
57
|
@ends_at = row_index + @repetitions unless @repetitions.nil?
|
|
58
58
|
end
|
|
59
|
+
|
|
60
|
+
sig { params(position: ::CSVPlusPlus::Runtime::Position).returns(::T::Boolean) }
|
|
61
|
+
# Does the given +position+ fall within this expand?
|
|
62
|
+
#
|
|
63
|
+
# @param position [Runtime::Position]
|
|
64
|
+
#
|
|
65
|
+
# @return [boolean]
|
|
66
|
+
def position_within?(position)
|
|
67
|
+
unless starts_at
|
|
68
|
+
raise(
|
|
69
|
+
::CSVPlusPlus::Error::CompilerError,
|
|
70
|
+
'Must call Template.expand_rows! before checking the scope of expands.'
|
|
71
|
+
)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
position.row_index >= ::T.must(starts_at) && (ends_at.nil? || position.row_index <= ::T.must(ends_at))
|
|
75
|
+
end
|
|
59
76
|
end
|
|
60
77
|
end
|
|
61
78
|
end
|
|
@@ -76,7 +76,12 @@ module CSVPlusPlus
|
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
sig
|
|
79
|
+
sig do
|
|
80
|
+
params(
|
|
81
|
+
options: ::CSVPlusPlus::Options::Options,
|
|
82
|
+
row_level: ::T::Boolean
|
|
83
|
+
).returns(::CSVPlusPlus::Modifier::Modifier)
|
|
84
|
+
end
|
|
80
85
|
# Return a +Modifier+ with the proper validation and helper functions attached for the given output
|
|
81
86
|
#
|
|
82
87
|
# @param options [boolean] is this a row level modifier? (otherwise cell-level)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module CSVPlusPlus
|
|
5
|
+
module Options
|
|
6
|
+
# The options that are specific for compiling to a file
|
|
7
|
+
#
|
|
8
|
+
# @attr output_filename [Pathname] The file to write our compiled results to
|
|
9
|
+
class FileOptions < ::CSVPlusPlus::Options::Options
|
|
10
|
+
extend ::T::Sig
|
|
11
|
+
extend ::T::Helpers
|
|
12
|
+
|
|
13
|
+
sig { returns(::Pathname) }
|
|
14
|
+
attr_accessor :output_filename
|
|
15
|
+
|
|
16
|
+
sig { params(sheet_name: ::String, output_filename: ::String).void }
|
|
17
|
+
# Initialize an +Options+ object for writing to a file
|
|
18
|
+
def initialize(sheet_name, output_filename)
|
|
19
|
+
super(sheet_name)
|
|
20
|
+
|
|
21
|
+
@output_filename = ::T.let(::Pathname.new(output_filename), ::Pathname)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
sig { override.returns(::CSVPlusPlus::Options::OutputFormat) }
|
|
25
|
+
# Given the options, figure out which type of +OutputFormat+ we'll be writing to
|
|
26
|
+
#
|
|
27
|
+
# @return [Options::OutputFormat]
|
|
28
|
+
def output_format
|
|
29
|
+
case output_filename.extname
|
|
30
|
+
when '.csv' then ::CSVPlusPlus::Options::OutputFormat::CSV
|
|
31
|
+
when '.ods' then ::CSVPlusPlus::Options::OutputFormat::OpenDocument
|
|
32
|
+
when /\.xl(sx|sm|tx|tm)$/ then ::CSVPlusPlus::Options::OutputFormat::Excel
|
|
33
|
+
else raise(::CSVPlusPlus::Error::CLIError, "Unsupported file extension: #{output_filename}")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
sig { override.returns(::String) }
|
|
38
|
+
# Verbose summary for options specific to compiling to a file
|
|
39
|
+
#
|
|
40
|
+
# @return [String]
|
|
41
|
+
def verbose_summary
|
|
42
|
+
shared_summary(
|
|
43
|
+
<<~OUTPUT)
|
|
44
|
+
> Output filename | #{output_filename}
|
|
45
|
+
OUTPUT
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module CSVPlusPlus
|
|
5
|
+
module Options
|
|
6
|
+
# The Google-specific options a user can supply.
|
|
7
|
+
#
|
|
8
|
+
# @attr sheet_id [String] The ID of the Google Sheet to write to.
|
|
9
|
+
class GoogleSheetsOptions < Options
|
|
10
|
+
extend ::T::Sig
|
|
11
|
+
|
|
12
|
+
sig { returns(::String) }
|
|
13
|
+
attr_reader :sheet_id
|
|
14
|
+
|
|
15
|
+
sig { params(sheet_name: ::String, sheet_id: ::String).void }
|
|
16
|
+
# @param sheet_name [String] The name of the sheet
|
|
17
|
+
# @param sheet_id [String] The unique ID Google uses to reference the sheet
|
|
18
|
+
def initialize(sheet_name, sheet_id)
|
|
19
|
+
super(sheet_name)
|
|
20
|
+
|
|
21
|
+
@sheet_id = sheet_id
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
sig { override.returns(::CSVPlusPlus::Options::OutputFormat) }
|
|
25
|
+
# @return [OutputFormat]
|
|
26
|
+
def output_format
|
|
27
|
+
::CSVPlusPlus::Options::OutputFormat::GoogleSheets
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
sig { override.returns(::String) }
|
|
31
|
+
# Format a string with a verbose description of Google-specific options
|
|
32
|
+
#
|
|
33
|
+
# @return [String]
|
|
34
|
+
def verbose_summary
|
|
35
|
+
shared_summary(
|
|
36
|
+
<<~SUMMARY)
|
|
37
|
+
> Sheet ID | #{@sheet_id}
|
|
38
|
+
SUMMARY
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module CSVPlusPlus
|
|
5
|
+
module Options
|
|
6
|
+
# The options a user can supply (via CLI flags)
|
|
7
|
+
#
|
|
8
|
+
# @attr backup [Boolean] Create a backup of the spreadsheet before writing
|
|
9
|
+
# @attr create_if_not_exists [Boolean] Create the spreadsheet if it does not exist?
|
|
10
|
+
# @attr key_values [Hash] Additional variables that can be supplied to the template
|
|
11
|
+
# @attr offset [Array<Integer>] An [x, y] offset (array with two integers)
|
|
12
|
+
# @attr overwrite_values [Boolean] Whether or not to overwrite existing values in the output spreadsheet.
|
|
13
|
+
# @attr sheet_name [String] The name of the spreadsheet to write to
|
|
14
|
+
# @attr verbose [Boolean] Include extra verbose output?
|
|
15
|
+
class Options
|
|
16
|
+
extend ::T::Sig
|
|
17
|
+
extend ::T::Helpers
|
|
18
|
+
|
|
19
|
+
abstract!
|
|
20
|
+
|
|
21
|
+
sig { returns(::T::Boolean) }
|
|
22
|
+
attr_accessor :backup
|
|
23
|
+
|
|
24
|
+
sig { returns(::T::Boolean) }
|
|
25
|
+
attr_accessor :create_if_not_exists
|
|
26
|
+
|
|
27
|
+
sig { returns(::T::Hash[::Symbol, ::CSVPlusPlus::Entities::Entity]) }
|
|
28
|
+
attr_accessor :key_values
|
|
29
|
+
|
|
30
|
+
sig { returns(::T::Array[::Integer]) }
|
|
31
|
+
attr_accessor :offset
|
|
32
|
+
|
|
33
|
+
sig { returns(::T::Boolean) }
|
|
34
|
+
attr_accessor :overwrite_values
|
|
35
|
+
|
|
36
|
+
sig { returns(::String) }
|
|
37
|
+
attr_accessor :sheet_name
|
|
38
|
+
|
|
39
|
+
sig { returns(::T::Boolean) }
|
|
40
|
+
attr_accessor :verbose
|
|
41
|
+
|
|
42
|
+
sig { params(sheet_name: ::String).void }
|
|
43
|
+
# Initialize a defaul +Options+ object
|
|
44
|
+
def initialize(sheet_name)
|
|
45
|
+
@backup = ::T.let(false, ::T::Boolean)
|
|
46
|
+
@create_if_not_exists = ::T.let(false, ::T::Boolean)
|
|
47
|
+
@key_values = ::T.let({}, ::T::Hash[::Symbol, ::CSVPlusPlus::Entities::Entity])
|
|
48
|
+
@offset = ::T.let([0, 0], ::T::Array[::Integer])
|
|
49
|
+
@overwrite_values = ::T.let(true, ::T::Boolean)
|
|
50
|
+
@sheet_name = sheet_name
|
|
51
|
+
@verbose = ::T.let(false, ::T::Boolean)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
sig { abstract.returns(::CSVPlusPlus::Options::OutputFormat) }
|
|
55
|
+
# Given the options, figure out which type of +OutputFormat+ we'll be writing to
|
|
56
|
+
#
|
|
57
|
+
# @return [Options::OutputFormat]
|
|
58
|
+
def output_format; end
|
|
59
|
+
|
|
60
|
+
sig { abstract.returns(::String) }
|
|
61
|
+
# Return a string with a verbose description of what we're doing with the options
|
|
62
|
+
#
|
|
63
|
+
# @return [String]
|
|
64
|
+
def verbose_summary; end
|
|
65
|
+
|
|
66
|
+
protected
|
|
67
|
+
|
|
68
|
+
sig { params(str: ::String).returns(::String) }
|
|
69
|
+
# Return a string with a verbose description of what we're doing with the options
|
|
70
|
+
#
|
|
71
|
+
# @return [String]
|
|
72
|
+
def shared_summary(str)
|
|
73
|
+
<<~SUMMARY
|
|
74
|
+
#{summary_divider}
|
|
75
|
+
|
|
76
|
+
# csv++ Command Options
|
|
77
|
+
|
|
78
|
+
> Sheet name | #{@sheet_name}
|
|
79
|
+
> Create sheet if it does not exist? | #{@create_if_not_exists}
|
|
80
|
+
> Spreadsheet row-offset | #{@offset[0]}
|
|
81
|
+
> Spreadsheet cell-offset | #{@offset[1]}
|
|
82
|
+
> User-supplied key-values | #{@key_values}
|
|
83
|
+
> Verbose | #{@verbose}
|
|
84
|
+
> Backup | #{@backup}
|
|
85
|
+
|
|
86
|
+
## Output Options
|
|
87
|
+
|
|
88
|
+
#{str}
|
|
89
|
+
|
|
90
|
+
#{summary_divider}
|
|
91
|
+
SUMMARY
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
sig { returns(::String) }
|
|
97
|
+
def summary_divider
|
|
98
|
+
'========================================================================='
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -2,17 +2,8 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
module CSVPlusPlus
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
# @attr backup [boolean] Create a backup of the spreadsheet before writing
|
|
8
|
-
# @attr create_if_not_exists [boolean] Create the spreadsheet if it does not exist?
|
|
9
|
-
# @attr key_values [Hash] Additional variables that can be supplied to the template
|
|
10
|
-
# @attr offset [Array<Integer>] An [x, y] offset (array with two integers)
|
|
11
|
-
# @attr output_filename [String] The file to write our compiled results to
|
|
12
|
-
# @attr sheet_name [String] The name of the spreadsheet to write to
|
|
13
|
-
# @attr verbose [boolean] Include extra verbose output?
|
|
14
|
-
# @attr_reader google [GoogleOptions] Options that are specific to the Google Sheets writer
|
|
15
|
-
class Options
|
|
5
|
+
# Options that a user can supply - either specific for compiling to a file (xlsx, csv) or Google Sheets
|
|
6
|
+
module Options
|
|
16
7
|
extend ::T::Sig
|
|
17
8
|
|
|
18
9
|
# The supported output formats. We use this to dispatch flow in several places
|
|
@@ -25,109 +16,30 @@ module CSVPlusPlus
|
|
|
25
16
|
end
|
|
26
17
|
end
|
|
27
18
|
|
|
28
|
-
sig
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
sig { returns(::T::Boolean) }
|
|
32
|
-
attr_accessor :create_if_not_exists
|
|
33
|
-
|
|
34
|
-
sig { returns(::T::Hash[::Symbol, ::String]) }
|
|
35
|
-
attr_accessor :key_values
|
|
36
|
-
|
|
37
|
-
sig { returns(::T::Array[::Integer]) }
|
|
38
|
-
attr_accessor :offset
|
|
39
|
-
|
|
40
|
-
sig { returns(::T.nilable(::String)) }
|
|
41
|
-
attr_accessor :output_filename
|
|
42
|
-
|
|
43
|
-
sig { returns(::T.nilable(::String)) }
|
|
44
|
-
attr_accessor :sheet_name
|
|
45
|
-
|
|
46
|
-
sig { returns(::T::Boolean) }
|
|
47
|
-
attr_accessor :verbose
|
|
48
|
-
|
|
49
|
-
sig { returns(::T.nilable(::CSVPlusPlus::GoogleOptions)) }
|
|
50
|
-
attr_reader :google
|
|
51
|
-
|
|
52
|
-
sig { void }
|
|
53
|
-
# Initialize a default +Options+ object
|
|
54
|
-
def initialize
|
|
55
|
-
@offset = ::T.let([0, 0], ::T::Array[::Integer])
|
|
56
|
-
@create_if_not_exists = ::T.let(false, ::T::Boolean)
|
|
57
|
-
@key_values = ::T.let({}, ::T::Hash[::Symbol, ::String])
|
|
58
|
-
@verbose = ::T.let(false, ::T::Boolean)
|
|
59
|
-
@backup = ::T.let(false, ::T::Boolean)
|
|
60
|
-
@google = ::T.let(nil, ::T.nilable(::CSVPlusPlus::GoogleOptions))
|
|
19
|
+
sig do
|
|
20
|
+
params(flags: ::T::Hash[::Symbol, ::String], input_filename: ::Pathname).returns(::CSVPlusPlus::Options::Options)
|
|
61
21
|
end
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# Set the Google Sheet ID
|
|
65
|
-
#
|
|
66
|
-
# @param sheet_id [::String] The identifier used by Google's API to reference the sheet. You can find it in the URL
|
|
67
|
-
# for the sheet
|
|
22
|
+
# Use the given +flags+ to determine if we're dealing with either a Google Sheets or file-based
|
|
23
|
+
# compilation and build an +Options+ instance accordingly.
|
|
68
24
|
#
|
|
69
|
-
# @
|
|
70
|
-
|
|
71
|
-
@google = ::CSVPlusPlus::GoogleOptions.new(sheet_id)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
sig { returns(::CSVPlusPlus::Options::OutputFormat) }
|
|
75
|
-
# Given the options, figure out which type of +OutputFormat+ we'll be writing to
|
|
25
|
+
# @param flags [Hash<Symbol, String>]
|
|
26
|
+
# @param input_filename [Pathname]
|
|
76
27
|
#
|
|
77
|
-
# @return [Options::
|
|
78
|
-
def
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
28
|
+
# @return [Options::Options]
|
|
29
|
+
def self.from_cli_flags(flags, input_filename)
|
|
30
|
+
sheet_name = flags[:'sheet-name'] || input_filename.sub_ext('').to_s
|
|
31
|
+
if (google_sheet_id = flags[:'google-sheet-id'])
|
|
32
|
+
::CSVPlusPlus::Options::GoogleSheetsOptions.new(sheet_name, google_sheet_id)
|
|
33
|
+
elsif (output_filename = flags[:output])
|
|
34
|
+
::CSVPlusPlus::Options::FileOptions.new(sheet_name, output_filename)
|
|
35
|
+
else
|
|
36
|
+
raise(::CSVPlusPlus::Error::CLIError, 'You must supply either -o/--output or -g/-google-sheet-id')
|
|
86
37
|
end
|
|
87
38
|
end
|
|
88
|
-
|
|
89
|
-
sig { returns(::T.nilable(::String)) }
|
|
90
|
-
# Returns an error string or nil if there are no validation problems
|
|
91
|
-
#
|
|
92
|
-
# @return [String, nil]
|
|
93
|
-
def validate
|
|
94
|
-
return if @google || @output_filename
|
|
95
|
-
|
|
96
|
-
'You must supply either a Google Sheet ID or an output file'
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
sig { returns(::String) }
|
|
100
|
-
# Return a string with a verbose description of what we're doing with the options
|
|
101
|
-
#
|
|
102
|
-
# @return [String]
|
|
103
|
-
def verbose_summary
|
|
104
|
-
<<~SUMMARY
|
|
105
|
-
#{summary_divider}
|
|
106
|
-
|
|
107
|
-
# csv++ Command Options
|
|
108
|
-
|
|
109
|
-
> Sheet name | #{@sheet_name}
|
|
110
|
-
> Create sheet if it does not exist? | #{@create_if_not_exists}
|
|
111
|
-
> Spreadsheet row-offset | #{@offset[0]}
|
|
112
|
-
> Spreadsheet cell-offset | #{@offset[1]}
|
|
113
|
-
> User-supplied key-values | #{@key_values}
|
|
114
|
-
> Verbose | #{@verbose}
|
|
115
|
-
|
|
116
|
-
## Output Options
|
|
117
|
-
|
|
118
|
-
> Backup | #{@backup}
|
|
119
|
-
> Output filename | #{@output_filename}
|
|
120
|
-
|
|
121
|
-
#{@google&.verbose_summary || ''}
|
|
122
|
-
#{summary_divider}
|
|
123
|
-
SUMMARY
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
private
|
|
127
|
-
|
|
128
|
-
sig { returns(::String) }
|
|
129
|
-
def summary_divider
|
|
130
|
-
'========================================================================='
|
|
131
|
-
end
|
|
132
39
|
end
|
|
133
40
|
end
|
|
41
|
+
|
|
42
|
+
require_relative './options/options'
|
|
43
|
+
|
|
44
|
+
require_relative './options/file_options'
|
|
45
|
+
require_relative './options/google_sheets_options'
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
require 'racc/parser.rb'
|
|
8
8
|
|
|
9
9
|
require_relative '../lexer'
|
|
10
|
+
require_relative '../lexer/racc_lexer'
|
|
10
11
|
require_relative '../entities/ast_builder'
|
|
11
12
|
|
|
12
13
|
module CSVPlusPlus
|
|
@@ -14,35 +15,43 @@ module CSVPlusPlus
|
|
|
14
15
|
class CellValue < Racc::Parser
|
|
15
16
|
|
|
16
17
|
module_eval(<<'...end cell_value.y/module_eval...', 'cell_value.y', 49)
|
|
18
|
+
extend ::T::Sig
|
|
19
|
+
extend ::T::Generic
|
|
17
20
|
include ::CSVPlusPlus::Entities::ASTBuilder
|
|
18
|
-
include ::CSVPlusPlus::Lexer
|
|
21
|
+
include ::CSVPlusPlus::Lexer::RaccLexer
|
|
22
|
+
|
|
23
|
+
ReturnType = type_member {{ fixed: ::T.nilable(::CSVPlusPlus::Entities::Entity) }}
|
|
19
24
|
|
|
20
25
|
protected
|
|
21
26
|
|
|
27
|
+
sig { override.params(input: ::String).returns(::T::Boolean) }
|
|
22
28
|
def anything_to_parse?(input)
|
|
23
29
|
input.strip.start_with?('=')
|
|
24
30
|
end
|
|
25
31
|
|
|
32
|
+
sig { override.returns(::String) }
|
|
26
33
|
def parse_subject
|
|
27
34
|
'cell value'
|
|
28
35
|
end
|
|
29
36
|
|
|
37
|
+
sig { override.returns(ReturnType) }
|
|
30
38
|
def return_value
|
|
31
39
|
@ast
|
|
32
40
|
end
|
|
33
41
|
|
|
42
|
+
sig { override.returns(::CSVPlusPlus::Lexer::Tokenizer) }
|
|
34
43
|
def tokenizer
|
|
35
44
|
::CSVPlusPlus::Lexer::Tokenizer.new(
|
|
36
45
|
catchall: /[\{\}\(\),=]/,
|
|
37
46
|
ignore: /\s+/,
|
|
38
47
|
tokens: [
|
|
39
|
-
TOKEN_LIBRARY[:TRUE],
|
|
40
|
-
TOKEN_LIBRARY[:FALSE],
|
|
41
|
-
TOKEN_LIBRARY[:NUMBER],
|
|
42
|
-
TOKEN_LIBRARY[:STRING],
|
|
43
|
-
TOKEN_LIBRARY[:INFIX_OP],
|
|
44
|
-
TOKEN_LIBRARY[:VAR_REF],
|
|
45
|
-
TOKEN_LIBRARY[:
|
|
48
|
+
::CSVPlusPlus::Lexer::TOKEN_LIBRARY[:TRUE],
|
|
49
|
+
::CSVPlusPlus::Lexer::TOKEN_LIBRARY[:FALSE],
|
|
50
|
+
::CSVPlusPlus::Lexer::TOKEN_LIBRARY[:NUMBER],
|
|
51
|
+
::CSVPlusPlus::Lexer::TOKEN_LIBRARY[:STRING],
|
|
52
|
+
::CSVPlusPlus::Lexer::TOKEN_LIBRARY[:INFIX_OP],
|
|
53
|
+
::CSVPlusPlus::Lexer::TOKEN_LIBRARY[:VAR_REF],
|
|
54
|
+
::CSVPlusPlus::Lexer::TOKEN_LIBRARY[:REF]
|
|
46
55
|
]
|
|
47
56
|
)
|
|
48
57
|
end
|
|
@@ -50,45 +59,43 @@ module_eval(<<'...end cell_value.y/module_eval...', 'cell_value.y', 49)
|
|
|
50
59
|
##### State transition tables begin ###
|
|
51
60
|
|
|
52
61
|
racc_action_table = [
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
11,
|
|
56
|
-
|
|
57
|
-
nil, nil, nil,
|
|
58
|
-
nil,
|
|
59
|
-
nil, 10, 9, 11, 8 ]
|
|
62
|
+
23, 19, 14, 2, 15, 7, 3, 13, 17, 15,
|
|
63
|
+
15, 7, 15, nil, nil, nil, 15, 7, nil, nil,
|
|
64
|
+
11, 24, 9, 12, 8, 10, 11, 7, 9, 12,
|
|
65
|
+
8, 10, 11, nil, 9, 12, 8, 10, 7, 21,
|
|
66
|
+
nil, nil, 11, nil, 9, 12, 8, 10, nil, nil,
|
|
67
|
+
nil, nil, nil, 11, nil, 9, 12, 8, 10 ]
|
|
60
68
|
|
|
61
69
|
racc_action_check = [
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
2, 2,
|
|
65
|
-
|
|
66
|
-
nil, nil, nil,
|
|
67
|
-
nil,
|
|
68
|
-
nil, 26, 26, 26, 26 ]
|
|
70
|
+
20, 16, 4, 0, 4, 2, 1, 3, 12, 18,
|
|
71
|
+
22, 7, 25, nil, nil, nil, 16, 15, nil, nil,
|
|
72
|
+
2, 20, 2, 2, 2, 2, 7, 24, 7, 7,
|
|
73
|
+
7, 7, 15, nil, 15, 15, 15, 15, 17, 17,
|
|
74
|
+
nil, nil, 24, nil, 24, 24, 24, 24, nil, nil,
|
|
75
|
+
nil, nil, nil, 17, nil, 17, 17, 17, 17 ]
|
|
69
76
|
|
|
70
77
|
racc_action_pointer = [
|
|
71
|
-
-
|
|
72
|
-
nil, nil,
|
|
73
|
-
-
|
|
78
|
+
-7, 6, 3, 7, -14, nil, nil, 9, nil, nil,
|
|
79
|
+
nil, nil, 6, nil, nil, 15, -2, 36, -9, nil,
|
|
80
|
+
-3, nil, -8, nil, 25, -6 ]
|
|
74
81
|
|
|
75
82
|
racc_action_default = [
|
|
76
|
-
-
|
|
77
|
-
-7, -8, -9,
|
|
78
|
-
-15,
|
|
83
|
+
-15, -15, -15, -15, -15, -2, -3, -15, -5, -6,
|
|
84
|
+
-7, -8, -9, 26, -1, -15, -15, -15, -14, -4,
|
|
85
|
+
-15, -11, -13, -10, -15, -12 ]
|
|
79
86
|
|
|
80
87
|
racc_goto_table = [
|
|
81
|
-
4, 1,
|
|
82
|
-
nil, nil, nil, nil,
|
|
83
|
-
nil, nil,
|
|
88
|
+
4, 1, 20, nil, nil, 16, nil, nil, nil, nil,
|
|
89
|
+
nil, nil, nil, 18, nil, 22, nil, nil, nil, nil,
|
|
90
|
+
nil, nil, 25 ]
|
|
84
91
|
|
|
85
92
|
racc_goto_check = [
|
|
86
93
|
2, 1, 5, nil, nil, 2, nil, nil, nil, nil,
|
|
87
|
-
nil, nil, nil, nil, 2, nil, nil,
|
|
88
|
-
nil, nil,
|
|
94
|
+
nil, nil, nil, 2, nil, 2, nil, nil, nil, nil,
|
|
95
|
+
nil, nil, 2 ]
|
|
89
96
|
|
|
90
97
|
racc_goto_pointer = [
|
|
91
|
-
nil, 1, -2, nil, nil, -
|
|
98
|
+
nil, 1, -2, nil, nil, -15 ]
|
|
92
99
|
|
|
93
100
|
racc_goto_default = [
|
|
94
101
|
nil, nil, nil, 5, 6, nil ]
|
|
@@ -99,21 +106,20 @@ racc_reduce_table = [
|
|
|
99
106
|
1, 27, :_reduce_none,
|
|
100
107
|
1, 27, :_reduce_none,
|
|
101
108
|
3, 27, :_reduce_4,
|
|
102
|
-
|
|
109
|
+
1, 27, :_reduce_5,
|
|
103
110
|
1, 27, :_reduce_6,
|
|
104
111
|
1, 27, :_reduce_7,
|
|
105
112
|
1, 27, :_reduce_8,
|
|
106
113
|
1, 27, :_reduce_9,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
3,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
3, 29, :_reduce_15 ]
|
|
114
|
+
4, 28, :_reduce_10,
|
|
115
|
+
3, 28, :_reduce_11,
|
|
116
|
+
3, 30, :_reduce_12,
|
|
117
|
+
1, 30, :_reduce_13,
|
|
118
|
+
3, 29, :_reduce_14 ]
|
|
113
119
|
|
|
114
|
-
racc_reduce_n =
|
|
120
|
+
racc_reduce_n = 15
|
|
115
121
|
|
|
116
|
-
racc_shift_n =
|
|
122
|
+
racc_shift_n = 26
|
|
117
123
|
|
|
118
124
|
racc_token_table = {
|
|
119
125
|
false => 0,
|
|
@@ -134,9 +140,9 @@ racc_token_table = {
|
|
|
134
140
|
"<>" => 15,
|
|
135
141
|
:EOL => 16,
|
|
136
142
|
:FALSE => 17,
|
|
137
|
-
:
|
|
138
|
-
:
|
|
139
|
-
:
|
|
143
|
+
:INFIX_OP => 18,
|
|
144
|
+
:NUMBER => 19,
|
|
145
|
+
:REF => 20,
|
|
140
146
|
:STRING => 21,
|
|
141
147
|
:TRUE => 22,
|
|
142
148
|
:VAR_REF => 23,
|
|
@@ -181,9 +187,9 @@ Racc_token_to_s_table = [
|
|
|
181
187
|
"\"<>\"",
|
|
182
188
|
"EOL",
|
|
183
189
|
"FALSE",
|
|
184
|
-
"ID",
|
|
185
190
|
"INFIX_OP",
|
|
186
191
|
"NUMBER",
|
|
192
|
+
"REF",
|
|
187
193
|
"STRING",
|
|
188
194
|
"TRUE",
|
|
189
195
|
"VAR_REF",
|
|
@@ -221,76 +227,69 @@ module_eval(<<'.,.,', 'cell_value.y', 25)
|
|
|
221
227
|
|
|
222
228
|
module_eval(<<'.,.,', 'cell_value.y', 26)
|
|
223
229
|
def _reduce_5(val, _values, result)
|
|
224
|
-
result =
|
|
230
|
+
result = string(val[0])
|
|
225
231
|
result
|
|
226
232
|
end
|
|
227
233
|
.,.,
|
|
228
234
|
|
|
229
235
|
module_eval(<<'.,.,', 'cell_value.y', 27)
|
|
230
236
|
def _reduce_6(val, _values, result)
|
|
231
|
-
result =
|
|
237
|
+
result = number(val[0])
|
|
232
238
|
result
|
|
233
239
|
end
|
|
234
240
|
.,.,
|
|
235
241
|
|
|
236
242
|
module_eval(<<'.,.,', 'cell_value.y', 28)
|
|
237
243
|
def _reduce_7(val, _values, result)
|
|
238
|
-
result =
|
|
244
|
+
result = boolean(true)
|
|
239
245
|
result
|
|
240
246
|
end
|
|
241
247
|
.,.,
|
|
242
248
|
|
|
243
249
|
module_eval(<<'.,.,', 'cell_value.y', 29)
|
|
244
250
|
def _reduce_8(val, _values, result)
|
|
245
|
-
result = boolean(
|
|
251
|
+
result = boolean(false)
|
|
246
252
|
result
|
|
247
253
|
end
|
|
248
254
|
.,.,
|
|
249
255
|
|
|
250
256
|
module_eval(<<'.,.,', 'cell_value.y', 30)
|
|
251
257
|
def _reduce_9(val, _values, result)
|
|
252
|
-
result =
|
|
258
|
+
result = reference(ref: val[0])
|
|
253
259
|
result
|
|
254
260
|
end
|
|
255
261
|
.,.,
|
|
256
262
|
|
|
257
|
-
module_eval(<<'.,.,', 'cell_value.y',
|
|
263
|
+
module_eval(<<'.,.,', 'cell_value.y', 32)
|
|
258
264
|
def _reduce_10(val, _values, result)
|
|
259
|
-
result =
|
|
265
|
+
result = function_call(val[0].to_sym, val[2])
|
|
260
266
|
result
|
|
261
267
|
end
|
|
262
268
|
.,.,
|
|
263
269
|
|
|
264
270
|
module_eval(<<'.,.,', 'cell_value.y', 33)
|
|
265
271
|
def _reduce_11(val, _values, result)
|
|
266
|
-
result = function_call(val[0].to_sym,
|
|
272
|
+
result = function_call(val[0].to_sym, [])
|
|
267
273
|
result
|
|
268
274
|
end
|
|
269
275
|
.,.,
|
|
270
276
|
|
|
271
|
-
module_eval(<<'.,.,', 'cell_value.y',
|
|
277
|
+
module_eval(<<'.,.,', 'cell_value.y', 35)
|
|
272
278
|
def _reduce_12(val, _values, result)
|
|
273
|
-
result =
|
|
279
|
+
result = val[0] << val[2]
|
|
274
280
|
result
|
|
275
281
|
end
|
|
276
282
|
.,.,
|
|
277
283
|
|
|
278
284
|
module_eval(<<'.,.,', 'cell_value.y', 36)
|
|
279
285
|
def _reduce_13(val, _values, result)
|
|
280
|
-
result = val[0] << val[2]
|
|
281
|
-
result
|
|
282
|
-
end
|
|
283
|
-
.,.,
|
|
284
|
-
|
|
285
|
-
module_eval(<<'.,.,', 'cell_value.y', 37)
|
|
286
|
-
def _reduce_14(val, _values, result)
|
|
287
286
|
result = [val[0]]
|
|
288
287
|
result
|
|
289
288
|
end
|
|
290
289
|
.,.,
|
|
291
290
|
|
|
292
|
-
module_eval(<<'.,.,', 'cell_value.y',
|
|
293
|
-
def
|
|
291
|
+
module_eval(<<'.,.,', 'cell_value.y', 38)
|
|
292
|
+
def _reduce_14(val, _values, result)
|
|
294
293
|
result = function_call(val[1].to_sym, [val[0], val[2]], infix: true)
|
|
295
294
|
result
|
|
296
295
|
end
|