2011-01-17 18 views
11

Jestem nowy w Haskell i próbuję parsować wyrażenia. Dowiedziałem się o Parsec i znalazłem także kilka artykułów, ale wydaje mi się, że nie rozumiem, co muszę zrobić. Mój problem polega na tym, że chcę podać wyrażenie takie jak "x^2 + 2 * x + 3", a wynik jest funkcją, która pobiera argument x i zwraca wartość. Jest mi bardzo przykro, jeśli jest to łatwe pytanie, ale naprawdę potrzebuję pomocy. Dzięki! Kod, który wstawiłem, pochodzi z artykułu, który można znaleźć na stronie this link.Funkcja parsowania w haskell

import Control.Monad(liftM) 
import Text.ParserCombinators.Parsec 
import Text.ParserCombinators.Parsec.Expr 
import Text.ParserCombinators.Parsec.Token 
import Text.ParserCombinators.Parsec.Language 

data Expr = Num Int  | Var String | Add Expr Expr 
      | Sub Expr Expr | Mul Expr Expr | Div Expr Expr 
      | Pow Expr Expr 
      deriving Show 

expr :: Parser Expr 
expr = buildExpressionParser table factor 
    <?> "expression" 

table = [[op "^" Pow AssocRight], 
     [op "*" Mul AssocLeft, op "/" Div AssocLeft], 
     [op "+" Add AssocLeft, op "-" Sub AssocLeft]] 
    where 
     op s f assoc 
      = Infix (do{ string s; return f}) assoc 
factor = do{ char '(' 
     ; x <- expr 
     ; char ')' 
     ; return x} 
    <|> number 
    <|> variable 
    <?> "simple expression" 

number :: Parser Expr 
number = do{ ds<- many1 digit 
     ; return (Num (read ds))} 
    <?> "number" 

variable :: Parser Expr 
variable = do{ ds<- many1 letter 
     ; return (Var ds)} 
    <?> "variable" 
+0

Mam coś, co znalazłem w niektórych artykułach, ale można go opublikować, nawet jeśli nie jest moją własnością? – izayoi

+0

proszę zamieścić go, jak inni mogą również okazać się przydatne. Pamiętaj o dołączeniu linku do oryginalnego źródła. –

Odpowiedz

13

To tylko parser dla wyrażeń ze zmiennymi. Właściwa interpretacja tego wyrażenia jest całkowicie odrębną kwestią.

Powinieneś utworzyć funkcję, która pobiera już przeanalizowane wyrażenie i wartości zmiennych, i zwraca wynik oceny wyrażenia. Pseudokod:

evaluate :: Expr -> Map String Int -> Int 
evaluate (Num n) _ = n 
evaluate (Var x) vars = {- Look up the value of x in vars -} 
evaluate (Plus e f) vars = {- Evaluate e and f, and return their sum -} 
... 

Celowo pominąłem niektóre szczegóły; miejmy nadzieję, odkrywając brakujące części, dowiesz się więcej o Haskell.

Jako następny krok, powinieneś spojrzeć na Reader monady na wygodny sposób przekazać mapę zmienną vars wokół i używając Maybe lub Error do sygnalizowania błędów, na przykład odwołanie do zmiennej, która nie jest powiązana w vars, lub dzielenie przez zero.