Commit 4b894e86 authored by POTTIER Francois's avatar POTTIER Francois

Fix an assertion failure.

A pseudo-token (declared e.g. by %left) could appear in a position where a
normal token was expected (e.g., as an actual parameter of a parameterized
symbol) and that was not detected, giving rise (later on) to an assertion
failure.
parent 5b05bee7
Pipeline #149587 passed with stages
in 28 seconds
......@@ -603,6 +603,37 @@ let check_inline_attribute prule =
| false, _ ->
()
let reserved =
[ "error" ]
let check_identifier_reference mark_token_as_used grammar prule is_prec s p =
if not is_prec && List.mem s prule.pr_parameters then
(* A parameter of this rule. *)
()
else if not is_prec && List.mem s reserved then
(* A reserved token. *)
mark_token_as_used s
else if not is_prec && StringMap.mem s grammar.p_rules then
(* A nonterminal symbol. *)
()
else match StringMap.find s grammar.p_tokens with
| prop ->
(* A token or pseudo-token. Mark it as used. *)
mark_token_as_used s;
if not is_prec && not prop.tk_is_declared then
(* A pseudo-token, declared by %left, %right or %nonassoc,
cannot be used as a normal identifier. It can be only in
a %prec annotation. *)
Error.error [ p ]
"The symbol %s has not been declared by %%token,\n\
so cannot be used here." s
| exception Not_found ->
(* An unknown symbol. *)
if is_prec then
Error.error [ p ] "The terminal symbol %s is undefined." s
else
Error.error [ p ] "The symbol %s is undefined." s
let check_parameterized_grammar_is_well_defined grammar =
(* Every start symbol is defined and has a %type declaration. *)
......@@ -621,8 +652,6 @@ let check_parameterized_grammar_is_well_defined grammar =
symbols and has, at its head, a nonterminal symbol. *)
(* Same check for %on_error_reduce definitions. *)
let reserved = [ "error" ] in
let rec check (kind : string) (must_be_nonterminal : bool) (p : Syntax.parameter) =
(* Destructure head and arguments. *)
let head, ps = Parameters.unapp p in
......@@ -657,21 +686,15 @@ let check_parameterized_grammar_is_well_defined grammar =
let used_tokens = ref StringSet.empty in
let mark_token_as_used token =
used_tokens := StringSet.add token !used_tokens
in
let check_identifier_reference grammar prule s p =
(* Mark the symbol as a used token if this is a token. *)
if StringMap.mem s grammar.p_tokens then
mark_token_as_used s;
if not (StringMap.mem s grammar.p_rules
|| StringMap.mem s grammar.p_tokens
|| List.mem s prule.pr_parameters
|| List.mem s reserved) then
Error.error [ p ] "%s is undefined." s
in
StringMap.iter
(fun k prule ->
let check_identifier_reference =
check_identifier_reference
mark_token_as_used grammar prule
in
(* The formal parameters of each rule must have distinct names. *)
prule.pr_parameters
|> List.sort compare
......@@ -700,36 +723,17 @@ let check_parameterized_grammar_is_well_defined grammar =
in
(* Check that the producer is defined somewhere. *)
check_identifier_reference grammar prule s p;
StringMap.iter (check_identifier_reference grammar prule)
check_identifier_reference false s p;
StringMap.iter (check_identifier_reference false)
(List.fold_left Parameters.identifiers StringMap.empty parameters);
(* If this producer seems to be a reference to a token, make sure it
is a real token, as opposed to a pseudo-token introduced in a
priority declaration. *)
(try
if not ((StringMap.find s grammar.p_tokens).tk_is_declared
|| List.mem s reserved) then
Error.errorp symbol
"%s has not been declared as a token." s
with Not_found -> ());
already_seen
) StringSet.empty producers);
match pr_branch_prec_annotation with
| None -> ()
| Some terminal ->
check_identifier_reference grammar prule
terminal.value terminal.position;
(* Furthermore, the symbol following %prec must be a valid
token identifier. *)
if not (StringMap.mem terminal.value grammar.p_tokens) then
Error.errorp terminal
"%s is undefined." terminal.value)
Option.iter (fun terminal ->
check_identifier_reference true terminal.value terminal.position
) pr_branch_prec_annotation)
prule.pr_branches;
......
File "invalid-token-in-prec.mly", line 4, characters 9-10:
Error: F is undefined.
Error: The terminal symbol F is undefined.
File "reference-to-pseudo-token.mly", line 6, characters 5-11:
Error: foobar has not been declared as a token.
Error: The symbol foobar has not been declared by %token,
so cannot be used here.
File "use_pseudo_token.mly", line 7, characters 6-7:
Error: The symbol A has not been declared by %token,
so cannot be used here.
%left A
%start<unit> main
%%
main: A+ {}
......@@ -8444,6 +8444,14 @@
(rule (alias inline-minimal-cycle)
(action (diff ../bad/inline-minimal-cycle.exp inline-minimal-cycle.out)))
(rule (target int-of-string.out) (deps ../bad/int-of-string.mly)
(action
(with-outputs-to int-of-string.out
(chdir ../bad (with-accepted-exit-codes (not 0) (run menhir %{deps}))))))
(rule (alias int-of-string)
(action (diff ../bad/int-of-string.exp int-of-string.out)))
(rule (target invalid-declarations-a.out)
(deps ../bad/invalid-declarations-a.mly)
(action
......@@ -9463,6 +9471,14 @@
(rule (alias use-index-not-id)
(action (diff ../bad/use-index-not-id.exp use-index-not-id.out)))
(rule (target use_pseudo_token.out) (deps ../bad/use_pseudo_token.mly)
(action
(with-outputs-to use_pseudo_token.out
(chdir ../bad (with-accepted-exit-codes (not 0) (run menhir %{deps}))))))
(rule (alias use_pseudo_token)
(action (diff ../bad/use_pseudo_token.exp use_pseudo_token.out)))
(alias (name test)
(deps
(alias JSParse)
......@@ -9676,6 +9692,7 @@
(alias inlined-dollar)
(alias inlining-capture)
(alias inliningWithSideEffects)
(alias int-of-string)
(alias invalid-declarations-a)
(alias invalid-declarations-b)
(alias invalid-declarations-c)
......@@ -9971,6 +9988,7 @@
(alias uppercase)
(alias uppercase-start)
(alias use-index-not-id)
(alias use_pseudo_token)
(alias useless-priorities)
(alias useless-pseudo-token)
(alias verilog)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment