Theory Byte_Level_Encoding.Focus_Parser
theory Focus_Parser
imports Lenses_And_Other_Optics.Focus Lenses_And_Other_Optics.List_Optics Lenses_And_Other_Optics.Array_Optics
begin
section‹Focus parsers›
subsection‹Definition›
datatype ('a, 'r) focus_parser
= FocusParser (run_parser: ‹('a, 'r × 'a) focus›)
subsection‹Parser combinators›
text‹Parsers can be sequenced:›
lift_definition iso_focus_prod_assoc :: ‹('a × 'b × 'c, ('a × 'b) × 'c) focus› is
‹iso⇩∫ (λ(x,y,z). ((x,y),z)) (λ((x,y),z). (x,y,z))›
by (simp add: case_prod_beta iso_focus_raw_valid)
text‹Use eta expansion during code generation to avoid ML value restriction:›
definition iso_focus_prod_assoc_lazy :: ‹unit ⇒ ('a × 'b × 'c, ('a × 'b) × 'c) focus› where
‹iso_focus_prod_assoc_lazy _ = iso_focus_prod_assoc›
declare iso_focus_prod_assoc_lazy_def [of ‹()›, symmetric, code_unfold]
declare iso_focus_prod_assoc_lazy_def [THEN arg_cong[where f="Rep_focus"], simplified iso_focus_prod_assoc.rep_eq, code]
lemma iso_focus_prod_components[focus_components]:
shows ‹focus_view iso_focus_prod_assoc (x,y,z) = Some ((x,y),z)›
and ‹focus_update iso_focus_prod_assoc ((x,y),z) t = (x,y,z)›
by (transfer; clarsimp simp add: iso_focus_raw_components)+
definition focus_parser_sequence :: ‹('a, 'r) focus_parser ⇒ ('a, 's) focus_parser ⇒
('a, 'r × 's) focus_parser› (infixl "--⇩∫" 58) where
‹focus_parser_sequence p0 p1 ≡ FocusParser (run_parser p0 ⋄ (id⇩∫ ×⇩∫ run_parser p1) ⋄ iso_focus_prod_assoc)›
text‹Parsers can be refined by applying a focus to a parsing result:›
definition focus_parser_map :: ‹('a, 'r) focus_parser ⇒ ('r, 's) focus ⇒
('a, 's) focus_parser› (infixl ">>⇩∫" 61) where
‹focus_parser_map p0 f ≡ FocusParser (run_parser p0 ⋄ (f ×⇩∫ id⇩∫))›
text‹With sequencing and forgetting, we can build a sequence combinator for parsers which forgets
the result of one of the two parsers:›
abbreviation focus_parser_sequence_forgetL :: ‹('a, 'r) focus_parser ⇒ ('a, 's) focus_parser ⇒
('a, 's) focus_parser› (infixl "|--⇩∫" 58) where
‹focus_parser_sequence_forgetL p0 p1 ≡ (p0 --⇩∫ p1) >>⇩∫ snd⇩∫›
abbreviation focus_parser_sequence_forgetR :: ‹('a, 'r) focus_parser ⇒ ('a, 's) focus_parser ⇒
('a, 'r) focus_parser› (infixl "--|⇩∫" 58) where
‹focus_parser_sequence_forgetR p0 p1 ≡ (p0 --⇩∫ p1) >>⇩∫ fst⇩∫›
bundle code_parser_notation
begin
notation focus_parser_sequence (infixl "--" 58)
notation focus_parser_map (infixl ">>" 61)
notation focus_parser_sequence_forgetR (infixl "--|" 58)
notation focus_parser_sequence_forgetL (infixl "|--" 58)
end
subsection‹Closing a parser›
text‹After parsing, we can forget the remaining data to obtain a focus onto the target value type:›
definition run_parser_partial :: ‹('a, 'r) focus_parser ⇒ ('a, 'r) focus› where
‹run_parser_partial p ≡ run_parser p ⋄ fst⇩∫›
text‹We may also want to check that we have consumed all data before closing the parser:›
definition run_parser_all :: ‹('a list, 'r) focus_parser ⇒ ('a list, 'r) focus› where
‹run_parser_all p ≡ run_parser p ⋄ (id⇩∫ ×⇩∫ list_empty_focus) ⋄ fst⇩∫›
subsection‹Basic parsers›
text‹Parse a single element from a list:›
definition parse_single :: ‹('a list, 'a) focus_parser› where
[code_unfold]: ‹parse_single ≡ FocusParser list_nonempty_focus›
text‹Parse a fixed number of elements off a list, into an array:›
definition parse_array :: ‹('a list, ('a, 'l::{len}) array) focus_parser› where
‹parse_array ≡ FocusParser list_minlen_focus›
abbreviation parse_array2 :: ‹('a list, ('a, 2) array) focus_parser› where
‹parse_array2 ≡ parse_array›
abbreviation parse_array4 :: ‹('a list, ('a, 4) array) focus_parser› where
‹parse_array4 ≡ parse_array›
abbreviation parse_array8 :: ‹('a list, ('a, 8) array) focus_parser› where
‹parse_array8 ≡ parse_array›
end