packages feed

husky-0.3: src/TokenParser.hs

{-----------------------------------------------------------------
 
  (c) 2008-2009 Markus Dittrich 
 
  This program is free software; you can redistribute it 
  and/or modify it under the terms of the GNU General Public 
  License Version 3 as published by the Free Software Foundation. 
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License Version 3 for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 59 Temple Place - Suite 330, 
  Boston, MA 02111-1307, USA.

--------------------------------------------------------------------}

-- | functionality related to parsing tokens
module TokenParser ( module Text.ParserCombinators.Parsec
                   , builtinFunctions
                   , float
                   , identifier
                   , integer
                   , parens
                   , lexer
                   , naturalOrFloat
                   , keywords
                   , OperatorAction
                   , operators
                   , reservedOp
                   , reserved
                   , stringLiteral
                   , unit_value
                   , unit_type
                   , variable 
                   , whiteSpace
                   ) where


-- imports
import Text.ParserCombinators.Parsec 
import qualified Text.ParserCombinators.Parsec.Token as PT
import Text.ParserCombinators.Parsec.Language (haskellDef
                                              , opLetter
                                              , reservedOpNames
                                              , reservedNames )
import Prelude


-- local imports
import CalculatorState



{- | some basic definitions for the calculator -}

-- | this is how valid variable names have to look like
variable :: CharParser CalcState String
variable = letter 
           >>= \first -> many alphaNum
           >>= \rest  -> return $ [first] ++ rest


-- | an identifier for a unit_value and unit_type is just a variable 
-- (at least for now). 
unit_value :: CharParser CalcState String
unit_value = variable

unit_type :: CharParser CalcState String
unit_type = variable


-- | these are all the names and corresponding functions
-- of keywords we know about
type OperatorAction = (Double -> Double)


-- | builtin functions of the form (a -> b)
builtinFunctions :: [(String, OperatorAction)]
builtinFunctions = [ ("sqrt",sqrt)
                   , ("exp",exp)
                   , ("log",log)
                   , ("log2", logBase 2)
                   , ("log10", logBase 10)
                   , ("sin",sin)
                   , ("cos",cos)
                   , ("tan",tan)
                   , ("asin", asin)
                   , ("acos", acos)
                   , ("atan", atan)
                   , ("sinh", sinh)
                   , ("cosh", cosh)
                   , ("tanh", tanh)
                   , ("asinh", sinh)
                   , ("acosh", cosh)
                   , ("atanh", atanh)]


-- | all other keywords that are not regular functions
keywords :: [String]
keywords = ["\\convert","\\c"]

operators :: [String]
operators = ["*","/","+","-","="]


{- | prepare needed parsers from Parsec.Token -}

-- | function generating a token parser based on a 
-- lexical parser combined with a language record definition
lexer :: PT.TokenParser st
lexer  = PT.makeTokenParser 
         ( haskellDef { reservedOpNames = operators
                      , opLetter = oneOf "*+/^"
                      , reservedNames   = keywords 
                                          ++ map fst builtinFunctions 
                      } )


-- | token parser for parenthesis
parens :: CharParser st a -> CharParser st a
parens = PT.parens lexer


-- | token parser for Integer
integer :: CharParser st Integer
integer = PT.integer lexer


-- | token parser for Char
stringLiteral :: CharParser st String
stringLiteral = PT.stringLiteral lexer


-- | token parser for Char
identifier :: CharParser st String
identifier = PT.stringLiteral lexer


-- | token parser for Double
float :: CharParser st Double
float = PT.float lexer


-- | token parser for Either Integer Double
naturalOrFloat :: CharParser st (Either Integer Double)
naturalOrFloat = PT.naturalOrFloat lexer


-- | token parser for keywords
reservedOp :: String -> CharParser st ()
reservedOp = PT.reservedOp lexer

-- | token parser for keywords
reserved :: String -> CharParser st ()
reserved = PT.reserved lexer

-- | token parser for whitespace
whiteSpace :: CharParser st ()
whiteSpace = PT.whiteSpace lexer