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