Org reader: Fix parsing of sub-/superscript expressions

This fixes the org-reader's handling of sub- and superscript
expressions.  Simple expressions (like `2^+10`), expressions in
parentheses (`a_(n+1)`) and nested sexp (like `a_(nested()parens)`) are
now read correctly.
This commit is contained in:
Albert Krewinkel
2014-04-11 11:05:42 +02:00
parent ca40acea5b
commit 6f19be7d40
2 changed files with 67 additions and 19 deletions
+37 -10
View File
@@ -622,17 +622,11 @@ displayMath = B.displayMath <$> choice [ rawMathBetween "\\[" "\\]"
, rawMathBetween "$$" "$$"
]
subscript :: OrgParser Inlines
subscript = B.subscript <$> try (char '_' *> maybeGroupedByBraces)
subscript :: OrgParser Inlines
subscript = B.subscript <$> try (char '_' *> subOrSuperExpr)
superscript :: OrgParser Inlines
superscript = B.superscript <$> try (char '^' *> maybeGroupedByBraces)
maybeGroupedByBraces :: OrgParser Inlines
maybeGroupedByBraces = try $
choice [ try $ enclosedInlines (char '{') (char '}')
, B.str . (:"") <$> anyChar
]
superscript :: OrgParser Inlines
superscript = B.superscript <$> try (char '^' *> subOrSuperExpr)
symbol :: OrgParser Inlines
symbol = B.str . (: "") <$> (oneOf specialChars >>= updatePositions)
@@ -805,3 +799,36 @@ notAfterForbiddenBorderChar = do
pos <- getPosition
lastFBCPos <- orgStateLastForbiddenCharPos <$> getState
return $ lastFBCPos /= Just pos
-- | Read a sub- or superscript expression
subOrSuperExpr :: OrgParser Inlines
subOrSuperExpr = try $ do
choice [ balancedSexp '{' '}'
, balancedSexp '(' ')' >>= return . enclosing ('(', ')')
, simpleSubOrSuperString
] >>= parseFromString (mconcat <$> many inline)
-- | Read a balanced sexp
balancedSexp :: Char
-> Char
-> OrgParser String
balancedSexp l r = try $ do
char l
res <- concat <$> many ( many1 (noneOf ([l, r] ++ "\n\r"))
<|> try (string [l, r])
<|> enclosing (l, r) <$> balancedSexp l r
)
char r
return res
simpleSubOrSuperString :: OrgParser String
simpleSubOrSuperString = try $
choice [ string "*"
, mappend <$> option [] ((:[]) <$> oneOf "+-")
<*> many1 alphaNum
]
enclosing :: (a, a)
-> [a]
-> [a]
enclosing (left, right) s = left : s ++ [right]
+30 -9
View File
@@ -78,15 +78,15 @@ tests =
"A * symbol" =?>
para (str "A" <> space <> str "*" <> space <> "symbol")
, "Superscript single char" =:
"2^n" =?>
para (str "2" <> superscript "n")
, "Superscript simple expression" =:
"2^-λ" =?>
para (str "2" <> superscript "-λ")
, "Superscript multi char" =:
"2^{n-1}" =?>
para (str "2" <> superscript "n-1")
, "Subscript single char" =:
, "Subscript simple expression" =:
"a_n" =?>
para (str "a" <> subscript "n")
@@ -105,11 +105,8 @@ tests =
])
, "No empty markup" =:
-- FIXME: __ is erroneously parsed as subscript "_"
-- "// ** __ ++ == ~~ $$" =?>
-- para (spcSep [ "//", "**", "__", "++", "==", "~~", "$$" ])
"// ** ++ == ~~ $$" =?>
para (spcSep [ "//", "**", "++", "==", "~~", "$$" ])
"// ** __ ++ == ~~ $$" =?>
para (spcSep [ "//", "**", "__", "++", "==", "~~", "$$" ])
, "Adherence to Org's rules for markup borders" =:
"/t/& a/ / ./r/ (*l*) /e/! /b/." =?>
@@ -143,6 +140,30 @@ tests =
]))
, "emph/" ])
, "Sub- and superscript expressions" =:
unlines [ "a_(a(b)(c)d)"
, "e^(f(g)h)"
, "i_(jk)l)"
, "m^()n"
, "o_{p{q{}r}}"
, "s^{t{u}v}"
, "w_{xy}z}"
, "1^{}2"
, "3_{{}}"
, "4^(a(*b(c*)d))"
] =?>
para (spcSep [ "a" <> subscript "(a(b)(c)d)"
, "e" <> superscript "(f(g)h)"
, "i" <> (subscript "(jk)") <> "l)"
, "m" <> (superscript "()") <> "n"
, "o" <> subscript "p{q{}r}"
, "s" <> superscript "t{u}v"
, "w" <> (subscript "xy") <> "z}"
, "1" <> (superscript "") <> "2"
, "3" <> subscript "{}"
, "4" <> superscript ("(a(" <> strong "b(c" <> ")d))")
])
, "Image" =:
"[[./sunset.jpg]]" =?>
(para $ image "./sunset.jpg" "" "")