(* Author:AkihisaYamada<ayamada@trs.cm.is.nagoya-u.ac.jp> Author:ChristianSternagel<c.sternagel@gmail.com>( Author:RenéThiemann<rene.thiemann@uibk.ac.at>
*) theory Xmlt imports "HOL-Library.Extended_Nat" Show.Number_Parser
Certification_Monads.Strict_Sum Show.Shows_Literal
Xml begin
text‹String literals in parser, for nicer generated code› type_synonym ltag = String.literal
datatype 'a xml_error = TagMismatch "ltag list" | Fatal 'a text‹
@{term "TagMismatch tags"} represents tag mismatch, expecting one of @{term tags} but
something else is encountered. ›
lemma xml_error_mono [partial_function_mono]: assumes p1: "∧tags. mono_option (p1 tags)" and p2: "∧x. mono_option (p2 x)" and f: "mono_option f" shows"mono_option (λg. case s of TagMismatch tags ==> p1 tags g | Fatal x ==> p2 x g)" using assms by (cases s, auto intro!:partial_function_mono)
text‹A state is a tuple of
the XML or list of XMLs to be parsed,
the attributes,
a flag indicating if mismatch is allowed,
a list of tags that have been mismatched,
the current position. › type_synonym 'a xmlt = "xml × (string × string) list × bool × ltag list × ltag list ==> String.literal xml_error +\<bottom> 'a" type_synonym 'a xmlst = "xml list × (string × string) list × bool × ltag list × ltag list ==> String.literal xml_error +\<bottom> 'a"
lemma xml_state_cases: assumes"∧p nam atts xmls. x = (XML nam atts xmls, p) ==> thesis" and"∧p txt. x = (XML_text txt, p) ==> thesis" shows thesis using assms by (cases x; cases "fst x", auto)
lemma xmls_state_cases: assumes"∧p. x = ([],p) ==> thesis" and"∧xml xmls p. x = (xml # xmls, p) ==> thesis" shows thesis using assms by (cases x; cases "fst x", auto)
lemma xmls_state_induct: fixes x :: "xml list × _" assumes"∧a b c d. P ([],a,b,c,d)" and"∧xml xmls a b c d. (∧a b c d. P (xmls,a,b,c,d)) ==> P (xml # xmls, a, b, c, d)" shows"P x" proof (induct x) case (fields xmls a b c d) with assms show ?caseby (induct xmls arbitrary:a b c d, auto) qed
definition xml_error where"xml_error str x ≡ case x of (xmls,_,_,_,pos) ==> let next = case xmls of XML tag _ _ # _ ==> STR ''<'' + String.implode tag + STR ''>'' | XML_text str # _ ==> STR ''text element \"'' + String.implode str + STR ''\"'' | [] ==> STR ''tag close'' in Left (Fatal (STR ''parse error on '' + next + STR '' at '' + default_showsl_list showsl_lit pos (STR '''') + STR '':🍋'' + str))"
definition xml_return :: "'a ==> 'a xmlst" where"xml_return v x ≡ case x of ([],_) ==> Right v | _ ==> xml_error (STR ''expecting tag close'') x"
definition"mismatch tag x ≡ case x of (xmls,atts,flag,cands,_) ==> if flag then Left (TagMismatch (tag#cands)) else xml_error (STR ''expecting '' + default_showsl_list showsl_lit (tag#cands) (STR '''')) x"
abbreviation xml_any :: "xml xmlt" where "xml_any x ≡ Right (fst x)"
text‹Conditional parsing depending on tag match.›
definition bind2 :: "'a +\<bottom>'b ==> ('a ==> 'c +\<bottom> 'd) ==> ('b ==> 'c +\<bottom> 'd) ==> 'c +\<bottom> 'd"where "bind2 x f g = (case x of Bottom ==> Bottom | Left a ==> f a | Right b ==> g b)"
lemma bind2_cong[fundef_cong]: "x = y ==> (∧ a. y = Left a ==> f1 a = f2 a) ==> (∧ b. y = Right b ==> g1 b = g2 b) ==> bind2 x f1 g1 = bind2 y f2 g2" by (cases x, auto simp: bind2_def)
lemma bind2_code[code]: "bind2 (sumbot a) f g = (case a of Inl a ==> f a | Inr b ==> g b)" by (cases a) (auto simp: bind2_def)
definition xml_or (infixr‹XMLor›51) where "xml_or p1 p2 x ≡ case x of (x1,atts,flag,cands,rest) ==> ( bind2 (p1 (x1,atts,True,cands,rest)) (λ err1. case err1 of TagMismatch cands1 ==> p2 (x1,atts,flag,cands1,rest) | err1 ==> Left err1) Right)"
definition xml_do :: "ltag ==> 'a xmlst ==> 'a xmlt"where "xml_do tag p x ≡ case x of (XML nam atts xmls, _, flag, cands, pos) ==> if nam = String.explode tag then p (xmls,atts,False,[],tag#pos) ― ‹inner tag mismatch is not allowed› else mismatch tag ([fst x], snd x) | _ ==> mismatch tag ([fst x], snd x)"
text‹parses the first child› definition xml_take :: "'a xmlt ==> ('a ==> 'b xmlst) ==> 'b xmlst" where"xml_take p1 p2 x ≡ case x of ([],rest) ==> ( ― ‹Only for accumulating expected tags.› bind2 (p1 (XML [] [] [], rest)) Left (λ a. Left (Fatal (STR ''unexpected''))) ) | (x#xs,atts,flag,cands,rest) ==> ( bind2 (p1 (x,atts,flag,cands,rest)) Left (λ a. p2 a (xs,atts,False,[],rest))) ― ‹If one child is parsed, then later mismatch is not allowed›"
definition xml_take_text :: "(string ==> 'a xmlst) ==> 'a xmlst" where "xml_take_text p xs ≡ case xs of (XML_text text # xmls, s) ==> p text (xmls,s)
| _ ==> xml_error (STR ''expecting a text'') xs"
definition xml_take_int :: "(int ==> 'a xmlst) ==> 'a xmlst" where "xml_take_int p xs ≡ case xs of (XML_text text # xmls, s) ==>
(case int_of_string text of Inl x ==> xml_error x xs | Inr n ==> p n (xmls,s))
| _ ==> xml_error (STR ''expecting an integer'') xs"
definition xml_take_nat :: "(nat ==> 'a xmlst) ==> 'a xmlst" where "xml_take_nat p xs ≡ case xs of (XML_text text # xmls, s) ==>
(case nat_of_string text of Inl x ==> xml_error x xs | Inr n ==> p n (xmls,s))
| _ ==> xml_error (STR ''expecting a number'') xs"
definition xml_leaf where "xml_leaf tag ret ≡ xml_do tag (xml_return ret)"
definition xml_text :: "ltag ==> string xmlt" where "xml_text tag ≡ xml_do tag (xml_take_text xml_return)"
definition xml_int :: "ltag ==> int xmlt" where "xml_int tag ≡ xml_do tag (xml_take_int xml_return)"
definition xml_nat :: "ltag ==> nat xmlt" where "xml_nat tag ≡ xml_do tag (xml_take_nat xml_return)"
definition bool_of_string :: "string ==> String.literal + bool" where "bool_of_string s ≡ if s = ''true'' then Inr True
else if s = ''false'' then Inr False
else Inl (STR ''cannot convert \"'' + String.implode s + STR ''\" into Boolean'')"
definition xml_bool :: "ltag ==> bool xmlt" where "xml_bool tag x ≡
bind2 (xml_text tag x) Left
(λ str. ( case bool_of_string str of Inr b ==> Right b
| Inl err ==> xml_error err ([fst x], snd x)
))"
definition xml_change :: "'a xmlt ==> ('a ==> 'b xmlst) ==> 'b xmlt" where "xml_change p f x ≡
bind2 (p x) Left (λ a. case x of (_,rest) ==> f a ([],rest))"
text ‹ Parses the first child, if tag matches. \<close> definition xml_take_optional :: " a xmlt ==> ('a option ==> 'b xmlst) ==> 'b xmlst"
where "xml_take_optional p1 p2 xs ≡
case xs of ([],_) ==> p2 None xs
| (xml # xmls, atts, allow, cands, rest) ==>
bind2 (p1 (xml, atts, True, cands, rest))
(λ e. case e of
TagMismatch cands1 ==> p2 None (xml#xmls, atts, allow, cands1, rest) ― ‹TagMismatch is allowed›
| _ ==> Left e)
(λ a. p2 (Some a) (xmls, atts, False, [], rest))"
xml_take_default :: "'a ==> 'a xmlt ==> ('a ==> 'b xmlst) ==> 'b xmlst"
where "xml_take_default a p1 p2 xs ≡
case xs of ([],_) ==> p2 a xs
| (xml # xmls, atts, allow, cands, rest) ==> (
bind2 (p1 (xml, atts, True, cands, rest))
(λ e. case e of
TagMismatch cands1 ==> p2 a (xml#xmls, atts, allow, cands1, rest) ― ‹TagMismatch is allowed›
| _ ==> Left e)
(λa. p2 a (xmls, atts, False, [], rest)))"
‹Take first children, as many as tag matches.›
xml_take_many_sub :: "'a list ==> nat ==> enat ==> 'a xmlt ==> ('a list ==> 'b xmlst) ==> 'b xmlst" where
"xml_take_many_sub acc minOccurs maxOccurs p1 p2 ([], atts, allow, rest) = (
if minOccurs = 0 then p2 (rev acc) ([], atts, allow, rest)
else ― ‹only for nice error log›
bind2 (p1 (XML [] [] [], atts, False, rest)) Left (λ _. Left (Fatal (STR ''unexpected'')))
)"
"xml_take_many_sub acc minOccurs maxOccurs p1 p2 (xml # xmls, atts, allow, cands, rest) = (
if maxOccurs = 0 then p2 (rev acc) (xml # xmls, atts, allow, cands, rest)
else
bind2 (p1 (xml, atts, minOccurs = 0, cands, rest))
(λ e. case e of
TagMismatch tags ==> p2 (rev acc) (xml # xmls, atts, allow, cands, rest)
| _ ==> Left e)
(λ a. xml_take_many_sub (a # acc) (minOccurs-1) (maxOccurs-1) p1 p2 (xmls, atts, False, [], rest))
)"
xml_take_many where "xml_take_many ≡ xml_take_many_sub []"
pick_up where
"pick_up rest key [] = None"
"pick_up rest key ((l,r)#s) = (if key = l then Some (r,rest@s) else pick_up ((l,r)#rest) key s)"
xml_take_attribute :: "ltag ==> (string ==> 'a xmlst) ==> 'a xmlst"
where "xml_take_attribute att p xs ≡
case xs of (xmls,atts,allow,cands,pos) ==> (
case pick_up [] (String.explode att) atts of
None ==> xml_error (STR ''attribute \"'' + att + STR ''\" not found'') xs
| Some(v,rest) ==> p v (xmls,rest,allow,cands,pos)
)"
xml_take_attribute_optional :: "ltag ==> (string option ==> 'a xmlst) ==> 'a xmlst"
where "xml_take_attribute_optional att p xs ≡
case xs of (xmls,atts,info) ==> (
case pick_up [] (String.explode att) atts of
None ==> p None xs
| Some(v,rest) ==> p (Some v) (xmls,rest,info)
)"
xml_take_attribute_default :: "string ==> ltag ==> (string ==> 'a xmlst) ==> 'a xmlst"
where "xml_take_attribute_default def att p xs ≡
case xs of (xmls,atts,info) ==> (
case pick_up [] (String.explode att) atts of
None ==> p def xs
| Some(v,rest) ==> p v (xmls,rest,info)
)"
parse_xml :: "'a xmlt ==> xml ==> string +\⊥ 'a"
where "parse_xml p xml ≡
bind2 (xml_take p xml_return ([xml],[],False,[],[]))
(Left o xml_error_to_string) Right"
(*BEGIN: special chars*) subsection‹Handling of special characters in text›
fun extract_special where "extract_special acc [] = None"
| "extract_special acc (x # xs) = (if x = CHR '';'' then map_option (λs. (s, xs)) (special_map (rev acc)) else extract_special (x#acc) xs)"
lemma extract_special_length [termination_simp]: assumes"extract_special acc xs = Some (y, ys)" shows"length ys < length xs" using assms by (induct acc xs rule: extract_special.induct) (auto split: if_splits)
fun normalize_special where "normalize_special [] = []"
| "normalize_special (x # xs) = (if x = CHR ''&'' then (case extract_special [] xs of None ==> ''&'' @ normalize_special xs | Some (spec, ys) ==> spec @ normalize_special ys) else x # normalize_special xs)"
fun map_xml_text :: "(string ==> string) ==> xml ==> xml" where "map_xml_text f (XML t as cs) = XML t as (map (map_xml_text f) cs)"
| "map_xml_text f (XML_text txt) = XML_text (f txt)" (*END: special chars*)
definition parse_xml_string :: "'a xmlt ==> string ==> string +\<bottom> 'a" where "parse_xml_string p str ≡ case doc_of_string str of Inl err ==> Left err | Inr (XMLDOC header xml) ==> parse_xml p (map_xml_text normalize_special xml)"
subsection‹For Terminating Parsers›
(*TODO: replace the default size of xml *) primrec size_xml where"size_xml (XML_text str) = size str"
| "size_xml (XML tag atts xmls) = 1 + size tag + (∑xml ← xmls. size_xml xml)"
lemma size_xml_nth [dest]: "i < length xmls ==> size_xml (xmls!i) ≤ sum_list (map size_xml xmls)" using elem_le_sum_list[of _ "map Xmlt.size_xml _", unfolded length_map] by auto
lemma xml_or_cong[fundef_cong]: assumes"∧info. p (fst x, info) = p' (fst x, info)" and"∧info. q (fst x, info) = q' (fst x, info)" and"x = x'" shows"(p XMLor q) x = (p' XMLor q') x'" using assms by (cases x, auto simp: xml_or_def intro!: Option.bind_cong split:sum.split xml_error.split)
lemma xml_do_cong[fundef_cong]: fixes p :: "'a xmlst" assumes"∧tag' atts xmls info. fst x = XML tag' atts xmls ==> String.explode tag = tag' ==> p (xmls,atts,info) = p' (xmls,atts,info)" and"x = x'" shows"xml_do tag p x = xml_do tag p' x'" using assms by (cases x, auto simp: xml_do_def split: xml.split)
lemma xml_take_cong[fundef_cong]: fixes p :: "'a xmlt"and q :: "'a ==> 'b xmlst" assumes"∧a as info. fst x = a#as ==> p (a, info) = p' (a, info)" and"∧a as ret info info'. x' = (a#as,info) ==> q ret (as, info') = q' ret (as, info')" and"∧info. p (XML [] [] [], info) = p' (XML [] [] [], info)" and"x = x'" shows"xml_take p q x = xml_take p' q' x'" using assms by (cases x, auto simp: xml_take_def intro!: Option.bind_cong split: list.split sum.split)
lemma xml_take_many_cong[fundef_cong]: fixes p :: "'a xmlt"and q :: "'a list ==> 'b xmlst" assumes p: "∧n info. n < length (fst x) ==> p (fst x' ! n, info) = p' (fst x' ! n, info)" and err: "∧info. p (XML [] [] [], info) = p' (XML [] [] [], info)" and q: "∧ret n info. q ret (drop n (fst x'), info) = q' ret (drop n (fst x'), info)" and xx': "x = x'" shows"xml_take_many_sub ret minOccurs maxOccurs p q x = xml_take_many_sub ret minOccurs maxOccurs p' q' x'" proof- obtain as b where x: "x = (as,b)"by (cases x, auto) show ?thesis proof (insert p q, fold xx', unfold x, induct as arbitrary: b minOccurs maxOccurs ret) case Nil with err show ?caseby (cases b, auto intro!: Option.bind_cong) next case (Cons a as) from Cons(2,3)[where n=0] Cons(2,3)[where n="Suc n"for n] show ?caseby (cases b, auto intro!: bind2_cong Cons(1) split: sum.split xml_error.split) qed qed
lemma xml_take_optional_cong[fundef_cong]: fixes p :: "'a xmlt"and q :: "'a option ==> 'b xmlst" assumes"∧a as info. fst x = a # as ==> p (a, info) = p' (a, info)" and"∧a as ret info. fst x = a # as ==> q (Some ret) (as, info) = q' (Some ret) (as, info)" and"∧info. q None (fst x', info) = q' None (fst x', info)" and xx': "x = x'" shows"xml_take_optional p q x = xml_take_optional p' q' x'" using assms by (cases x', auto simp: xml_take_optional_def split: list.split sum.split xml_error.split intro!: bind2_cong)
lemma xml_take_default_cong[fundef_cong]: fixes p :: "'a xmlt"and q :: "'a ==> 'b xmlst" assumes"∧a as info. fst x = a # as ==> p (a, info) = p' (a, info)" and"∧a as ret info. fst x = a # as ==> q ret (as, info) = q' ret (as, info)" and"∧info. q d (fst x', info) = q' d (fst x', info)" and xx': "x = x'" shows"xml_take_default d p q x = xml_take_default d p' q' x'" using assms by (cases x', auto simp: xml_take_default_def split: list.split sum.split xml_error.split intro!: bind2_cong)
lemma xml_change_cong[fundef_cong]: assumes"x = x'" and"p x' = p' x'" and"∧ret y. p x = Right ret ==> q ret y = q' ret y" shows"xml_change p q x = xml_change p' q' x'" using assms by (cases x', auto simp: xml_change_def split: option.split sum.split intro!: bind2_cong)
lemma if_cong_applied[fundef_cong]: "b = c ==> (c ==> x z = u w) ==> (¬ c ==> y z = v w) ==> z = w ==> (if b then x else y) z = (if c then u else v) w" by auto
lemma option_case_cong[fundef_cong]: "option = option' ==> (option' = None ==> f1 z = g1 w) ==> (∧x2. option' = Some x2 ==> f2 x2 z = g2 x2 w) ==> z = w ==> (case option of None ==> f1 | Some x2 ==> f2 x2) z = (case option' of None ==> g1 | Some x2 ==> g2 x2) w" by (cases option, auto)
lemma sum_case_cong[fundef_cong]: "s = ss ==> (∧x1. ss = Inl x1 ==> f1 x1 z = g1 x1 w) ==> (∧x2. ss = Inr x2 ==> f2 x2 z = g2 x2 w) ==> z = w ==> (case s of Inl x1 ==> f1 x1 | Inr x2 ==> f2 x2) z = (case ss of Inl x1 ==> g1 x1 | Inr x2 ==> g2 x2) w" by (cases s, auto)
lemma prod_case_cong[fundef_cong]: "p = pp ==> (∧x1 x2. pp = (x1, x2) ==> f x1 x2 z = g x1 x2 w) ==> (case p of (x1, x2) ==> f x1 x2) z = (case pp of (x1, x2) ==> g x1 x2) w" by (auto split: prod.split)
text‹Mononicity rules of combinators for partial-function command.›
lemma bind2_mono [partial_function_mono]: assumes p0: "mono_sum_bot p0" assumes p1: "∧y. mono_sum_bot (p1 y)" assumes p2: "∧y. mono_sum_bot (p2 y)" shows"mono_sum_bot (λg. bind2 (p0 g) (λy. p1 y g) (λy. p2 y g))" proof (rule monotoneI) fix f g :: "'a ==> 'b +\<bottom> 'c" assume fg: "fun_ord sum_bot_ord f g" with p0 have"sum_bot_ord (p0 f) (p0 g)"by (rule monotoneD[of _ _ _ f g]) thenhave"sum_bot_ord (bind2 (p0 f) (λ y. p1 y f) (λ y. p2 y f)) (bind2 (p0 g) (λ y. p1 y f) (λ y. p2 y f))" unfolding flat_ord_def bind2_def by auto alsofrom p1 have"∧ y'. sum_bot_ord (p1 y' f) (p1 y' g)" by (rule monotoneD) (rule fg) thenhave"sum_bot_ord (bind2 (p0 g) (λ y. p1 y f) (λ y. p2 y f)) (bind2 (p0 g) (λ y. p1 y g) (λ y. p2 y f))" unfolding flat_ord_def by (cases "p0 g") (auto simp: bind2_def) also (sum_bot.leq_trans) from p2 have"∧ y'. sum_bot_ord (p2 y' f) (p2 y' g)" by (rule monotoneD) (rule fg) thenhave"sum_bot_ord (bind2 (p0 g) (λ y. p1 y g) (λ y. p2 y f)) (bind2 (p0 g) (λ y. p1 y g) (λ y. p2 y g))" unfolding flat_ord_def by (cases "p0 g") (auto simp: bind2_def) finally (sum_bot.leq_trans) show"sum_bot_ord (bind2 (p0 f) (λy. p1 y f) (λy. p2 y f)) (bind2 (p0 g) (λya. p1 ya g) (λya. p2 ya g))" . qed
lemma xml_or_mono [partial_function_mono]: assumes p1: "∧y. mono_sum_bot (p1 y)" assumes p2: "∧y. mono_sum_bot (p2 y)" shows"mono_sum_bot (λg. xml_or (λy. p1 y g) (λy. p2 y g) x)" using p1 unfolding xml_or_def by (cases x, auto simp: xml_or_def intro!: partial_function_mono,
intro monotoneI, auto split: xml_error.splits simp: sum_bot.leq_refl dest: monotoneD[OF p2])
lemma xml_do_mono [partial_function_mono]: assumes p1: "∧y. mono_sum_bot (p1 y)" shows"mono_sum_bot (λg. xml_do t (λy. p1 y g) x)" by (cases x, cases "fst x") (auto simp: xml_do_def intro!: partial_function_mono p1)
lemma xml_take_mono [partial_function_mono]: assumes p1: "∧y. mono_sum_bot (p1 y)" assumes p2: "∧x z. mono_sum_bot (λ y. p2 z x y)" shows"mono_sum_bot (λg. xml_take (λy. p1 y g) (λ x y. p2 x y g) x)" proof (cases x) case (fields a b c d e) show ?thesis unfolding xml_take_def fields split by (cases a, auto intro!: partial_function_mono p2 p1) qed
lemma xml_take_default_mono [partial_function_mono]: assumes p1: "∧y. mono_sum_bot (p1 y)" assumes p2: "∧x z. mono_sum_bot (λ y. p2 z x y)" shows"mono_sum_bot (λg. xml_take_default a (λy. p1 y g) (λ x y. p2 x y g) x)" proof (cases x) case (fields a b c d e) show ?thesis unfolding xml_take_default_def fields split by (cases a, auto intro!: partial_function_mono p2 p1, intro monotoneI,
auto split: xml_error.splits simp: sum_bot.leq_refl dest: monotoneD[OF p2]) qed
lemma xml_take_optional_mono [partial_function_mono]: assumes p1: "∧y. mono_sum_bot (p1 y)" assumes p2: "∧x z. mono_sum_bot (λ y. p2 z x y)" shows"mono_sum_bot (λg. xml_take_optional (λy. p1 y g) (λ x y. p2 x y g) x)" proof (cases x) case (fields a b c d e) show ?thesis unfolding xml_take_optional_def fields split by (cases a, auto intro!: partial_function_mono p2 p1, intro monotoneI,
auto split: xml_error.splits simp: sum_bot.leq_refl dest: monotoneD[OF p2]) qed
lemma xml_change_mono [partial_function_mono]: assumes p1: "∧y. mono_sum_bot (p1 y)" assumes p2: "∧x z. mono_sum_bot (λ y. p2 z x y)" shows"mono_sum_bot (λg. xml_change (λy. p1 y g) (λ x y. p2 x y g) x)" unfolding xml_change_def by (intro partial_function_mono p1, cases x, auto intro: p2)
lemma xml_take_many_sub_mono [partial_function_mono]: assumes p1: "∧y. mono_sum_bot (p1 y)" assumes p2: "∧x z. mono_sum_bot (λ y. p2 z x y)" shows"mono_sum_bot (λg. xml_take_many_sub a b c (λy. p1 y g) (λ x y. p2 x y g) x)" proof - obtain xs atts allow cands rest where x: "x = (xs, atts, allow, cands, rest)"by (cases x) show ?thesis unfolding x proof (induct xs arbitrary: a b c atts allow rest cands) case Nil show ?caseby (auto intro!: partial_function_mono p1 p2) next case (Cons x xs) show ?caseunfolding xml_take_many_sub.simps by (auto intro!: partial_function_mono p2 p1 Cons, intro monotoneI,
auto split: xml_error.splits simp: sum_bot.leq_refl dest: monotoneD[OF p2]) qed qed
partial_function (sum_bot) xml_foldl :: "('a ==> 'b xmlt) ==> ('a ==> 'b ==> 'a) ==> 'a ==> 'a xmlst"where
[code]: "xml_foldl p f a xs = (case xs of ([],_) ==> Right a | _ ==> xml_take (p a) (λ b. xml_foldl p f (f a b)) xs)"
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.