Commit ef6ef63e authored by POTTIER Francois's avatar POTTIER Francois

Improved the spurious reduction warning to include state numbers.

parent 1e62aadb
...@@ -218,13 +218,13 @@ let default_message = ...@@ -218,13 +218,13 @@ let default_message =
"<YOUR SYNTAX ERROR MESSAGE HERE>\n" "<YOUR SYNTAX ERROR MESSAGE HERE>\n"
(* [print_messages_auto] displays just the sentence and the auto-generated (* [print_messages_auto] displays just the sentence and the auto-generated
comments. [os'] may be [None], in which case the auto-generated comment comments. [otarget] may be [None], in which case the auto-generated comment
is just a warning that this sentence does not end in an error. *) is just a warning that this sentence does not end in an error. *)
let print_messages_auto (nt, sentence, otarget) : unit = let print_messages_auto (nt, sentence, otarget) : unit =
(* Print the sentence, followed with auto-generated comments. *) (* Print the sentence, followed with auto-generated comments. *)
print_string (print_sentence (Some nt, sentence)); print_string (print_sentence (Some nt, sentence));
match otarget with match (otarget : target option) with
| None -> | None ->
Printf.printf Printf.printf
"##\n\ "##\n\
...@@ -248,9 +248,10 @@ let print_messages_auto (nt, sentence, otarget) : unit = ...@@ -248,9 +248,10 @@ let print_messages_auto (nt, sentence, otarget) : unit =
## accurate view of the past (what has been recognized so far), they\n\ ## accurate view of the past (what has been recognized so far), they\n\
## may provide an INCOMPLETE view of the future (what was expected next).\n" ## may provide an INCOMPLETE view of the future (what was expected next).\n"
; ;
List.iter (fun prod -> List.iter (fun (s, prod) ->
Printf.printf Printf.printf
"## Spurious reduction of production %s\n" "## In state %d, spurious reduction of production %s\n"
(Lr1.number s)
(Production.print prod) (Production.print prod)
) spurious; ) spurious;
Printf.printf "##\n" Printf.printf "##\n"
...@@ -279,10 +280,10 @@ let write_run : maybe_targeted_run -> unit = ...@@ -279,10 +280,10 @@ let write_run : maybe_targeted_run -> unit =
(* First, print every sentence and human comment. *) (* First, print every sentence and human comment. *)
List.iter (fun sentence_or_comment -> List.iter (fun sentence_or_comment ->
match sentence_or_comment with match sentence_or_comment with
| Sentence ((poss, ((_, toks) as sentence)), os') -> | Sentence ((poss, ((_, toks) as sentence)), target) ->
let nt = start poss sentence in let nt = start poss sentence in
(* Every sentence is followed with newly generated auto-comments. *) (* Every sentence is followed with newly generated auto-comments. *)
print_messages_auto (nt, toks, os') print_messages_auto (nt, toks, target)
| Comment c -> | Comment c ->
print_string c print_string c
) sentences_or_comments; ) sentences_or_comments;
......
...@@ -236,11 +236,11 @@ let interpret log nt lexer lexbuf = ...@@ -236,11 +236,11 @@ let interpret log nt lexer lexbuf =
open MenhirLib.General (* streams *) open MenhirLib.General (* streams *)
type spurious_reductions = type spurious_reduction =
Production.index list Lr1.node * Production.index
type target = type target =
Lr1.node * spurious_reductions Lr1.node * spurious_reduction list
type check_error_path_outcome = type check_error_path_outcome =
(* Bad: the input was read past its end. *) (* Bad: the input was read past its end. *)
...@@ -268,6 +268,22 @@ let check_error_path nt input = ...@@ -268,6 +268,22 @@ let check_error_path nt input =
end) end)
in in
(* Determine the initial state. *)
let entry = Lr1.entry_of_nt nt in
(* This function helps extract the current parser state out of [env].
It may become unnecessary if the [Engine] API offers it. *)
let current env =
(* Peek at the stack. If empty, then we must be in the initial state. *)
match Lazy.force (E.stack env) with
| Nil ->
entry
| Cons (E.Element (s, _, _, _), _) ->
s
in
(* Set up a function that delivers tokens one by one. *) (* Set up a function that delivers tokens one by one. *)
let input = ref input in let input = ref input in
...@@ -284,7 +300,7 @@ let check_error_path nt input = ...@@ -284,7 +300,7 @@ let check_error_path nt input =
!input = [] !input = []
in in
(* Run it. We wish to stop at the first error (without handling the error (* Run. We wish to stop at the first error (without handling the error
in any way) and report in which state the error occurred. A clean way in any way) and report in which state the error occurred. A clean way
of doing this is to use the incremental API, as follows. The main loop of doing this is to use the incremental API, as follows. The main loop
resembles the [loop] function in [Engine]. *) resembles the [loop] function in [Engine]. *)
...@@ -293,9 +309,7 @@ let check_error_path nt input = ...@@ -293,9 +309,7 @@ let check_error_path nt input =
spurious reductions. We accumulate these reductions in [spurious], a spurious reductions. We accumulate these reductions in [spurious], a
(reversed) list of productions. *) (reversed) list of productions. *)
let entry = Lr1.entry_of_nt nt in let rec loop (result : cst E.result) (spurious : spurious_reduction list) =
let rec loop (result : cst E.result) (spurious : Production.index list) =
match result with match result with
| E.InputNeeded _ -> | E.InputNeeded _ ->
begin match next() with begin match next() with
...@@ -312,7 +326,7 @@ let check_error_path nt input = ...@@ -312,7 +326,7 @@ let check_error_path nt input =
a default reduction, then this is a spurious reduction. *) a default reduction, then this is a spurious reduction. *)
let spurious = let spurious =
if looking_at_last_token() && not (E.has_default_reduction env) then if looking_at_last_token() && not (E.has_default_reduction env) then
prod :: spurious (current env, prod) :: spurious
else else
spurious spurious
in in
...@@ -321,16 +335,8 @@ let check_error_path nt input = ...@@ -321,16 +335,8 @@ let check_error_path nt input =
(* Check that all of the input has been read. Otherwise, the error (* Check that all of the input has been read. Otherwise, the error
has occurred sooner than expected. *) has occurred sooner than expected. *)
if !input = [] then if !input = [] then
(* Return the current state. This is done by peeking at the stack. (* Return the current state and the list of spurious reductions. *)
If the stack is empty, then we must be in the initial state. *) OK (current env, List.rev spurious)
let s =
match Lazy.force (E.stack env) with
| Nil ->
entry
| Cons (E.Element (s, _, _, _), _) ->
s
in
OK (s, List.rev spurious)
else else
OInputNotFullyConsumed OInputNotFullyConsumed
| E.Accepted _ -> | E.Accepted _ ->
......
...@@ -24,11 +24,11 @@ val interpret: ...@@ -24,11 +24,11 @@ val interpret:
in the expected state. It is also used by several of the command line in the expected state. It is also used by several of the command line
options [--interpret-error], [--compile-errors], etc. *) options [--interpret-error], [--compile-errors], etc. *)
type spurious_reductions = type spurious_reduction =
Production.index list Lr1.node * Production.index
type target = type target =
Lr1.node * spurious_reductions Lr1.node * spurious_reduction list
type check_error_path_outcome = type check_error_path_outcome =
(* Bad: the input was read past its end. *) (* Bad: the input was read past its end. *)
......
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