Se trata de extender la calculadora en postfijo realizada en la práctica 8.12.
La nueva calculadora deberá estar implantada mediante una clase
PostfixCalc
y dispone de dos operadores =
y !
que permiten respectivamente
asignar valores a variables
y obtener el valor ligado a una variable.
Los objetos PostfixCalc
disponen de un atributo stack
(de sólo lectura),
de un atributo st
que contiene la tabla de símbolos.
El objeto dispone también de un hash privado que mantiene las lambdas (véase la seccion 13.11) que implantan las operaciones de suma, resta, multiplicación, división, etc.
@f = { '+' => lambda { |a,b| a+b}, '*' => lambda { |a,b| a*b}, ... }
El siguiente ejemplo muestra un código que usa la clase:
43 if __FILE__ == $0 44 include Math 45 46 expr = ARGV.join(" ") 47 c = PostfixCalc.new({'sin' => lambda { |a| sin(a) }}) 48 49 c.eval(expr) 50 51 puts "----stack------" 52 c.stack.each { |m| puts m } 53 puts "----symbol table------" 54 c.st.each { |k,v| puts "#{k} => #{v}" } 55 end
Siguen varias ejecuciones:
~/rubytesting$ ruby postfixwithhashfunctions3.rb '3.14159 2 / sin' ----stack------ 0.99999999999912Por defecto la calculadora contiene un conjunto básico de operaciones. El programa cliente puede añadir nuevas operaciones como ocurre en el ejemplo:
c = PostfixCalc.new({'sin' => lambda { |a| sin(a) }})El siguiente ejemplo muestra el uso del operador de asignación
=
y del operador de carga (fetch) !
:
----symbol table------ ~/rubytesting$ ruby postfixwithhashfunctions3.rb '2 a = 3 b = a ! b ! *' ----stack------ 6.0 ----symbol table------ a => 2.0 b => 3.0La expresión
2 a =
retira el 2
y la a
de la pila y
almacena en la entrada a
de la tabla de símbolos de la calculadora
un 2
. No añade nada al top de la pila.
La expresión a !
empuja en el top de la pila el valor asociado
con la entrada a
de la tabla de símbolos.
La función p
imprime el elemento en el top de la pila:
~/rubytesting$ ruby postfixwithhashfunctions3.rb '2 a = 3 a ! 4 + p' 6.0 ----stack------ 3.0 6.0 ----symbol table------ a => 2.0
merge!
de la clase Hash
=
y !
puedan ir pegados al identificador:
~/rubytesting$ ruby postfixwithhashfunctions3.rb '2 a= 3 a! 4 + p' 6.0 ----stack------ 3.0 6.0 ----symbol table------ a => 2.0Hay varias soluciones. Una es usar
scan
:
>> "12 -3+ 4- 5*".scan(/-?\d+|[-+*]/) => ["12", "-3", "+", "4", "-", "5", "*"] >>Otra es usar
gsub
. Consulte el método gsub
de la clase String, que permite sustituciones
globales:
expr.gsub!(/([a-zA-Z_]\w)*([!=])/, '\1 \2')
Casiano Rodriguez León 2015-01-07