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 '<' = "<" |
|
1035 encode '>' = ">" |
|
1036 encode '&' = "&" |
|
1037 encode '\'' = "'" |
|
1038 encode '\"' = """ |
|
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 '<' = "<" |
|
1129 encode '>' = ">" |
|
1130 encode '&' = "&" |
|
1131 encode '\'' = "'" |
|
1132 encode '\"' = """ |
|
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 |