Commit 3917543e authored by POTTIER Francois's avatar POTTIER Francois

Take priority levels into account in [%on_error_reduce] declarations.

parent 5848e24a
......@@ -1069,19 +1069,19 @@ let default_conflict_resolution () =
Error.grammar_warning [] "%d states have an end-of-stream conflict." !ambiguities
(* ------------------------------------------------------------------------ *)
(* Extra reductions. 2015/10/19 *)
(* Extra reductions. *)
(* If a state can reduce one production whose left-hand symbol has been marked
[%on_error_reduce], and only one such production, then every error action
in this state is replaced with a reduction action. This is done even though
this state may have outgoing shift transitions: thus, we are forcing one
interpretation of the past, among several possible interpretations. *)
(* 2015/10/19 Original implementation. *)
(* 2016/07/13 Use priority levels to choose which productions to reduce
when several productions are eligible. *)
(* The above is the lax interpretation of the criterion. In a stricter
interpretation, one could require the state to be able to reduce only
one production, and furthermore require this production to be marked.
In practice, the lax interpretation makes [%on_error_reduce] more
powerful, and this extra power seems useful. *)
(* If a state can reduce some productions whose left-hand symbol has been
marked [%on_error_reduce], and if one such production [prod] is preferable
to every other (according to the priority rules of [%on_error_reduce]
declarations), then every error action in this state is replaced with a
reduction of [prod]. This is done even though this state may have outgoing
shift transitions: thus, we are forcing one interpretation of the past,
among several possible interpretations. *)
(* The code below looks like the decision on a default reduction in
[Invariant], except we do not impose the absence of outgoing terminal
......@@ -1097,6 +1097,12 @@ let default_conflict_resolution () =
let extra =
ref 0
(* A count of how many states have more than one eligible production, but one
is preferable to every other (so priority plays a role). *)
let prioritized =
ref 0
(* The set of nonterminal symbols in the left-hand side of an extra reduction. *)
let extra_nts =
......@@ -1110,18 +1116,20 @@ let extra_reductions_in_node node =
in
(* Keep only those whose left-hand symbol is marked [%on_error_reduce]. *)
let prods = List.filter OnErrorReduce.reduce prods in
(* Check if this only one such production remains. *)
match prods with
| []
| _ :: _ :: _ ->
(* Check if one of them is preferable to every other one. *)
match Misc.best OnErrorReduce.preferable prods with
| None ->
(* Either no production is marked [%on_error_reduce], or several of them
are marked and none is preferable. *)
()
| [ prod ] ->
| Some prod ->
let acceptable = acceptable_tokens node in
(* An extra reduction is possible. Replace every error action with
a reduction of [prod]. If we replace at least one error action
with a reduction, update [extra] and [extra_nts]. *)
let triggered = lazy (
incr extra;
if List.length prods > 1 then incr prioritized;
extra_nts := NonterminalSet.add (Production.nt prod) !extra_nts
) in
Terminal.iter_real (fun tok ->
......@@ -1142,7 +1150,8 @@ let extra_reductions () =
(* Info message. *)
if !extra > 0 then
Error.logA 1 (fun f ->
Printf.fprintf f "Extra reductions on error were added in %d states.\n" !extra
Printf.fprintf f "Extra reductions on error were added in %d states.\n" !extra;
Printf.fprintf f "Priority played a role in %d of these states.\n" !prioritized
);
(* Warn about useless %on_error_reduce declarations. *)
OnErrorReduce.iter (fun nt ->
......
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