module CSVDecision::Parse

Methods to parse the decision table and return CSVDecision::Table object. @api private

Public Class Methods

table(data:, options:) click to toggle source

Parse the CSV file or input data and create a new decision table object.

@param (see CSVDecision.parse) @return (see CSVDecision.parse)

# File lib/csv_decision/parse.rb, line 58
def self.table(data:, options:)
  table = CSVDecision::Table.new

  # In most cases the decision table will be loaded from a CSV file.
  table.file = data if Data.input_file?(data)

  parse_table(table: table, input: data, options: options)

  # The table object is now immutable.
  table.columns.freeze
  table.freeze
rescue CSVDecision::Error => exp
  raise_error(file: table.file, exception: exp)
end

Private Class Methods

outs_functions(table:, index:) click to toggle source
# File lib/csv_decision/parse.rb, line 154
def self.outs_functions(table:, index:)
  return if table.outs_rows[index].procs.empty?

  # Set this flag as the table has output functions
  table.outs_functions = true

  # Update the output columns that contain functions needing evaluation.
  table.outs_rows[index].procs.each { |col| table.columns.outs[col].eval = true }
end
parse_data(table:, matchers:) click to toggle source
# File lib/csv_decision/parse.rb, line 109
def self.parse_data(table:, matchers:)
  table.rows.each_with_index do |row, index|
    # Mutate the row if we find anything other than a simple string constant in its
    # data cells.
    row = parse_row(table: table, matchers: matchers, row: row, index: index)

    # Does the row have any output functions?
    outs_functions(table: table, index: index)

    # No more mutations required for this row.
    row.freeze
  end
end
parse_row(table:, matchers:, row:, index:) click to toggle source
# File lib/csv_decision/parse.rb, line 124
def self.parse_row(table:, matchers:, row:, index:)
  # Parse the input cells for this row
  row = parse_row_ins(table: table, matchers: matchers, row: row, index: index)

  # Parse the output cells for this row
  parse_row_outs(table: table, matchers: matchers, row: row, index: index)
end
parse_row_ins(table:, matchers:, row:, index:) click to toggle source
# File lib/csv_decision/parse.rb, line 133
def self.parse_row_ins(table:, matchers:, row:, index:)
  # Parse the input cells for this row
  row, table.scan_rows[index] = matchers.parse_ins(columns: table.columns.ins, row: row)

  # Add any symbol references made by input cell procs to the column dictionary
  Columns.ins_dictionary(columns: table.columns.dictionary, row: row)

  row
end
parse_row_outs(table:, matchers:, row:, index:) click to toggle source
# File lib/csv_decision/parse.rb, line 144
def self.parse_row_outs(table:, matchers:, row:, index:)
  # Parse the output cells for this row
  row, table.outs_rows[index] = matchers.parse_outs(columns: table.columns.outs, row: row)

  Columns.outs_dictionary(columns: table.columns, row: row)

  row
end
parse_table(table:, input:, options:) click to toggle source
# File lib/csv_decision/parse.rb, line 81
def self.parse_table(table:, input:, options:)
  # Parse input data into an array of arrays.
  table.rows = Data.to_array(data: input)

  # Pick up any options specified in the CSV file before the header row.
  # These override any options passed as parameters to the parse method.
  table.options = Options.from_csv(rows: table.rows, options: options).freeze

  # Parse table header and data rows with special cell matchers.
  parse_with_matchers(table: table, matchers: CSVDecision::Matchers.new(options))

  # Build the data index if one is indicated
  Index.build(table: table)

  # Build a paths index if one is indicated
  Paths.scan(table: table)
end
parse_with_matchers(table:, matchers:) click to toggle source
# File lib/csv_decision/parse.rb, line 100
def self.parse_with_matchers(table:, matchers:)
  # Parse the header row
  table.columns = Header.parse(table: table, matchers: matchers)

  # Parse the table's the data rows.
  parse_data(table: table, matchers: matchers)
end
raise_error(file:, exception:) click to toggle source
# File lib/csv_decision/parse.rb, line 73
def self.raise_error(file:, exception:)
  raise exception unless file

  raise CSVDecision::FileError,
        "error processing CSV file #{file}\n#{exception.inspect}"
end