Skip to content

Commit

Permalink
Check for invalid bindings to empty token variants
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason Evans committed Aug 6, 2024
1 parent 727e1bc commit 4c7162f
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 11 deletions.
46 changes: 38 additions & 8 deletions bootstrap/bin/hocc/spec.ml
Original file line number Diff line number Diff line change
Expand Up @@ -305,13 +305,6 @@ let symbols_init io precs symbols hmh =
match prod_param with
| Parse.ProdParamBinding {prod_param_symbol; _}
| Parse.ProdParam {prod_param_symbol} -> begin
let binding = match prod_param with
| Parse.ProdParamBinding {ident=IdentUident {uident=Uident {uident=ident}}; _}
| Parse.ProdParamBinding {ident=IdentCident {cident=Cident {cident=ident}}; _} ->
Some (string_of_token ident)
| Parse.ProdParamBinding {ident=IdentUscore _; _}
| Parse.ProdParam _ -> None
in
let io, symbol_name, qtype = match prod_param_symbol with
| ProdParamSymbolCident {cident=Cident {cident}} -> begin
let symbol_name = string_of_token cident in
Expand Down Expand Up @@ -355,6 +348,44 @@ let symbols_init io precs symbols hmh =
| Some Symbols.{name; qtype; _} -> io, name, qtype
end
in
let io, binding = match prod_param with
| Parse.ProdParamBinding
{ident=IdentUident {uident=Uident {uident=ident}}; colon; prod_param_symbol}
| Parse.ProdParamBinding
{ident=IdentCident {cident=Cident {cident=ident}}; colon; prod_param_symbol} -> begin
let Symbols.{name; qtype; _} = match prod_param_symbol with
| ProdParamSymbolCident {cident=Cident {cident}} -> begin
Symbols.info_of_name_hlt (Hmc.Source.Slice.to_string (Scan.Token.source cident))
symbols
end
| ProdParamSymbolAlias {alias} -> begin
Symbols.info_of_alias_hlt (Hmc.Source.Slice.to_string (Scan.Token.source alias))
symbols
end
in
let io = match qtype with
| {explicit_opt=None; _} -> begin
let base = Scan.Token.source ident |> Hmc.Source.Slice.base in
let past = Scan.Token.source colon |> Hmc.Source.Slice.past in
let source = Hmc.Source.Slice.of_cursors ~base ~past in
let io =
io.err
|> Fmt.fmt "hocc: At "
|> Hmc.Source.Slice.pp source
|> Fmt.fmt ": Cannot bind to empty token variant: "
|> Fmt.fmt (Hmc.Source.Slice.to_string (Scan.Token.source ident))
|> Fmt.fmt ":" |> Fmt.fmt name |> Fmt.fmt "\n"
|> Io.with_err io
in
Io.fatal io
end
| {explicit_opt=Some _; _} -> io
in
io, Some (string_of_token ident)
end
| Parse.ProdParamBinding {ident=IdentUscore _; _}
| Parse.ProdParam _ -> io, None
in
let param =
Reduction.Param.init ~binding ~symbol_name ~qtype ~prod_param:(Some prod_param) in
io, param :: prod_params
Expand Down Expand Up @@ -3324,7 +3355,6 @@ let expand_hm_template template_indentation template hocc_block
|> (fun formatter ->
match binding with
| Some uname -> begin
(* XXX Binding to a payload-free token should be an error. *)
formatter
|> Fmt.fmt "{symbol=Symbol."
|> Fmt.fmt symbol_constructor
Expand Down
3 changes: 3 additions & 0 deletions bootstrap/bin/hocc/symbols.ml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ let info_of_alias alias ({aliases; tokens; _} as t) =
| None -> None
| Some symbol_index -> info_of_name Symbol.((Ordmap.get_hlt symbol_index tokens).name) t

let info_of_alias_hlt alias t =
Option.value_hlt (info_of_alias alias t)

let insert_token ~name ~qtype ~prec ~stmt ~alias
({infos; names; aliases; symbols; tokens; _} as t) =
let index = Map.length infos in
Expand Down
8 changes: 6 additions & 2 deletions bootstrap/bin/hocc/symbols.mli
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ type info = {
(** Optional token alias. *)

qtype: QualifiedType.t;
(** Qualified type, e.g. [Implicit] for [token SOME_TOKEN], or [Explicit {module_:Zint; type:t}]
for [token INT of Zint.t. *)
(** Qualified type, e.g. [explicit_opt=None] for [token SOME_TOKEN], or [explicit_opt=Some
{module_:Zint; type:t}] for [token INT of Zint.t. *)
}

type t
Expand Down Expand Up @@ -56,6 +56,10 @@ val info_of_alias: string -> t -> info option
(** [info_of_alias alias t] returns [Some info] if a symbol with the specified [alias] exists,
[None] otherwise. Note that names and aliases are in separate namespaces. *)

val info_of_alias_hlt: string -> t -> info
(** [info_of_alias alias t] returns [Some info] if a symbol with the specified [alias] exists, halts
otherwise. Note that names and aliases are in separate namespaces. *)

val symbol_index_of_name: string -> t -> Symbol.Index.t option
(** [symbol_index_of_name name t] returns [Some index] if a symbol with the specified [name] exists,
[None] otherwise. *)
Expand Down
3 changes: 3 additions & 0 deletions bootstrap/test/hocc/Binding_error.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
hocc: Parsing "./Binding_error.hmh"
hocc: Generating LR(1) specification
hocc: At ["./Binding_error.hmh":8:8.."./Binding_error.hmh":8:10): Cannot bind to empty token variant: t:T
8 changes: 8 additions & 0 deletions bootstrap/test/hocc/Binding_error.hmh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
hocc
token T
token U of Unit.t
token EOI
start S of Token.t ::=
| T EOI -> T
| u:U EOI -> U u
| t:T U EOI -> U t # Invalid binding; `T` has no payload.
2 changes: 1 addition & 1 deletion bootstrap/test/hocc/Parse_a.hmh
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ include hocc
| epsilon -> ()

nonterm N7 of Unit.t ::=
| o:OP _:N1 N2 -> foo
| OP n:N1 _:N2 -> foo

Code = {
}
Expand Down
12 changes: 12 additions & 0 deletions bootstrap/test/hocc/dune
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,18 @@
(alias runtest)
(action (diff Parse_error_hmhi.expected Parse_error_hmhi.out)))

(rule
(deps
(glob_files Binding_error.hmh*)
%{bin:hocc})
(action
(with-accepted-exit-codes
(or 0 1)
(with-outputs-to Binding_error.out (run ./hocc_test %{bin:hocc} Binding_error -v)))))
(rule
(alias runtest)
(action (diff Binding_error.expected Binding_error.out)))

(rule
(deps
(glob_files Unused.hmh*)
Expand Down

0 comments on commit 4c7162f

Please sign in to comment.