Class: Glaemscribe::API::Eval::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/api/eval.rb

Instance Method Summary collapse

Instance Method Details

#cast_constant(const) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/api/eval.rb', line 238

def cast_constant(const)
  if constant_is_int?(const)
    const.to_i
  elsif constant_is_float?(const)
    const.to_f
  elsif const[/^\'(.*)\'$/] || const[/^\"(.*)\"$/]
    $1
  elsif const == 'true'
    true
  elsif const == 'false'
    false
  elsif const == 'nil'
    nil
  elsif(@vars[const] != nil)
    @vars[const]
  else
    raise SyntaxError.new("Cannot understand constant '#{const}'.")
  end   
end

#constant_is_float?(const) ⇒ Boolean

Returns:

  • (Boolean)


223
224
225
# File 'lib/api/eval.rb', line 223

def constant_is_float?(const)
  Float(const) rescue false
end

#constant_is_int?(const) ⇒ Boolean

Returns:

  • (Boolean)


227
228
229
# File 'lib/api/eval.rb', line 227

def constant_is_int?(const)
  Integer(const) rescue false
end

#constant_is_string?(const) ⇒ Boolean

Returns:

  • (Boolean)


231
232
233
234
235
236
# File 'lib/api/eval.rb', line 231

def constant_is_string?(const)
  return false if const.length < 2
  f = const[0]
  l = const[-1]
  return ( f == l && (l == "'" || l == '"') )
end

#explore_addObject



178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/api/eval.rb', line 178

def explore_add
  v = explore_mult
  loop do
    case @lexer.advance().name
    when 'add_plus'     then v += explore_mult
    when 'add_minus'    then v -= explore_mult
    else break
    end
  end
  @lexer.uneat # Keep the unused token for the higher level
  v
end

#explore_boolObject



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/api/eval.rb', line 138

def explore_bool
  v = explore_compare
  loop do
    case @lexer.advance().name
    when 'bool_or'
      if v
        explore_bool
      else
        v = explore_compare
      end
    when 'bool_and'
      if !v
        explore_bool 
      else
        v = explore_compare
      end
    else break
    end
  end      
  @lexer.uneat # Keep the unused token for the higher level
  v
end

#explore_compareObject



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/api/eval.rb', line 161

def explore_compare
  v = explore_add
  loop do
    case @lexer.advance().name
    when 'cond_inf_eq'  then v = (v <= explore_add)
    when 'cond_inf'     then v = (v <  explore_add)
    when 'cond_sup_eq'  then v = (v >= explore_add)
    when 'cond_sup'     then v = (v >  explore_add)
    when 'cond_eq'      then v = (v == explore_add)
    when 'cond_not_eq'  then v = (v != explore_add)
    else break
    end
  end
  @lexer.uneat # Keep the unused token for the higher level
  v      
end

#explore_multObject



191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/api/eval.rb', line 191

def explore_mult
  v = explore_primary
  loop do
    case @lexer.advance().name
    when 'mult_times'   then v *= explore_primary
    when 'mult_div'     then v /= explore_primary
    when 'mult_modulo'  then v %= explore_primary
    else break
    end
  end
  @lexer.uneat # Keep the unused token for the higher level
  v
end

#explore_primaryObject



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/api/eval.rb', line 205

def explore_primary
  token = @lexer.advance()
  case token.name
  when 'prim_const'
    v = cast_constant(token.value)
  when 'add_minus' # Allow the use of - as primary token for negative numbers
    v = -explore_primary
  when 'prim_not' # Allow the use of ! for booleans
    v = !explore_primary
  when 'prim_lparen'
    v           = parse_top_level
    rtoken      = @lexer.advance() 
    raise SyntaxError.new("Missing right parenthesis.") if(rtoken.name != 'prim_rparen') 
  else raise SyntaxError.new("Cannot understand: #{token.value}.")
  end
  v
end

#parse(exp, vars) ⇒ Object



128
129
130
131
132
# File 'lib/api/eval.rb', line 128

def parse(exp, vars)
  @lexer  = Lexer.new(exp)
  @vars   = {}; vars.each{ |k,v| @vars[k.to_s] = v } # Cast symbols
  parse_top_level
end

#parse_top_levelObject



134
135
136
# File 'lib/api/eval.rb', line 134

def parse_top_level
  explore_bool
end