From f5c7ff30039eddadaf01468d96926a11e9bad538 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Tue, 13 Aug 2024 19:14:17 -0700 Subject: [PATCH] Start bootstrapping the hocc parser --- bootstrap/bin/hocc/ParseLR.hmh | 1611 ++++++++++++++++++++++++++++++++ 1 file changed, 1611 insertions(+) create mode 100644 bootstrap/bin/hocc/ParseLR.hmh diff --git a/bootstrap/bin/hocc/ParseLR.hmh b/bootstrap/bin/hocc/ParseLR.hmh new file mode 100644 index 00000000..9e530346 --- /dev/null +++ b/bootstrap/bin/hocc/ParseLR.hmh @@ -0,0 +1,1611 @@ +open Basis +open! Basis.Rudiments + +module X = struct (* XXX Workaround for qualified type syntax limitation. *) +type uident = + | Uident of {uident: Scan.Token.t} + and cident = + | Cident of {cident: Scan.Token.t} + and ident = + | IdentUident of {uident: uident} + | IdentCident of {cident: cident} + | IdentUscore of {uscore: Scan.Token.t} + and precs_tl = + | PrecsTlCommaUident of {comma: Scan.Token.t; uident: uident; precs_tl: precs_tl} + | PrecsTlEpsilon + and precs = + | Precs of {uident: uident; precs_tl: precs_tl} + and prec_rels = + | PrecRelsLtPrecs of {lt: Scan.Token.t; precs: precs} + | PrecRelsEpsilon + and prec_type = + | PrecTypeNeutral of {neutral_: Scan.Token.t} + | PrecTypeLeft of {left_: Scan.Token.t} + | PrecTypeRight of {right_: Scan.Token.t} + and prec_ = + | Prec of {prec_type: prec_type; uident: uident; prec_rels: prec_rels} + and of_type = + | OfType of {of_: Scan.Token.t; type_module: cident; dot: Scan.Token.t; type_type: uident} + and of_type0 = + | OfType0OfType of {of_type: of_type} + | OfType0Epsilon + and prec_ref = + | PrecRefPrecUident of {prec_: Scan.Token.t; uident: uident} + | PrecRefEpsilon + and token_alias = + | TokenAlias of {alias: Scan.Token.t} + | TokenAliasEpsilon + and token_ = + | Token of {token_: Scan.Token.t; cident: cident; token_alias: token_alias; of_type0: of_type0; + prec_ref: prec_ref} + and sep = + | SepLineDelim of {line_delim: Scan.Token.t} + | SepSemi of {semi: Scan.Token.t} + | SepBar of {bar: Scan.Token.t} + and codes_tl = + | CodesTlSepCode of {sep: sep; code: code; codes_tl: codes_tl} + | CodesTlEpsilon + and codes = + | Codes of {code: code; codes_tl: codes_tl} + and codes0 = + | Codes0Codes of {codes: codes} + | Codes0Epsilon + and delimited = + | DelimitedBlock of {indent: Scan.Token.t; codes: codes; dedent: Scan.Token.t} + | DelimitedParen of {lparen: Scan.Token.t; codes0: codes0; rparen: Scan.Token.t} + | DelimitedCapture of {lcapture: Scan.Token.t; codes0: codes0; rcapture: Scan.Token.t} + | DelimitedList of {lbrack: Scan.Token.t; codes0: codes0; rbrack: Scan.Token.t} + | DelimitedArray of {larray: Scan.Token.t; codes0: codes0; rarray: Scan.Token.t} + | DelimitedModule of {lcurly: Scan.Token.t; codes0: codes0; rcurly: Scan.Token.t} + and code_tl = + | CodeTlDelimited of {delimited: delimited; code_tl: code_tl} + | CodeTlToken of {token_: Scan.Token.t; code_tl: code_tl} + | CodeTlEpsilon + and code = + | CodeDelimited of {delimited: delimited; code_tl: code_tl} + | CodeToken of {token_: Scan.Token.t; code_tl: code_tl} + and prod_param_symbol = + | ProdParamSymbolCident of {cident: cident} + | ProdParamSymbolAlias of {alias: Scan.Token.t} + and prod_param = + | ProdParamBinding of {ident: ident; colon: Scan.Token.t; prod_param_symbol: prod_param_symbol} + | ProdParam of {prod_param_symbol: prod_param_symbol} + and prod_params_tl = + | ProdParamsTlProdParam of {prod_param: prod_param; prod_params_tl: prod_params_tl} + | ProdParamsTlEpsilon + and prod_params = + | ProdParamsProdParam of {prod_param: prod_param; prod_params_tl: prod_params_tl} + and prod_pattern = + | ProdPatternParams of {prod_params: prod_params} + | ProdPatternEpsilon of {epsilon_: Scan.Token.t} + and prod = + | Prod of {prod_pattern: prod_pattern; prec_ref: prec_ref} + and prods_tl = + | ProdsTlBarProd of {bar: Scan.Token.t; prod: prod; prods_tl: prods_tl} + | ProdsTlEpsilon + and prods = + | ProdsBarProd of {bar: Scan.Token.t; prod: prod; prods_tl: prods_tl} + | ProdsProd of {prod: prod; prods_tl: prods_tl} + and reduction = + | Reduction of {prods: prods; arrow: Scan.Token.t; code: code} + and reductions_tl = + | ReductionsTlBarReduction of {bar: Scan.Token.t; reduction: reduction; + reductions_tl: reductions_tl} + | ReductionsTlEpsilon + and reductions = + | ReductionsReduction of {reduction: reduction; reductions_tl: reductions_tl} + and nonterm_type = + | NontermTypeNonterm of {nonterm_: Scan.Token.t} + | NontermTypeStart of {start_: Scan.Token.t} + and nonterm_ = + | NontermProds of {nonterm_type: nonterm_type; cident: cident; prec_ref: prec_ref; + cce: Scan.Token.t; prods: prods} + | NontermReductions of {nonterm_type: nonterm_type; cident: cident; of_type: of_type; + prec_ref: prec_ref; cce: Scan.Token.t; reductions: reductions} + and stmt = + | StmtPrec of {prec_: prec_} + | StmtToken of {token_: token_} + | StmtNonterm of {nonterm_: nonterm_} + | StmtCode of {code: code} + and stmts_tl = + | StmtsTl of {line_delim: Scan.Token.t; stmt: stmt; stmts_tl: stmts_tl} + | StmtsTlEpsilon + and stmts = + | Stmts of {stmt: stmt; stmts_tl: stmts_tl} + and hocc_ = + | Hocc of {hocc_: Scan.Token.t; indent: Scan.Token.t; stmts: stmts; dedent: Scan.Token.t} + and eoi = + | Eoi of {eoi: Scan.Token.t} + and matter = + | Matter of {token_: Scan.Token.t; matter: matter} + | MatterEpsilon + and hmh = + | Hmh of {prelude: matter; hocc_: hocc_; postlude: matter; eoi: eoi} + and hmhi = + | Hmhi of {prelude: matter; hocc_: Scan.Token.t; postlude: matter; eoi: eoi} + end + +(* XXX Workaround for lack of parser support for `Scan.Token.t` as token type. *) +module ScanToken = Scan.Token + +include hocc + (* hocc-specific keywords *) + token HOCC "hocc" of ScanToken.t + token NONTERM "nonterm" of ScanToken.t + token EPSILON_ "epsilon" of ScanToken.t + token START "start" of ScanToken.t + token TOKEN "token" of ScanToken.t + token NEUTRAL "neutral" of ScanToken.t + token LEFT "left" of ScanToken.t + token RIGHT "right" of ScanToken.t + token PREC "prec" of ScanToken.t + + (* Identifiers *) + token UIDENT of ScanToken.t # Uncapitalized + token CIDENT of ScanToken.t # Capitalized + token USCORE "_" of ScanToken.t + + (* Token alias *) + token STRING of ScanToken.t + + (* Punctuation/separators *) + token COLON_COLON_EQ "::=" of ScanToken.t + token OF "of" of ScanToken.t + token COLON ":" of ScanToken.t + token DOT "." of ScanToken.t + token ARROW "->" of ScanToken.t + token BAR "|" of ScanToken.t + token LT "<" of ScanToken.t + token COMMA "," of ScanToken.t + token SEMI ";" of ScanToken.t + token LINE_DELIM of ScanToken.t + + (* Left-right paired delimiters *) + token INDENT of ScanToken.t + token DEDENT of ScanToken.t + token LPAREN "(" of ScanToken.t + token RPAREN ")" of ScanToken.t + token LCAPTURE "(|" of ScanToken.t + token RCAPTURE "|)" of ScanToken.t + token LBRACK "[" of ScanToken.t + token RBRACK "]" of ScanToken.t + token LARRAY "[|" of ScanToken.t + token RARRAY "|]" of ScanToken.t + token LCURLY "{" of ScanToken.t + token RCURLY "}" of ScanToken.t + + (* Miscellaneous Hemlock token in embedded code *) + token CODE_TOKEN of ScanToken.t + + (* End of input, used to terminate start symbols *) + token EOI of ScanToken.t + + nonterm Uident of X.uident ::= + | uident:UIDENT -> Uident {uident} + + nonterm Cident of X.cident ::= + | cident:CIDENT -> Cident {cident} + + nonterm Ident of X.ident ::= + | uident:Uident -> IdentUident {uident} + | cident:Cident -> IdentCident {cident} + | uscore:"_" -> IdentUscore {uscore} + + nonterm PrecsTl of X.precs_tl ::= + | comma:"," uident:Uident precs_tl:PrecsTl -> PrecsTlCommaUident {comma; uident; precs_tl} + | epsilon -> PrecsTlEpsilon + + nonterm Precs of X.precs ::= + | uident:Uident precs_tl:PrecsTl -> Precs {uident; precs_tl} + + nonterm PrecRels of X.prec_rels ::= + | lt:"<" precs:Precs -> PrecRelsLtPrecs {lt; precs} + | epsilon -> PrecRelsEpsilon + + nonterm PrecType of X.prec_type ::= + | neutral_:"neutral" -> PrecTypeNeutral {neutral_} + | left_:"left" -> PrecTypeLeft {left_} + | right_:"right" -> PrecTypeRight {right_} + + nonterm Prec of X.prec_ ::= + | prec_type:PrecType uident:Uident prec_rels:PrecRels -> Prec {prec_type; uident; prec_rels} + + nonterm OfType of X.of_type ::= + | of_:"of" type_module:Cident dot:"." type_type:Uident -> + OfType {of_; type_module; dot; type_type} + + nonterm OfType0 of X.of_type0 ::= + | of_type:OfType -> OfType0OfType {of_type} + | epsilon -> OfType0Epsilon + + nonterm PrecRef of X.prec_ref ::= + | prec_:"prec" uident:Uident -> PrecRefPrecUident {prec_; uident} + | epsilon -> PrecRefEpsilon + + nonterm TokenAlias of X.token_alias ::= + | alias:STRING -> TokenAlias {alias} + | epsilon -> TokenAliasEpsilon + + nonterm Token of X.token_ ::= + | token_:"token" cident:Cident token_alias:TokenAlias of_type0:OfType0 prec_ref:PrecRef -> + Token {token_; cident; token_alias; of_type0; prec_ref} + + nonterm Sep of X.sep ::= + | line_delim:LINE_DELIM -> SepLineDelim {line_delim} + | semi:";" -> SepSemi {semi} + | bar:"|" -> SepBar {bar} + + nonterm CodesTl of X.codes_tl ::= + | sep:Sep code:Code codes_tl:CodesTl -> CodesTlSepCode {sep; code; codes_tl} + | epsilon -> CodesTlEpsilon + + nonterm Codes of X.codes ::= + | code:Code codes_tl:CodesTl -> Codes {code; codes_tl} + + nonterm Codes0 of X.codes0 ::= + | codes:Codes -> Codes0Codes {codes} + | epsilon -> Codes0Epsilon + + nonterm Delimited of X.delimited ::= + | indent:INDENT codes:Codes dedent:DEDENT -> DelimitedBlock {indent; codes; dedent} + | lparen:"(" codes0:Codes0 rparen:")" -> DelimitedParen {lparen; codes0; rparen} + | lcapture:"(|" codes0:Codes0 rcapture:"|)" -> DelimitedCapture {lcapture; codes0; rcapture} + | lbrack:"[" codes0:Codes0 rbrack:"]" -> DelimitedList {lbrack; codes0; rbrack} + | larray:"[|" codes0:Codes0 rarray:"|]" -> DelimitedArray {larray; codes0; rarray} + | lcurly:"{" codes0:Codes0 rcurly:"}" -> DelimitedModule {lcurly; codes0; rcurly} + + nonterm CodeTl of X.code_tl ::= + | delimited:Delimited code_tl:CodeTl -> CodeTlDelimited {delimited; code_tl} + | token_:CODE_TOKEN code_tl:CodeTl -> CodeTlToken {token_; code_tl} + | epsilon -> CodeTlEpsilon + + nonterm Code of X.code ::= + | delimited:Delimited code_tl:CodeTl -> CodeDelimited {delimited; code_tl} + | token_:CODE_TOKEN code_tl:CodeTl -> CodeToken {token_; code_tl} + + nonterm ProdParamSymbol of X.prod_param_symbol ::= + | cident:Cident -> ProdParamSymbolCident {cident} + | alias:STRING -> ProdParamSymbolAlias {alias} + + nonterm ProdParam of X.prod_param ::= + | ident:Ident colon:":" prod_param_symbol:ProdParamSymbol -> + ProdParamBinding {ident; colon; prod_param_symbol} + | prod_param_symbol:ProdParamSymbol -> ProdParam {prod_param_symbol} + + nonterm ProdParamsTl of X.prod_params_tl ::= + | prod_param:ProdParam prod_params_tl:ProdParamsTl -> + ProdParamsTlProdParam {prod_param; prod_params_tl} + | epsilon -> ProdParamsTlEpsilon + + nonterm ProdParams of X.prod_params ::= + | prod_param:ProdParam prod_params_tl:ProdParamsTl -> + ProdParamsProdParam {prod_param; prod_params_tl} + + nonterm ProdPattern of X.prod_pattern ::= + | prod_params:ProdParams -> ProdPatternParams {prod_params} + | epsilon_:"epsilon" -> ProdPatternEpsilon {epsilon_} + + nonterm Prod of X.prod ::= + | prod_pattern:ProdPattern prec_ref:PrecRef -> Prod {prod_pattern; prec_ref} + + nonterm ProdsTl of X.prods_tl ::= + | bar:"|" prod:Prod prods_tl:ProdsTl -> ProdsTlBarProd {bar; prod; prods_tl} + | epsilon -> ProdsTlEpsilon + + nonterm Prods of X.prods ::= + | bar:"|" prod:Prod prods_tl:ProdsTl -> ProdsBarProd {bar; prod; prods_tl} + | prod:Prod prods_tl:ProdsTl -> ProdsProd {prod; prods_tl} + + nonterm Reduction of X.reduction ::= + | prods:Prods arrow:"->" code:Code -> Reduction {prods; arrow; code} + + nonterm ReductionsTl of X.reductions_tl ::= + | bar:"|" reduction:Reduction reductions_tl:ReductionsTl -> + ReductionsTlBarReduction {bar; reduction; reductions_tl} + | epsilon -> ReductionsTlEpsilon + + nonterm Reductions of X.reductions ::= + | reduction:Reduction reductions_tl:ReductionsTl -> + ReductionsReduction {reduction; reductions_tl} + + nonterm NontermType of X.nonterm_type ::= + | nonterm_:"nonterm" -> NontermTypeNonterm {nonterm_} + | start_:"start" -> NontermTypeStart {start_} + + nonterm Nonterm of X.nonterm_ ::= + | nonterm_type:NontermType cident:Cident prec_ref:PrecRef cce:"::=" prods:Prods -> + NontermProds {nonterm_type; cident; prec_ref; cce; prods} + | nonterm_type:NontermType cident:Cident of_type:OfType prec_ref:PrecRef cce:"::=" + reductions:Reductions -> + NontermReductions {nonterm_type; cident; of_type; prec_ref; cce; reductions} + + nonterm Stmt of X.stmt ::= + | prec_:Prec -> StmtPrec {prec_} + | token_:Token -> StmtToken {token_} + | nonterm_:Nonterm -> StmtNonterm {nonterm_} + | code:Code -> StmtCode {code} + + nonterm StmtsTl of X.stmts_tl ::= + | line_delim:LINE_DELIM stmt:Stmt stmts_tl:StmtsTl -> StmtsTl {line_delim; stmt; stmts_tl} + | epsilon -> StmtsTlEpsilon + + nonterm Stmts of X.stmts ::= + | stmt:Stmt stmts_tl:StmtsTl -> Stmts {stmt; stmts_tl} + + nonterm Hocc of X.hocc_ ::= + | hocc_:"hocc" indent:INDENT stmts:Stmts dedent:DEDENT -> Hocc {hocc_; indent; stmts; dedent} + + nonterm Eoi of X.eoi ::= + | eoi:EOI -> Eoi {eoi} + + nonterm Matter of X.matter ::= + | token_:CODE_TOKEN matter:Matter -> Matter {token_; matter} + | epsilon -> MatterEpsilon + + start Hmh of X.hmh ::= + | prelude:Matter hocc_:Hocc postlude:Matter eoi:Eoi -> Hmh {prelude; hocc_; postlude; eoi} + + start Hmhi of X.hmhi ::= + | prelude:Matter hocc_:"hocc" postlude:Matter eoi:Eoi -> Hmhi {prelude; hocc_; postlude; eoi} + +let hmh scanner = + let rec inner scanner parser = begin + let scanner', tok = Scan.next scanner in + (* XXX Wrap scanner token in parser Token constructor. *) + let {status; _} as parser' = next tok parser in + match status with + | Prefix -> inner scanner' parser' + | Accept (Hmh hmh) -> scanner', (hmh, []) + | Reject _ -> halt "Parse error" + | _ -> not_reached () + end in + let parser = Start.Hmh.boi in + inner scanner parser + +(**************************************************************************************************) +(* source_of_* functions. *) + +(* Not to be confused with joining forces. *) +let join_sources source0_opt source1_opt = + match source0_opt, source1_opt with + | None, None -> None + | Some _, None -> source0_opt + | None, Some _ -> source1_opt + | Some source0, Some source1 -> begin + let open Hmc.Source in + let base0, past0 = Slice.cursors source0 in + let base1, past1 = Slice.cursors source1 in + let open Cmp in + let base = match Cursor.cmp base0 base1 with + | Lt + | Eq -> base0 + | Gt -> base1 + in + let past = match Cursor.cmp past0 past1 with + | Lt + | Eq -> past1 + | Gt -> past0 + in + Some (Slice.of_cursors ~base ~past) + end + +(* Not to be confused with a token force. *) +let token_source token_ = + Some (Scan.Token.source token_) + +let rec source_of_uident = function + | Uident {uident} -> token_source uident + + and source_of_cident = function + | Cident {cident} -> token_source cident + + and source_of_ident = function + | IdentUident {uident} -> source_of_uident uident + | IdentCident {cident} -> source_of_cident cident + | IdentUscore {uscore} -> token_source uscore + + and source_of_precs_tl = function + | PrecsTlCommaUident {comma; uident; precs_tl} -> + token_source comma + |> join_sources (source_of_uident uident) + |> join_sources (source_of_precs_tl precs_tl) + | PrecsTlEpsilon -> None + + and source_of_precs = function + | Precs {uident; precs_tl} -> + source_of_uident uident + |> join_sources (source_of_precs_tl precs_tl) + + and source_of_prec_rels = function + | PrecRelsLtPrecs {lt; precs} -> + token_source lt + |> join_sources (source_of_precs precs) + | PrecRelsEpsilon -> None + + and source_of_prec_type = function + | PrecTypeNeutral {neutral_} -> token_source neutral_ + | PrecTypeLeft {left_} -> token_source left_ + | PrecTypeRight {right_} -> token_source right_ + + and source_of_prec = function + | Prec {prec_type; uident; prec_rels} -> + source_of_prec_type prec_type + |> join_sources (source_of_uident uident) + |> join_sources (source_of_prec_rels prec_rels) + + and source_of_of_type = function + | OfType {of_; type_module=_; dot; type_type} -> + token_source of_ + |> join_sources (token_source dot) + |> join_sources (source_of_uident type_type) + + and source_of_of_type0 = function + | OfType0OfType {of_type} -> source_of_of_type of_type + | OfType0Epsilon -> None + + and source_of_prec_ref = function + | PrecRefPrecUident {prec_; uident} -> + token_source prec_ + |> join_sources (source_of_uident uident) + | PrecRefEpsilon -> None + + and source_of_token_alias = function + | TokenAlias {alias} -> token_source alias + | TokenAliasEpsilon -> None + + and source_of_token = function + | Token {token_; cident; token_alias; of_type0; prec_ref} -> + token_source token_ + |> join_sources (source_of_cident cident) + |> join_sources (source_of_token_alias token_alias) + |> join_sources (source_of_of_type0 of_type0) + |> join_sources (source_of_prec_ref prec_ref) + + and source_of_sep = function + | SepLineDelim {line_delim} -> token_source line_delim + | SepSemi {semi} -> token_source semi + | SepBar {bar} -> token_source bar + + and source_of_codes_tl = function + | CodesTlSepCode {sep; code; codes_tl} -> + source_of_sep sep + |> join_sources (source_of_code code) + |> join_sources (source_of_codes_tl codes_tl) + | CodesTlEpsilon -> None + + and source_of_codes = function + | Codes {code; codes_tl} -> + source_of_code code + |> join_sources (source_of_codes_tl codes_tl) + + and source_of_codes0 = function + | Codes0Codes {codes} -> source_of_codes codes + | Codes0Epsilon -> None + + and source_of_delimited = function + | DelimitedBlock {indent=ldelim; codes=_; dedent=rdelim} + | DelimitedParen {lparen=ldelim; codes0=_; rparen=rdelim} + | DelimitedCapture {lcapture=ldelim; codes0=_; rcapture=rdelim} + | DelimitedList {lbrack=ldelim; codes0=_; rbrack=rdelim} + | DelimitedArray {larray=ldelim; codes0=_; rarray=rdelim} + | DelimitedModule {lcurly=ldelim; codes0=_; rcurly=rdelim} -> + token_source ldelim + |> join_sources (token_source rdelim) + + and source_of_code_tl = function + | CodeTlDelimited {delimited; code_tl} -> + source_of_delimited delimited + |> join_sources (source_of_code_tl code_tl) + | CodeTlToken {token_; code_tl} -> + token_source token_ + |> join_sources (source_of_code_tl code_tl) + | CodeTlEpsilon -> None + + and source_of_code = function + | CodeDelimited {delimited; code_tl} -> + source_of_delimited delimited + |> join_sources (source_of_code_tl code_tl) + | CodeToken {token_; code_tl} -> + token_source token_ + |> join_sources (source_of_code_tl code_tl) + + and source_of_prod_param_symbol = function + | ProdParamSymbolCident {cident} -> source_of_cident cident + | ProdParamSymbolAlias {alias} -> token_source alias + + and source_of_prod_param = function + | ProdParamBinding {ident; colon=_; prod_param_symbol} -> + source_of_ident ident + |> join_sources (source_of_prod_param_symbol prod_param_symbol) + | ProdParam {prod_param_symbol} -> + source_of_prod_param_symbol prod_param_symbol + + and source_of_prod_params_tl = function + | ProdParamsTlProdParam {prod_param; prod_params_tl} -> + source_of_prod_param prod_param + |> join_sources (source_of_prod_params_tl prod_params_tl) + | ProdParamsTlEpsilon -> None + + and source_of_prod_params = function + | ProdParamsProdParam {prod_param; prod_params_tl} -> + source_of_prod_param prod_param + |> join_sources (source_of_prod_params_tl prod_params_tl) + + and source_of_prod_pattern = function + | ProdPatternParams {prod_params} -> source_of_prod_params prod_params + | ProdPatternEpsilon {epsilon_} -> token_source epsilon_ + + and source_of_prod = function + | Prod {prod_pattern; prec_ref} -> + source_of_prod_pattern prod_pattern + |> join_sources (source_of_prec_ref prec_ref) + + and source_of_prods_tl = function + | ProdsTlBarProd {bar; prod; prods_tl} -> + token_source bar + |> join_sources (source_of_prod prod) + |> join_sources (source_of_prods_tl prods_tl) + | ProdsTlEpsilon -> None + + and source_of_prods = function + | ProdsBarProd {bar; prod; prods_tl} -> + token_source bar + |> join_sources (source_of_prod prod) + |> join_sources (source_of_prods_tl prods_tl) + | ProdsProd {prod; prods_tl} -> + source_of_prod prod + |> join_sources (source_of_prods_tl prods_tl) + + and source_of_reduction = function + | Reduction {prods; arrow=_; code} -> + source_of_prods prods + |> join_sources (source_of_code code) + + and source_of_reductions_tl = function + | ReductionsTlBarReduction {bar; reduction; reductions_tl} -> + token_source bar + |> join_sources (source_of_reduction reduction) + |> join_sources (source_of_reductions_tl reductions_tl) + | ReductionsTlEpsilon -> None + + and source_of_reductions = function + | ReductionsReduction {reduction; reductions_tl} -> + source_of_reduction reduction + |> join_sources (source_of_reductions_tl reductions_tl) + + and source_of_nonterm_type = function + | NontermTypeNonterm {nonterm_} -> token_source nonterm_ + | NontermTypeStart {start_} -> token_source start_ + + and source_of_nonterm = function + | NontermProds {nonterm_type; cident=_; prec_ref=_; cce=_; prods} -> + source_of_nonterm_type nonterm_type + |> join_sources (source_of_prods prods) + | NontermReductions {nonterm_type; cident=_; of_type=_; prec_ref=_; cce=_; reductions} -> + source_of_nonterm_type nonterm_type + |> join_sources (source_of_reductions reductions) + + and source_of_stmt = function + | StmtPrec {prec_} -> source_of_prec prec_ + | StmtToken {token_} -> source_of_token token_ + | StmtNonterm {nonterm_} -> source_of_nonterm nonterm_ + | StmtCode {code} -> source_of_code code + + and source_of_stmts_tl = function + | StmtsTl {line_delim; stmt; stmts_tl} -> + token_source line_delim + |> join_sources (source_of_stmt stmt) + |> join_sources (source_of_stmts_tl stmts_tl) + | StmtsTlEpsilon -> None + + and source_of_stmts = function + | Stmts {stmt; stmts_tl} -> + source_of_stmt stmt + |> join_sources (source_of_stmts_tl stmts_tl) + + and source_of_hocc = function + | Hocc {hocc_; indent=_; stmts=_; dedent} -> + token_source hocc_ + |> join_sources (token_source dedent) + + and source_of_eoi = function + | Eoi {eoi} -> token_source eoi + + and source_of_matter = function + | Matter {token_; matter} -> + token_source token_ + |> join_sources (source_of_matter matter) + | MatterEpsilon -> None + + and source_of_hmh = function + | Hmh {prelude; hocc_; postlude=_; eoi} -> + source_of_matter prelude + |> join_sources (source_of_hocc hocc_) + |> join_sources (source_of_eoi eoi) + + and source_of_hmhi = function + | Hmhi {prelude; hocc_; postlude=_; eoi} -> + source_of_matter prelude + |> join_sources (token_source hocc_) + |> join_sources (source_of_eoi eoi) + +(**************************************************************************************************) +(* fmt_* functions. *) + +let rec fmt_lcurly ~alt ~width formatter = + match alt with + | false -> formatter |> Fmt.fmt "{" + | true -> + formatter + |> Fmt.fmt "{\n" + |> Fmt.fmt ~pad:" " ~just:Fmt.Left ~width:(width + (extend_of_int 4)) "" + + and fmt_semi ~alt ~width formatter = + match alt with + | false -> formatter |> Fmt.fmt "; " + | true -> + formatter + |> Fmt.fmt "\n" + |> Fmt.fmt ~pad:" " ~just:Fmt.Left ~width:(width + (extend_of_int 4)) "" + + and fmt_rcurly ~alt ~width formatter = + match alt with + | false -> formatter |> Fmt.fmt "}" + | true -> + formatter + |> Fmt.fmt "\n" + |> Fmt.fmt ~pad:" " ~just:Fmt.Left ~width:(width + (extend_of_int 2)) "" + |> Fmt.fmt "}" + + and fmt_uident ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) uident formatter = + match uident with + | Uident {uident} -> + formatter + |> Fmt.fmt "Uident " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "uident=" |> Scan.Token.pp uident + |> fmt_rcurly ~alt ~width + and pp_uident uident formatter = + fmt_uident uident formatter + + and fmt_cident ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) cident formatter = + match cident with + | Cident {cident} -> + formatter + |> Fmt.fmt "Cident " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "cident=" |> Scan.Token.pp cident + |> fmt_rcurly ~alt ~width + and pp_cident cident formatter = + fmt_cident cident formatter + + and fmt_ident ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) ident formatter = + match ident with + | IdentUident {uident} -> + formatter |> Fmt.fmt "IdentUident " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "uident=" |> pp_uident uident + |> fmt_rcurly ~alt ~width + | IdentCident {cident} -> + formatter |> Fmt.fmt "IdentCident " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "cident=" |> pp_cident cident + |> fmt_rcurly ~alt ~width + | IdentUscore {uscore} -> + formatter |> Fmt.fmt "IdentUscore " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "uscore=" |> Scan.Token.pp uscore + |> fmt_rcurly ~alt ~width + and pp_ident ident formatter = + fmt_ident ident formatter + + and fmt_precs_tl ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) precs_tl formatter = + let width' = width + (extend_of_int 4) in + match precs_tl with + | PrecsTlCommaUident {comma; uident; precs_tl} -> + formatter |> Fmt.fmt "PrecsTlCommaUident " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "comma=" |> Scan.Token.pp comma + |> fmt_semi ~alt ~width + |> Fmt.fmt "uident=" |> fmt_uident ~alt ~width:width' uident + |> fmt_semi ~alt ~width + |> Fmt.fmt "precs_tl=" |> fmt_precs_tl ~alt ~width:width' precs_tl + |> fmt_rcurly ~alt ~width + | PrecsTlEpsilon -> + formatter |> Fmt.fmt "PrecsTlEpsilon" + and pp_precs_tl precs_tl formatter = + fmt_precs_tl precs_tl formatter + + and fmt_precs ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) precs formatter = + let width' = width + (extend_of_int 4) in + match precs with + | Precs {uident; precs_tl} -> + formatter |> Fmt.fmt "Precs " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "uident=" |> fmt_uident ~alt ~width:width' uident + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "precs_tl=" |> fmt_precs_tl ~alt ~width:width' precs_tl + |> fmt_rcurly ~alt ~width + and pp_precs precs formatter = + fmt_precs precs formatter + + and fmt_prec_rels ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prec_rels formatter = + let width' = width + (extend_of_int 4) in + match prec_rels with + | PrecRelsLtPrecs {lt; precs} -> + formatter |> Fmt.fmt "PrecRelsLtPrecs " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "lt=" |> Scan.Token.pp lt + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "precs=" |> fmt_precs ~alt ~width:width' precs + |> fmt_rcurly ~alt ~width + | PrecRelsEpsilon -> + formatter |> Fmt.fmt "PrecRelsEpsilon" + and pp_prec_rels prec_rels formatter = + fmt_prec_rels prec_rels formatter + + and fmt_prec_type ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prec_type formatter = + match prec_type with + | PrecTypeNeutral {neutral_} -> + formatter |> Fmt.fmt "PrecTypeNeutral " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "neutral_=" |> Scan.Token.pp neutral_ + |> fmt_rcurly ~alt ~width + | PrecTypeLeft {left_} -> + formatter |> Fmt.fmt "PrecTypeLeft " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "left_=" |> Scan.Token.pp left_ + |> fmt_rcurly ~alt ~width + | PrecTypeRight {right_} -> + formatter |> Fmt.fmt "PrecTypeRight " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "right_=" |> Scan.Token.pp right_ + |> fmt_rcurly ~alt ~width + and pp_prec_type prec_type formatter = + fmt_prec_type prec_type formatter + + and fmt_prec ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prec_ formatter = + let width' = width + (extend_of_int 4) in + match prec_ with + | Prec {prec_type; uident; prec_rels} -> + formatter |> Fmt.fmt "Prec " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prec_type=" |> fmt_prec_type ~alt ~width:width' prec_type + |> fmt_semi ~alt ~width + |> Fmt.fmt "uident=" |> fmt_uident ~alt ~width:width' uident + |> fmt_semi ~alt ~width + |> Fmt.fmt "prec_rels=" |> fmt_prec_rels ~alt ~width:width' prec_rels + |> fmt_rcurly ~alt ~width + and pp_prec prec_ formatter = + fmt_prec prec_ formatter + + and fmt_of_type ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) of_type formatter = + let width' = width + (extend_of_int 4) in + match of_type with + | OfType {of_; type_module; dot; type_type} -> + formatter |> Fmt.fmt "OfType " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "of_=" |> Scan.Token.pp of_ + |> fmt_semi ~alt ~width + |> Fmt.fmt "type_module=" |> fmt_cident ~alt ~width:width' type_module + |> fmt_semi ~alt ~width + |> Fmt.fmt "dot=" |> Scan.Token.pp dot + |> fmt_semi ~alt ~width + |> Fmt.fmt "type_type=" |> fmt_uident ~alt ~width:width' type_type + |> fmt_rcurly ~alt ~width + and pp_of_type of_type formatter = + fmt_of_type of_type formatter + + and fmt_of_type0 ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) of_type0 formatter = + let width' = width + (extend_of_int 4) in + match of_type0 with + | OfType0OfType {of_type} -> + formatter |> Fmt.fmt "OfType0OfType " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "of_type=" |> fmt_of_type ~alt ~width:width' of_type + |> fmt_rcurly ~alt ~width + | OfType0Epsilon -> + formatter |> Fmt.fmt "OfType0Epsilon" + and pp_of_type0 of_type0 formatter = + fmt_of_type0 of_type0 formatter + + and fmt_prec_ref ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prec_ref formatter = + let width' = width + (extend_of_int 4) in + match prec_ref with + | PrecRefPrecUident {prec_; uident} -> + formatter |> Fmt.fmt "PrecRefPrecUident " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prec_=" |> Scan.Token.pp prec_ + |> fmt_semi ~alt ~width + |> Fmt.fmt "uident=" |> fmt_uident ~alt ~width:width' uident + |> fmt_rcurly ~alt ~width + | PrecRefEpsilon -> + formatter |> Fmt.fmt "PrecRefEpsilon" + and pp_prec_ref prec_ref formatter = + fmt_prec_ref prec_ref formatter + + and fmt_token_alias ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) token_alias formatter = + match token_alias with + | TokenAlias {alias} -> + formatter |> Fmt.fmt "Token " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "alias=" |> Scan.Token.pp alias + |> fmt_rcurly ~alt ~width + | TokenAliasEpsilon -> + formatter |> Fmt.fmt "TokenAliasEpsilon" + and pp_token_alias token_alias formatter = + fmt_token_alias token_alias formatter + + and fmt_token ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) token_ formatter = + let width' = width + (extend_of_int 4) in + match token_ with + | Token {token_; cident; token_alias; of_type0; prec_ref} -> + formatter |> Fmt.fmt "Token " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "token_=" |> Scan.Token.pp token_ + |> fmt_semi ~alt ~width + |> Fmt.fmt "cident=" |> fmt_cident ~alt ~width:width' cident + |> fmt_semi ~alt ~width + |> Fmt.fmt "token_alias=" |> fmt_token_alias ~alt ~width:width' token_alias + |> fmt_semi ~alt ~width + |> Fmt.fmt "of_type0=" |> fmt_of_type0 ~alt ~width:width' of_type0 + |> fmt_semi ~alt ~width + |> Fmt.fmt "prec_ref=" |> fmt_prec_ref ~alt ~width:width' prec_ref + |> fmt_rcurly ~alt ~width + and pp_token token_ formatter = + fmt_token token_ formatter + + and fmt_sep ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) sep formatter = + match sep with + | SepLineDelim {line_delim} -> + formatter |> Fmt.fmt "SepLineDelim " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "line_delim=" |> Scan.Token.pp line_delim + |> fmt_rcurly ~alt ~width + | SepSemi {semi} -> + formatter |> Fmt.fmt "SepSemi " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "semi=" |> Scan.Token.pp semi + |> fmt_rcurly ~alt ~width + | SepBar {bar} -> + formatter |> Fmt.fmt "SepBar " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "bar=" |> Scan.Token.pp bar + |> fmt_rcurly ~alt ~width + and pp_sep sep formatter = + fmt_sep sep formatter + + and fmt_codes_tl ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) codes_tl formatter = + let width' = width + (extend_of_int 4) in + match codes_tl with + | CodesTlSepCode {sep; code; codes_tl} -> + formatter |> Fmt.fmt "CodesTlSepCode " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "sep=" |> fmt_sep ~alt ~width:width' sep + |> fmt_semi ~alt ~width + |> Fmt.fmt "code=" |> fmt_code ~alt ~width:width' code + |> fmt_rcurly ~alt ~width + |> Fmt.fmt "codes_tl=" |> fmt_codes_tl ~alt ~width:width' codes_tl + |> fmt_rcurly ~alt ~width + | CodesTlEpsilon -> formatter |> Fmt.fmt "CodesTlEpsilon" + and pp_codes_tl codes_tl formatter = + fmt_codes codes_tl formatter + + and fmt_codes ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) codes formatter = + let width' = width + (extend_of_int 4) in + match codes with + | Codes {code; codes_tl} -> + formatter |> Fmt.fmt "Codes " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "code=" |> fmt_code ~alt ~width:width' code + |> fmt_semi ~alt ~width + |> Fmt.fmt "codes_tl=" |> fmt_codes_tl ~alt ~width:width' codes_tl + |> fmt_rcurly ~alt ~width + and pp_codes codes formatter = + fmt_codes codes formatter + + and fmt_codes0 ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) codes0 formatter = + let width' = width + (extend_of_int 4) in + match codes0 with + | Codes0Codes {codes} -> + formatter |> Fmt.fmt "Codes0Codes " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "codes=" |> fmt_codes ~alt ~width:width' codes + |> fmt_rcurly ~alt ~width + | Codes0Epsilon -> + formatter |> Fmt.fmt "Codes0Epsilon" + and pp_codes0 codes formatter = + fmt_codes codes formatter + + and fmt_delimited ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) delimited formatter = + let width' = width + (extend_of_int 4) in + match delimited with + | DelimitedBlock {indent; codes; dedent} -> + formatter |> Fmt.fmt "DelimitedBlock " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "indent=" |> Scan.Token.pp indent + |> fmt_semi ~alt ~width + |> Fmt.fmt "codes=" |> fmt_codes ~alt ~width:width' codes + |> fmt_semi ~alt ~width + |> Fmt.fmt "dedent=" |> Scan.Token.pp dedent + |> fmt_rcurly ~alt ~width + | DelimitedParen {lparen; codes0; rparen} -> + formatter |> Fmt.fmt "DelimitedParen " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "lparen=" |> Scan.Token.pp lparen + |> fmt_semi ~alt ~width + |> Fmt.fmt "codes0=" |> fmt_codes0 ~alt ~width:width' codes0 + |> fmt_semi ~alt ~width + |> Fmt.fmt "rparen=" |> Scan.Token.pp rparen + |> fmt_rcurly ~alt ~width + | DelimitedCapture {lcapture; codes0; rcapture} -> + formatter |> Fmt.fmt "DelimitedCapture " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "lcapture=" |> Scan.Token.pp lcapture + |> fmt_semi ~alt ~width + |> Fmt.fmt "codes0=" |> fmt_codes0 ~alt ~width:width' codes0 + |> fmt_semi ~alt ~width + |> Fmt.fmt "rcapture=" |> Scan.Token.pp rcapture + |> fmt_rcurly ~alt ~width + | DelimitedList {lbrack; codes0; rbrack} -> + formatter |> Fmt.fmt "DelimitedList " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "lbrack=" |> Scan.Token.pp lbrack + |> fmt_semi ~alt ~width + |> Fmt.fmt "codes0=" |> fmt_codes0 ~alt ~width:width' codes0 + |> fmt_semi ~alt ~width + |> Fmt.fmt "rbrack=" |> Scan.Token.pp rbrack + |> fmt_rcurly ~alt ~width + | DelimitedArray {larray; codes0; rarray} -> + formatter |> Fmt.fmt "DelimitedArray " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "larray=" |> Scan.Token.pp larray + |> fmt_semi ~alt ~width + |> Fmt.fmt "codes0=" |> fmt_codes0 ~alt ~width:width' codes0 + |> fmt_semi ~alt ~width + |> Fmt.fmt "rarray=" |> Scan.Token.pp rarray + |> fmt_rcurly ~alt ~width + | DelimitedModule {lcurly; codes0; rcurly} -> + formatter |> Fmt.fmt "DelimitedModule " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "lcurly=" |> Scan.Token.pp lcurly + |> fmt_semi ~alt ~width + |> Fmt.fmt "codes0=" |> fmt_codes0 ~alt ~width:width' codes0 + |> fmt_semi ~alt ~width + |> Fmt.fmt "rcurly=" |> Scan.Token.pp rcurly + |> fmt_rcurly ~alt ~width + and pp_delimited delimited formatter = + fmt_delimited delimited formatter + + and fmt_code_tl ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) code_tl formatter = + let width' = width + (extend_of_int 4) in + match code_tl with + | CodeTlDelimited {delimited; code_tl} -> + formatter |> Fmt.fmt "CodeTlDelimited " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "delimited=" |> fmt_delimited ~alt ~width:width' delimited + |> fmt_semi ~alt ~width + |> Fmt.fmt "code_tl=" |> fmt_code_tl ~alt ~width:width' code_tl + |> fmt_rcurly ~alt ~width + | CodeTlToken {token_; code_tl} -> + formatter |> Fmt.fmt "CodeTlToken " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "token_=" |> Scan.Token.pp token_ + |> fmt_semi ~alt ~width + |> Fmt.fmt "code_tl=" |> fmt_code_tl ~alt ~width:width' code_tl + |> fmt_rcurly ~alt ~width + | CodeTlEpsilon -> + formatter |> Fmt.fmt "CodeTlEpsilon" + and pp_code_tl code_tl formatter = + fmt_code code_tl formatter + + and fmt_code ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) code formatter = + let width' = width + (extend_of_int 4) in + match code with + | CodeDelimited {delimited; code_tl} -> + formatter |> Fmt.fmt "CodeDelimited " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "delimited=" |> fmt_delimited ~alt ~width:width' delimited + |> fmt_semi ~alt ~width + |> Fmt.fmt "code_tl=" |> fmt_code_tl ~alt ~width:width' code_tl + |> fmt_rcurly ~alt ~width + | CodeToken {token_; code_tl} -> + formatter |> Fmt.fmt "CodeToken " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "token_=" |> Scan.Token.pp token_ + |> fmt_semi ~alt ~width + |> Fmt.fmt "code_tl=" |> fmt_code_tl ~alt ~width:width' code_tl + |> fmt_rcurly ~alt ~width + and pp_code code formatter = + fmt_code code formatter + + and fmt_prod_param_symbol ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prod_param_symbol + formatter = + let width' = width + (extend_of_int 4) in + match prod_param_symbol with + | ProdParamSymbolCident {cident} -> + formatter |> Fmt.fmt "ProdParamSymbolCident " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "cident=" |> fmt_cident ~alt ~width:width' cident + |> fmt_rcurly ~alt ~width + | ProdParamSymbolAlias {alias} -> + formatter |> Fmt.fmt "ProdParamSymbolAlias " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "alias=" |> Scan.Token.pp alias + |> fmt_rcurly ~alt ~width + and pp_prod_param_symbol prod_param_symbol formatter = + fmt_prod_param_symbol prod_param_symbol formatter + + and fmt_prod_param ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prod_param formatter = + let width' = width + (extend_of_int 4) in + match prod_param with + | ProdParamBinding {ident; colon; prod_param_symbol} -> + formatter |> Fmt.fmt "ProdParam " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "ident=" |> fmt_ident ~alt ~width:width' ident + |> fmt_semi ~alt ~width + |> Fmt.fmt "colon=" |> Scan.Token.pp colon + |> fmt_semi ~alt ~width + |> Fmt.fmt "prod_param_symbol=" + |> fmt_prod_param_symbol ~alt ~width:width' prod_param_symbol + |> fmt_rcurly ~alt ~width + | ProdParam {prod_param_symbol} -> + formatter |> Fmt.fmt "ProdParam " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prod_param_symbol=" + |> fmt_prod_param_symbol ~alt ~width:width' prod_param_symbol + |> fmt_rcurly ~alt ~width + and pp_prod_param prod_param formatter = + fmt_prod_param prod_param formatter + + and fmt_prod_params_tl ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prod_params_tl + formatter = + let width' = width + (extend_of_int 4) in + match prod_params_tl with + | ProdParamsTlProdParam {prod_param; prod_params_tl} -> + formatter |> Fmt.fmt "ProdParamsTlProdParam " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prod_param=" |> fmt_prod_param ~alt ~width:width' prod_param + |> fmt_semi ~alt ~width + |> Fmt.fmt "prod_params_tl=" |> fmt_prod_params_tl ~alt ~width:width' prod_params_tl + |> fmt_rcurly ~alt ~width + | ProdParamsTlEpsilon -> + formatter |> Fmt.fmt "ProdParamsTlEpsilon" + and pp_prod_params_tl prod_params_tl formatter = + fmt_prod_params_tl prod_params_tl formatter + + and fmt_prod_params ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prod_params formatter = + let width' = width + (extend_of_int 4) in + match prod_params with + | ProdParamsProdParam {prod_param; prod_params_tl} -> + formatter |> Fmt.fmt "ProdParamsProdParam " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prod_param=" |> fmt_prod_param ~alt ~width:width' prod_param + |> fmt_semi ~alt ~width + |> Fmt.fmt "prod_params_tl=" |> fmt_prod_params_tl ~alt ~width:width' prod_params_tl + |> fmt_rcurly ~alt ~width + and pp_prod_params prod_params formatter = + fmt_prod_params prod_params formatter + + and fmt_prod_pattern ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prod_pattern formatter = + let width' = width + (extend_of_int 4) in + match prod_pattern with + | ProdPatternParams {prod_params} -> + formatter |> Fmt.fmt "ProdPatternParams " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prod_params=" |> fmt_prod_params ~alt ~width:width' prod_params + |> fmt_rcurly ~alt ~width + | ProdPatternEpsilon {epsilon_} -> + formatter |> Fmt.fmt "ProdPatternEpsilon " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "epsilon_=" |> Scan.Token.pp epsilon_ + |> fmt_rcurly ~alt ~width + and pp_prod_pattern prod_pattern formatter = + fmt_prod_pattern prod_pattern formatter + + and fmt_prod ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prod formatter = + let width' = width + (extend_of_int 4) in + match prod with + | Prod {prod_pattern; prec_ref} -> + formatter |> Fmt.fmt "Prod " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prod_pattern=" |> fmt_prod_pattern ~alt ~width:width' prod_pattern + |> fmt_semi ~alt ~width + |> Fmt.fmt "prec_ref=" |> fmt_prec_ref ~alt ~width:width' prec_ref + |> fmt_rcurly ~alt ~width + and pp_prod prod formatter = + fmt_prod prod formatter + + and fmt_prods_tl ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prods_tl formatter = + let width' = width + (extend_of_int 4) in + match prods_tl with + | ProdsTlBarProd {bar; prod; prods_tl} -> + formatter |> Fmt.fmt "ProdsTlBarProd " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "bar=" |> Scan.Token.pp bar + |> fmt_semi ~alt ~width + |> Fmt.fmt "prod=" |> fmt_prod ~alt ~width:width' prod + |> fmt_semi ~alt ~width + |> Fmt.fmt "prods_tl=" |> fmt_prods_tl ~alt ~width:width' prods_tl + |> fmt_rcurly ~alt ~width + | ProdsTlEpsilon -> + formatter |> Fmt.fmt "ProdsTlEpsilon" + and pp_prods_tl prods_tl formatter = + fmt_prods_tl prods_tl formatter + + and fmt_prods ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) prods formatter = + let width' = width + (extend_of_int 4) in + match prods with + | ProdsBarProd {bar; prod; prods_tl} -> + formatter |> Fmt.fmt "ProdsBarProd " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "bar=" |> Scan.Token.pp bar + |> fmt_semi ~alt ~width + |> Fmt.fmt "prod=" |> fmt_prod ~alt ~width:width' prod + |> fmt_semi ~alt ~width + |> Fmt.fmt "prods_tl=" |> fmt_prods_tl ~alt ~width:width' prods_tl + |> fmt_rcurly ~alt ~width + | ProdsProd {prod; prods_tl} -> + formatter |> Fmt.fmt "ProdsProd " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prod=" |> fmt_prod ~alt ~width:width' prod + |> fmt_semi ~alt ~width + |> Fmt.fmt "prods_tl=" |> fmt_prods_tl ~alt ~width:width' prods_tl + |> fmt_rcurly ~alt ~width + and pp_prods prods formatter = + fmt_prods prods formatter + + and fmt_reduction ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) reduction formatter = + let width' = width + (extend_of_int 4) in + match reduction with + | Reduction {prods; arrow; code} -> + formatter |> Fmt.fmt "Reduction " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prods=" |> fmt_prods ~alt ~width:width' prods + |> fmt_semi ~alt ~width + |> Fmt.fmt "arrow=" |> Scan.Token.pp arrow + |> fmt_semi ~alt ~width + |> Fmt.fmt "code=" |> pp_code code + |> fmt_rcurly ~alt ~width + and pp_reduction reduction formatter = + fmt_reduction reduction formatter + + and fmt_reductions_tl ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) reductions_tl formatter = + let width' = width + (extend_of_int 4) in + match reductions_tl with + | ReductionsTlBarReduction {bar; reduction; reductions_tl} -> + formatter |> Fmt.fmt "ReductionsTlBarReduction " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "bar=" |> Scan.Token.pp bar + |> fmt_semi ~alt ~width + |> Fmt.fmt "reduction=" |> fmt_reduction ~alt ~width:width' reduction + |> fmt_semi ~alt ~width + |> Fmt.fmt "reductions_tl=" |> fmt_reductions_tl ~alt ~width:width' reductions_tl + |> fmt_rcurly ~alt ~width + | ReductionsTlEpsilon -> + formatter |> Fmt.fmt "ReductionsTlEpsilon" + and pp_reductions_tl reductions_tl formatter = + fmt_reductions_tl reductions_tl formatter + + and fmt_reductions ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) reductions formatter = + let width' = width + (extend_of_int 4) in + match reductions with + | ReductionsReduction {reduction; reductions_tl} -> + formatter |> Fmt.fmt "ReductionsReduction " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "reduction=" |> fmt_reduction ~alt ~width:width' reduction + |> fmt_semi ~alt ~width + |> Fmt.fmt "reductions_tl=" |> fmt_reductions_tl ~alt ~width:width' reductions_tl + |> fmt_rcurly ~alt ~width + and pp_reductions reductions formatter = + fmt_reductions reductions formatter + + and fmt_nonterm_type ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) nonterm_type formatter = + match nonterm_type with + | NontermTypeNonterm {nonterm_} -> + formatter |> Fmt.fmt "NontermTypeNonterm " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "nonterm_=" |> Scan.Token.pp nonterm_ + |> fmt_rcurly ~alt ~width + | NontermTypeStart {start_} -> + formatter |> Fmt.fmt "NontermTypeStart " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "start_=" |> Scan.Token.pp start_ + |> fmt_rcurly ~alt ~width + and pp_nonterm_type nonterm_type formatter = + fmt_nonterm_type nonterm_type formatter + + and fmt_nonterm ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) nonterm_ formatter = + let width' = width + (extend_of_int 4) in + match nonterm_ with + | NontermProds {nonterm_type; cident; prec_ref; cce; prods} -> + formatter |> Fmt.fmt "NontermProds " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "nonterm_type=" |> fmt_nonterm_type ~alt ~width:width' nonterm_type + |> fmt_semi ~alt ~width + |> Fmt.fmt "cident=" |> fmt_cident ~alt ~width:width' cident + |> fmt_semi ~alt ~width + |> Fmt.fmt "prec_ref=" |> fmt_prec_ref ~alt ~width:width' prec_ref + |> fmt_semi ~alt ~width + |> Fmt.fmt "cce=" |> Scan.Token.pp cce + |> fmt_semi ~alt ~width + |> Fmt.fmt "prods=" |> fmt_prods ~alt ~width:width' prods + |> fmt_rcurly ~alt ~width + | NontermReductions {nonterm_type; cident; of_type; prec_ref; cce; reductions} -> + formatter |> Fmt.fmt "NontermReductions " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "nonterm_type=" |> fmt_nonterm_type ~alt ~width:width' nonterm_type + |> fmt_semi ~alt ~width + |> Fmt.fmt "cident=" |> fmt_cident ~alt ~width:width' cident + |> fmt_semi ~alt ~width + |> Fmt.fmt "of_type=" |> fmt_of_type ~alt ~width:width' of_type + |> fmt_semi ~alt ~width + |> Fmt.fmt "prec_ref=" |> fmt_prec_ref ~alt ~width:width' prec_ref + |> fmt_semi ~alt ~width + |> Fmt.fmt "cce=" |> Scan.Token.pp cce + |> fmt_semi ~alt ~width + |> Fmt.fmt "reductions=" |> fmt_reductions ~alt ~width:width' reductions + |> fmt_rcurly ~alt ~width + and pp_nonterm nonterm_ formatter = + fmt_nonterm nonterm_ formatter + + and fmt_stmt ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) stmt formatter = + let width' = width + (extend_of_int 4) in + match stmt with + | StmtPrec {prec_} -> + formatter |> Fmt.fmt "StmtPrec " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prec_=" |> fmt_prec ~alt ~width:width' prec_ + |> fmt_rcurly ~alt ~width + | StmtToken {token_} -> + formatter |> Fmt.fmt "StmtToken " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "token_=" |> fmt_token ~alt ~width:width' token_ + |> fmt_rcurly ~alt ~width + | StmtNonterm {nonterm_} -> + formatter |> Fmt.fmt "StmtNonterm " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "nonterm_=" |> fmt_nonterm ~alt ~width:width' nonterm_ + |> fmt_rcurly ~alt ~width + | StmtCode {code} -> + formatter |> Fmt.fmt "StmtCode " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "code=" |> fmt_code ~alt ~width:width' code + |> fmt_rcurly ~alt ~width + and pp_stmt stmt formatter = + fmt_stmt stmt formatter + + and fmt_stmts_tl ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) stmts_tl formatter = + let width' = width + (extend_of_int 4) in + match stmts_tl with + | StmtsTl {line_delim; stmt; stmts_tl} -> + formatter |> Fmt.fmt "StmtsTl " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "line_delim=" |> Scan.Token.pp line_delim + |> fmt_semi ~alt ~width + |> Fmt.fmt "stmt=" |> fmt_stmt ~alt ~width:width' stmt + |> fmt_semi ~alt ~width + |> Fmt.fmt "stmts_tl=" |> fmt_stmts_tl ~alt ~width:width' stmts_tl + |> fmt_rcurly ~alt ~width + | StmtsTlEpsilon -> + formatter |> Fmt.fmt "StmtsTlEpsilon" + and pp_stmts_tl stmts_tl formatter = + fmt_stmts_tl stmts_tl formatter + + and fmt_stmts ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) stmts formatter = + let width' = width + (extend_of_int 4) in + match stmts with + | Stmts {stmt; stmts_tl} -> + formatter |> Fmt.fmt "Stmts " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "stmt=" |> fmt_stmt ~alt ~width:width' stmt + |> fmt_semi ~alt ~width + |> Fmt.fmt "stmts_tl=" |> fmt_stmts_tl ~alt ~width:width' stmts_tl + |> fmt_rcurly ~alt ~width + and pp_stmts stmts formatter = + fmt_stmts stmts formatter + + and fmt_hocc ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) hocc_ formatter = + let width' = width + (extend_of_int 4) in + match hocc_ with + | Hocc {hocc_; indent; stmts; dedent} -> + formatter |> Fmt.fmt "Hocc " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "hocc_=" |> Scan.Token.pp hocc_ + |> fmt_semi ~alt ~width + |> Fmt.fmt "indent=" |> Scan.Token.pp indent + |> fmt_semi ~alt ~width + |> Fmt.fmt "stmts=" |> fmt_stmts ~alt ~width:width' stmts + |> fmt_semi ~alt ~width + |> Fmt.fmt "dedent=" |> Scan.Token.pp dedent + |> fmt_rcurly ~alt ~width + and pp_hocc hocc_ formatter = + fmt_hocc hocc_ formatter + + and fmt_eoi ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) eoi formatter = + match eoi with + | Eoi {eoi} -> + formatter |> Fmt.fmt "Eoi " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "eoi=" |> Scan.Token.pp eoi + |> fmt_rcurly ~alt ~width + and pp_eoi eoi formatter = + fmt_eoi eoi formatter + + and fmt_matter ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) matter formatter = + let width' = width + (extend_of_int 4) in + match matter with + | Matter {token_; matter} -> + formatter |> Fmt.fmt "Matter " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "token_=" |> Scan.Token.pp token_ + |> fmt_semi ~alt ~width + |> Fmt.fmt "matter=" |> fmt_matter ~alt ~width:width' matter + |> fmt_rcurly ~alt ~width + | MatterEpsilon -> + formatter |> Fmt.fmt "MatterEpsilon" + and pp_matter matter formatter = + fmt_matter matter formatter + + and fmt_hmh ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) hmh formatter = + let width' = width + (extend_of_int 4) in + match hmh with + | Hmh {prelude; hocc_; postlude; eoi} -> + formatter |> Fmt.fmt "Hmh " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prelude=" |> pp_matter prelude + |> fmt_semi ~alt ~width + |> Fmt.fmt "hocc_=" |> fmt_hocc ~alt ~width:width' hocc_ + |> fmt_semi ~alt ~width + |> Fmt.fmt "postlude=" |> pp_matter postlude + |> fmt_semi ~alt ~width + |> Fmt.fmt "eoi=" |> fmt_eoi ~alt ~width:width' eoi + |> fmt_rcurly ~alt ~width + and pp_hmh hmh formatter = + fmt_hmh hmh formatter + + and fmt_hmhi ?(alt=Fmt.alt_default) ?(width=Fmt.width_default) hmhi formatter = + let width' = width + (extend_of_int 4) in + match hmhi with + | Hmhi {prelude; hocc_; postlude; eoi} -> + formatter |> Fmt.fmt "Hmhi " + |> fmt_lcurly ~alt ~width + |> Fmt.fmt "prelude=" |> pp_matter prelude + |> fmt_semi ~alt ~width + |> Fmt.fmt "hocc_=" |> Scan.Token.pp hocc_ + |> fmt_semi ~alt ~width + |> Fmt.fmt "postlude=" |> pp_matter postlude + |> fmt_semi ~alt ~width + |> Fmt.fmt "eoi=" |> fmt_eoi ~alt ~width:width' eoi + |> fmt_rcurly ~alt ~width + and pp_hmhi hmhi formatter = + fmt_hmhi hmhi formatter + +(**************************************************************************************************) +(* Miscellaneous helper functions. *) + +let min_comment_indentation_of_hocc_block = function + | Hocc {indent; _} -> + Scan.Token.source indent + |> Hmc.Source.Slice.base + |> Hmc.Source.Cursor.pos + |> Text.Pos.col + +let base_of_code code = + let of_token token_ = + let open Scan.Token in + let source = match token_ with + | HmcToken ctok -> ctok |> Hmc.Scan.ConcreteToken.source + | HoccToken ctok -> ctok |> Scan.ConcreteToken.source + in + Hmc.Source.Slice.base source + in + let rec of_delimited = function + | DelimitedBlock {indent=token_; _} + | DelimitedParen {lparen=token_; _} + | DelimitedCapture {lcapture=token_; _} + | DelimitedList {lbrack=token_; _} + | DelimitedArray {larray=token_; _} + | DelimitedModule {lcurly=token_; _} -> of_token token_ + and of_code = function + | CodeDelimited {delimited; _} -> of_delimited delimited + | CodeToken {token_; _} -> of_token token_ + in + of_code code + +let last_token_of_code hocc_block code = + let min_comment_indentation = min_comment_indentation_of_hocc_block hocc_block in + let rec of_codes_tl = function + | CodesTlSepCode {code; codes_tl; _} -> begin + of_codes_tl codes_tl + |> Option.some_or_thunk ~f:(fun () -> Some (of_code code)) + end + | CodesTlEpsilon -> None + and of_codes = function + | Codes {code; codes_tl} -> begin + of_codes_tl codes_tl + |> Option.value_or_thunk ~f:(fun () -> of_code code) + end + and of_delimited = function + | DelimitedBlock {codes; dedent; _} -> begin + of_codes codes + |> Option.some_or_thunk ~f:(fun () -> Some dedent) + |> Option.value_hlt + end + | DelimitedParen {rparen=token_; _} + | DelimitedCapture {rcapture=token_; _} + | DelimitedList {rbrack=token_; _} + | DelimitedArray {rarray=token_; _} + | DelimitedModule {rcurly=token_; _} -> token_ + and of_code_tl = function + | CodeTlDelimited {delimited; code_tl} -> + of_code_tl code_tl + |> Option.some_or_thunk ~f:(fun () -> Some (of_delimited delimited)) + | CodeTlToken {token_; code_tl} -> begin + of_code_tl code_tl + |> Option.some_or_thunk ~f:(fun () -> + (* Exclude comments less indented than `hocc` block from the tail. *) + match token_ with + | HmcToken ctok -> begin + match Hmc.Scan.ConcreteToken.atok ctok with + | Tok_hash_comment + | Tok_paren_comment _ -> begin + let ctok_indentation = + ctok + |> Hmc.Scan.ConcreteToken.source + |> Hmc.Source.Slice.base + |> Hmc.Source.Cursor.pos + |> Text.Pos.col + in + match ctok_indentation >= min_comment_indentation with + | true -> Some token_ + | false -> None + end + | _ -> Some token_ + end + | HoccToken _ -> Some token_ + ) + end + | CodeTlEpsilon -> None + and of_code = function + | CodeDelimited {delimited; code_tl} -> + of_code_tl code_tl |> Option.some_or_thunk ~f:(fun () -> Some (of_delimited delimited)) + | CodeToken {token_; code_tl} -> + of_code_tl code_tl |> Option.some_or_thunk ~f:(fun () -> Some token_) + in + of_code code + |> Option.value_hlt + +let past_of_code hocc_block code = + let of_token token_ = + let open Scan.Token in + let source = match token_ with + | HmcToken ctok -> ctok |> Hmc.Scan.ConcreteToken.source + | HoccToken ctok -> ctok |> Scan.ConcreteToken.source + in + Hmc.Source.Slice.past source + in + last_token_of_code hocc_block code + |> of_token + +let source_of_code hocc_block code = + let base = base_of_code code in + let past = past_of_code hocc_block code in + Hmc.Source.Slice.of_cursors ~base ~past + +let indentation_of_code hocc_block code = + let min_comment_indentation = min_comment_indentation_of_hocc_block hocc_block in + match code with + | CodeDelimited _ -> min_comment_indentation + (extend_of_int 4) + | CodeToken _ -> min_comment_indentation + +(* Find the base cursor for the postlude that preserves comments/whitespace that fall outside the + * `hocc` block. *) +let postlude_base_of_hocc (Hocc {stmts=Stmts {stmt; stmts_tl}; _} as hocc_block) = + let rec of_uident = function + | Uident {uident} -> uident + and of_cident = function + | Cident {cident} -> cident + and of_precs_tl = function + | PrecsTlCommaUident {uident; precs_tl; _} -> + Some ( + of_precs_tl precs_tl + |> Option.value_or_thunk ~f:(fun () -> of_uident uident) + ) + | PrecsTlEpsilon -> None + and of_precs = function + | Precs {uident; precs_tl} -> begin + of_precs_tl precs_tl + |> Option.value_or_thunk ~f:(fun () -> of_uident uident) + end + and of_prec_rels = function + | PrecRelsLtPrecs {precs; _} -> Some (of_precs precs) + | PrecRelsEpsilon -> None + and of_of_type = function + | OfType {type_type; _} -> of_uident type_type + and of_of_type0 = function + | OfType0OfType {of_type} -> Some (of_of_type of_type) + | OfType0Epsilon -> None + and of_prec_ref = function + | PrecRefPrecUident {uident; _} -> Some (of_uident uident) + | PrecRefEpsilon -> None + and of_token_alias = function + | TokenAlias {alias} -> Some alias + | TokenAliasEpsilon -> None + and of_prod_param_symbol = function + | ProdParamSymbolCident {cident} -> of_cident cident + | ProdParamSymbolAlias {alias} -> alias + and of_prod_param = function + | ProdParamBinding {prod_param_symbol; _} + | ProdParam {prod_param_symbol} -> of_prod_param_symbol prod_param_symbol + and of_prod_params_tl = function + | ProdParamsTlProdParam {prod_param; prod_params_tl} -> begin + of_prod_params_tl prod_params_tl + |> Option.some_or_thunk ~f:(fun () -> Some (of_prod_param prod_param)) + end + | ProdParamsTlEpsilon -> None + and of_prod_params = function + | ProdParamsProdParam {prod_param; prod_params_tl} -> begin + of_prod_params_tl prod_params_tl + |> Option.value_or_thunk ~f:(fun () -> of_prod_param prod_param) + end + and of_prod_pattern = function + | ProdPatternParams {prod_params} -> of_prod_params prod_params + | ProdPatternEpsilon {epsilon_} -> epsilon_ + and of_prod = function + | Prod {prod_pattern; prec_ref} -> begin + of_prec_ref prec_ref + |> Option.value_or_thunk ~f:(fun () -> of_prod_pattern prod_pattern) + end + and of_prods_tl = function + | ProdsTlBarProd {prod; prods_tl; _} -> begin + of_prods_tl prods_tl + |> Option.some_or_thunk ~f:(fun () -> Some (of_prod prod)) + end + | ProdsTlEpsilon -> None + and of_prods = function + | ProdsBarProd {prod; prods_tl; _} + | ProdsProd {prod; prods_tl} -> begin + of_prods_tl prods_tl + |> Option.value_or_thunk ~f:(fun () -> of_prod prod) + end + and of_reduction = function + | Reduction {code; _} -> last_token_of_code hocc_block code + and of_reductions_tl = function + | ReductionsTlBarReduction {reduction; reductions_tl; _} -> begin + of_reductions_tl reductions_tl + |> Option.some_or_thunk ~f:(fun () -> Some (of_reduction reduction)) + end + | ReductionsTlEpsilon -> None + and of_reductions = function + | ReductionsReduction {reduction; reductions_tl} -> begin + of_reductions_tl reductions_tl + |> Option.value_or_thunk ~f:(fun () -> of_reduction reduction) + end + and of_nonterm = function + | NontermProds {prods; _} -> of_prods prods + | NontermReductions {reductions; _} -> of_reductions reductions + and of_stmt = function + | StmtPrec {prec_=Prec {uident; prec_rels; _}} -> begin + of_prec_rels prec_rels + |> Option.value_or_thunk ~f:(fun () -> of_uident uident) + end + | StmtToken {token_=Token {cident; token_alias; of_type0; prec_ref; _}} -> begin + of_prec_ref prec_ref + |> Option.some_or_thunk ~f:(fun () -> of_of_type0 of_type0) + |> Option.some_or_thunk ~f:(fun () -> of_token_alias token_alias) + |> Option.value_or_thunk ~f:(fun () -> of_cident cident) + end + | StmtNonterm {nonterm_} -> of_nonterm nonterm_ + | StmtCode {code} -> last_token_of_code hocc_block code + and of_stmts_tl = function + | StmtsTl {stmt; stmts_tl; _} -> begin + (of_stmts_tl stmts_tl) + |> Option.some_or_thunk ~f:(fun () -> Some (of_stmt stmt)) + end + | StmtsTlEpsilon -> None + in + of_stmts_tl stmts_tl + |> Option.value_or_thunk ~f:(fun () -> of_stmt stmt) + |> Scan.Token.source + |> Hmc.Source.Slice.past