class MathExpression

Public Class Methods

new() click to toggle source
# File lib/Expression/parser.rb, line 9
def initialize()
  @input = nil
  @look = nil
end

Public Instance Methods

eval(input) click to toggle source
# File lib/Expression/parser.rb, line 14
def eval(input)
  @input = input
  init
  temp = calculate
  unless @look.nil?
    raise InvalidInput, "unexpected input: \"#{@look}\""
  end
  temp
end

Private Instance Methods

addop?(x) click to toggle source
# File lib/Expression/identifiers.rb, line 4
def addop?(x)
  ['+', '-'].include? x
end
alpha?(x) click to toggle source
# File lib/Expression/identifiers.rb, line 12
def alpha?(x)
  [*('a'..'z')].include? x
end
calculate() click to toggle source
# File lib/Expression/parser.rb, line 49
def calculate
  if addop? @look
    value = 0
  else
    value = term
  end
  while addop?(@look)
    case @look
    when '+'
      match('+')
      value += term
    when '-'
      match('-')
      value -= term
    end
  end
  value
end
digit?(x) click to toggle source
# File lib/Expression/identifiers.rb, line 8
def digit?(x)
  [*(0..9)].map(&:to_s).include?(x)
end
expected(msg) click to toggle source
# File lib/Expression/parser.rb, line 27
def expected(msg)
  raise InvalidInput, "\a\"#{msg}\" expected"
end
factor() click to toggle source
# File lib/Expression/parser.rb, line 31
def factor

  if @look == '('
    match('(')
    value = calculate
    match(')')
  elsif @look == '['
    match('[')
    value = calculate
    match(']')
  elsif alpha? @look
    value = trig
  else
    value = get_number
  end
  value
end
get_char() click to toggle source
# File lib/Expression/getters.rb, line 4
def get_char
  @look = @input.shift
end
get_number() click to toggle source
# File lib/Expression/getters.rb, line 8
def get_number
  value = 0
  nb_decimals = false
  expected('integer') if (!digit?(@look) && @look != '.')
  while (digit?(@look) || @look == '.')
    if @look == '.'
      match '.'
      if nb_decimals
        expected "integer"
      end
      nb_decimals = 1
    else
      if nb_decimals
        nb_decimals *= 10
        value = value + @look.to_f / nb_decimals
        get_char
        skip_white
      else
        value = 10 * value + @look.to_i
        get_char
        skip_white
      end
    end
  end
  value
end
ident() click to toggle source
# File lib/Expression/parser.rb, line 68
def ident
  value = factor
  while  %w{! % ^}.include? @look
    case @look
    when '^'
      match('^')
      value **= factor
    when '%'
      match '%'
      value = value % factor
    when '!'
      match('!')
      str = value.to_s.split(".")
      if str[1] == "0" || str.size == 1
        temp = (1..value).reduce(1, :*)
        value = temp
      else
        raise InvalidInput, "Factorial is not defined for floats"
      end
    end
  end
  value
end
init() click to toggle source
# File lib/Expression/parser.rb, line 113
def init
  @input = @input.downcase.split('')
  get_char
  skip_white
end
match(char) click to toggle source
# File lib/Expression/identifiers.rb, line 16
def match(char)
  if @look == char
    get_char
    skip_white
  else
    expected(char)
  end
end
match_all(string) click to toggle source
# File lib/Expression/identifiers.rb, line 25
def match_all(string)
  string.each_char { |x| match(x) }
end
skip_white() click to toggle source
# File lib/Expression/identifiers.rb, line 29
def skip_white
  while @look =~ /\s/
    get_char
  end
end
term() click to toggle source
# File lib/Expression/parser.rb, line 92
def term
  value = ident
  while ['*', '/'].include? @look
    case @look
    when '*'
      match('*')
      value *= ident
    when '/'
      match('/')
      numerator = value
      denomenator = ident
      if denomenator == 0
        raise IndeterminedForm, "Division by zero is undefined"
      else
        value = numerator.to_f / denomenator
      end
    end
  end
  value
end
trig() click to toggle source
# File lib/Expression/identifiers.rb, line 34
def trig
  case @look
  when 'c'
    match_all('cos')
    case @look
    when 'h'
      match_all('h(')
      value = cosh(calculate)
    when '('
      match('(')
      value = cos(calculate)
    else
      expected('cos() or cosh()')
    end
  when 's'
    match('s')
    if @look == 'q'
      match_all('qrt(')
      value = sqrt(calculate)
    else
      match_all('in')
      case @look
      when 'h'
        match_all('h(')
        value = sinh(calculate)
      when '('
        match('(')
        value = sin(calculate)
      else
        expected('sin() or sinh()')
      end
    end
  when 'r'
    match_all('root')
    base = get_number
    match('(')
    value = calculate ** (1.0/base)
  when 't'
    match_all('tan')
    case @look
    when 'h'
      match_all('h(')
      value = tanh(calculate)
    when '('
      match('(')
      value = tan(calculate)
    else
      expected('tan() or tanh()')
    end
  when 'l'
    match('l')
    case @look
    when 'n'
      match_all('n(')
      value = log(calculate)
    when 'o'
      match_all('og')
      if digit? @look
        base = get_number
      elsif @look == "("
        base = 10
      else
        expected("integer or ( ")
      end
      match('(')
      value = log(calculate, base)
    else
      expected('ln() or log()')
    end
  when 'e'
    match_all('exp(')
    value = exp(calculate)
  when 'a'
    match_all('arc')
    case @look
    when 'c'
      match_all('cos')
      case @look
      when 'h'
        match_all('h(')
        value = acosh(calculate)
      when '('
        match('(')
        value = acos(calculate)
      else
        expected('arccos() or arccosh()')
      end
    when 's'
      match_all('sin')
      case @look
      when 'h'
        match_all('h(')
        value = asinh(calculate)
      when '('
        match('(')
        value = asin(calculate)
      else
        expected('arcsin() or arcsinh()')
      end
    when 't'
      match_all('tan')
      case @look
      when 'h'
        match_all('h(')
        value = atanh(calculate)
      when '('
        match('(')
        value = atan(calculate)
      else
        expected('arctan() or arctanh()')
      end
    end
  else
    raise InvalidInput, "unexpected input: \"#{@look}\""
  end
  match(')')
  value
end