egison-4.0.1: hs-src/Language/Egison/PrettyMath/AST.hs
{- |
Module : Language.Egison.PrettyMath.AST
Licence : MIT
-}
module Language.Egison.PrettyMath.AST
( MathExpr(..)
, MathIndex(..)
, isSub
, parseExpr
) where
import Text.ParserCombinators.Parsec hiding (spaces)
data MathExpr
= Atom String [MathIndex]
| NegativeAtom String
| Plus [MathExpr]
| Multiply [MathExpr]
| Power MathExpr MathExpr
| Func MathExpr [MathExpr]
| Tensor [MathExpr] [MathIndex]
| Tuple [MathExpr]
| Collection [MathExpr]
| Exp MathExpr
| Quote MathExpr
| Partial MathExpr [MathExpr]
deriving (Eq, Show)
data MathIndex
= Super MathExpr
| Sub MathExpr
deriving (Eq, Show)
isSub :: MathIndex -> Bool
isSub (Sub _) = True
isSub _ = False
--
-- Parser
--
spaces :: Parser ()
spaces = skipMany1 space
spaces0 :: Parser ()
spaces0 = skipMany space
symbol :: Parser Char
symbol = oneOf "!$%&*+-/:<=>?@#"
parseAtom :: Parser MathExpr
parseAtom = Atom <$> ((:) <$> (letter <|> symbol <|> digit) <*> many (letter <|> digit <|> symbol)) <*> many parseScript
parseAtom' :: Parser MathExpr
parseAtom' = flip Atom [] <$> ((:) <$> (letter <|> symbol <|> digit) <*> many (letter <|> digit <|> symbol))
parsePartial :: Parser MathExpr
parsePartial = Partial <$> parseAtom <*> many1 (char '|' >> parseAtom)
parseNegativeAtom :: Parser MathExpr
parseNegativeAtom = char '-' >> NegativeAtom <$> ((:) <$> (letter <|> symbol <|> digit) <*> many (letter <|> digit <|> symbol))
parseList :: Parser [MathExpr]
parseList = sepEndBy parseExpr spaces
parseScript :: Parser MathIndex
parseScript = Sub <$> (char '_' >> parseAtom')
<|> Super <$> (char '~' >> parseAtom')
parsePlus :: Parser MathExpr
parsePlus = string "(+" >> spaces >> Plus <$> parseList <* char ')'
parseMultiply :: Parser MathExpr
parseMultiply = string "(*" >> spaces >> Multiply <$> parseList <* char ')'
parseFunction :: Parser MathExpr
parseFunction = char '(' >> Func <$> parseAtom <* spaces <*> parseList <* char ')'
parseTensor :: Parser MathExpr
parseTensor = string "[|" >> spaces0 >> Tensor <$> parseList <* spaces0 <* string "|]" <*> many parseScript
parseTuple :: Parser MathExpr
parseTuple = char '[' >> Tuple <$> parseList <* char ']'
parseCollection :: Parser MathExpr
parseCollection = char '{' >> Collection <$> parseList <* char '}'
parseExp :: Parser MathExpr
parseExp = string "(exp" >> spaces >> Exp <$> parseExpr <* char ')'
parseQuote :: Parser MathExpr
parseQuote = char '\'' >> Quote <$> parseExpr'
parseExpr' :: Parser MathExpr
parseExpr' = parseNegativeAtom
<|> try parsePartial
<|> parseAtom
<|> parseQuote
<|> try parseExp
<|> try parsePlus
<|> try parseMultiply
<|> try parseFunction
<|> try parseTensor
<|> try parseTuple
<|> try parseCollection
parseExpr :: Parser MathExpr
parseExpr = do
x <- parseExpr'
option x $ Power x <$> try (char '^' >> parseExpr')