git.iko.soy/typeable/pandoc
on master help sign in
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.

commit6f19be7d40f583ee4e10fa2b0f20bd4f1fa80c43 authorAlbert Krewinkel <tarleb@moltkeplatz.de> dateFri 11 Apr 2014, 11:05 (13 years ago) parentca40ace
2 files changed+67−19
src/Text/Pandoc/Readers/Org.hs+37−10 tests/Tests/Readers/Org.hs+30−9
src/Text/Pandoc/Readers/Org.hs+37−10
@@ -622,17 +622,11 @@ displayMath = B.displayMath <$> choice [ rawMathBetween "\\[" "\\]"
622622 , rawMathBetween "$$" "$$"
623623 ]
624624
625−subscript :: OrgParser Inlines
626−subscript = B.subscript <$> try (char '_' *> maybeGroupedByBraces)
625+subscript :: OrgParser Inlines
626+subscript = B.subscript <$> try (char '_' *> subOrSuperExpr)
627627
628−superscript :: OrgParser Inlines
629−superscript = B.superscript <$> try (char '^' *> maybeGroupedByBraces)
630−
631−maybeGroupedByBraces :: OrgParser Inlines
632−maybeGroupedByBraces = try $
633− choice [ try $ enclosedInlines (char '{') (char '}')
634− , B.str . (:"") <$> anyChar
635− ]
628+superscript :: OrgParser Inlines
629+superscript = B.superscript <$> try (char '^' *> subOrSuperExpr)
636630
637631symbol :: OrgParser Inlines
638632symbol = B.str . (: "") <$> (oneOf specialChars >>= updatePositions)
@@ -805,3 +799,36 @@ notAfterForbiddenBorderChar = do
805799 pos <- getPosition
806800 lastFBCPos <- orgStateLastForbiddenCharPos <$> getState
807801 return $ lastFBCPos /= Just pos
802+
803+-- | Read a sub- or superscript expression
804+subOrSuperExpr :: OrgParser Inlines
805+subOrSuperExpr = try $ do
806+ choice [ balancedSexp '{' '}'
807+ , balancedSexp '(' ')' >>= return . enclosing ('(', ')')
808+ , simpleSubOrSuperString
809+ ] >>= parseFromString (mconcat <$> many inline)
810+
811+-- | Read a balanced sexp
812+balancedSexp :: Char
813+ -> Char
814+ -> OrgParser String
815+balancedSexp l r = try $ do
816+ char l
817+ res <- concat <$> many ( many1 (noneOf ([l, r] ++ "\n\r"))
818+ <|> try (string [l, r])
819+ <|> enclosing (l, r) <$> balancedSexp l r
820+ )
821+ char r
822+ return res
823+
824+simpleSubOrSuperString :: OrgParser String
825+simpleSubOrSuperString = try $
826+ choice [ string "*"
827+ , mappend <$> option [] ((:[]) <$> oneOf "+-")
828+ <*> many1 alphaNum
829+ ]
830+
831+enclosing :: (a, a)
832+ -> [a]
833+ -> [a]
834+enclosing (left, right) s = left : s ++ [right]
tests/Tests/Readers/Org.hs+30−9
@@ -78,15 +78,15 @@ tests =
7878 "A * symbol" =?>
7979 para (str "A" <> space <> str "*" <> space <> "symbol")
8080
81− , "Superscript single char" =:
82− "2^n" =?>
83− para (str "2" <> superscript "n")
81+ , "Superscript simple expression" =:
82+ "2^-λ" =?>
83+ para (str "2" <> superscript "-λ")
8484
8585 , "Superscript multi char" =:
8686 "2^{n-1}" =?>
8787 para (str "2" <> superscript "n-1")
8888
89− , "Subscript single char" =:
89+ , "Subscript simple expression" =:
9090 "a_n" =?>
9191 para (str "a" <> subscript "n")
9292
@@ -105,11 +105,8 @@ tests =
105105 ])
106106
107107 , "No empty markup" =:
108− -- FIXME: __ is erroneously parsed as subscript "_"
109− -- "// ** __ ++ == ~~ $$" =?>
110− -- para (spcSep [ "//", "**", "__", "++", "==", "~~", "$$" ])
111− "// ** ++ == ~~ $$" =?>
112− para (spcSep [ "//", "**", "++", "==", "~~", "$$" ])
108+ "// ** __ ++ == ~~ $$" =?>
109+ para (spcSep [ "//", "**", "__", "++", "==", "~~", "$$" ])
113110
114111 , "Adherence to Org's rules for markup borders" =:
115112 "/t/& a/ / ./r/ (*l*) /e/! /b/." =?>
@@ -143,6 +140,30 @@ tests =
143140 ]))
144141 , "emph/" ])
145142
143+ , "Sub- and superscript expressions" =:
144+ unlines [ "a_(a(b)(c)d)"
145+ , "e^(f(g)h)"
146+ , "i_(jk)l)"
147+ , "m^()n"
148+ , "o_{p{q{}r}}"
149+ , "s^{t{u}v}"
150+ , "w_{xy}z}"
151+ , "1^{}2"
152+ , "3_{{}}"
153+ , "4^(a(*b(c*)d))"
154+ ] =?>
155+ para (spcSep [ "a" <> subscript "(a(b)(c)d)"
156+ , "e" <> superscript "(f(g)h)"
157+ , "i" <> (subscript "(jk)") <> "l)"
158+ , "m" <> (superscript "()") <> "n"
159+ , "o" <> subscript "p{q{}r}"
160+ , "s" <> superscript "t{u}v"
161+ , "w" <> (subscript "xy") <> "z}"
162+ , "1" <> (superscript "") <> "2"
163+ , "3" <> subscript "{}"
164+ , "4" <> superscript ("(a(" <> strong "b(c" <> ")d))")
165+ ])
166+
146167 , "Image" =:
147168 "[[./sunset.jpg]]" =?>
148169 (para $ image "./sunset.jpg" "" "")