0votos

Calculadora en Haskell

por josejuan hace 5 años

Típico ejercicio de compiladores.

Dado una cadena que exprese una expresión matematica simple, resolverla siguiendo las jerarquia de los operadores.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{- 
 
    Hay muchas formas de implementarlo, por ejemplo en 
    javascript podría ser: 
     
        eval(expr) 
     
    De lo que se trata (seguramente) es de implementar 
    la gramática directamente sin usar ninguna librería 
    ni utilidad específicas. 
     
    La gramática lógicamente es: 
 
        L0 := L1 + L0 | L1 - L0 | L1 
        L1 := L2 * L1 | L2 / L1 | L2 
        L2 := ( L0 )  | K 
 
-} 
 
import Data.List 
import Data.Char 
import Control.Monad 
 
-- La gramática se puede procesar directamente tal como está expresada: 
l0 xs = op l1 l0 '+' (+) xs .|. op l1 l0 '-' (-) xs .|. l1 xs 
l1 xs = op l2 l1 '*' (*) xs .|. op l2 l1 '/' div xs .|. l2 xs 
l2 xs = parentheses xs .|. number xs 
 
parentheses ('(':xs) = l0 xs >>= c where { c (y, ')':rs) = return (y, rs); c _ = Nothing } 
parentheses       _  = Nothing 
 
number ('-':xs) = number xs >>= \(y, rs) -> return (-y, rs) 
number xs = let (ds, rs) = break (not.isDigit) xs in if null ds then Nothing else Just (read ds, rs) 
 
 
 
 
 
-- La computación de los operadores binarios se puede expresar de la misma forma: 
op xa xb c f xs = do { (a, r:rs) <- xa xs; (b,   ys) <- xb rs; if r /= c then Nothing else return (f a b, ys) } 
 
-- Y la elección de la expresión con éxito puede hacer cómodamente con un operador 
Nothing .|. y = y 
x       .|. _ = x 
 
 
 
 
{- 
 
  Por ejemplo: 
 
 
  *Main> l0 "3*5+((4+2*3)*(4+5))/2" 
  Just (60,"") 
   
   
  Y los errores quedan anotados por la cadena pendiente de procesar: 
   
   
  *Main> l0 "3*5+((4+*2*3)*(4+5))/2" 
  Just (15,"+((4+*2*3)*(4+5))/2") 
   
 
-} 

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.