diff --git a/Text/TeXMath/MathMLWriter.hs b/Text/TeXMath/MathMLWriter.hs
--- a/Text/TeXMath/MathMLWriter.hs
+++ b/Text/TeXMath/MathMLWriter.hs
@@ -25,6 +25,7 @@
 import qualified Data.Map as M
 import Text.XML.Light
 import Text.TeXMath.Parser
+import Data.Generics (everywhere, mkT)
 
 data DisplayType = DisplayBlock
                  | DisplayInline
@@ -32,7 +33,7 @@
 
 toMathML :: DisplayType -> [Exp] -> Element
 toMathML dt exprs =
-  add_attr dtattr $ math $ map (showExp . expandMathOp dt) exprs
+  add_attr dtattr $ math $ map showExp $ everywhere (mkT $ handleDownup dt) exprs
     where dtattr = Attr (unqual "display") dt'
           dt' =  case dt of
                       DisplayBlock  -> "block"
@@ -135,13 +136,14 @@
 accent = add_attr (Attr (unqual "accent") "true") .
            unode "mo"
 
-expandMathOp :: DisplayType -> Exp -> Exp
-expandMathOp DisplayInline (EMathOperator x)               = EIdentifier x
-expandMathOp DisplayInline x                               = x
-expandMathOp DisplayBlock  (ESub (EMathOperator x) y)      = EUnder (EIdentifier x) y
-expandMathOp DisplayBlock  (ESubsup (EMathOperator x) y z) = EUnder (ESuper (EIdentifier x) z) y
-expandMathOp DisplayBlock  (EMathOperator x)               = EIdentifier x
-expandMathOp DisplayBlock  x                               = x
+handleDownup :: DisplayType -> Exp -> Exp
+handleDownup DisplayInline (EDown x y)     = ESub x y
+handleDownup DisplayBlock  (EDown x y)     = EUnder x y
+handleDownup DisplayInline (EUp x y)       = ESuper x y
+handleDownup DisplayBlock  (EUp x y)       = EOver x y
+handleDownup DisplayInline (EDownup x y z) = ESubsup x y z
+handleDownup DisplayBlock  (EDownup x y z) = EUnderover x y z
+handleDownup _             x               = x
 
 showExp :: Exp -> Element
 showExp e =
@@ -150,7 +152,7 @@
    EGrouped [x]     -> showExp x
    EGrouped xs      -> mrow $ map showExp xs
    EIdentifier x    -> unode "mi" x
-   EMathOperator x  -> unode "mi" x --in case expandMathOp is not used
+   EMathOperator x  -> unode "mi" x
    ESymbol Accent x -> accent x
    EStretchy (ESymbol Open x)  -> makeStretchy $ unode "mo" x
    EStretchy (ESymbol Close x) -> makeStretchy $ unode "mo" x
@@ -170,4 +172,6 @@
    EScaled s x      -> makeScaled s $ showExp x
    EArray as ls     -> makeArray as ls
    EText a s        -> makeText a s
+   x                -> error $ "showExp encountered " ++ show x
+                       -- note: EUp, EDown, EDownup should be removed by handleDownup
 
diff --git a/Text/TeXMath/Parser.hs b/Text/TeXMath/Parser.hs
--- a/Text/TeXMath/Parser.hs
+++ b/Text/TeXMath/Parser.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE DeriveDataTypeable #-}
 {-
 Copyright (C) 2009 John MacFarlane <jgm@berkeley.edu>
 
@@ -23,17 +24,18 @@
 where
 
 import Control.Monad
-import Data.Char (isAlphaNum, isDigit)
+import Data.Char (isAlphaNum, isDigit, isAscii)
 import qualified Data.Map as M
 import Text.ParserCombinators.Parsec
 import qualified Text.ParserCombinators.Parsec.Token as P
 import Text.ParserCombinators.Parsec.Language
+import Data.Generics
 
 data TeXSymbolType = Ord | Op | Bin | Rel | Open | Close | Pun | Accent
-                     deriving (Show, Read, Eq)
+                     deriving (Show, Read, Eq, Data, Typeable)
 
 data Alignment = AlignLeft | AlignCenter | AlignRight | AlignDefault
-                 deriving (Show, Read, Eq)
+                 deriving (Show, Read, Eq, Data, Typeable)
 
 type ArrayLine = [[Exp]]
 
@@ -51,12 +53,15 @@
   | EOver Exp Exp
   | EUnder Exp Exp
   | EUnderover Exp Exp Exp
+  | EUp Exp Exp
+  | EDown Exp Exp
+  | EDownup Exp Exp Exp
   | EUnary String Exp
   | EScaled String Exp
   | EStretchy Exp
   | EArray [Alignment] [ArrayLine]
   | EText String String
-  deriving (Show, Read, Eq)
+  deriving (Show, Read, Eq, Data, Typeable)
 
 texMathDef :: LanguageDef st
 texMathDef = LanguageDef 
@@ -89,6 +94,7 @@
   , array
   , diacritical
   , escaped
+  , unicode
   ]
 
 formula :: GenParser Char st [Exp]
@@ -101,9 +107,15 @@
 expr :: GenParser Char st Exp
 expr = do
   a <- expr1
-  limits <- option False (try $ symbol "\\limits" >> return True)
+  limits <- limitsIndicator
   subSup limits a <|> superOrSubscripted limits a <|> return a
 
+limitsIndicator :: GenParser Char st (Maybe Bool)
+limitsIndicator =
+   try (symbol "\\limits" >> return (Just True))
+  <|> try (symbol "\\nolimits" >> return (Just False))
+  <|> return Nothing
+
 inbraces :: GenParser Char st Exp
 inbraces = liftM EGrouped (braces $ many $ notFollowedBy (char '}') >> expr)
 
@@ -237,33 +249,53 @@
   spaces
   return $ EIdentifier [v]
 
-subSup :: Bool -> Exp -> GenParser Char st Exp
+isConvertible :: Exp -> Bool
+isConvertible (EMathOperator x) = x `elem` convertibleOps
+  where convertibleOps = ["lim","liminf","limsup","inf","sup"]
+isConvertible (ESymbol Rel _) = True
+isConvertible (ESymbol Bin _) = True
+isConvertible (EUnder _ _)    = True
+isConvertible (EOver _ _)     = True
+isConvertible (EUnderover _ _ _) = True
+isConvertible (ESymbol Op x) = x `elem` convertibleSyms
+  where convertibleSyms = ["\x2211","\x220F","\x22C2",
+           "\x22C3","\x22C0","\x22C1","\x2A05","\x2A06",
+           "\x2210","\x2A01","\x2A02","\x2A00","\x2A04"]
+isConvertible _ = False
+
+subSup :: Maybe Bool -> Exp -> GenParser Char st Exp
 subSup limits a = try $ do
   char '_'
   b <- expr1
   char '^'
   c <- expr
-  return $ if limits
-              then EUnderover a b c
-              else ESubsup a b c 
+  return $ case limits of
+            Just True  -> EUnderover a b c
+            Nothing | isConvertible a -> EDownup a b c
+            _          -> ESubsup a b c
 
-superOrSubscripted :: Bool -> Exp -> GenParser Char st Exp
+superOrSubscripted :: Maybe Bool -> Exp -> GenParser Char st Exp
 superOrSubscripted limits a = try $ do
   c <- oneOf "^_"
   b <- expr
   case c of
-       '^' -> return $ if limits
-                          then EOver a b
-                          else ESuper a b
-       '_' -> return $ if limits
-                          then EUnder a b
-                          else ESub a b
-       _   -> pzero 
+       '^' -> return $ case limits of
+                        Just True  -> EOver a b
+                        Nothing | isConvertible a -> EUp a b
+                        _          -> ESuper a b
+       '_' -> return $ case limits of
+                        Just True  -> EUnder a b
+                        Nothing | isConvertible a -> EDown a b
+                        _          -> ESub a b
+       _   -> pzero
 
 escaped :: GenParser Char st Exp
 escaped = lexeme $ try $ 
           char '\\' >>
           liftM (ESymbol Ord . (:[])) (satisfy $ not . isAlphaNum)
+
+unicode :: GenParser Char st Exp
+unicode = lexeme $ liftM (ESymbol Ord . (:[])) $ satisfy (not . isAscii)
 
 command :: GenParser Char st String
 command = try $ char '\\' >> liftM ('\\':) (identifier <|> lexeme (count 1 anyChar))
diff --git a/tests/06.xhtml b/tests/06.xhtml
--- a/tests/06.xhtml
+++ b/tests/06.xhtml
@@ -6,7 +6,7 @@
   <body>
     <math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
       <mrow>
-        <msubsup>
+        <munderover>
           <mo>&#8721;</mo>
           <mrow>
             <mi>m</mi>
@@ -14,8 +14,8 @@
             <mn>1</mn>
           </mrow>
           <mo>&#8734;</mo>
-        </msubsup>
-        <msubsup>
+        </munderover>
+        <munderover>
           <mo>&#8721;</mo>
           <mrow>
             <mi>n</mi>
@@ -23,7 +23,7 @@
             <mn>1</mn>
           </mrow>
           <mo>&#8734;</mo>
-        </msubsup>
+        </munderover>
         <mfrac>
           <mrow>
             <msup>
diff --git a/tests/13.xhtml b/tests/13.xhtml
--- a/tests/13.xhtml
+++ b/tests/13.xhtml
@@ -42,7 +42,7 @@
         <mi>z</mi>
         <mo stretchy="false">)</mo>
         <mo>=</mo>
-        <msubsup>
+        <munderover>
           <mo>&#8721;</mo>
           <mrow>
             <mi>n</mi>
@@ -50,7 +50,7 @@
             <mn>0</mn>
           </mrow>
           <mo>&#8734;</mo>
-        </msubsup>
+        </munderover>
         <mfrac>
           <mrow>
             <mo stretchy="false">(</mo>
diff --git a/tests/unicode.tex b/tests/unicode.tex
new file mode 100644
--- /dev/null
+++ b/tests/unicode.tex
@@ -0,0 +1,1 @@
+f : X → Y
diff --git a/tests/unicode.xhtml b/tests/unicode.xhtml
new file mode 100644
--- /dev/null
+++ b/tests/unicode.xhtml
@@ -0,0 +1,17 @@
+<?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" />
+  </head>
+  <body>
+    <math display="block" xmlns="http://www.w3.org/1998/Math/MathML">
+      <mrow>
+        <mi>f</mi>
+        <mo>:</mo>
+        <mi>X</mi>
+        <mo>&#8594;</mo>
+        <mi>Y</mi>
+      </mrow>
+    </math>
+  </body>
+</html>
diff --git a/texmath.cabal b/texmath.cabal
--- a/texmath.cabal
+++ b/texmath.cabal
@@ -1,5 +1,5 @@
 Name:                texmath
-Version:             0.2.0.4
+Version:             0.3
 Cabal-version:       >= 1.2
 Build-type:          Custom
 Synopsis:            Conversion of LaTeX math formulas to MathML.
@@ -44,7 +44,8 @@
                      tests/quadratic_formula.tex, tests/quadratic_formula.xhtml,
                      tests/schwinger_dyson.tex, tests/schwinger_dyson.xhtml,
                      tests/sophomores_dream.tex, tests/sophomores_dream.xhtml,
-                     tests/sphere_volume.tex, tests/sphere_volume.xhtml
+                     tests/sphere_volume.tex, tests/sphere_volume.xhtml,
+                     tests/unicode.tex, tests/unicode.xhtml
 
 Flag cgi
   description:       Compile cgi executable.
@@ -55,7 +56,11 @@
   default:           False
 
 Library
-    Build-depends:       xml, parsec >= 2, containers, base >= 3 && < 5
+    Build-depends:       xml, parsec >= 2, containers
+    if impl(ghc >= 6.10)
+      Build-depends: base >= 4 && < 5, syb
+    else
+      Build-depends: base >= 3 && < 4
     Exposed-modules:     Text.TeXMath, Text.TeXMath.Parser, Text.TeXMath.MathMLWriter
 
     Ghc-Options:         -Wall -fno-warn-unused-do-bind
