-
Notifications
You must be signed in to change notification settings - Fork 1
/
Math.hs
92 lines (75 loc) · 2.57 KB
/
Math.hs
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
module Text.HeX.Math (defaultsFor, arrayLines) where
import Text.HeX
import Control.Applicative ((<$>))
import Data.Char (isAscii, isAlphaNum)
defaultsFor :: MathWriter -> HeX ()
defaultsFor writer = do
addParser [Math] $ mathParser writer
addParser [Block,Inline] $ dollars writer
newCommand [Inline] "(" $ parenMath writer
newCommand [Inline,Block] "[" $ bracketMath writer
newCommand [Inline] "ensuremath" $ ensureMath Inline writer
newCommand [Math] "ensuremath" $ ensureMath Math writer
dollars :: MathWriter -> HeX Doc
dollars writer = do
char '$'
display <- option False $ char '$' >> return True
spaces
let delim = if display
then char '$' >> char '$'
else char '$'
parseMath writer display delim
parenMath :: MathWriter -> HeX Doc
parenMath writer = spaces >> parseMath writer False (try $ string "\\)")
bracketMath :: MathWriter -> HeX Doc
bracketMath writer = spaces >> parseMath writer True (try $ string "\\]")
parseMath :: MathWriter -> Bool -> HeX a -> HeX Doc
parseMath writer display closer = do
setVar "displaymath" display
res <- mconcat <$> manyTill math closer
setVar "displaymath" False
return $ if display
then displayMath writer res
else inlineMath writer res
mathParser :: MathWriter -> HeX Doc
mathParser writer = do
spaces
res <- environment Math
<|> command Math
<|> comment
<|> grouped writer <$> group math
<|> number writer <$> pNumber
<|> variable writer <$> pVariable
<|> operator writer <$> pOperator
<|> (operator writer . (:[])) <$> (pEscaped <|> pUnicode)
spaces
return res
opLetters :: [Char]
opLetters = ":+*/=-(),;.?'~[]<>!"
pOperator :: HeX String
pOperator = many1 (char '\'') <|> count 1 (oneOf opLetters)
pNumber :: HeX String
pNumber = many1 digit
pVariable :: HeX Char
pVariable = letter
pEscaped :: HeX Char
pEscaped = try $ char '\\' >> satisfy (not . isAlphaNum)
pUnicode :: HeX Char
pUnicode = satisfy (not . isAscii)
ensureMath :: Mode -> MathWriter -> HeX Doc
ensureMath current writer = do
if current == Math
then math
else inlineMath writer <$> math
endLine :: HeX ()
endLine = try $ do
string "\\\\"
optional inbrackets -- can contain e.g. [1.0in] for a line height, not yet supported
return ()
inbrackets :: HeX String
inbrackets = try $ char '[' >> manyTill (satisfy (/=']')) (char ']')
arrayLine :: HeX Doc -> HeX [Doc]
arrayLine expr =
sepBy1 (mconcat <$> many (notFollowedBy endLine >> expr)) (char '&')
arrayLines :: HeX Doc -> HeX [[Doc]]
arrayLines expr = sepEndBy1 (arrayLine expr) endLine