src/Tools/Haskell/Haskell.thy
changeset 74091 5721f1843e93
parent 74090 c26f4ec59835
child 74092 1d26f1a49480
equal deleted inserted replaced
74090:c26f4ec59835 74091:5721f1843e93
   165   encode = encode . Text.pack
   165   encode = encode . Text.pack
   166   decode :: Bytes -> String
   166   decode :: Bytes -> String
   167   decode = Text.unpack . decode
   167   decode = Text.unpack . decode
   168 \<close>
   168 \<close>
   169 
   169 
   170 generate_file "Isabelle/Symbol.hs" = \<open>
       
   171 {-  Title:      Isabelle/Symbols.hs
       
   172     Author:     Makarius
       
   173     LICENSE:    BSD 3-clause (Isabelle)
       
   174 
       
   175 Isabelle text symbols.
       
   176 -}
       
   177 
       
   178 module Isabelle.Symbol where
       
   179 
       
   180 {- ASCII characters -}
       
   181 
       
   182 is_ascii_letter :: Char -> Bool
       
   183 is_ascii_letter c = 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
       
   184 
       
   185 is_ascii_digit :: Char -> Bool
       
   186 is_ascii_digit c = '0' <= c && c <= '9'
       
   187 
       
   188 is_ascii_hex :: Char -> Bool
       
   189 is_ascii_hex c = '0' <= c && c <= '9' || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f'
       
   190 
       
   191 is_ascii_quasi :: Char -> Bool
       
   192 is_ascii_quasi c = c == '_' || c == '\''
       
   193 
       
   194 is_ascii_blank :: Char -> Bool
       
   195 is_ascii_blank c = c `elem` " \t\n\11\f\r"
       
   196 
       
   197 is_ascii_line_terminator :: Char -> Bool
       
   198 is_ascii_line_terminator c = c == '\r' || c == '\n'
       
   199 
       
   200 is_ascii_letdig :: Char -> Bool
       
   201 is_ascii_letdig c = is_ascii_letter c || is_ascii_digit c || is_ascii_quasi c
       
   202 
       
   203 is_ascii_identifier :: String -> Bool
       
   204 is_ascii_identifier s =
       
   205   not (null s) && is_ascii_letter (head s) && all is_ascii_letdig s
       
   206 \<close>
       
   207 
       
   208 generate_file "Isabelle/Library.hs" = \<open>
   170 generate_file "Isabelle/Library.hs" = \<open>
   209 {-  Title:      Isabelle/Library.hs
   171 {-  Title:      Isabelle/Library.hs
   210     Author:     Makarius
   172     Author:     Makarius
   211     LICENSE:    BSD 3-clause (Isabelle)
   173     LICENSE:    BSD 3-clause (Isabelle)
   212 
   174 
   327       _ -> line
   289       _ -> line
   328   else line
   290   else line
   329 
   291 
   330 clean_name :: String -> String
   292 clean_name :: String -> String
   331 clean_name = reverse #> dropWhile (== '_') #> reverse
   293 clean_name = reverse #> dropWhile (== '_') #> reverse
       
   294 \<close>
       
   295 
       
   296 
       
   297 generate_file "Isabelle/Symbol.hs" = \<open>
       
   298 {-  Title:      Isabelle/Symbols.hs
       
   299     Author:     Makarius
       
   300     LICENSE:    BSD 3-clause (Isabelle)
       
   301 
       
   302 Isabelle text symbols.
       
   303 -}
       
   304 
       
   305 module Isabelle.Symbol where
       
   306 
       
   307 {- ASCII characters -}
       
   308 
       
   309 is_ascii_letter :: Char -> Bool
       
   310 is_ascii_letter c = 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
       
   311 
       
   312 is_ascii_digit :: Char -> Bool
       
   313 is_ascii_digit c = '0' <= c && c <= '9'
       
   314 
       
   315 is_ascii_hex :: Char -> Bool
       
   316 is_ascii_hex c = '0' <= c && c <= '9' || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f'
       
   317 
       
   318 is_ascii_quasi :: Char -> Bool
       
   319 is_ascii_quasi c = c == '_' || c == '\''
       
   320 
       
   321 is_ascii_blank :: Char -> Bool
       
   322 is_ascii_blank c = c `elem` " \t\n\11\f\r"
       
   323 
       
   324 is_ascii_line_terminator :: Char -> Bool
       
   325 is_ascii_line_terminator c = c == '\r' || c == '\n'
       
   326 
       
   327 is_ascii_letdig :: Char -> Bool
       
   328 is_ascii_letdig c = is_ascii_letter c || is_ascii_digit c || is_ascii_quasi c
       
   329 
       
   330 is_ascii_identifier :: String -> Bool
       
   331 is_ascii_identifier s =
       
   332   not (null s) && is_ascii_letter (head s) && all is_ascii_letdig s
   332 \<close>
   333 \<close>
   333 
   334 
   334 generate_file "Isabelle/Value.hs" = \<open>
   335 generate_file "Isabelle/Value.hs" = \<open>
   335 {-  Title:      Isabelle/Value.hs
   336 {-  Title:      Isabelle/Value.hs
   336     Author:     Makarius
   337     Author:     Makarius
   970 
   971 
   971 no_output :: Output
   972 no_output :: Output
   972 no_output = ("", "")
   973 no_output = ("", "")
   973 \<close>
   974 \<close>
   974 
   975 
       
   976 generate_file "Isabelle/XML.hs" = \<open>
       
   977 {-  Title:      Isabelle/XML.hs
       
   978     Author:     Makarius
       
   979     LICENSE:    BSD 3-clause (Isabelle)
       
   980 
       
   981 Untyped XML trees and representation of ML values.
       
   982 
       
   983 See also \<^file>\<open>$ISABELLE_HOME/src/Pure/PIDE/xml.ML\<close>.
       
   984 -}
       
   985 
       
   986 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
       
   987 
       
   988 module Isabelle.XML (Attributes, Body, Tree(..), wrap_elem, unwrap_elem, content_of)
       
   989 where
       
   990 
       
   991 import Isabelle.Library
       
   992 import qualified Isabelle.Properties as Properties
       
   993 import qualified Isabelle.Markup as Markup
       
   994 import qualified Isabelle.Buffer as Buffer
       
   995 
       
   996 
       
   997 {- types -}
       
   998 
       
   999 type Attributes = Properties.T
       
  1000 type Body = [Tree]
       
  1001 data Tree = Elem (Markup.T, Body) | Text String
       
  1002 
       
  1003 
       
  1004 {- wrapped elements -}
       
  1005 
       
  1006 wrap_elem :: ((Markup.T, Body), [Tree]) -> Tree
       
  1007 wrap_elem (((a, atts), body1), body2) =
       
  1008   Elem ((\<open>XML.xml_elemN\<close>, (\<open>XML.xml_nameN\<close>, a) : atts), Elem ((\<open>XML.xml_bodyN\<close>, []), body1) : body2)
       
  1009 
       
  1010 unwrap_elem :: Tree -> Maybe ((Markup.T, Body), [Tree])
       
  1011 unwrap_elem
       
  1012   (Elem ((\<open>XML.xml_elemN\<close>, (\<open>XML.xml_nameN\<close>, a) : atts), Elem ((\<open>XML.xml_bodyN\<close>, []), body1) : body2)) =
       
  1013   Just (((a, atts), body1), body2)
       
  1014 unwrap_elem _ = Nothing
       
  1015 
       
  1016 
       
  1017 {- text content -}
       
  1018 
       
  1019 add_content :: Tree -> Buffer.T -> Buffer.T
       
  1020 add_content tree =
       
  1021   case unwrap_elem tree of
       
  1022     Just (_, ts) -> fold add_content ts
       
  1023     Nothing ->
       
  1024       case tree of
       
  1025         Elem (_, ts) -> fold add_content ts
       
  1026         Text s -> Buffer.add s
       
  1027 
       
  1028 content_of :: Body -> String
       
  1029 content_of body = Buffer.empty |> fold add_content body |> Buffer.content
       
  1030 
       
  1031 
       
  1032 {- string representation -}
       
  1033 
       
  1034 encode '<' = "&lt;"
       
  1035 encode '>' = "&gt;"
       
  1036 encode '&' = "&amp;"
       
  1037 encode '\'' = "&apos;"
       
  1038 encode '\"' = "&quot;"
       
  1039 encode c = [c]
       
  1040 
       
  1041 instance Show Tree where
       
  1042   show tree =
       
  1043     Buffer.empty |> show_tree tree |> Buffer.content
       
  1044     where
       
  1045       show_tree (Elem ((name, atts), [])) =
       
  1046         Buffer.add "<" #> Buffer.add (show_elem name atts) #> Buffer.add "/>"
       
  1047       show_tree (Elem ((name, atts), ts)) =
       
  1048         Buffer.add "<" #> Buffer.add (show_elem name atts) #> Buffer.add ">" #>
       
  1049         fold show_tree ts #>
       
  1050         Buffer.add "</" #> Buffer.add name #> Buffer.add ">"
       
  1051       show_tree (Text s) = Buffer.add (show_text s)
       
  1052 
       
  1053       show_elem name atts =
       
  1054         unwords (name : map (\(a, x) -> a <> "=\"" <> show_text x <> "\"") atts)
       
  1055 
       
  1056       show_text = concatMap encode
       
  1057 \<close>
       
  1058 
       
  1059 generate_file "Isabelle/XML/Encode.hs" = \<open>
       
  1060 {-  Title:      Isabelle/XML/Encode.hs
       
  1061     Author:     Makarius
       
  1062     LICENSE:    BSD 3-clause (Isabelle)
       
  1063 
       
  1064 XML as data representation language.
       
  1065 
       
  1066 See also \<^file>\<open>$ISABELLE_HOME/src/Pure/PIDE/xml.ML\<close>.
       
  1067 -}
       
  1068 
       
  1069 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
       
  1070 
       
  1071 module Isabelle.XML.Encode (
       
  1072   A, T, V, P,
       
  1073 
       
  1074   int_atom, bool_atom, unit_atom,
       
  1075 
       
  1076   tree, properties, string, int, bool, unit, pair, triple, list, option, variant
       
  1077 )
       
  1078 where
       
  1079 
       
  1080 import Isabelle.Library
       
  1081 import qualified Isabelle.Value as Value
       
  1082 import qualified Isabelle.Properties as Properties
       
  1083 import qualified Isabelle.XML as XML
       
  1084 
       
  1085 
       
  1086 type A a = a -> String
       
  1087 type T a = a -> XML.Body
       
  1088 type V a = a -> Maybe ([String], XML.Body)
       
  1089 type P a = a -> [String]
       
  1090 
       
  1091 
       
  1092 -- atomic values
       
  1093 
       
  1094 int_atom :: A Int
       
  1095 int_atom = Value.print_int
       
  1096 
       
  1097 bool_atom :: A Bool
       
  1098 bool_atom False = "0"
       
  1099 bool_atom True = "1"
       
  1100 
       
  1101 unit_atom :: A ()
       
  1102 unit_atom () = ""
       
  1103 
       
  1104 
       
  1105 -- structural nodes
       
  1106 
       
  1107 node ts = XML.Elem ((":", []), ts)
       
  1108 
       
  1109 vector = map_index (\(i, x) -> (int_atom i, x))
       
  1110 
       
  1111 tagged (tag, (xs, ts)) = XML.Elem ((int_atom tag, vector xs), ts)
       
  1112 
       
  1113 
       
  1114 -- representation of standard types
       
  1115 
       
  1116 tree :: T XML.Tree
       
  1117 tree t = [t]
       
  1118 
       
  1119 properties :: T Properties.T
       
  1120 properties props = [XML.Elem ((":", props), [])]
       
  1121 
       
  1122 string :: T String
       
  1123 string "" = []
       
  1124 string s = [XML.Text s]
       
  1125 
       
  1126 int :: T Int
       
  1127 int = string . int_atom
       
  1128 
       
  1129 bool :: T Bool
       
  1130 bool = string . bool_atom
       
  1131 
       
  1132 unit :: T ()
       
  1133 unit = string . unit_atom
       
  1134 
       
  1135 pair :: T a -> T b -> T (a, b)
       
  1136 pair f g (x, y) = [node (f x), node (g y)]
       
  1137 
       
  1138 triple :: T a -> T b -> T c -> T (a, b, c)
       
  1139 triple f g h (x, y, z) = [node (f x), node (g y), node (h z)]
       
  1140 
       
  1141 list :: T a -> T [a]
       
  1142 list f xs = map (node . f) xs
       
  1143 
       
  1144 option :: T a -> T (Maybe a)
       
  1145 option _ Nothing = []
       
  1146 option f (Just x) = [node (f x)]
       
  1147 
       
  1148 variant :: [V a] -> T a
       
  1149 variant fs x = [tagged (the (get_index (\f -> f x) fs))]
       
  1150 \<close>
       
  1151 
       
  1152 generate_file "Isabelle/XML/Decode.hs" = \<open>
       
  1153 {-  Title:      Isabelle/XML/Decode.hs
       
  1154     Author:     Makarius
       
  1155     LICENSE:    BSD 3-clause (Isabelle)
       
  1156 
       
  1157 XML as data representation language.
       
  1158 
       
  1159 See also \<^file>\<open>$ISABELLE_HOME/src/Pure/PIDE/xml.ML\<close>.
       
  1160 -}
       
  1161 
       
  1162 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
       
  1163 
       
  1164 module Isabelle.XML.Decode (
       
  1165   A, T, V, P,
       
  1166 
       
  1167   int_atom, bool_atom, unit_atom,
       
  1168 
       
  1169   tree, properties, string, int, bool, unit, pair, triple, list, option, variant
       
  1170 )
       
  1171 where
       
  1172 
       
  1173 import Isabelle.Library
       
  1174 import qualified Isabelle.Value as Value
       
  1175 import qualified Isabelle.Properties as Properties
       
  1176 import qualified Isabelle.XML as XML
       
  1177 
       
  1178 
       
  1179 type A a = String -> a
       
  1180 type T a = XML.Body -> a
       
  1181 type V a = ([String], XML.Body) -> a
       
  1182 type P a = [String] -> a
       
  1183 
       
  1184 err_atom = error "Malformed XML atom"
       
  1185 err_body = error "Malformed XML body"
       
  1186 
       
  1187 
       
  1188 {- atomic values -}
       
  1189 
       
  1190 int_atom :: A Int
       
  1191 int_atom s =
       
  1192   case Value.parse_int s of
       
  1193     Just i -> i
       
  1194     Nothing -> err_atom
       
  1195 
       
  1196 bool_atom :: A Bool
       
  1197 bool_atom "0" = False
       
  1198 bool_atom "1" = True
       
  1199 bool_atom _ = err_atom
       
  1200 
       
  1201 unit_atom :: A ()
       
  1202 unit_atom "" = ()
       
  1203 unit_atom _ = err_atom
       
  1204 
       
  1205 
       
  1206 {- structural nodes -}
       
  1207 
       
  1208 node (XML.Elem ((":", []), ts)) = ts
       
  1209 node _ = err_body
       
  1210 
       
  1211 vector atts =
       
  1212   map_index (\(i, (a, x)) -> if int_atom a == i then x else err_atom) atts
       
  1213 
       
  1214 tagged (XML.Elem ((name, atts), ts)) = (int_atom name, (vector atts, ts))
       
  1215 tagged _ = err_body
       
  1216 
       
  1217 
       
  1218 {- representation of standard types -}
       
  1219 
       
  1220 tree :: T XML.Tree
       
  1221 tree [t] = t
       
  1222 tree _ = err_body
       
  1223 
       
  1224 properties :: T Properties.T
       
  1225 properties [XML.Elem ((":", props), [])] = props
       
  1226 properties _ = err_body
       
  1227 
       
  1228 string :: T String
       
  1229 string [] = ""
       
  1230 string [XML.Text s] = s
       
  1231 string _ = err_body
       
  1232 
       
  1233 int :: T Int
       
  1234 int = int_atom . string
       
  1235 
       
  1236 bool :: T Bool
       
  1237 bool = bool_atom . string
       
  1238 
       
  1239 unit :: T ()
       
  1240 unit = unit_atom . string
       
  1241 
       
  1242 pair :: T a -> T b -> T (a, b)
       
  1243 pair f g [t1, t2] = (f (node t1), g (node t2))
       
  1244 pair _ _ _ = err_body
       
  1245 
       
  1246 triple :: T a -> T b -> T c -> T (a, b, c)
       
  1247 triple f g h [t1, t2, t3] = (f (node t1), g (node t2), h (node t3))
       
  1248 triple _ _ _ _ = err_body
       
  1249 
       
  1250 list :: T a -> T [a]
       
  1251 list f ts = map (f . node) ts
       
  1252 
       
  1253 option :: T a -> T (Maybe a)
       
  1254 option _ [] = Nothing
       
  1255 option f [t] = Just (f (node t))
       
  1256 option _ _ = err_body
       
  1257 
       
  1258 variant :: [V a] -> T a
       
  1259 variant fs [t] = (fs !! tag) (xs, ts)
       
  1260   where (tag, (xs, ts)) = tagged t
       
  1261 variant _ _ = err_body
       
  1262 \<close>
       
  1263 
       
  1264 generate_file "Isabelle/YXML.hs" = \<open>
       
  1265 {-  Title:      Isabelle/YXML.hs
       
  1266     Author:     Makarius
       
  1267     LICENSE:    BSD 3-clause (Isabelle)
       
  1268 
       
  1269 Efficient text representation of XML trees.  Suitable for direct
       
  1270 inlining into plain text.
       
  1271 
       
  1272 See also \<^file>\<open>$ISABELLE_HOME/src/Pure/PIDE/yxml.ML\<close>.
       
  1273 -}
       
  1274 
       
  1275 {-# OPTIONS_GHC -fno-warn-missing-signatures -fno-warn-incomplete-patterns #-}
       
  1276 
       
  1277 module Isabelle.YXML (charX, charY, strX, strY, detect, output_markup,
       
  1278   buffer_body, buffer, string_of_body, string_of, parse_body, parse)
       
  1279 where
       
  1280 
       
  1281 import qualified Data.Char as Char
       
  1282 import qualified Data.List as List
       
  1283 
       
  1284 import Isabelle.Library
       
  1285 import qualified Isabelle.Markup as Markup
       
  1286 import qualified Isabelle.XML as XML
       
  1287 import qualified Isabelle.Buffer as Buffer
       
  1288 
       
  1289 
       
  1290 {- markers -}
       
  1291 
       
  1292 charX, charY :: Char
       
  1293 charX = Char.chr 5
       
  1294 charY = Char.chr 6
       
  1295 
       
  1296 strX, strY, strXY, strXYX :: String
       
  1297 strX = [charX]
       
  1298 strY = [charY]
       
  1299 strXY = strX <> strY
       
  1300 strXYX = strXY <> strX
       
  1301 
       
  1302 detect :: String -> Bool
       
  1303 detect = any (\c -> c == charX || c == charY)
       
  1304 
       
  1305 
       
  1306 {- output -}
       
  1307 
       
  1308 output_markup :: Markup.T -> Markup.Output
       
  1309 output_markup markup@(name, atts) =
       
  1310   if Markup.is_empty markup then Markup.no_output
       
  1311   else (strXY <> name <> concatMap (\(a, x) -> strY <> a <> "=" <> x) atts <> strX, strXYX)
       
  1312 
       
  1313 buffer_attrib (a, x) =
       
  1314   Buffer.add strY #> Buffer.add a #> Buffer.add "=" #> Buffer.add x
       
  1315 
       
  1316 buffer_body :: XML.Body -> Buffer.T -> Buffer.T
       
  1317 buffer_body = fold buffer
       
  1318 
       
  1319 buffer :: XML.Tree -> Buffer.T -> Buffer.T
       
  1320 buffer (XML.Elem ((name, atts), ts)) =
       
  1321   Buffer.add strXY #> Buffer.add name #> fold buffer_attrib atts #> Buffer.add strX #>
       
  1322   buffer_body ts #>
       
  1323   Buffer.add strXYX
       
  1324 buffer (XML.Text s) = Buffer.add s
       
  1325 
       
  1326 string_of_body :: XML.Body -> String
       
  1327 string_of_body body = Buffer.empty |> buffer_body body |> Buffer.content
       
  1328 
       
  1329 string_of :: XML.Tree -> String
       
  1330 string_of = string_of_body . single
       
  1331 
       
  1332 
       
  1333 {- parse -}
       
  1334 
       
  1335 -- split: fields or non-empty tokens
       
  1336 
       
  1337 split :: Bool -> Char -> String -> [String]
       
  1338 split _ _ [] = []
       
  1339 split fields sep str = splitting str
       
  1340   where
       
  1341     splitting rest =
       
  1342       case span (/= sep) rest of
       
  1343         (_, []) -> cons rest []
       
  1344         (prfx, _ : rest') -> cons prfx (splitting rest')
       
  1345     cons item = if fields || not (null item) then (:) item else id
       
  1346 
       
  1347 
       
  1348 -- structural errors
       
  1349 
       
  1350 err msg = error ("Malformed YXML: " <> msg)
       
  1351 err_attribute = err "bad attribute"
       
  1352 err_element = err "bad element"
       
  1353 err_unbalanced "" = err "unbalanced element"
       
  1354 err_unbalanced name = err ("unbalanced element " <> quote name)
       
  1355 
       
  1356 
       
  1357 -- stack operations
       
  1358 
       
  1359 add x ((elem, body) : pending) = (elem, x : body) : pending
       
  1360 
       
  1361 push "" _ _ = err_element
       
  1362 push name atts pending = ((name, atts), []) : pending
       
  1363 
       
  1364 pop ((("", _), _) : _) = err_unbalanced ""
       
  1365 pop ((markup, body) : pending) = add (XML.Elem (markup, reverse body)) pending
       
  1366 
       
  1367 
       
  1368 -- parsing
       
  1369 
       
  1370 parse_attrib s =
       
  1371   case List.elemIndex '=' s of
       
  1372     Just i | i > 0 -> (take i s, drop (i + 1) s)
       
  1373     _ -> err_attribute
       
  1374 
       
  1375 parse_chunk ["", ""] = pop
       
  1376 parse_chunk ("" : name : atts) = push name (map parse_attrib atts)
       
  1377 parse_chunk txts = fold (add . XML.Text) txts
       
  1378 
       
  1379 parse_body :: String -> XML.Body
       
  1380 parse_body source =
       
  1381   case fold parse_chunk chunks [(("", []), [])] of
       
  1382     [(("", _), result)] -> reverse result
       
  1383     ((name, _), _) : _ -> err_unbalanced name
       
  1384   where chunks = split False charX source |> map (split True charY)
       
  1385 
       
  1386 parse :: String -> XML.Tree
       
  1387 parse source =
       
  1388   case parse_body source of
       
  1389     [result] -> result
       
  1390     [] -> XML.Text ""
       
  1391     _ -> err "multiple results"
       
  1392 \<close>
       
  1393 
   975 generate_file "Isabelle/Completion.hs" = \<open>
  1394 generate_file "Isabelle/Completion.hs" = \<open>
   976 {-  Title:      Isabelle/Completion.hs
  1395 {-  Title:      Isabelle/Completion.hs
   977     Author:     Makarius
  1396     Author:     Makarius
   978     LICENSE:    BSD 3-clause (Isabelle)
  1397     LICENSE:    BSD 3-clause (Isabelle)
   979 
  1398 
  1063   IO.withFile path IO.WriteMode (\h -> do setup h; IO.hPutStr h s)
  1482   IO.withFile path IO.WriteMode (\h -> do setup h; IO.hPutStr h s)
  1064 
  1483 
  1065 append :: IO.FilePath -> String -> IO ()
  1484 append :: IO.FilePath -> String -> IO ()
  1066 append path s =
  1485 append path s =
  1067   IO.withFile path IO.AppendMode (\h -> do setup h; IO.hPutStr h s)
  1486   IO.withFile path IO.AppendMode (\h -> do setup h; IO.hPutStr h s)
  1068 \<close>
       
  1069 
       
  1070 generate_file "Isabelle/XML.hs" = \<open>
       
  1071 {-  Title:      Isabelle/XML.hs
       
  1072     Author:     Makarius
       
  1073     LICENSE:    BSD 3-clause (Isabelle)
       
  1074 
       
  1075 Untyped XML trees and representation of ML values.
       
  1076 
       
  1077 See also \<^file>\<open>$ISABELLE_HOME/src/Pure/PIDE/xml.ML\<close>.
       
  1078 -}
       
  1079 
       
  1080 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
       
  1081 
       
  1082 module Isabelle.XML (Attributes, Body, Tree(..), wrap_elem, unwrap_elem, content_of)
       
  1083 where
       
  1084 
       
  1085 import Isabelle.Library
       
  1086 import qualified Isabelle.Properties as Properties
       
  1087 import qualified Isabelle.Markup as Markup
       
  1088 import qualified Isabelle.Buffer as Buffer
       
  1089 
       
  1090 
       
  1091 {- types -}
       
  1092 
       
  1093 type Attributes = Properties.T
       
  1094 type Body = [Tree]
       
  1095 data Tree = Elem (Markup.T, Body) | Text String
       
  1096 
       
  1097 
       
  1098 {- wrapped elements -}
       
  1099 
       
  1100 wrap_elem :: ((Markup.T, Body), [Tree]) -> Tree
       
  1101 wrap_elem (((a, atts), body1), body2) =
       
  1102   Elem ((\<open>XML.xml_elemN\<close>, (\<open>XML.xml_nameN\<close>, a) : atts), Elem ((\<open>XML.xml_bodyN\<close>, []), body1) : body2)
       
  1103 
       
  1104 unwrap_elem :: Tree -> Maybe ((Markup.T, Body), [Tree])
       
  1105 unwrap_elem
       
  1106   (Elem ((\<open>XML.xml_elemN\<close>, (\<open>XML.xml_nameN\<close>, a) : atts), Elem ((\<open>XML.xml_bodyN\<close>, []), body1) : body2)) =
       
  1107   Just (((a, atts), body1), body2)
       
  1108 unwrap_elem _ = Nothing
       
  1109 
       
  1110 
       
  1111 {- text content -}
       
  1112 
       
  1113 add_content :: Tree -> Buffer.T -> Buffer.T
       
  1114 add_content tree =
       
  1115   case unwrap_elem tree of
       
  1116     Just (_, ts) -> fold add_content ts
       
  1117     Nothing ->
       
  1118       case tree of
       
  1119         Elem (_, ts) -> fold add_content ts
       
  1120         Text s -> Buffer.add s
       
  1121 
       
  1122 content_of :: Body -> String
       
  1123 content_of body = Buffer.empty |> fold add_content body |> Buffer.content
       
  1124 
       
  1125 
       
  1126 {- string representation -}
       
  1127 
       
  1128 encode '<' = "&lt;"
       
  1129 encode '>' = "&gt;"
       
  1130 encode '&' = "&amp;"
       
  1131 encode '\'' = "&apos;"
       
  1132 encode '\"' = "&quot;"
       
  1133 encode c = [c]
       
  1134 
       
  1135 instance Show Tree where
       
  1136   show tree =
       
  1137     Buffer.empty |> show_tree tree |> Buffer.content
       
  1138     where
       
  1139       show_tree (Elem ((name, atts), [])) =
       
  1140         Buffer.add "<" #> Buffer.add (show_elem name atts) #> Buffer.add "/>"
       
  1141       show_tree (Elem ((name, atts), ts)) =
       
  1142         Buffer.add "<" #> Buffer.add (show_elem name atts) #> Buffer.add ">" #>
       
  1143         fold show_tree ts #>
       
  1144         Buffer.add "</" #> Buffer.add name #> Buffer.add ">"
       
  1145       show_tree (Text s) = Buffer.add (show_text s)
       
  1146 
       
  1147       show_elem name atts =
       
  1148         unwords (name : map (\(a, x) -> a <> "=\"" <> show_text x <> "\"") atts)
       
  1149 
       
  1150       show_text = concatMap encode
       
  1151 \<close>
       
  1152 
       
  1153 generate_file "Isabelle/XML/Encode.hs" = \<open>
       
  1154 {-  Title:      Isabelle/XML/Encode.hs
       
  1155     Author:     Makarius
       
  1156     LICENSE:    BSD 3-clause (Isabelle)
       
  1157 
       
  1158 XML as data representation language.
       
  1159 
       
  1160 See also \<^file>\<open>$ISABELLE_HOME/src/Pure/PIDE/xml.ML\<close>.
       
  1161 -}
       
  1162 
       
  1163 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
       
  1164 
       
  1165 module Isabelle.XML.Encode (
       
  1166   A, T, V, P,
       
  1167 
       
  1168   int_atom, bool_atom, unit_atom,
       
  1169 
       
  1170   tree, properties, string, int, bool, unit, pair, triple, list, option, variant
       
  1171 )
       
  1172 where
       
  1173 
       
  1174 import Isabelle.Library
       
  1175 import qualified Isabelle.Value as Value
       
  1176 import qualified Isabelle.Properties as Properties
       
  1177 import qualified Isabelle.XML as XML
       
  1178 
       
  1179 
       
  1180 type A a = a -> String
       
  1181 type T a = a -> XML.Body
       
  1182 type V a = a -> Maybe ([String], XML.Body)
       
  1183 type P a = a -> [String]
       
  1184 
       
  1185 
       
  1186 -- atomic values
       
  1187 
       
  1188 int_atom :: A Int
       
  1189 int_atom = Value.print_int
       
  1190 
       
  1191 bool_atom :: A Bool
       
  1192 bool_atom False = "0"
       
  1193 bool_atom True = "1"
       
  1194 
       
  1195 unit_atom :: A ()
       
  1196 unit_atom () = ""
       
  1197 
       
  1198 
       
  1199 -- structural nodes
       
  1200 
       
  1201 node ts = XML.Elem ((":", []), ts)
       
  1202 
       
  1203 vector = map_index (\(i, x) -> (int_atom i, x))
       
  1204 
       
  1205 tagged (tag, (xs, ts)) = XML.Elem ((int_atom tag, vector xs), ts)
       
  1206 
       
  1207 
       
  1208 -- representation of standard types
       
  1209 
       
  1210 tree :: T XML.Tree
       
  1211 tree t = [t]
       
  1212 
       
  1213 properties :: T Properties.T
       
  1214 properties props = [XML.Elem ((":", props), [])]
       
  1215 
       
  1216 string :: T String
       
  1217 string "" = []
       
  1218 string s = [XML.Text s]
       
  1219 
       
  1220 int :: T Int
       
  1221 int = string . int_atom
       
  1222 
       
  1223 bool :: T Bool
       
  1224 bool = string . bool_atom
       
  1225 
       
  1226 unit :: T ()
       
  1227 unit = string . unit_atom
       
  1228 
       
  1229 pair :: T a -> T b -> T (a, b)
       
  1230 pair f g (x, y) = [node (f x), node (g y)]
       
  1231 
       
  1232 triple :: T a -> T b -> T c -> T (a, b, c)
       
  1233 triple f g h (x, y, z) = [node (f x), node (g y), node (h z)]
       
  1234 
       
  1235 list :: T a -> T [a]
       
  1236 list f xs = map (node . f) xs
       
  1237 
       
  1238 option :: T a -> T (Maybe a)
       
  1239 option _ Nothing = []
       
  1240 option f (Just x) = [node (f x)]
       
  1241 
       
  1242 variant :: [V a] -> T a
       
  1243 variant fs x = [tagged (the (get_index (\f -> f x) fs))]
       
  1244 \<close>
       
  1245 
       
  1246 generate_file "Isabelle/XML/Decode.hs" = \<open>
       
  1247 {-  Title:      Isabelle/XML/Decode.hs
       
  1248     Author:     Makarius
       
  1249     LICENSE:    BSD 3-clause (Isabelle)
       
  1250 
       
  1251 XML as data representation language.
       
  1252 
       
  1253 See also \<^file>\<open>$ISABELLE_HOME/src/Pure/PIDE/xml.ML\<close>.
       
  1254 -}
       
  1255 
       
  1256 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
       
  1257 
       
  1258 module Isabelle.XML.Decode (
       
  1259   A, T, V, P,
       
  1260 
       
  1261   int_atom, bool_atom, unit_atom,
       
  1262 
       
  1263   tree, properties, string, int, bool, unit, pair, triple, list, option, variant
       
  1264 )
       
  1265 where
       
  1266 
       
  1267 import Isabelle.Library
       
  1268 import qualified Isabelle.Value as Value
       
  1269 import qualified Isabelle.Properties as Properties
       
  1270 import qualified Isabelle.XML as XML
       
  1271 
       
  1272 
       
  1273 type A a = String -> a
       
  1274 type T a = XML.Body -> a
       
  1275 type V a = ([String], XML.Body) -> a
       
  1276 type P a = [String] -> a
       
  1277 
       
  1278 err_atom = error "Malformed XML atom"
       
  1279 err_body = error "Malformed XML body"
       
  1280 
       
  1281 
       
  1282 {- atomic values -}
       
  1283 
       
  1284 int_atom :: A Int
       
  1285 int_atom s =
       
  1286   case Value.parse_int s of
       
  1287     Just i -> i
       
  1288     Nothing -> err_atom
       
  1289 
       
  1290 bool_atom :: A Bool
       
  1291 bool_atom "0" = False
       
  1292 bool_atom "1" = True
       
  1293 bool_atom _ = err_atom
       
  1294 
       
  1295 unit_atom :: A ()
       
  1296 unit_atom "" = ()
       
  1297 unit_atom _ = err_atom
       
  1298 
       
  1299 
       
  1300 {- structural nodes -}
       
  1301 
       
  1302 node (XML.Elem ((":", []), ts)) = ts
       
  1303 node _ = err_body
       
  1304 
       
  1305 vector atts =
       
  1306   map_index (\(i, (a, x)) -> if int_atom a == i then x else err_atom) atts
       
  1307 
       
  1308 tagged (XML.Elem ((name, atts), ts)) = (int_atom name, (vector atts, ts))
       
  1309 tagged _ = err_body
       
  1310 
       
  1311 
       
  1312 {- representation of standard types -}
       
  1313 
       
  1314 tree :: T XML.Tree
       
  1315 tree [t] = t
       
  1316 tree _ = err_body
       
  1317 
       
  1318 properties :: T Properties.T
       
  1319 properties [XML.Elem ((":", props), [])] = props
       
  1320 properties _ = err_body
       
  1321 
       
  1322 string :: T String
       
  1323 string [] = ""
       
  1324 string [XML.Text s] = s
       
  1325 string _ = err_body
       
  1326 
       
  1327 int :: T Int
       
  1328 int = int_atom . string
       
  1329 
       
  1330 bool :: T Bool
       
  1331 bool = bool_atom . string
       
  1332 
       
  1333 unit :: T ()
       
  1334 unit = unit_atom . string
       
  1335 
       
  1336 pair :: T a -> T b -> T (a, b)
       
  1337 pair f g [t1, t2] = (f (node t1), g (node t2))
       
  1338 pair _ _ _ = err_body
       
  1339 
       
  1340 triple :: T a -> T b -> T c -> T (a, b, c)
       
  1341 triple f g h [t1, t2, t3] = (f (node t1), g (node t2), h (node t3))
       
  1342 triple _ _ _ _ = err_body
       
  1343 
       
  1344 list :: T a -> T [a]
       
  1345 list f ts = map (f . node) ts
       
  1346 
       
  1347 option :: T a -> T (Maybe a)
       
  1348 option _ [] = Nothing
       
  1349 option f [t] = Just (f (node t))
       
  1350 option _ _ = err_body
       
  1351 
       
  1352 variant :: [V a] -> T a
       
  1353 variant fs [t] = (fs !! tag) (xs, ts)
       
  1354   where (tag, (xs, ts)) = tagged t
       
  1355 variant _ _ = err_body
       
  1356 \<close>
       
  1357 
       
  1358 generate_file "Isabelle/YXML.hs" = \<open>
       
  1359 {-  Title:      Isabelle/YXML.hs
       
  1360     Author:     Makarius
       
  1361     LICENSE:    BSD 3-clause (Isabelle)
       
  1362 
       
  1363 Efficient text representation of XML trees.  Suitable for direct
       
  1364 inlining into plain text.
       
  1365 
       
  1366 See also \<^file>\<open>$ISABELLE_HOME/src/Pure/PIDE/yxml.ML\<close>.
       
  1367 -}
       
  1368 
       
  1369 {-# OPTIONS_GHC -fno-warn-missing-signatures -fno-warn-incomplete-patterns #-}
       
  1370 
       
  1371 module Isabelle.YXML (charX, charY, strX, strY, detect, output_markup,
       
  1372   buffer_body, buffer, string_of_body, string_of, parse_body, parse)
       
  1373 where
       
  1374 
       
  1375 import qualified Data.Char as Char
       
  1376 import qualified Data.List as List
       
  1377 
       
  1378 import Isabelle.Library
       
  1379 import qualified Isabelle.Markup as Markup
       
  1380 import qualified Isabelle.XML as XML
       
  1381 import qualified Isabelle.Buffer as Buffer
       
  1382 
       
  1383 
       
  1384 {- markers -}
       
  1385 
       
  1386 charX, charY :: Char
       
  1387 charX = Char.chr 5
       
  1388 charY = Char.chr 6
       
  1389 
       
  1390 strX, strY, strXY, strXYX :: String
       
  1391 strX = [charX]
       
  1392 strY = [charY]
       
  1393 strXY = strX <> strY
       
  1394 strXYX = strXY <> strX
       
  1395 
       
  1396 detect :: String -> Bool
       
  1397 detect = any (\c -> c == charX || c == charY)
       
  1398 
       
  1399 
       
  1400 {- output -}
       
  1401 
       
  1402 output_markup :: Markup.T -> Markup.Output
       
  1403 output_markup markup@(name, atts) =
       
  1404   if Markup.is_empty markup then Markup.no_output
       
  1405   else (strXY <> name <> concatMap (\(a, x) -> strY <> a <> "=" <> x) atts <> strX, strXYX)
       
  1406 
       
  1407 buffer_attrib (a, x) =
       
  1408   Buffer.add strY #> Buffer.add a #> Buffer.add "=" #> Buffer.add x
       
  1409 
       
  1410 buffer_body :: XML.Body -> Buffer.T -> Buffer.T
       
  1411 buffer_body = fold buffer
       
  1412 
       
  1413 buffer :: XML.Tree -> Buffer.T -> Buffer.T
       
  1414 buffer (XML.Elem ((name, atts), ts)) =
       
  1415   Buffer.add strXY #> Buffer.add name #> fold buffer_attrib atts #> Buffer.add strX #>
       
  1416   buffer_body ts #>
       
  1417   Buffer.add strXYX
       
  1418 buffer (XML.Text s) = Buffer.add s
       
  1419 
       
  1420 string_of_body :: XML.Body -> String
       
  1421 string_of_body body = Buffer.empty |> buffer_body body |> Buffer.content
       
  1422 
       
  1423 string_of :: XML.Tree -> String
       
  1424 string_of = string_of_body . single
       
  1425 
       
  1426 
       
  1427 {- parse -}
       
  1428 
       
  1429 -- split: fields or non-empty tokens
       
  1430 
       
  1431 split :: Bool -> Char -> String -> [String]
       
  1432 split _ _ [] = []
       
  1433 split fields sep str = splitting str
       
  1434   where
       
  1435     splitting rest =
       
  1436       case span (/= sep) rest of
       
  1437         (_, []) -> cons rest []
       
  1438         (prfx, _ : rest') -> cons prfx (splitting rest')
       
  1439     cons item = if fields || not (null item) then (:) item else id
       
  1440 
       
  1441 
       
  1442 -- structural errors
       
  1443 
       
  1444 err msg = error ("Malformed YXML: " <> msg)
       
  1445 err_attribute = err "bad attribute"
       
  1446 err_element = err "bad element"
       
  1447 err_unbalanced "" = err "unbalanced element"
       
  1448 err_unbalanced name = err ("unbalanced element " <> quote name)
       
  1449 
       
  1450 
       
  1451 -- stack operations
       
  1452 
       
  1453 add x ((elem, body) : pending) = (elem, x : body) : pending
       
  1454 
       
  1455 push "" _ _ = err_element
       
  1456 push name atts pending = ((name, atts), []) : pending
       
  1457 
       
  1458 pop ((("", _), _) : _) = err_unbalanced ""
       
  1459 pop ((markup, body) : pending) = add (XML.Elem (markup, reverse body)) pending
       
  1460 
       
  1461 
       
  1462 -- parsing
       
  1463 
       
  1464 parse_attrib s =
       
  1465   case List.elemIndex '=' s of
       
  1466     Just i | i > 0 -> (take i s, drop (i + 1) s)
       
  1467     _ -> err_attribute
       
  1468 
       
  1469 parse_chunk ["", ""] = pop
       
  1470 parse_chunk ("" : name : atts) = push name (map parse_attrib atts)
       
  1471 parse_chunk txts = fold (add . XML.Text) txts
       
  1472 
       
  1473 parse_body :: String -> XML.Body
       
  1474 parse_body source =
       
  1475   case fold parse_chunk chunks [(("", []), [])] of
       
  1476     [(("", _), result)] -> reverse result
       
  1477     ((name, _), _) : _ -> err_unbalanced name
       
  1478   where chunks = split False charX source |> map (split True charY)
       
  1479 
       
  1480 parse :: String -> XML.Tree
       
  1481 parse source =
       
  1482   case parse_body source of
       
  1483     [result] -> result
       
  1484     [] -> XML.Text ""
       
  1485     _ -> err "multiple results"
       
  1486 \<close>
  1487 \<close>
  1487 
  1488 
  1488 generate_file "Isabelle/Pretty.hs" = \<open>
  1489 generate_file "Isabelle/Pretty.hs" = \<open>
  1489 {-  Title:      Isabelle/Pretty.hs
  1490 {-  Title:      Isabelle/Pretty.hs
  1490     Author:     Makarius
  1491     Author:     Makarius