diff --git a/bootstrap/bin/hocc/nonterm.ml b/bootstrap/bin/hocc/nonterm.ml index e86c6577a..31686be9d 100644 --- a/bootstrap/bin/hocc/nonterm.ml +++ b/bootstrap/bin/hocc/nonterm.ml @@ -2,12 +2,19 @@ open Basis open Basis.Rudiments module T = struct + type type_ = { + module_: string; + type_: string; + } + type t = { index: uns; name: string; start: bool; + type_: type_ option; prec: Prec.t option; prods: (Prod.t, Prod.cmper_witness) Ordset.t; + stmt: Parse.nonterm; } let hash_fold {index; _} state = @@ -16,17 +23,25 @@ module T = struct let cmp {index=index0; _} {index=index1; _} = Uns.cmp index0 index1 - let pp {index; name; start; prec; prods} formatter = + let pp_type {module_; type_} formatter = + formatter + |> Fmt.fmt "{module_=" |> String.pp module_ + |> Fmt.fmt "; type_=" |> String.pp type_ + |> Fmt.fmt "}" + + let pp {index; name; start; type_; prec; prods; stmt} formatter = formatter |> Fmt.fmt "{index=" |> Uns.pp index |> Fmt.fmt "; name=" |> String.pp name |> Fmt.fmt "; start=" |> Bool.pp start + |> Fmt.fmt "; type_=" |> (Option.pp pp_type) type_ |> Fmt.fmt "; prec=" |> (Option.pp Prec.pp) prec |> Fmt.fmt "; prods=" |> (List.pp Prod.pp) (Ordset.to_list prods) + |> Fmt.fmt "; stmt=" |> Parse.fmt_nonterm stmt |> Fmt.fmt "}" end include T include Identifiable.Make(T) -let init ~index ~name ~start ~prec ~prods = - {index; name; start; prec; prods} +let init ~index ~name ~start ~type_ ~prec ~prods ~stmt = + {index; name; start; type_; prec; prods; stmt} diff --git a/bootstrap/bin/hocc/nonterm.mli b/bootstrap/bin/hocc/nonterm.mli index 87d10deff..4c57fc9e3 100644 --- a/bootstrap/bin/hocc/nonterm.mli +++ b/bootstrap/bin/hocc/nonterm.mli @@ -1,15 +1,22 @@ open Basis open Basis.Rudiments +type type_ = { + module_: string; + type_: string; +} + type t = { index: uns; name: string; start: bool; + type_: type_ option; prec: Prec.t option; prods: (Prod.t, Prod.cmper_witness) Ordset.t; + stmt: Parse.nonterm; } include IdentifiableIntf.S with type t := t -val init: index:uns -> name:string -> start:bool -> prec:Prec.t option - -> prods:(Prod.t, Prod.cmper_witness) Ordset.t -> t +val init: index:uns -> name:string -> start:bool -> type_:type_ option -> prec:Prec.t option + -> prods:(Prod.t, Prod.cmper_witness) Ordset.t -> stmt:Parse.nonterm -> t diff --git a/bootstrap/bin/hocc/prod.ml b/bootstrap/bin/hocc/prod.ml index ca2d6dadf..15a3d62bc 100644 --- a/bootstrap/bin/hocc/prod.ml +++ b/bootstrap/bin/hocc/prod.ml @@ -7,6 +7,7 @@ module T = struct lhs_index: uns; rhs_indexes: uns array; prec: Prec.t option; + stmt: Parse.prod; } let hash_fold {index; _} state = @@ -15,16 +16,17 @@ module T = struct let cmp {index=index0; _} {index=index1; _} = Uns.cmp index0 index1 - let pp {index; lhs_index; rhs_indexes; prec} formatter = + let pp {index; lhs_index; rhs_indexes; prec; stmt} formatter = formatter |> Fmt.fmt "{index=" |> Uns.pp index |> Fmt.fmt "; lhs_index=" |> Uns.pp lhs_index |> Fmt.fmt "; rhs_indexes=" |> (Array.pp Uns.pp) rhs_indexes |> Fmt.fmt "; prec=" |> (Option.pp Prec.pp) prec + |> Fmt.fmt "; stmt=" |> Parse.fmt_prod stmt |> Fmt.fmt "}" end include T include Identifiable.Make(T) -let init ~index ~lhs_index ~rhs_indexes ~prec = - {index; lhs_index; rhs_indexes; prec} +let init ~index ~lhs_index ~rhs_indexes ~prec ~stmt = + {index; lhs_index; rhs_indexes; prec; stmt} diff --git a/bootstrap/bin/hocc/prod.mli b/bootstrap/bin/hocc/prod.mli index a9329382f..252996407 100644 --- a/bootstrap/bin/hocc/prod.mli +++ b/bootstrap/bin/hocc/prod.mli @@ -6,8 +6,10 @@ type t = { lhs_index: uns; rhs_indexes: uns array; prec: Prec.t option; + stmt: Parse.prod; } include IdentifiableIntf.S with type t := t -val init: index:uns -> lhs_index:uns -> rhs_indexes:uns array -> prec:Prec.t option -> t +val init: index:uns -> lhs_index:uns -> rhs_indexes:uns array -> prec:Prec.t option + -> stmt:Parse.prod -> t diff --git a/bootstrap/bin/hocc/reduction.ml b/bootstrap/bin/hocc/reduction.ml new file mode 100644 index 000000000..ad2e8be14 --- /dev/null +++ b/bootstrap/bin/hocc/reduction.ml @@ -0,0 +1,52 @@ +open Basis +open Basis.Rudiments + +module T = struct + type type_ = { + module_: string; + type_: string; + } + + type param = { + name: string option; + type_: type_; + } + + type t = { + index: uns; + lhs: type_; + rhs: param array; + code: Parse.code option; + } + + let hash_fold {index; _} state = + Uns.hash_fold index state + + let cmp {index=index0; _} {index=index1; _} = + Uns.cmp index0 index1 + + let pp_type {module_; type_} formatter = + formatter + |> Fmt.fmt "{module_=" |> String.pp module_ + |> Fmt.fmt "; type_=" |> String.pp type_ + |> Fmt.fmt "}" + + let pp_param {name; type_} formatter = + formatter + |> Fmt.fmt "{name=" |> (Option.pp String.pp) name + |> Fmt.fmt "; type_=" |> pp_type type_ + |> Fmt.fmt "}" + + let pp {index; lhs; rhs; code} formatter = + formatter + |> Fmt.fmt "{index=" |> Uns.pp index + |> Fmt.fmt "; lhs=" |> pp_type lhs + |> Fmt.fmt "; rhs=" |> (Array.pp pp_param) rhs + |> Fmt.fmt "; code=" |> (Option.pp Parse.fmt_code) code + |> Fmt.fmt "}" +end +include T +include Identifiable.Make(T) + +let init ~index ~lhs ~rhs ~code = + {index; lhs; rhs; code} diff --git a/bootstrap/bin/hocc/reduction.mli b/bootstrap/bin/hocc/reduction.mli new file mode 100644 index 000000000..b6c820217 --- /dev/null +++ b/bootstrap/bin/hocc/reduction.mli @@ -0,0 +1,23 @@ +open Basis +open Basis.Rudiments + +type type_ = { + module_: string; + type_: string; +} + +type param = { + name: string option; + type_: type_; +} + +type t = { + index: uns; + lhs: type_; + rhs: param array; + code: Parse.code option; +} + +include IdentifiableIntf.S with type t := t + +val init: index:uns -> lhs:type_ -> rhs:param array -> code:Parse.code option -> t diff --git a/bootstrap/bin/hocc/spec.ml b/bootstrap/bin/hocc/spec.ml index af4efeaf9..b64f4d1f1 100644 --- a/bootstrap/bin/hocc/spec.ml +++ b/bootstrap/bin/hocc/spec.ml @@ -4,6 +4,8 @@ open! Basis.Rudiments type t = { precs: Prec.t array; symbols: Symbol.t array; + prods: Prod.t array; + reductions: Reduction.t array; } let string_of_token token = @@ -122,24 +124,407 @@ let precs_init io hmh = match Array.get i precs_kvpairs with | (_, prec) -> prec ) in - io, precs + io, precs_map, precs -let tokens_init io _precs _hmh = - io, [|(*XXX*)|] +let tokens_init io ~precs_map hmh = + let fold_token io ~precs_map ~tokens_map ~aliases_map token = begin + match token with + | Parse.Token {cident=Cident {cident}; token_alias; of_type0; prec_ref; _} -> begin + let index = Map.length tokens_map in + let name = string_of_token cident in + let alias = match token_alias with + | TokenAlias {alias} -> Some (string_of_token alias) + | TokenAliasEpsilon -> None + in + let type_ = match of_type0 with + | OfType0OfType {of_type=OfType { + type_module=Cident {cident}; type_type=Uident {uident}; _}} -> begin + let module_ = string_of_token cident in + let type_ = string_of_token uident in + Some Token.{module_; type_} + end + | OfType0Epsilon -> None + in + let prec = match prec_ref with + | PrecRefPrecUident {uident=Uident {uident}; _} -> begin + let prec_name = string_of_token uident in + match Map.get prec_name precs_map with + | None -> begin + let io = + io.err + |> Fmt.fmt "hocc: At " |> Hmc.Source.Slice.pp (Scan.Token.source uident) + |> Fmt.fmt ": Undefined precedence: " |> Fmt.fmt prec_name |> Fmt.fmt "\n" + |> Io.with_err io + in + Io.fatal io + end + | Some _ as prec -> prec + end + | PrecRefEpsilon -> None + in + let token = Token.init ~index ~name ~alias ~type_ ~prec ~stmt:token in + let tokens_map = match Map.mem name tokens_map with + | true -> begin + let io = + io.err + |> Fmt.fmt "hocc: At " |> Hmc.Source.Slice.pp (Scan.Token.source cident) + |> Fmt.fmt ": Redefined token: " |> Fmt.fmt name |> Fmt.fmt "\n" + |> Io.with_err io + in + Io.fatal io + end + | false -> Map.insert_hlt ~k:name ~v:token tokens_map + in + let aliases_map = match token_alias with + | TokenAlias {alias=a} -> begin + let alias_name = string_of_token a in + match Map.mem alias_name aliases_map with + | true -> begin + let io = + io.err + |> Fmt.fmt "hocc: At " |> Hmc.Source.Slice.pp (Scan.Token.source a) + |> Fmt.fmt ": Redefined token alias: " |> Fmt.fmt alias_name |> Fmt.fmt "\n" + |> Io.with_err io + in + Io.fatal io + end + | false -> Map.insert_hlt ~k:alias_name ~v:index aliases_map + end + | TokenAliasEpsilon -> aliases_map + in + io, tokens_map, aliases_map + end + end in + let fold_stmt io ~precs_map ~tokens_map ~aliases_map stmt = begin + match stmt with + | Parse.StmtToken {token} -> fold_token io ~precs_map ~tokens_map ~aliases_map token + | _ -> io, tokens_map, aliases_map + end in + let rec fold_stmts_tl io ~precs_map ~tokens_map ~aliases_map stmts_tl = begin + match stmts_tl with + | Parse.StmtsTl {stmt; stmts_tl; _} -> begin + let io, tokens_map, aliases_map = fold_stmt io ~precs_map ~tokens_map ~aliases_map stmt in + fold_stmts_tl io ~precs_map ~tokens_map ~aliases_map stmts_tl + end + | StmtsTlEpsilon -> io, tokens_map, aliases_map + end in + let fold_stmts io ~precs_map ~tokens_map ~aliases_map stmts = begin + match stmts with + | Parse.Stmts {stmt; stmts_tl} -> begin + let io, tokens_map, aliases_map = fold_stmt io ~precs_map ~tokens_map ~aliases_map stmt in + fold_stmts_tl io ~precs_map ~tokens_map ~aliases_map stmts_tl + end + end in + let io, tokens_map, aliases_map = match hmh with Parse.Hmh {hocc=Hocc {stmts; _}; _} -> + fold_stmts io ~precs_map ~tokens_map:(Map.empty (module String)) + ~aliases_map:(Map.empty (module String)) stmts + in + io, tokens_map, aliases_map -let symbol_map_init io _precs _tokens _hmh = - io, Map.empty (module String) +let symbol_indexes_init io ~tokens_map hmh = + let fold_nonterm io ~symbol_indexes nonterm = begin + match nonterm with + | Parse.NontermReductions {cident=Cident {cident}; _} + | Parse.NontermProds {cident=Cident {cident}; _} -> begin + let index = Map.length symbol_indexes in + let name = string_of_token cident in + let symbol_indexes = match Map.mem name symbol_indexes with + | true -> begin + let io = + io.err + |> Fmt.fmt "hocc: At " |> Hmc.Source.Slice.pp (Scan.Token.source cident) + |> Fmt.fmt ": Redefined symbol: " |> Fmt.fmt name |> Fmt.fmt "\n" + |> Io.with_err io + in + Io.fatal io + end + | false -> Map.insert_hlt ~k:name ~v:index symbol_indexes + in + io, symbol_indexes + end + end in + let fold_stmt io ~symbol_indexes stmt = begin + match stmt with + | Parse.StmtNonterm {nonterm} -> fold_nonterm io ~symbol_indexes nonterm + | _ -> io, symbol_indexes + end in + let rec fold_stmts_tl io ~symbol_indexes stmts_tl = begin + match stmts_tl with + | Parse.StmtsTl {stmt; stmts_tl; _} -> begin + let io, symbol_indexes = fold_stmt io ~symbol_indexes stmt in + fold_stmts_tl io ~symbol_indexes stmts_tl + end + | StmtsTlEpsilon -> io, symbol_indexes + end in + let fold_stmts io ~symbol_indexes stmts = begin + match stmts with + | Parse.Stmts {stmt; stmts_tl} -> begin + let io, symbol_indexes = fold_stmt io ~symbol_indexes stmt in + fold_stmts_tl io ~symbol_indexes stmts_tl + end + end in + let symbol_indexes = Map.fold ~init:(Map.empty (module String)) + ~f:(fun symbol_indexes (name, token) -> + Map.insert_hlt ~k:name ~v:Token.(token.index) symbol_indexes + ) tokens_map in + let io, symbol_indexes = match hmh with Parse.Hmh {hocc=Hocc {stmts; _}; _} -> + fold_stmts io ~symbol_indexes stmts + in + io, symbol_indexes + +let symbols_init io ~precs_map ~tokens_map ~aliases_map ~symbol_indexes hmh = + (* XXX + let fold_reductions io ~precs_map ~aliases_map ~symbol_indexes ~prods_set ~reductions_map + nonterm_prodless reductions = begin -let symbols_init io _precs tokens _symbol_map _hmh = - io, tokens (* XXX *) + io, Ordset.empty (module Prod), prods_set, reductions_map + end in + *) + let fold_prod_param io ~aliases_map ~symbol_indexes prod_params prod_param = begin + match prod_param with + | Parse.ProdParam {prod_param_ident; prod_param_type} -> begin + let io = match prod_param_ident with + | ProdParamIdentIdentColon {ident=IdentUident {uident=Uident {uident=ident}}; _} + | ProdParamIdentIdentColon {ident=IdentCident {cident=Cident {cident=ident}}; _} -> begin + let binding = string_of_token ident in + io.log + |> Fmt.fmt "hocc: At " |> Hmc.Source.Slice.pp (Scan.Token.source ident) + |> Fmt.fmt ": Unused parameter binding: " |> Fmt.fmt binding |> Fmt.fmt "\n" + |> Io.with_log io + end + | ProdParamIdentIdentColon {ident=IdentUscore _; _} + | ProdParamIdentEpsilon -> io + in + let param = match prod_param_type with + | ProdParamTypeCident {cident=Cident {cident}} -> begin + let type_name = string_of_token cident in + match Map.get type_name symbol_indexes with + | None -> begin + let io = + io.err + |> Fmt.fmt "hocc: At " |> Hmc.Source.Slice.pp (Scan.Token.source cident) + |> Fmt.fmt ": Undefined symbol: " |> Fmt.fmt type_name |> Fmt.fmt "\n" + |> Io.with_err io + in + Io.fatal io + end + | Some index -> index + end + | ProdParamTypeAlias {alias} -> begin + let alias_name = string_of_token alias in + match Map.get alias_name aliases_map with + | None -> begin + let io = + io.err + |> Fmt.fmt "hocc: At " |> Hmc.Source.Slice.pp (Scan.Token.source alias) + |> Fmt.fmt ": Undefined alias: " |> Fmt.fmt alias_name |> Fmt.fmt "\n" + |> Io.with_err io + in + Io.fatal io + end + | Some index -> index + end + in + io, param :: prod_params + end + end in + let rec fold_prod_params_tl io ~aliases_map ~symbol_indexes prod_params + prod_params_tl = begin + match prod_params_tl with + | Parse.ProdParamsTlProdParam {prod_param; prod_params_tl} -> begin + let io, prod_params = + fold_prod_param io ~aliases_map ~symbol_indexes prod_params prod_param in + fold_prod_params_tl io ~aliases_map ~symbol_indexes prod_params prod_params_tl + end + | ProdParamsTlEpsilon -> io, Array.of_list_rev prod_params + end in + let fold_prod_pattern io ~aliases_map ~symbol_indexes prod_pattern = begin + match prod_pattern with + | Parse.ProdPatternParams {prod_params=ProdParamsProdParam {prod_param; prod_params_tl}} + -> begin + let io, prod_params = fold_prod_param io ~aliases_map ~symbol_indexes [] prod_param in + fold_prod_params_tl io ~aliases_map ~symbol_indexes prod_params prod_params_tl + end + | ProdPatternEpsilon _ -> io, [||] + end in + let fold_prod io ~precs_map ~aliases_map ~symbol_indexes ~prods_set ~reductions_map + nonterm_prodless nonterm_prods_set prod = begin + match prod with + | Parse.Prod {prod_pattern; prec_ref} -> begin + let index = Ordset.length prods_set in + let lhs_index = Nonterm.(nonterm_prodless.index) in + let io, rhs_indexes = fold_prod_pattern io ~aliases_map ~symbol_indexes prod_pattern in + let prec = match prec_ref with + | PrecRefPrecUident {uident=Uident {uident}; _} -> begin + let prec_name = string_of_token uident in + match Map.get prec_name precs_map with + | None -> begin + let io = + io.err + |> Fmt.fmt "hocc: At " |> Hmc.Source.Slice.pp (Scan.Token.source uident) + |> Fmt.fmt ": Undefined precedence: " |> Fmt.fmt prec_name |> Fmt.fmt "\n" + |> Io.with_err io + in + Io.fatal io + end + | Some _ as prec -> prec + end + | PrecRefEpsilon -> None + in + let prod = Prod.init ~index ~lhs_index ~rhs_indexes ~prec ~stmt:prod in + let nonterm_prods_set = Ordset.insert prod nonterm_prods_set in + let prods_set = Ordset.insert prod prods_set in + io, nonterm_prods_set, prods_set, reductions_map + end + end in + let rec fold_prods_tl io ~precs_map ~aliases_map ~symbol_indexes ~prods_set ~reductions_map + nonterm_prodless nonterm_prods_set prods_tl = begin + match prods_tl with + | Parse.ProdsTlBarProd {prod; prods_tl; _} -> begin + let io, nonterm_prods_set, prods_set, reductions_map = + fold_prod io ~precs_map ~aliases_map ~symbol_indexes ~prods_set + ~reductions_map nonterm_prodless nonterm_prods_set prod in + fold_prods_tl io ~precs_map ~aliases_map ~symbol_indexes ~prods_set + ~reductions_map nonterm_prodless nonterm_prods_set prods_tl + end + | ProdsTlEpsilon -> io, nonterm_prods_set, prods_set, reductions_map + end in + let fold_prods io ~precs_map ~aliases_map ~symbol_indexes ~prods_set ~reductions_map + nonterm_prodless prods = begin + match prods with + | Parse.ProdsBarProd {prod; prods_tl; _} + | ProdsProd {prod; prods_tl} -> begin + let nonterm_prods_set = Ordset.empty (module Prod) in + let io, nonterm_prods_set, prods_set, reductions_map = + fold_prod io ~precs_map ~aliases_map ~symbol_indexes ~prods_set ~reductions_map + nonterm_prodless nonterm_prods_set prod in + fold_prods_tl io ~precs_map ~aliases_map ~symbol_indexes ~prods_set ~reductions_map + nonterm_prodless nonterm_prods_set prods_tl + end + end in + let fold_nonterm io ~precs_map ~aliases_map ~symbol_indexes ~symbols_map ~prods_set + ~reductions_map nonterm = begin + let start, name, prec = match nonterm with + | Parse.NontermReductions {nonterm_type; cident=Cident {cident}; prec_ref; _} + | NontermProds {nonterm_type; cident=Cident {cident}; prec_ref; _} -> begin + let start = match nonterm_type with + | NontermTypeNonterm _ -> false + | NontermTypeStart _ -> true + in + let name = string_of_token cident in + let prec = match prec_ref with + | PrecRefPrecUident {uident=Uident {uident}; _} -> begin + let prec_name = string_of_token uident in + match Map.get prec_name precs_map with + | None -> begin + let io = + io.err + |> Fmt.fmt "hocc: At " |> Hmc.Source.Slice.pp (Scan.Token.source uident) + |> Fmt.fmt ": Undefined precedence: " |> Fmt.fmt prec_name |> Fmt.fmt "\n" + |> Io.with_err io + in + Io.fatal io + end + | Some _ as prec -> prec + end + | PrecRefEpsilon -> None + in + start, name, prec + end + in + (* XXX Handle start symbols specially. *) + let index = Map.get_hlt name symbol_indexes in + let type_ = match nonterm with + | NontermReductions {of_type=OfType { + type_module=Cident {cident}; type_type=Uident {uident}; _}; _} -> begin + let module_ = string_of_token cident in + let type_ = string_of_token uident in + Some Nonterm.{module_; type_} + end + | NontermProds _ -> None + in + let nonterm_prodless = Nonterm.init ~index ~name ~start ~type_ ~prec + ~prods:(Ordset.empty (module Prod)) ~stmt:nonterm in + let io, prods, prods_set, reductions_map = match nonterm with + | NontermReductions {reductions=_XXX; _} -> + not_implemented "XXX" + (* fold_reductions io ~precs_map ~aliases_map ~symbol_indexes ~prods_set ~reductions_map + nonterm_prodless reductions *) + | NontermProds {prods; _} -> + fold_prods io ~precs_map ~aliases_map ~symbol_indexes ~prods_set ~reductions_map + nonterm_prodless prods + in + let nonterm = Nonterm.init ~index ~name ~start ~type_ ~prec ~prods ~stmt:nonterm in + let symbols_map = Map.insert_hlt ~k:name ~v:(Symbol.of_nonterm nonterm) symbols_map in + io, symbols_map, prods_set, reductions_map + end in + let fold_stmt io ~precs_map ~aliases_map ~symbol_indexes ~symbols_map ~prods_set ~reductions_map + stmt = begin + match stmt with + | Parse.StmtNonterm {nonterm} -> + fold_nonterm io ~precs_map ~aliases_map ~symbol_indexes ~symbols_map ~prods_set + ~reductions_map nonterm + | _ -> io, symbols_map, prods_set, reductions_map + end in + let rec fold_stmts_tl io ~precs_map ~aliases_map ~symbol_indexes ~symbols_map ~prods_set + ~reductions_map stmts_tl = begin + match stmts_tl with + | Parse.StmtsTl {stmt; stmts_tl; _} -> begin + let io, symbols_map, prods_set, reductions_map = + fold_stmt io ~precs_map ~aliases_map ~symbol_indexes ~symbols_map ~prods_set + ~reductions_map stmt in + fold_stmts_tl io ~precs_map ~aliases_map ~symbol_indexes ~symbols_map ~prods_set + ~reductions_map stmts_tl + end + | StmtsTlEpsilon -> io, symbols_map, prods_set, reductions_map + end in + let fold_stmts io ~precs_map ~aliases_map ~symbol_indexes ~symbols_map ~prods_set ~reductions_map + stmts = begin + match stmts with + | Parse.Stmts {stmt; stmts_tl} -> begin + let io, symbols_map, prods_set, reductions_map = + fold_stmt io ~precs_map ~aliases_map ~symbol_indexes ~symbols_map ~prods_set + ~reductions_map stmt in + fold_stmts_tl io ~precs_map ~aliases_map ~symbol_indexes ~symbols_map ~prods_set + ~reductions_map stmts_tl + end + end in + let symbols_map = Map.fold ~init:(Map.empty (module String)) ~f:(fun symbols_map (name, token) -> + Map.insert_hlt ~k:name ~v:(Symbol.of_token token) symbols_map + ) tokens_map in + let reductions_map = Map.empty (module Reduction) in + let prods_set = Ordset.empty (module Prod) in + let io, symbols_map, prods_set, reductions_map = + match hmh with Parse.Hmh {hocc=Hocc {stmts; _}; _} -> + fold_stmts io ~precs_map ~aliases_map ~symbol_indexes ~symbols_map ~prods_set ~reductions_map + stmts + in + let symbols_kvpairs = + Map.to_array symbols_map + |> Array.sort ~cmp:(fun (_, symbol0) (_, symbol1) -> Symbol.cmp symbol0 symbol1) in + let symbols = Array.init (Array.range symbols_kvpairs) ~f:(fun i -> + match Array.get i symbols_kvpairs with + | (_, symbol) -> symbol + ) in + let prods = Ordset.to_array prods_set in + let reductions_kvpairs = + Map.to_array reductions_map + |> Array.sort ~cmp:(fun (_, symbol0) (_, symbol1) -> Reduction.cmp symbol0 symbol1) in + let reductions = Array.init (Array.range reductions_kvpairs) ~f:(fun i -> + match Array.get i reductions_kvpairs with + | (_, symbol) -> symbol + ) in + io, symbols, prods, reductions +(* XXX Log unused symbols. *) let init io hmh = let io = io.log |> Fmt.fmt "hocc: Generating specification\n" |> Io.with_log io in - let io, precs = precs_init io hmh in - let io, tokens = tokens_init io precs hmh in - let io, symbol_map = symbol_map_init io precs tokens hmh in - let io, symbols = symbols_init io precs tokens symbol_map hmh in - io, {precs; symbols} + let io, precs_map, precs = precs_init io hmh in + let io, tokens_map, aliases_map = tokens_init io ~precs_map hmh in + let io, symbol_indexes = symbol_indexes_init io ~tokens_map hmh in + let io, symbols, prods, reductions = + symbols_init io ~precs_map ~tokens_map ~aliases_map ~symbol_indexes hmh in + io, {precs; symbols; prods; reductions} let to_txt conf io t = let io = io.log |> Fmt.fmt "hocc: Generating text report\n" |> Io.with_log io in diff --git a/bootstrap/bin/hocc/spec.mli b/bootstrap/bin/hocc/spec.mli index b0a788a71..c2a33e8c9 100644 --- a/bootstrap/bin/hocc/spec.mli +++ b/bootstrap/bin/hocc/spec.mli @@ -4,6 +4,8 @@ open! Basis.Rudiments type t = { precs: Prec.t array; symbols: Symbol.t array; + prods: Prod.t array; + reductions: Reduction.t array; } val init: Io.t -> Parse.hmh -> Io.t * t diff --git a/bootstrap/bin/hocc/symbol.ml b/bootstrap/bin/hocc/symbol.ml index 92310948e..9ffbe6338 100644 --- a/bootstrap/bin/hocc/symbol.ml +++ b/bootstrap/bin/hocc/symbol.ml @@ -31,3 +31,11 @@ let of_token token = let of_nonterm nonterm = Nonterm nonterm + +let index = function + | Token {index; _} + | Nonterm {index; _} -> index + +let name = function + | Token {name; _} + | Nonterm {name; _} -> name diff --git a/bootstrap/bin/hocc/symbol.mli b/bootstrap/bin/hocc/symbol.mli index f21450ad8..a1c269983 100644 --- a/bootstrap/bin/hocc/symbol.mli +++ b/bootstrap/bin/hocc/symbol.mli @@ -9,3 +9,6 @@ include IdentifiableIntf.S with type t := t val of_token: Token.t -> t val of_nonterm: Nonterm.t -> t + +val index: t -> uns +val name: t -> string diff --git a/bootstrap/bin/hocc/token.ml b/bootstrap/bin/hocc/token.ml index 5d74d53b3..870a9ce95 100644 --- a/bootstrap/bin/hocc/token.ml +++ b/bootstrap/bin/hocc/token.ml @@ -2,11 +2,18 @@ open Basis open Basis.Rudiments module T = struct + type type_ = { + module_: string; + type_: string; + } + type t = { index: uns; name: string; alias: string option; + type_: type_ option; prec: Prec.t option; + stmt: Parse.token; } let hash_fold {index; _} state = @@ -15,16 +22,24 @@ module T = struct let cmp {index=index0; _} {index=index1; _} = Uns.cmp index0 index1 - let pp {index; name; alias; prec} formatter = + let pp_type {module_; type_} formatter = + formatter + |> Fmt.fmt "{module_=" |> String.pp module_ + |> Fmt.fmt "; type_=" |> String.pp type_ + |> Fmt.fmt "}" + + let pp {index; name; alias; type_; prec; stmt} formatter = formatter |> Fmt.fmt "{index=" |> Uns.pp index |> Fmt.fmt "; name=" |> String.pp name |> Fmt.fmt "; alias=" |> (Option.pp String.pp) alias + |> Fmt.fmt "; type_=" |> (Option.pp pp_type) type_ |> Fmt.fmt "; prec=" |> (Option.pp Prec.pp) prec + |> Fmt.fmt "; stmt=" |> Parse.fmt_token stmt |> Fmt.fmt "}" end include T include Identifiable.Make(T) -let init ~index ~name ~alias ~prec = - {index; name; alias; prec} +let init ~index ~name ~alias ~type_ ~prec ~stmt = + {index; name; alias; type_; prec; stmt} diff --git a/bootstrap/bin/hocc/token.mli b/bootstrap/bin/hocc/token.mli index d7c7e6d8c..da83eec4b 100644 --- a/bootstrap/bin/hocc/token.mli +++ b/bootstrap/bin/hocc/token.mli @@ -1,13 +1,21 @@ open Basis open Basis.Rudiments +type type_ = { + module_: string; + type_: string; +} + type t = { index: uns; name: string; alias: string option; + type_: type_ option; prec: Prec.t option; + stmt: Parse.token; } include IdentifiableIntf.S with type t := t -val init: index:uns -> name:string -> alias:string option -> prec:Prec.t option -> t +val init: index:uns -> name:string -> alias:string option -> type_:type_ option + -> prec:Prec.t option -> stmt:Parse.token -> t diff --git a/bootstrap/test/hocc/Hocc.hmh b/bootstrap/test/hocc/Hocc.hmh index 7f1fc5f37..0920f1d8c 100644 --- a/bootstrap/test/hocc/Hocc.hmh +++ b/bootstrap/test/hocc/Hocc.hmh @@ -4,6 +4,7 @@ hocc token NONTERM "nonterm" token EPSILON "epsilon" token START "start" + token TOKEN "token" token PREC "prec" token LEFT "left" token RIGHT "right" @@ -19,6 +20,7 @@ hocc # Punctuation/separators token COLON_COLON_EQ "::=" token OF "of" + token COLON ":" token DOT "." token ARROW "->" token BAR "|" diff --git a/bootstrap/test/hocc/Lyken.hmh b/bootstrap/test/hocc/Lyken.hmh index a58ec3c99..bedff95da 100644 --- a/bootstrap/test/hocc/Lyken.hmh +++ b/bootstrap/test/hocc/Lyken.hmh @@ -560,13 +560,13 @@ hocc | Lval LPAREN RPAREN | Lval LPAREN CallList RPAREN | Lval LPAREN Expr RPAREN - | LVAL LPAREN LVAL RPAREN + | Lval LPAREN Lval RPAREN | Lval LPAREN ExprListBody RPAREN | Lval LPAREN LvalListBody RPAREN | Lval LPAREN RPAREN COMMA InitFieldList | Lval LPAREN CallList RPAREN COMMA InitFieldList | Lval LPAREN Expr RPAREN COMMA InitFieldList - | LVAL LPAREN LVAL RPAREN COMMA InitFieldList + | Lval LPAREN Lval RPAREN COMMA InitFieldList | Lval LPAREN ExprListBody RPAREN COMMA InitFieldList | Lval LPAREN LvalListBody RPAREN COMMA InitFieldList | InitFieldList @@ -1012,7 +1012,7 @@ hocc | FOR AssnExprLeft IN Expr | FOR AssnExprLeft IN Lval | FOR Lval IN Expr - | FOR LVAL IN Lval + | FOR Lval IN Lval | FOR AssnExprLeft IN ExprList | FOR Lval IN ExprList nonterm ForClauseList ::= @@ -1235,7 +1235,7 @@ hocc | NondelimitedExpr | Lval - | ExprListprec prec pStmt + | ExprList prec pStmt nonterm DelimitedStmt ::= | CblockStmt diff --git a/bootstrap/test/hocc/M.hmh b/bootstrap/test/hocc/M.hmh index 267232cdd..6e8da9f81 100644 --- a/bootstrap/test/hocc/M.hmh +++ b/bootstrap/test/hocc/M.hmh @@ -1,30 +1,30 @@ # Example grammar G2 from Pager(1977), pp 256. hocc - token A - token B - token C - token D - token E - token T - token U + token At + token Bt + token Ct + token Dt + token Et + token Tt + token Ut - start X ::= - | A Y D - | A Z C - | A T - | B Y E - | B Z D - | B T + start Xn ::= + | At Yn Dt + | At Zn Ct + | At Tn + | Bt Yn Et + | Bt Zn Dt + | Bt Tn - nonterm Y ::= - | T W - | U X + nonterm Yn ::= + | Tt Wn + | Ut Xn - nonterm Z ::= T U + nonterm Zn ::= Tt Ut - nonterm T ::= U X A + nonterm Tn ::= Ut Xn At - nonterm W ::= U V + nonterm Wn ::= Ut Vn - nonterm V ::= epsilon + nonterm Vn ::= epsilon diff --git a/bootstrap/test/hocc/Parse_a.hmh b/bootstrap/test/hocc/Parse_a.hmh index 205b935ac..03d29c5bb 100644 --- a/bootstrap/test/hocc/Parse_a.hmh +++ b/bootstrap/test/hocc/Parse_a.hmh @@ -8,6 +8,8 @@ include hocc left p5 < p1, p2 right p6 < p3, p4, p5 + prec mul + prec add < mul token OP token PLUS "+" token UNS of Uns.t diff --git a/doc/tools/hocc.md b/doc/tools/hocc.md index 6aa76e052..217a92566 100644 --- a/doc/tools/hocc.md +++ b/doc/tools/hocc.md @@ -702,6 +702,7 @@ hocc token NONTERM "nonterm" token EPSILON "epsilon" token START "start" + token TOKEN "token" token PREC "prec" token LEFT "left" token RIGHT "right" @@ -717,6 +718,7 @@ hocc # Punctuation/separators token COLON_COLON_EQ "::=" token OF "of" + token COLON ":" token DOT "." token ARROW "->" token BAR "|"