src/Tools/Haskell/YXML.hs
author wenzelm
Sat, 10 Nov 2018 17:12:09 +0100
changeset 69280 e1d01b351724
parent 69248 9f21381600e3
child 69290 fb77612d11eb
permissions -rw-r--r--
more formal references;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
69227
71b48b749836 tuned message (e.g. see Options.save_prefs);
wenzelm
parents: 69226
diff changeset
     1
{- generated by Isabelle -}
69226
68f5dc2275ac tuned whitespace;
wenzelm
parents: 69225
diff changeset
     2
69225
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
     3
{-  Title:      Tools/Haskell/YXML.hs
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
     4
    Author:     Makarius
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
     5
    LICENSE:    BSD 3-clause (Isabelle)
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
     6
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
     7
Efficient text representation of XML trees.  Suitable for direct
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
     8
inlining into plain text.
69280
e1d01b351724 more formal references;
wenzelm
parents: 69248
diff changeset
     9
e1d01b351724 more formal references;
wenzelm
parents: 69248
diff changeset
    10
See also "$ISABELLE_HOME/src/Pure/PIDE/yxml.ML".
69225
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    11
-}
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    12
69248
9f21381600e3 more Haskell operations;
wenzelm
parents: 69228
diff changeset
    13
module Isabelle.YXML (charX, charY, strX, strY, detect, output_markup,
69225
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    14
  buffer_body, buffer, string_of_body, string_of, parse_body, parse)
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    15
where
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    16
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    17
import qualified Data.Char as Char
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    18
import qualified Data.List as List
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    19
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    20
import Isabelle.Library
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    21
import qualified Isabelle.Markup as Markup
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    22
import qualified Isabelle.XML as XML
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    23
import qualified Isabelle.Buffer as Buffer
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    24
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    25
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    26
{- markers -}
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    27
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    28
charX, charY :: Char
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    29
charX = Char.chr 5
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    30
charY = Char.chr 6
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    31
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    32
strX, strY, strXY, strXYX :: String
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    33
strX = [charX]
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    34
strY = [charY]
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    35
strXY = strX ++ strY
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    36
strXYX = strXY ++ strX
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    37
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    38
detect :: String -> Bool
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    39
detect = any (\c -> c == charX || c == charY)
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    40
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    41
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    42
{- output -}
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    43
69248
9f21381600e3 more Haskell operations;
wenzelm
parents: 69228
diff changeset
    44
output_markup :: Markup.T -> Markup.Output
9f21381600e3 more Haskell operations;
wenzelm
parents: 69228
diff changeset
    45
output_markup markup@(name, atts) =
9f21381600e3 more Haskell operations;
wenzelm
parents: 69228
diff changeset
    46
  if Markup.is_empty markup then Markup.no_output
9f21381600e3 more Haskell operations;
wenzelm
parents: 69228
diff changeset
    47
  else (strXY ++ name ++ concatMap (\(a, x) -> strY ++ a ++ "=" ++ x) atts ++ strX, strXYX)
9f21381600e3 more Haskell operations;
wenzelm
parents: 69228
diff changeset
    48
69225
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    49
buffer_attrib (a, x) =
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    50
  Buffer.add strY #> Buffer.add a #> Buffer.add "=" #> Buffer.add x
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    51
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    52
buffer_body :: XML.Body -> Buffer.T -> Buffer.T
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    53
buffer_body = fold buffer
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    54
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    55
buffer :: XML.Tree -> Buffer.T -> Buffer.T
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    56
buffer (XML.Elem (name, atts) ts) =
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    57
  Buffer.add strXY #> Buffer.add name #> fold buffer_attrib atts #> Buffer.add strX #>
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    58
  buffer_body ts #>
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    59
  Buffer.add strXYX
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    60
buffer (XML.Text s) = Buffer.add s
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    61
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    62
string_of_body :: XML.Body -> String
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    63
string_of_body body = Buffer.empty |> buffer_body body |> Buffer.content
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    64
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    65
string_of :: XML.Tree -> String
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    66
string_of = string_of_body . single
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    67
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    68
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    69
{- parse -}
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    70
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    71
-- split: fields or non-empty tokens
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    72
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    73
split :: Bool -> Char -> String -> [String]
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    74
split _ _ [] = []
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    75
split fields sep str = splitting str
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    76
  where
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    77
    splitting rest =
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    78
      case span (/= sep) rest of
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    79
        (_, []) -> cons rest []
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    80
        (prfx, _ : rest') -> cons prfx (splitting rest')
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    81
    cons item = if fields || not (null item) then (:) item else id
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    82
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    83
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    84
-- structural errors
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    85
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    86
err msg = error ("Malformed YXML: " ++ msg)
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    87
err_attribute = err "bad attribute"
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    88
err_element = err "bad element"
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    89
err_unbalanced "" = err "unbalanced element"
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    90
err_unbalanced name = err ("unbalanced element " ++ quote name)
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    91
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    92
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    93
-- stack operations
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    94
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    95
add x ((elem, body) : pending) = (elem, x : body) : pending
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    96
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    97
push "" _ _ = err_element
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    98
push name atts pending = ((name, atts), []) : pending
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
    99
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   100
pop ((("", _), _) : _) = err_unbalanced ""
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   101
pop ((markup, body) : pending) = add (XML.Elem markup (reverse body)) pending
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   102
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   103
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   104
-- parsing
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   105
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   106
parse_attrib s =
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   107
  case List.elemIndex '=' s of
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   108
    Just i | i > 0 -> (take i s, drop (i + 1) s)
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   109
    _ -> err_attribute
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   110
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   111
parse_chunk ["", ""] = pop
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   112
parse_chunk ("" : name : atts) = push name (map parse_attrib atts)
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   113
parse_chunk txts = fold (add . XML.Text) txts
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   114
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   115
parse_body :: String -> XML.Body
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   116
parse_body source =
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   117
  case fold parse_chunk chunks [(("", []), [])] of
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   118
    [(("", _), result)] -> reverse result
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   119
    ((name, _), _) : _ -> err_unbalanced name
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   120
  where chunks = split False charX source |> map (split True charY)
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   121
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   122
parse :: String -> XML.Tree
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   123
parse source =
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   124
  case parse_body source of
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   125
    [result] -> result
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   126
    [] -> XML.Text ""
bf2fecda8383 support for Isabelle tools in Haskell;
wenzelm
parents:
diff changeset
   127
    _ -> err "multiple results"