Dan__88
29-10-2011, 15:43
Ciao a Tutti!
Ho creato un parser in Haskell di un espressione matematica (per ora senza le parentesi, ma con la precedenza degli operatori).
Il programma funziona, tuttavia essendo nuovo della programmazione funzionale potreste dirmi se ho fatto tutto correttamente e se ci sono eventuali migliorie applicabili?
import Text.ParserCombinators.Parsec
type Var = String
data IntExp
= IVar Var
| ICon Int
| Add IntExp IntExp
| Sub IntExp IntExp
| Mul IntExp IntExp
| Div IntExp IntExp
deriving (Read, Show)
number = do
x <- many1(digit)
return (read x :: Int)
-- Parserizza l'espressione ed esegue i calcoli
eseguiTutto:: Parser Int
eseguiTutto =
do
x <- expression
return (executeFunc(x))
-- Parserizza l'espressione dividento in termini (moltiplicazioni e divisioni),
-- e li somma/sottrae (in modo da mantenere la precedenza degli operatori)
expression:: Parser IntExp
expression =
do
x <- term
op <- optionMaybe(char '+' <|> char '-')
case op of
Nothing -> return x
Just op -> do
y <- expression
return (createOperation op x y)
-- Parserizza moltiplicazioni e divisioni consecutive
term :: Parser IntExp
term =
do
x <- number
op <- optionMaybe(char '*' <|> char '/')
case op of
Nothing -> return (ICon x)
Just op -> do
y <- term
return ( createOperation op (ICon x) y )
-- Crea l'operazione a seconda del contenuto del char op
createOperation:: Char -> IntExp -> IntExp -> IntExp
createOperation op x y
| op == '+' = Add x y
| op == '-' = Sub x y
| op == '*' = Mul x y
| op == '/' = Div x y
-- Esegue i calcoli utilizzando la struttura dati
executeFunc :: IntExp -> Int
executeFunc (ICon x) = x
executeFunc (Add x y) = executeFunc(x) + executeFunc(y)
executeFunc (Sub x y) = executeFunc(x) - executeFunc(y)
executeFunc (Mul x y) = executeFunc(x) * executeFunc(y)
executeFunc (Div x y) = executeFunc(x) `div` executeFunc(y)
-- Funzione di utilità, trovata in rete
run :: Show a => Parser a -> String -> IO ()
run p input
= case (parse p "" input) of
Left err -> do{ putStr "parse error at "
; print err
}
Right x -> print x
Per l'esecuzione:
:load Scrivania/haskell/parser.hs
run eseguiTutto "100/2+50*2-4"
146
Ho creato un parser in Haskell di un espressione matematica (per ora senza le parentesi, ma con la precedenza degli operatori).
Il programma funziona, tuttavia essendo nuovo della programmazione funzionale potreste dirmi se ho fatto tutto correttamente e se ci sono eventuali migliorie applicabili?
import Text.ParserCombinators.Parsec
type Var = String
data IntExp
= IVar Var
| ICon Int
| Add IntExp IntExp
| Sub IntExp IntExp
| Mul IntExp IntExp
| Div IntExp IntExp
deriving (Read, Show)
number = do
x <- many1(digit)
return (read x :: Int)
-- Parserizza l'espressione ed esegue i calcoli
eseguiTutto:: Parser Int
eseguiTutto =
do
x <- expression
return (executeFunc(x))
-- Parserizza l'espressione dividento in termini (moltiplicazioni e divisioni),
-- e li somma/sottrae (in modo da mantenere la precedenza degli operatori)
expression:: Parser IntExp
expression =
do
x <- term
op <- optionMaybe(char '+' <|> char '-')
case op of
Nothing -> return x
Just op -> do
y <- expression
return (createOperation op x y)
-- Parserizza moltiplicazioni e divisioni consecutive
term :: Parser IntExp
term =
do
x <- number
op <- optionMaybe(char '*' <|> char '/')
case op of
Nothing -> return (ICon x)
Just op -> do
y <- term
return ( createOperation op (ICon x) y )
-- Crea l'operazione a seconda del contenuto del char op
createOperation:: Char -> IntExp -> IntExp -> IntExp
createOperation op x y
| op == '+' = Add x y
| op == '-' = Sub x y
| op == '*' = Mul x y
| op == '/' = Div x y
-- Esegue i calcoli utilizzando la struttura dati
executeFunc :: IntExp -> Int
executeFunc (ICon x) = x
executeFunc (Add x y) = executeFunc(x) + executeFunc(y)
executeFunc (Sub x y) = executeFunc(x) - executeFunc(y)
executeFunc (Mul x y) = executeFunc(x) * executeFunc(y)
executeFunc (Div x y) = executeFunc(x) `div` executeFunc(y)
-- Funzione di utilità, trovata in rete
run :: Show a => Parser a -> String -> IO ()
run p input
= case (parse p "" input) of
Left err -> do{ putStr "parse error at "
; print err
}
Right x -> print x
Per l'esecuzione:
:load Scrivania/haskell/parser.hs
run eseguiTutto "100/2+50*2-4"
146