texmath (empty) → 0.1
raw patch · 10 files changed
+1359/−0 lines, 10 filesdep +basedep +cgidep +containerssetup-changed
Dependencies added: base, cgi, containers, json, parsec, xml
Files
- LICENSE +340/−0
- Setup.hs +2/−0
- Text/TeXMath.hs +33/−0
- Text/TeXMath/MathMLWriter.hs +157/−0
- Text/TeXMath/Parser.hs +637/−0
- cgi/texmath-cgi.hs +20/−0
- cgi/texmath.xhtml +50/−0
- examples +48/−0
- testTeXMathML.hs +21/−0
- texmath.cabal +51/−0
+ LICENSE view
@@ -0,0 +1,340 @@+ GNU GENERAL PUBLIC LICENSE+ Version 2, June 1991++ Copyright (C) 1989, 1991 Free Software Foundation, Inc.+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++ Preamble++ The licenses for most software are designed to take away your+freedom to share and change it. By contrast, the GNU General Public+License is intended to guarantee your freedom to share and change free+software--to make sure the software is free for all its users. This+General Public License applies to most of the Free Software+Foundation's software and to any other program whose authors commit to+using it. (Some other Free Software Foundation software is covered by+the GNU Library General Public License instead.) You can apply it to+your programs, too.++ When we speak of free software, we are referring to freedom, not+price. Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+this service if you wish), that you receive source code or can get it+if you want it, that you can change the software or use pieces of it+in new free programs; and that you know you can do these things.++ To protect your rights, we need to make restrictions that forbid+anyone to deny you these rights or to ask you to surrender the rights.+These restrictions translate to certain responsibilities for you if you+distribute copies of the software, or if you modify it.++ For example, if you distribute copies of such a program, whether+gratis or for a fee, you must give the recipients all the rights that+you have. You must make sure that they, too, receive or can get the+source code. And you must show them these terms so they know their+rights.++ We protect your rights with two steps: (1) copyright the software, and+(2) offer you this license which gives you legal permission to copy,+distribute and/or modify the software.++ Also, for each author's protection and ours, we want to make certain+that everyone understands that there is no warranty for this free+software. If the software is modified by someone else and passed on, we+want its recipients to know that what they have is not the original, so+that any problems introduced by others will not reflect on the original+authors' reputations.++ Finally, any free program is threatened constantly by software+patents. We wish to avoid the danger that redistributors of a free+program will individually obtain patent licenses, in effect making the+program proprietary. To prevent this, we have made it clear that any+patent must be licensed for everyone's free use or not licensed at all.++ The precise terms and conditions for copying, distribution and+modification follow.++ GNU GENERAL PUBLIC LICENSE+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++ 0. This License applies to any program or other work which contains+a notice placed by the copyright holder saying it may be distributed+under the terms of this General Public License. The "Program", below,+refers to any such program or work, and a "work based on the Program"+means either the Program or any derivative work under copyright law:+that is to say, a work containing the Program or a portion of it,+either verbatim or with modifications and/or translated into another+language. (Hereinafter, translation is included without limitation in+the term "modification".) Each licensee is addressed as "you".++Activities other than copying, distribution and modification are not+covered by this License; they are outside its scope. The act of+running the Program is not restricted, and the output from the Program+is covered only if its contents constitute a work based on the+Program (independent of having been made by running the Program).+Whether that is true depends on what the Program does.++ 1. You may copy and distribute verbatim copies of the Program's+source code as you receive it, in any medium, provided that you+conspicuously and appropriately publish on each copy an appropriate+copyright notice and disclaimer of warranty; keep intact all the+notices that refer to this License and to the absence of any warranty;+and give any other recipients of the Program a copy of this License+along with the Program.++You may charge a fee for the physical act of transferring a copy, and+you may at your option offer warranty protection in exchange for a fee.++ 2. You may modify your copy or copies of the Program or any portion+of it, thus forming a work based on the Program, and copy and+distribute such modifications or work under the terms of Section 1+above, provided that you also meet all of these conditions:++ a) You must cause the modified files to carry prominent notices+ stating that you changed the files and the date of any change.++ b) You must cause any work that you distribute or publish, that in+ whole or in part contains or is derived from the Program or any+ part thereof, to be licensed as a whole at no charge to all third+ parties under the terms of this License.++ c) If the modified program normally reads commands interactively+ when run, you must cause it, when started running for such+ interactive use in the most ordinary way, to print or display an+ announcement including an appropriate copyright notice and a+ notice that there is no warranty (or else, saying that you provide+ a warranty) and that users may redistribute the program under+ these conditions, and telling the user how to view a copy of this+ License. (Exception: if the Program itself is interactive but+ does not normally print such an announcement, your work based on+ the Program is not required to print an announcement.)++These requirements apply to the modified work as a whole. If+identifiable sections of that work are not derived from the Program,+and can be reasonably considered independent and separate works in+themselves, then this License, and its terms, do not apply to those+sections when you distribute them as separate works. But when you+distribute the same sections as part of a whole which is a work based+on the Program, the distribution of the whole must be on the terms of+this License, whose permissions for other licensees extend to the+entire whole, and thus to each and every part regardless of who wrote it.++Thus, it is not the intent of this section to claim rights or contest+your rights to work written entirely by you; rather, the intent is to+exercise the right to control the distribution of derivative or+collective works based on the Program.++In addition, mere aggregation of another work not based on the Program+with the Program (or with a work based on the Program) on a volume of+a storage or distribution medium does not bring the other work under+the scope of this License.++ 3. You may copy and distribute the Program (or a work based on it,+under Section 2) in object code or executable form under the terms of+Sections 1 and 2 above provided that you also do one of the following:++ a) Accompany it with the complete corresponding machine-readable+ source code, which must be distributed under the terms of Sections+ 1 and 2 above on a medium customarily used for software interchange; or,++ b) Accompany it with a written offer, valid for at least three+ years, to give any third party, for a charge no more than your+ cost of physically performing source distribution, a complete+ machine-readable copy of the corresponding source code, to be+ distributed under the terms of Sections 1 and 2 above on a medium+ customarily used for software interchange; or,++ c) Accompany it with the information you received as to the offer+ to distribute corresponding source code. (This alternative is+ allowed only for noncommercial distribution and only if you+ received the program in object code or executable form with such+ an offer, in accord with Subsection b above.)++The source code for a work means the preferred form of the work for+making modifications to it. For an executable work, complete source+code means all the source code for all modules it contains, plus any+associated interface definition files, plus the scripts used to+control compilation and installation of the executable. However, as a+special exception, the source code distributed need not include+anything that is normally distributed (in either source or binary+form) with the major components (compiler, kernel, and so on) of the+operating system on which the executable runs, unless that component+itself accompanies the executable.++If distribution of executable or object code is made by offering+access to copy from a designated place, then offering equivalent+access to copy the source code from the same place counts as+distribution of the source code, even though third parties are not+compelled to copy the source along with the object code.++ 4. You may not copy, modify, sublicense, or distribute the Program+except as expressly provided under this License. Any attempt+otherwise to copy, modify, sublicense or distribute the Program is+void, and will automatically terminate your rights under this License.+However, parties who have received copies, or rights, from you under+this License will not have their licenses terminated so long as such+parties remain in full compliance.++ 5. You are not required to accept this License, since you have not+signed it. However, nothing else grants you permission to modify or+distribute the Program or its derivative works. These actions are+prohibited by law if you do not accept this License. Therefore, by+modifying or distributing the Program (or any work based on the+Program), you indicate your acceptance of this License to do so, and+all its terms and conditions for copying, distributing or modifying+the Program or works based on it.++ 6. Each time you redistribute the Program (or any work based on the+Program), the recipient automatically receives a license from the+original licensor to copy, distribute or modify the Program subject to+these terms and conditions. You may not impose any further+restrictions on the recipients' exercise of the rights granted herein.+You are not responsible for enforcing compliance by third parties to+this License.++ 7. If, as a consequence of a court judgment or allegation of patent+infringement or for any other reason (not limited to patent issues),+conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License. If you cannot+distribute so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you+may not distribute the Program at all. For example, if a patent+license would not permit royalty-free redistribution of the Program by+all those who receive copies directly or indirectly through you, then+the only way you could satisfy both it and this License would be to+refrain entirely from distribution of the Program.++If any portion of this section is held invalid or unenforceable under+any particular circumstance, the balance of the section is intended to+apply and the section as a whole is intended to apply in other+circumstances.++It is not the purpose of this section to induce you to infringe any+patents or other property right claims or to contest validity of any+such claims; this section has the sole purpose of protecting the+integrity of the free software distribution system, which is+implemented by public license practices. Many people have made+generous contributions to the wide range of software distributed+through that system in reliance on consistent application of that+system; it is up to the author/donor to decide if he or she is willing+to distribute software through any other system and a licensee cannot+impose that choice.++This section is intended to make thoroughly clear what is believed to+be a consequence of the rest of this License.++ 8. If the distribution and/or use of the Program is restricted in+certain countries either by patents or by copyrighted interfaces, the+original copyright holder who places the Program under this License+may add an explicit geographical distribution limitation excluding+those countries, so that distribution is permitted only in or among+countries not thus excluded. In such case, this License incorporates+the limitation as if written in the body of this License.++ 9. The Free Software Foundation may publish revised and/or new versions+of the General Public License from time to time. Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++Each version is given a distinguishing version number. If the Program+specifies a version number of this License which applies to it and "any+later version", you have the option of following the terms and conditions+either of that version or of any later version published by the Free+Software Foundation. If the Program does not specify a version number of+this License, you may choose any version ever published by the Free Software+Foundation.++ 10. If you wish to incorporate parts of the Program into other free+programs whose distribution conditions are different, write to the author+to ask for permission. For software which is copyrighted by the Free+Software Foundation, write to the Free Software Foundation; we sometimes+make exceptions for this. Our decision will be guided by the two goals+of preserving the free status of all derivatives of our free software and+of promoting the sharing and reuse of software generally.++ NO WARRANTY++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,+REPAIR OR CORRECTION.++ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE+POSSIBILITY OF SUCH DAMAGES.++ END OF TERMS AND CONDITIONS++ How to Apply These Terms to Your New Programs++ If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++ To do so, attach the following notices to the program. It is safest+to attach them to the start of each source file to most effectively+convey the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++ <one line to give the program's name and a brief idea of what it does.>+ Copyright (C) <year> <name of author>++ This program is free software; you can redistribute it and/or modify+ it under the terms of the GNU General Public License as published by+ the Free Software Foundation; either version 2 of the License, or+ (at your option) any later version.++ 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 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+++Also add information on how to contact you by electronic and paper mail.++If the program is interactive, make it output a short notice like this+when it starts in an interactive mode:++ Gnomovision version 69, Copyright (C) year name of author+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+ This is free software, and you are welcome to redistribute it+ under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License. Of course, the commands you use may+be called something other than `show w' and `show c'; they could even be+mouse-clicks or menu items--whatever suits your program.++You should also get your employer (if you work as a programmer) or your+school, if any, to sign a "copyright disclaimer" for the program, if+necessary. Here is a sample; alter the names:++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program+ `Gnomovision' (which makes passes at compilers) written by James Hacker.++ <signature of Ty Coon>, 1 April 1989+ Ty Coon, President of Vice++This General Public License does not permit incorporating your program into+proprietary programs. If your program is a subroutine library, you may+consider it more useful to permit linking proprietary applications with the+library. If this is what you want to do, use the GNU Library General+Public License instead of this License.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Text/TeXMath.hs view
@@ -0,0 +1,33 @@+{-+Copyright (C) 2009 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++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 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+-}++{- | Functions for converting LaTeX math formulas to MathML.+-}++module Text.TeXMath ( texMathToMathML, DisplayType(..) )+where+import Text.TeXMath.Parser+import Text.TeXMath.MathMLWriter+import Text.XML.Light+import Text.ParserCombinators.Parsec (parse)++texMathToMathML :: DisplayType -> String -> Either String Element+texMathToMathML dt inp = inp `seq`+ case parse formula "TeX math input" inp of+ Left err -> Left (show err)+ Right v -> Right $ toMathML dt v
+ Text/TeXMath/MathMLWriter.hs view
@@ -0,0 +1,157 @@+{-+Copyright (C) 2009 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++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 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+-}++{- | Functions for writing a parsed formula as MathML.+-}++module Text.TeXMath.MathMLWriter (toMathML, DisplayType(..), showExp)+where++import qualified Data.Map as M+import Text.XML.Light+import Text.TeXMath.Parser++data DisplayType = DisplayBlock+ | DisplayInline+ deriving Show++toMathML :: DisplayType -> [Exp] -> Element+toMathML dt exprs =+ add_attr dtattr $ math $ map showExp exprs+ where dtattr = Attr (unqual "display") dt'+ dt' = case dt of+ DisplayBlock -> "block"+ DisplayInline -> "inline"++math :: [Element] -> Element+math = add_attr (Attr (unqual "xmlns") "http://www.w3.org/1998/Math/MathML") . unode "math" . unode "mrow"++mrow :: [Element] -> Element+mrow = unode "mrow"++{- Firefox seems to set spacing based on its own dictionary,+- so I believe this is unnecessary.+ +setSpacing :: String -> String -> Bool -> Element -> Element+setSpacing left right stretchy elt =+ add_attr (Attr (unqual "lspace") left) $+ add_attr (Attr (unqual "rspace") right) $+ if stretchy+ then add_attr (Attr (unqual "stretchy") "true") elt+ else elt++showSymbol (ESymbol s x) =+ case s of+ Ord x -> unode "mo" x+ Op x -> setSpacing "0" "0.167em" True $ unode "mo" x+ Bin x -> setSpacing "0.222em" "0.222em" False $ unode "mo" x+ Rel x -> setSpacing "0.278em" "0.278em" False $ unode "mo" x+ Open x -> setSpacing "0" "0" True $ unode "mo" x+ Close x -> setSpacing "0" "0" True $ unode "mo" x+ Pun x -> setSpacing "0" "0.167em" False $ unode "mo" x+-}++unaryOps :: M.Map String String+unaryOps = M.fromList+ [ ("\\sqrt", "msqrt")+ , ("\\surd", "msqrt")+ ]++showUnary :: String -> Exp -> Element+showUnary c x =+ case M.lookup c unaryOps of+ Just c' -> unode c' (showExp x)+ Nothing -> error $ "Unknown unary op: " ++ c++binaryOps :: Node a => M.Map String (a -> Element)+binaryOps = M.fromList+ [ ("\\frac", unode "mfrac")+ , ("\\tfrac", withAttribute "displaystyle" "false" .+ unode "mstyle" . unode "mfrac")+ , ("\\dfrac", withAttribute "displaystyle" "true" .+ unode "mstyle" . unode "mfrac")+ , ("\\sqrt", unode "mroot")+ , ("\\stackrel", unode "mover")+ , ("\\overset", unode "mover")+ , ("\\underset", unode "munder")+ ]++showBinary :: String -> Exp -> Exp -> Element+showBinary c x y =+ case M.lookup c binaryOps of+ Just f -> f [showExp x, showExp y]+ Nothing -> error $ "Unknown binary op: " ++ c++spaceWidth :: String -> Element+spaceWidth w = withAttribute "width" w $ unode "mspace" ()++makeStretchy :: Element -> Element+makeStretchy = withAttribute "stretchy" "true"++makeScaled :: String -> Element -> Element+makeScaled s = withAttribute "minsize" s . withAttribute "maxsize" s++makeText :: String -> String -> Element+makeText a s = if trailingSp+ then mrow [s', sp]+ else s'+ where sp = spaceWidth "0.333em"+ s' = withAttribute "mathvariant" a $ unode "mtext" s+ trailingSp = not (null s) && last s `elem` " \t"++makeArray :: [Alignment] -> [ArrayLine] -> Element+makeArray as ls = unode "mtable" $+ map (unode "mtr" .+ zipWith (\a -> setAlignment a . unode "mtd". map showExp) as') ls+ where setAlignment AlignLeft = withAttribute "columnalign" "left"+ setAlignment AlignRight = withAttribute "columnalign" "right"+ setAlignment AlignCenter = withAttribute "columnalign" "center"+ setAlignment AlignDefault = id + as' = as ++ cycle [AlignDefault]++withAttribute :: String -> String -> Element -> Element+withAttribute a = add_attr . Attr (unqual a)++accent :: String -> Element+accent = add_attr (Attr (unqual "accent") "true") .+ unode "mo"++showExp :: Exp -> Element+showExp e =+ case e of+ EInteger x -> unode "mn" $ show x+ EFloat x -> unode "mn" $ show x+ EGrouped [x] -> showExp x+ EGrouped xs -> mrow $ map showExp xs+ EIdentifier x -> unode "mi" x+ ESymbol Accent x -> accent x+ ESymbol _ x -> unode "mo" x+ ESpace x -> spaceWidth x+ EBinary c x y -> showBinary c x y+ ESub x y -> unode "msub" $ map showExp [x, y]+ ESuper x y -> unode "msup" $ map showExp [x, y]+ ESubsup x y z -> unode "msubsup" $ map showExp [x, y, z]+ EUnder x y -> unode "munder" $ map showExp [x, y]+ EOver x y -> unode "mover" $ map showExp [x, y]+ EUnderover x y z -> unode "munderover" $ map showExp [x, y, z]+ EUnary c x -> showUnary c x+ EStretchy x -> makeStretchy $ showExp x+ EScaled s x -> makeScaled s $ showExp x+ EArray as ls -> makeArray as ls+ EText a s -> makeText a s+
+ Text/TeXMath/Parser.hs view
@@ -0,0 +1,637 @@+{-+Copyright (C) 2009 John MacFarlane <jgm@berkeley.edu>++This program is free software; you can redistribute it and/or modify+it under the terms of the GNU General Public License as published by+the Free Software Foundation; either version 2 of the License, or+(at your option) any later version.++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 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+-}++{- | Functions for parsing a LaTeX formula to a Haskell representation.+-}++module Text.TeXMath.Parser (expr, formula, Exp(..), TeXSymbolType(..), ArrayLine, Alignment(..))+where++import Control.Monad+import Data.Char (isAlphaNum)+import qualified Data.Map as M+import Text.ParserCombinators.Parsec+import qualified Text.ParserCombinators.Parsec.Token as P+import Text.ParserCombinators.Parsec.Language++data TeXSymbolType = Ord | Op | Bin | Rel | Open | Close | Pun | Accent+ deriving (Show, Read, Eq)++data Alignment = AlignLeft | AlignCenter | AlignRight | AlignDefault+ deriving (Show, Read, Eq)++type ArrayLine = [[Exp]]++data Exp =+ EInteger Integer+ | EFloat Double + | EGrouped [Exp]+ | EIdentifier String+ | ESymbol TeXSymbolType String+ | ESpace String+ | EBinary String Exp Exp+ | ESub Exp Exp+ | ESuper Exp Exp+ | ESubsup Exp Exp Exp+ | EOver Exp Exp+ | EUnder Exp Exp+ | EUnderover Exp Exp Exp+ | EUnary String Exp+ | EScaled String Exp+ | EStretchy Exp+ | EArray [Alignment] [ArrayLine]+ | EText String String+ deriving (Show, Read, Eq)++texMathDef :: LanguageDef st+texMathDef = LanguageDef + { commentStart = ""+ , commentEnd = ""+ , commentLine = "%"+ , nestedComments = False+ , identStart = letter+ , identLetter = alphaNum+ , opStart = opLetter texMathDef+ , opLetter = oneOf ":_+/=^-(),;.?'~[]<>!"+ , reservedOpNames= []+ , reservedNames = []+ , caseSensitive = True+ }++-- The parser++expr1 :: GenParser Char st Exp+expr1 = choice [+ inbraces+ , variable+ , number+ , texSymbol+ , text+ , root + , unary+ , binary+ , enclosure+ , array+ , diacritical+ , escaped+ ]++formula :: GenParser Char st [Exp]+formula = do+ whiteSpace+ f <- many expr+ eof+ return f++expr :: GenParser Char st Exp+expr = subSup <|> superOrSubscripted <|> expr1++inbraces :: GenParser Char st Exp+inbraces = liftM EGrouped (braces $ many $ notFollowedBy (char '}') >> expr)++inbrackets :: GenParser Char st Exp+inbrackets = liftM EGrouped (brackets $ many $ notFollowedBy (char ']') >> expr)++number :: GenParser Char st Exp+number = try (liftM EFloat float)+ <|> liftM EInteger decimal ++enclosure :: GenParser Char st Exp+enclosure = basicEnclosure <|> leftright <|> scaledEnclosure++basicEnclosure :: GenParser Char st Exp+basicEnclosure = choice $ map (\(s, v) -> try (symbol s) >> return v) enclosures++leftright :: GenParser Char st Exp+leftright = try $ do+ typ <- (try (symbol "\\left") >> return Open)+ <|> (symbol "\\right" >> return Close)+ enc <- enclosure <|> (symbol "." >> return (ESymbol typ "\xFEFF"))+ case enc of+ ESymbol t x | t == typ -> return $ EStretchy $ ESymbol t x+ _ -> pzero ++scaledEnclosure :: GenParser Char st Exp+scaledEnclosure = try $ do+ cmd <- command+ case M.lookup cmd scalers of+ Just r -> liftM (EScaled r . EStretchy) basicEnclosure+ Nothing -> pzero ++arrayLine :: GenParser Char st ArrayLine+arrayLine = notFollowedBy (try $ char '\\' >> symbol "end" >> return '\n') >>+ sepBy1 (many (notFollowedBy (try $ char '\\' >> char '\\') >> expr)) (symbol "&")++array :: GenParser Char st Exp+array = stdarray <|> eqnarray <|> cases++stdarray :: GenParser Char st Exp+stdarray = inEnvironment "array" $ do+ aligns <- option [] arrayAlignments+ liftM (EArray aligns) $ sepEndBy1 arrayLine (try $ symbol "\\\\")++eqnarray :: GenParser Char st Exp+eqnarray = inEnvironment "eqnarray" $+ liftM (EArray [AlignRight, AlignCenter, AlignLeft]) $+ sepEndBy1 arrayLine (try $ symbol "\\\\")++cases :: GenParser Char st Exp+cases = inEnvironment "cases" $ do+ rs <- sepEndBy1 arrayLine (try $ symbol "\\\\")+ return $ EGrouped [EStretchy (ESymbol Open "{"), EArray [] rs]++arrayAlignments :: GenParser Char st [Alignment]+arrayAlignments = try $ do+ as <- braces (many letter)+ let letterToAlignment 'l' = AlignLeft+ letterToAlignment 'c' = AlignCenter+ letterToAlignment 'r' = AlignRight+ letterToAlignment _ = AlignDefault+ return $ map letterToAlignment as++inEnvironment :: String+ -> GenParser Char st Exp+ -> GenParser Char st Exp+inEnvironment envType p = try $ do+ char '\\'+ symbol "begin"+ braces $ symbol envType >> optional (symbol "*")+ result <- p+ char '\\'+ symbol "end"+ braces $ symbol envType >> optional (symbol "*")+ return result ++variable :: GenParser Char st Exp+variable = do+ v <- letter+ spaces+ return $ EIdentifier [v]++subSup :: GenParser Char st Exp+subSup = try $ do+ a <- expr1+ char '_'+ b <- expr1+ char '^'+ c <- expr+ return $ ESubsup a b c ++superOrSubscripted :: GenParser Char st Exp+superOrSubscripted = try $ do+ a <- expr1+ c <- oneOf "^_"+ b <- expr+ case c of+ '^' -> return $ ESuper a b+ '_' -> return $ ESub a b+ _ -> pzero ++escaped :: GenParser Char st Exp+escaped = lexeme $ try $ + char '\\' >>+ liftM (ESymbol Ord . (:[])) (satisfy $ not . isAlphaNum)++command :: GenParser Char st String+command = try $ char '\\' >> liftM ('\\':) (identifier <|> count 1 anyChar)++unaryOps :: [String]+unaryOps = ["\\sqrt", "\\surd"]++textOps :: M.Map String (String -> Exp)+textOps = M.fromList+ [ ("\\textrm", EText "normal")+ , ("\\text", EText "normal")+ , ("\\mbox", EText "normal")+ , ("\\mathbf", EText "bold")+ , ("\\textbf", EText "bold")+ , ("\\mathit", EText "italic")+ , ("\\textit", EText "italic")+ , ("\\mathtt", EText "monospace")+ , ("\\texttt", EText "monospace")+ , ("\\mathsf", EText "sans-serif")+ , ("\\mathbb", EText "double-struck")+ , ("\\mathcal", EText "script")+ , ("\\mathfrak", EText "fraktur")+ ]++diacritical :: GenParser Char st Exp+diacritical = try $ do+ c <- command+ case M.lookup c diacriticals of+ Just r -> liftM r inbraces+ Nothing -> pzero ++diacriticals :: M.Map String (Exp -> Exp)+diacriticals = M.fromList+ [ ("\\acute", \e -> EOver e (ESymbol Accent "\x00B4"))+ , ("\\grave", \e -> EOver e (ESymbol Accent "\x0060"))+ , ("\\breve", \e -> EOver e (ESymbol Accent "\x02D8"))+ , ("\\check", \e -> EOver e (ESymbol Accent "\x02C7"))+ , ("\\dot", \e -> EOver e (ESymbol Accent "."))+ , ("\\ddot", \e -> EOver e (ESymbol Accent ".."))+ , ("\\mathring", \e -> EOver e (ESymbol Accent "\x00B0"))+ , ("\\vec", \e -> EOver e (ESymbol Accent "\x20D7"))+ , ("\\overrightarrow", \e -> EOver e (ESymbol Accent "\x20D7"))+ , ("\\overleftarrow", \e -> EOver e (ESymbol Accent "\x20D6"))+ , ("\\hat", \e -> EOver e (ESymbol Accent "\x005E"))+ , ("\\widehat", \e -> EOver e (ESymbol Accent "\x0302"))+ , ("\\tilde", \e -> EOver e (ESymbol Accent "~"))+ , ("\\widetilde", \e -> EOver e (ESymbol Accent "\x02DC"))+ , ("\\bar", \e -> EOver e (ESymbol Accent "\x203E"))+ , ("\\overbrace", \e -> EOver e (ESymbol Accent "\xFE37"))+ , ("\\overbracket", \e -> EOver e (ESymbol Accent "\x23B4"))+ , ("\\overline", \e -> EOver e (ESymbol Accent "\x00AF"))+ , ("\\underbrace", \e -> EUnder e (ESymbol Accent "\xFE38"))+ , ("\\underbracket", \e -> EUnder e (ESymbol Accent "\x23B5"))+ , ("\\underline", \e -> EUnder e (ESymbol Accent "\x00AF"))+ ]++unary :: GenParser Char st Exp+unary = try $ do+ c <- command+ unless (c `elem` unaryOps) pzero + a <- inbraces+ return $ EUnary c a++text :: GenParser Char st Exp+text = try $ do+ c <- command+ case M.lookup c textOps of+ Just f -> liftM f $ braces (many (noneOf "}" <|> (char '\\' >> char '}')))+ Nothing -> pzero ++-- note: sqrt can be unary, \sqrt{2}, or binary, \sqrt[3]{2}+root :: GenParser Char st Exp+root = try $ do+ try (symbol "\\sqrt") <|> symbol "\\surd"+ a <- inbrackets+ b <- inbraces+ return $ EBinary "\\sqrt" b a++binary :: GenParser Char st Exp+binary = try $ do+ c <- command+ unless (c `elem` binaryOps) pzero + a <- inbraces+ b <- inbraces+ return $ EBinary c a b++texSymbol :: GenParser Char st Exp+texSymbol = try $ do+ sym <- operator <|> command+ case M.lookup sym symbols of+ Just s -> return s+ Nothing -> pzero ++-- The lexer+lexer :: P.TokenParser st+lexer = P.makeTokenParser texMathDef+ +lexeme :: CharParser st a -> CharParser st a+lexeme = P.lexeme lexer++whiteSpace :: CharParser st () +whiteSpace = P.whiteSpace lexer++identifier :: CharParser st String+identifier = lexeme (P.identifier lexer)++operator :: CharParser st String+operator = lexeme $ liftM (:[]) (opLetter texMathDef)+ <|> many1 (char '\'')++decimal :: CharParser st Integer+decimal = lexeme (P.decimal lexer)++float :: CharParser st Double+float = lexeme (P.float lexer)++symbol :: String -> CharParser st String+symbol = lexeme . P.symbol lexer++braces :: CharParser st a -> CharParser st a +braces = lexeme . P.braces lexer++brackets :: CharParser st a -> CharParser st a+brackets = lexeme . P.brackets lexer++binaryOps :: [String]+binaryOps = ["\\frac", "\\tfrac", "\\dfrac", "\\stackrel", "\\overset", "\\underset"]++scalers :: M.Map String String+scalers = M.fromList+ [ ("\\bigg", "2.2")+ , ("\\Bigg", "2.9")+ , ("\\big", "1.2")+ , ("\\Big", "1.6")+ ]++enclosures :: [(String, Exp)]+enclosures = [ ("(", ESymbol Open "(")+ , (")", ESymbol Close ")")+ , ("[", ESymbol Open "[")+ , ("]", ESymbol Close "]")+ , ("\\{", ESymbol Open "{")+ , ("\\}", ESymbol Close "}")+ , ("\\lbrack", ESymbol Open "[")+ , ("\\lbrace", ESymbol Open "{")+ , ("\\rbrack", ESymbol Close "]")+ , ("\\rbrace", ESymbol Close "}")+ , ("\\langle", ESymbol Open "\x3009")+ , ("\\rangle", ESymbol Close "\x300A")+ , ("\\lfloor", ESymbol Open "\x230A")+ , ("\\rfloor", ESymbol Close "\x230B")+ , ("\\lceil", ESymbol Open "\x2308")+ , ("\\rceil", ESymbol Close "\x2309")+ , ("|", ESymbol Open "\x2223")+ , ("|", ESymbol Close "\x2223")+ , ("\\|", ESymbol Open "\x2225")+ , ("\\|", ESymbol Close "\x2225")+ , ("\\vert", ESymbol Open "\x2223")+ , ("\\vert", ESymbol Close "\x2223")+ , ("\\Vert", ESymbol Open "\x2225")+ , ("\\Vert", ESymbol Close "\x2225")+ ]++symbols :: M.Map String Exp+symbols = M.fromList [+ ("+", ESymbol Bin "+")+ , ("-", ESymbol Bin "-")+ , (",", ESymbol Pun ",")+ , (".", ESymbol Pun ".")+ , (";", ESymbol Pun ";")+ , (":", ESymbol Pun ":")+ , ("?", ESymbol Pun "?")+ , (">", ESymbol Rel ">")+ , ("<", ESymbol Rel "<")+ , ("!", ESymbol Ord "!")+ , ("'", ESymbol Ord "\x02B9")+ , ("''", ESymbol Ord "\x02BA")+ , ("'''", ESymbol Ord "\x2034")+ , ("''''", ESymbol Ord "\x2057")+ , ("=", ESymbol Rel "=")+ , (":=", ESymbol Rel ":=")+ , ("\\mid", ESymbol Bin "\x2223")+ , ("\\parallel", ESymbol Rel "\x2225")+ , ("\\backslash", ESymbol Bin "\x2216")+ , ("/", ESymbol Bin "/")+ , ("\\setminus", ESymbol Bin "\\")+ , ("\\times", ESymbol Bin "\x00D7")+ , ("\\alpha", ESymbol Ord "\x03B1")+ , ("\\beta", ESymbol Ord "\x03B2")+ , ("\\chi", ESymbol Ord "\x03C7")+ , ("\\delta", ESymbol Ord "\x03B4")+ , ("\\Delta", ESymbol Op "\x0394")+ , ("\\epsi", ESymbol Ord "\x03B5")+ , ("\\varepsilon", ESymbol Ord "\x025B")+ , ("\\eta", ESymbol Ord "\x03B7")+ , ("\\gamma", ESymbol Ord "\x03B3")+ , ("\\Gamma", ESymbol Op "\x0393") + , ("\\iota", ESymbol Ord "\x03B9")+ , ("\\kappa", ESymbol Ord "\x03BA")+ , ("\\lambda", ESymbol Ord "\x03BB")+ , ("\\Lambda", ESymbol Op "\x039B") + , ("\\mu", ESymbol Ord "\x03BC")+ , ("\\nu", ESymbol Ord "\x03BD")+ , ("\\omega", ESymbol Ord "\x03C9")+ , ("\\Omega", ESymbol Op "\x03A9")+ , ("\\phi", ESymbol Ord "\x03C6")+ , ("\\varphi", ESymbol Ord "\x03D5")+ , ("\\Phi", ESymbol Op "\x03A6") + , ("\\pi", ESymbol Ord "\x03C0")+ , ("\\Pi", ESymbol Op "\x03A0") + , ("\\psi", ESymbol Ord "\x03C8")+ , ("\\Psi", ESymbol Ord "\x03A8")+ , ("\\rho", ESymbol Ord "\x03C1")+ , ("\\sigma", ESymbol Ord "\x03C3")+ , ("\\Sigma", ESymbol Op "\x03A3") + , ("\\tau", ESymbol Ord "\x03C4")+ , ("\\theta", ESymbol Ord "\x03B8")+ , ("\\vartheta", ESymbol Ord "\x03D1")+ , ("\\Theta", ESymbol Op "\x0398") + , ("\\upsilon", ESymbol Ord "\x03C5")+ , ("\\xi", ESymbol Ord "\x03BE")+ , ("\\Xi", ESymbol Op "\x039E") + , ("\\zeta", ESymbol Ord "\x03B6")+ , ("\\frac12", ESymbol Ord "\x00BD")+ , ("\\frac14", ESymbol Ord "\x00BC")+ , ("\\frac34", ESymbol Ord "\x00BE")+ , ("\\frac13", ESymbol Ord "\x2153")+ , ("\\frac23", ESymbol Ord "\x2154")+ , ("\\frac15", ESymbol Ord "\x2155")+ , ("\\frac25", ESymbol Ord "\x2156")+ , ("\\frac35", ESymbol Ord "\x2157")+ , ("\\frac45", ESymbol Ord "\x2158")+ , ("\\frac16", ESymbol Ord "\x2159")+ , ("\\frac56", ESymbol Ord "\x215A")+ , ("\\frac18", ESymbol Ord "\x215B")+ , ("\\frac38", ESymbol Ord "\x215C")+ , ("\\frac58", ESymbol Ord "\x215D")+ , ("\\frac78", ESymbol Ord "\x215E")+ , ("\\pm", ESymbol Bin "\x00B1")+ , ("\\mp", ESymbol Bin "\x2213")+ , ("\\triangleleft", ESymbol Bin "\x22B2")+ , ("\\triangleright", ESymbol Bin "\x22B3")+ , ("\\cdot", ESymbol Bin "\x22C5")+ , ("\\star", ESymbol Bin "\x22C6")+ , ("\\ast", ESymbol Bin "\x002A")+ , ("\\times", ESymbol Bin "\x00D7")+ , ("\\div", ESymbol Bin "\x00F7")+ , ("\\circ", ESymbol Bin "\x2218")+ , ("\\bullet", ESymbol Bin "\x2022")+ , ("\\oplus", ESymbol Bin "\x2295")+ , ("\\ominus", ESymbol Bin "\x2296")+ , ("\\otimes", ESymbol Bin "\x2297")+ , ("\\bigcirc", ESymbol Bin "\x25CB")+ , ("\\oslash", ESymbol Bin "\x2298")+ , ("\\odot", ESymbol Bin "\x2299")+ , ("\\land", ESymbol Bin "\x2227")+ , ("\\wedge", ESymbol Bin "\x2227")+ , ("\\lor", ESymbol Bin "\x2228")+ , ("\\vee", ESymbol Bin "\x2228")+ , ("\\cap", ESymbol Bin "\x2229")+ , ("\\cup", ESymbol Bin "\x222A")+ , ("\\sqcap", ESymbol Bin "\x2293")+ , ("\\sqcup", ESymbol Bin "\x2294")+ , ("\\uplus", ESymbol Bin "\x228E")+ , ("\\amalg", ESymbol Bin "\x2210")+ , ("\\bigtriangleup", ESymbol Bin "\x25B3")+ , ("\\bigtriangledown", ESymbol Bin "\x25BD")+ , ("\\dag", ESymbol Bin "\x2020")+ , ("\\dagger", ESymbol Bin "\x2020")+ , ("\\ddag", ESymbol Bin "\x2021")+ , ("\\ddagger", ESymbol Bin "\x2021")+ , ("\\lhd", ESymbol Bin "\x22B2")+ , ("\\rhd", ESymbol Bin "\x22B3")+ , ("\\unlhd", ESymbol Bin "\x22B4")+ , ("\\unrhd", ESymbol Bin "\x22B5")+ , ("\\lt", ESymbol Rel "<")+ , ("\\gt", ESymbol Rel ">")+ , ("\\ne", ESymbol Rel "\x2260")+ , ("\\neq", ESymbol Rel "\x2260")+ , ("\\le", ESymbol Rel "\x2264")+ , ("\\leq", ESymbol Rel "\x2264")+ , ("\\leqslant", ESymbol Rel "\x2264")+ , ("\\ge", ESymbol Rel "\x2265")+ , ("\\geq", ESymbol Rel "\x2265")+ , ("\\geqslant", ESymbol Rel "\x2265")+ , ("\\equiv", ESymbol Rel "\x2261")+ , ("\\ll", ESymbol Rel "\x226A")+ , ("\\gg", ESymbol Rel "\x226B")+ , ("\\doteq", ESymbol Rel "\x2250")+ , ("\\prec", ESymbol Rel "\x227A")+ , ("\\succ", ESymbol Rel "\x227B")+ , ("\\preceq", ESymbol Rel "\x227C")+ , ("\\succeq", ESymbol Rel "\x227D")+ , ("\\subset", ESymbol Rel "\x2282")+ , ("\\supset", ESymbol Rel "\x2283")+ , ("\\subseteq", ESymbol Rel "\x2286")+ , ("\\supseteq", ESymbol Rel "\x2287")+ , ("\\sqsubset", ESymbol Rel "\x228F")+ , ("\\sqsupset", ESymbol Rel "\x2290")+ , ("\\sqsubseteq", ESymbol Rel "\x2291")+ , ("\\sqsupseteq", ESymbol Rel "\x2292")+ , ("\\sim", ESymbol Rel "\x223C")+ , ("\\simeq", ESymbol Rel "\x2243")+ , ("\\approx", ESymbol Rel "\x2248")+ , ("\\cong", ESymbol Rel "\x2245")+ , ("\\Join", ESymbol Rel "\x22C8")+ , ("\\bowtie", ESymbol Rel "\x22C8")+ , ("\\in", ESymbol Rel "\x2208")+ , ("\\ni", ESymbol Rel "\x220B")+ , ("\\owns", ESymbol Rel "\x220B")+ , ("\\propto", ESymbol Rel "\x221D")+ , ("\\vdash", ESymbol Rel "\x22A2")+ , ("\\dashv", ESymbol Rel "\x22A3")+ , ("\\models", ESymbol Rel "\x22A8")+ , ("\\perp", ESymbol Rel "\x22A5")+ , ("\\smile", ESymbol Rel "\x2323")+ , ("\\frown", ESymbol Rel "\x2322")+ , ("\\asymp", ESymbol Rel "\x224D")+ , ("\\notin", ESymbol Rel "\x2209")+ , ("\\gets", ESymbol Rel "\x2190")+ , ("\\leftarrow", ESymbol Rel "\x2190")+ , ("\\to", ESymbol Rel "\x2192")+ , ("\\rightarrow", ESymbol Rel "\x2192")+ , ("\\leftrightarrow", ESymbol Rel "\x2194")+ , ("\\uparrow", ESymbol Rel "\x2191")+ , ("\\downarrow", ESymbol Rel "\x2193")+ , ("\\updownarrow", ESymbol Rel "\x2195")+ , ("\\Leftarrow", ESymbol Rel "\x21D0")+ , ("\\Rightarrow", ESymbol Rel "\x21D2")+ , ("\\Leftrightarrow", ESymbol Rel "\x21D4")+ , ("\\iff", ESymbol Rel "\x21D4")+ , ("\\Uparrow", ESymbol Rel "\x21D1")+ , ("\\Downarrow", ESymbol Rel "\x21D3")+ , ("\\Updownarrow", ESymbol Rel "\x21D5")+ , ("\\mapsto", ESymbol Rel "\x21A6")+ , ("\\longleftarrow", ESymbol Rel "\x2190")+ , ("\\longrightarrow", ESymbol Rel "\x2192")+ , ("\\longleftrightarrow", ESymbol Rel "\x2194")+ , ("\\Longleftarrow", ESymbol Rel "\x21D0")+ , ("\\Longrightarrow", ESymbol Rel "\x21D2")+ , ("\\Longleftrightarrow", ESymbol Rel "\x21D4")+ , ("\\longmapsto", ESymbol Rel "\x21A6")+ , ("\\sum", ESymbol Op "\x2211")+ , ("\\prod", ESymbol Op "\x220F")+ , ("\\bigcap", ESymbol Op "\x22C2")+ , ("\\bigcup", ESymbol Op "\x22C3")+ , ("\\bigwedge", ESymbol Op "\x22C0")+ , ("\\bigvee", ESymbol Op "\x22C1")+ , ("\\bigsqcap", ESymbol Op "\x2A05")+ , ("\\bigsqcup", ESymbol Op "\x2A06")+ , ("\\coprod", ESymbol Op "\x2210")+ , ("\\bigoplus", ESymbol Op "\x2A01")+ , ("\\bigotimes", ESymbol Op "\x2A02")+ , ("\\bigodot", ESymbol Op "\x2A00")+ , ("\\biguplus", ESymbol Op "\x2A04")+ , ("\\int", ESymbol Op "\x222B")+ , ("\\oint", ESymbol Op "\x222E")+ , ("\\prime", ESymbol Ord "\x2032")+ , ("\\dots", ESymbol Ord "\x2026")+ , ("\\ldots", ESymbol Ord "\x2026")+ , ("\\cdots", ESymbol Ord "\x22EF")+ , ("\\vdots", ESymbol Ord "\x22EE")+ , ("\\ddots", ESymbol Ord "\x22F1")+ , ("\\forall", ESymbol Op "\x2200")+ , ("\\exists", ESymbol Op "\x2203")+ , ("\\Re", ESymbol Ord "\x211C")+ , ("\\Im", ESymbol Ord "\x2111")+ , ("\\aleph", ESymbol Ord "\x2135")+ , ("\\hbar", ESymbol Ord "\x210F")+ , ("\\ell", ESymbol Ord "\x2113")+ , ("\\wp", ESymbol Ord "\x2118")+ , ("\\emptyset", ESymbol Ord "\x2205")+ , ("\\infty", ESymbol Ord "\x221E")+ , ("\\partial", ESymbol Ord "\x2202")+ , ("\\nabla", ESymbol Ord "\x2207")+ , ("\\triangle", ESymbol Ord "\x25B3")+ , ("\\therefore", ESymbol Pun "\x2234")+ , ("\\angle", ESymbol Ord "\x2220")+ , ("\\diamond", ESymbol Op "\x22C4")+ , ("\\Diamond", ESymbol Op "\x25C7")+ , ("\\neg", ESymbol Op "\x00AC")+ , ("\\lnot", ESymbol Ord "\x00AC")+ , ("\\bot", ESymbol Ord "\x22A5")+ , ("\\top", ESymbol Ord "\x22A4")+ , ("\\square", ESymbol Ord "\x25AB")+ , ("\\Box", ESymbol Op "\x25A1")+ , ("\\wr", ESymbol Ord "\x2240")+ , ("\\!", ESpace "-0.167em")+ , ("\\,", ESpace "0.167em")+ , ("\\>", ESpace "0.222em")+ , ("\\:", ESpace "0.222em")+ , ("\\;", ESpace "0.278em")+ , ("~", ESpace "0.333em")+ , ("\\quad", ESpace "1em")+ , ("\\qquad", ESpace "2em")+ , ("\\arccos", EIdentifier "arccos")+ , ("\\arcsin", EIdentifier "arcsin")+ , ("\\arctan", EIdentifier "arctan")+ , ("\\arg", EIdentifier "arg")+ , ("\\cos", EIdentifier "cos")+ , ("\\cosh", EIdentifier "cosh")+ , ("\\cot", EIdentifier "cot")+ , ("\\coth", EIdentifier "coth")+ , ("\\csc", EIdentifier "csc")+ , ("\\deg", EIdentifier "deg")+ , ("\\det", EIdentifier "det")+ , ("\\dim", EIdentifier "dim")+ , ("\\exp", EIdentifier "exp")+ , ("\\gcd", EIdentifier "gcd")+ , ("\\hom", EIdentifier "hom")+ , ("\\inf", EIdentifier "inf")+ , ("\\ker", EIdentifier "ker")+ , ("\\lg", EIdentifier "lg")+ , ("\\lim", EIdentifier "lim")+ , ("\\liminf", EIdentifier "liminf")+ , ("\\limsup", EIdentifier "limsup")+ , ("\\ln", EIdentifier "ln")+ , ("\\log", EIdentifier "log")+ , ("\\max", EIdentifier "max")+ , ("\\min", EIdentifier "min")+ , ("\\Pr", EIdentifier "Pr")+ , ("\\sec", EIdentifier "sec")+ , ("\\sin", EIdentifier "sin")+ , ("\\sinh", EIdentifier "sinh")+ , ("\\sup", EIdentifier "sup")+ , ("\\tan", EIdentifier "tan")+ , ("\\tanh", EIdentifier "tanh")+ ] +
+ cgi/texmath-cgi.hs view
@@ -0,0 +1,20 @@+module Main where+import Network.CGI+import Text.XML.Light+import Text.TeXMath+import Data.Maybe (fromMaybe)+import Control.Monad+import Text.JSON++cgiMain :: CGI CGIResult+cgiMain = do+ latexFormula <- liftM (fromMaybe "") $ getInput "latexFormula"+ setHeader "Content-type" "text/xhtml; charset=UTF-8"+ output . encodeStrict $+ case texMathToMathML DisplayBlock latexFormula of+ Left e -> toJSObject [("success", JSBool False), ("error", JSString $ toJSString e)]+ Right v -> toJSObject [("success", JSBool True), ("mathml", JSString $ toJSString $ ppElement v)]++main :: IO ()+main = runCGI $ handleErrors cgiMain+
+ cgi/texmath.xhtml view
@@ -0,0 +1,50 @@+<?xml version='1.0' ?>+<html xmlns="http://www.w3.org/1999/xhtml">+ <head>+ <meta content="application/xhtml+xml; charset=UTF-8" http-equiv="Content-Type" />+ <style type="text/css">+ <![CDATA[+ div#result { width : 31em; }+ div#result math { font-size: medium; border: 1px solid red; padding: 1em; margin: 1em; }+ pre#xml { font-size: small; color: blue; }+ ]]>+ </style>+ <script type="text/javascript" src="/scripts/jquery.js"></script>+ <script type="text/javascript">+ <![CDATA[+ $(document).ready(function(){+ $('#convert').click(function() {+ $.getJSON("/cgi-bin/texmath-cgi", { 'latexFormula' : $('#latexFormula').val() },+ function(result){+ if (result.success) {+ if ($.browser.mozilla) {+ $('#result').html(result.mathml);+ } else {+ $('#result').html('<p>Use Firefox to see the rendered MathML</p>');+ };+ $('#xml').text(result.mathml); + } else {+ $('#result').html('');+ $('#xml').text(result.error);+ };+ })+ });+ });+ ]]>+ </script>+ </head>+ <body>+ <h1>LaTeX to MathML converter</h1>+ <label for="latexFormula">Enter a LaTeX formula here:</label><br/>+ <textarea name="latexFormula" rows="10" cols="60" id="latexFormula">\phi_n(\kappa) =+ \frac{1}{4\pi^2\kappa^2} \int_0^\infty+ \frac{\sin(\kappa R)}{\kappa R}+ \frac{\partial}{\partial R}+ \left[R^2\frac{\partial D_n(R)}{\partial R}\right]\,dR+ </textarea><br/>+ <input type="submit" id="convert" value="Convert" /> using+ <a href="http://github.com/jgm/texmath/tree/master">texmath</a>+ <div id="result"></div>+ <pre id="xml"></pre>+ </body>+</html>
+ examples view
@@ -0,0 +1,48 @@+x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}++2 = \left(+ \frac{\left(3-x\right) \times 2}{3-x}+ \right)++ax^2 + bx + c = 0++S_{\text{new}} = S_{\text{old}} - \frac{ \left( 5-T \right) ^2} {2}++\int_a^x \!\!\!\int_a^s f(y)\,dy\,ds+ = \int_a^x f(y)(x-y)\,dy++\sum_{m=1}^\infty\sum_{n=1}^\infty\frac{m^2\,n}+ {3^m\left(m\,3^n+n\,3^m\right)}++u'' + p(x)u' + q(x)u=f(x),\quad x>a++|\bar{z}| = |z|,+ |(\bar{z})^n| = |z|^n,+ \arg(z^n) = n \arg(z)++\lim_{z\rightarrow z_0} f(z)=f(z_0)++\phi_n(\kappa) =+ \frac{1}{4\pi^2\kappa^2} \int_0^\infty+ \frac{\sin(\kappa R)}{\kappa R}+ \frac{\partial}{\partial R}+ \left[R^2\frac{\partial D_n(R)}{\partial R}\right]\,dR++\phi_n(\kappa) = + 0.033C_n^2\kappa^{-11/3},\quad+ \frac{1}{L_0}\ll\kappa\ll\frac{1}{l_0}++f(x) =+ \begin{cases}+ 1 & -1 \le x < 0 \\+ \frac{1}{2} & x = 0 \\+ 1 - x^2 & \mbox{otherwise}+ \end{cases}++{}_pF_q(a_1,\dots,a_p;c_1,\dots,c_q;z)+ = \sum_{n=0}^\infty+ \frac{(a_1)_n\cdots(a_p)_n}{(c_1)_n\cdots(c_q)_n}+ \frac{z^n}{n!}++ \frac {a}{b}\ \tfrac {a}{b}+
+ testTeXMathML.hs view
@@ -0,0 +1,21 @@+module Main where++import Text.TeXMath+import Text.XML.Light++inHtml :: Element -> Element+inHtml x =+ add_attr (Attr (unqual "xmlns") "http://www.w3.org/1999/xhtml") $+ unode "html"+ [ unode "head" $+ add_attr (Attr (unqual "content") "application/xhtml+xml; charset=UTF-8") $+ add_attr (Attr (unqual "http-equiv") "Content-Type") $+ unode "meta" ()+ , unode "body" x ]++main :: IO ()+main = do+ inp <- getContents+ case (texMathToMathML DisplayBlock $! inp) of+ Left err -> putStrLn err+ Right v -> putStr . ppTopElement . inHtml $ v
+ texmath.cabal view
@@ -0,0 +1,51 @@+Name: texmath+Version: 0.1+Cabal-version: >= 1.2+Build-type: Simple+Synopsis: Conversion of LaTeX math formulas to MathML.+Description: The texmathml library provides functions to convert LaTeX+ math formulas to presentation MathML. It supports+ basic LaTeX and AMS extensions, but not macros.+Category: Text+Stability: Experimental+License: GPL+License-File: LICENSE+Author: John MacFarlane+Maintainer: jgm@berkeley.edu+Homepage: http://github.com/jgm/texmath+Data-Files: cgi/texmath.xhtml, examples++Flag cgi+ description: Compile cgi executable.+ default: True++Flag test+ description: Compile test executable.+ default: True++Library+ Build-depends: base >= 4 && < 5, xml, parsec >= 2 && < 3, containers++ Exposed-modules: Text.TeXMath, Text.TeXMath.Parser, Text.TeXMath.MathMLWriter++ Ghc-Options: -Wall+ Ghc-Prof-Options: -auto-all++Executable testTeXMathML+ Main-is: testTeXMathML.hs+ Ghc-Options: -Wall+ Ghc-Prof-Options: -auto-all+ if flag(test)+ Buildable: True+ else+ Buildable: False++Executable texmath-cgi+ Main-is: cgi/texmath-cgi.hs+ Build-depends: cgi, json+ Ghc-Options: -Wall+ Ghc-Prof-Options: -auto-all+ if flag(cgi)+ Buildable: True+ else+ Buildable: False