Method: Formula#parse_tokens

Defined in:
lib/WriteExcel/formula.rb

#parse_tokens(tokens) ⇒ Object

parse_tokens()

Convert each token or token pair to its Excel ‘ptg’ equivalent.



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/WriteExcel/formula.rb', line 66

def parse_tokens(tokens)
  parse_str   = ''
  last_type   = ''
  modifier    = ''
  num_args    = 0
  _class      = 0
  _classary   = [1]
  args        = tokens.dup
  # A note about the class modifiers used below. In general the class,
  # "reference" or "value", of a function is applied to all of its operands.
  # However, in certain circumstances the operands can have mixed classes,
  # e.g. =VLOOKUP with external references. These will eventually be dealt
  # with by the parser. However, as a workaround the class type of a token
  # can be changed via the repeat_formula interface. Thus, a _ref2d token can
  # be changed by the user to _ref2dA or _ref2dR to change its token class.
  #
  while (!args.empty?)
    token = args.shift

    if (token == '_arg')
      num_args = args.shift
    elsif (token == '_class')
      token = args.shift
      _class = @functions[token][2]
      # If _class is undef then it means that the function isn't valid.
      exit "Unknown function #{token}() in formula\n" if _class.nil?
      _classary.push(_class)
    elsif (token == '_vol')
      parse_str = parse_str + convert_volatile()
    elsif (token == 'ptgBool')
      token = args.shift
      parse_str = parse_str + convert_bool(token)
    elsif (token == '_num')
      token = args.shift
      parse_str = parse_str + convert_number(token)
    elsif (token == '_str')
      token = args.shift
      parse_str = parse_str + convert_string(token)
    elsif (token =~ /^_ref2d/)
      modifier  = token.sub(/_ref2d/, '')
      _class      = _classary[-1]
      _class      = 0 if modifier == 'R'
      _class      = 1 if modifier == 'V'
      token      = args.shift
      parse_str = parse_str + convert_ref2d(token, _class)
    elsif (token =~ /^_ref3d/)
      modifier  = token.sub(/_ref3d/,'')
      _class      = _classary[-1]
      _class      = 0 if modifier == 'R'
      _class      = 1 if modifier == 'V'
      token      = args.shift
      parse_str = parse_str + convert_ref3d(token, _class)
    elsif (token =~ /^_range2d/)
      modifier  = token.sub(/_range2d/,'')
      _class      = _classary[-1]
      _class      = 0 if modifier == 'R'
      _class      = 1 if modifier == 'V'
      token      = args.shift
      parse_str = parse_str + convert_range2d(token, _class)
    elsif (token =~ /^_range3d/)
      modifier  = token.sub(/_range3d/,'')
      _class      = _classary[-1]
      _class      = 0 if modifier == 'R'
      _class      = 1 if modifier == 'V'
      token      = args.shift
      parse_str = parse_str + convert_range3d(token, _class)
    elsif (token == '_func')
      token = args.shift
      parse_str = parse_str + convert_function(token, num_args.to_i)
      _classary.pop
      num_args = 0 # Reset after use
    elsif @ptg[token]
      parse_str = parse_str + [@ptg[token]].pack("C")
    else
      # Unrecognised token
      return nil
    end
  end


  return parse_str
end