Commit 586c30ec by POTTIER Francois

Removed support for the $previouserror keyword.

parent ca793975
2014/12/02:
Removed support for the $previouserror keyword.
2014/02/18:
In the Coq backend, use ' instead of _ as separator in identifiers.
Also, correct a serious bug that was inadvertently introduced on
......
......@@ -1609,7 +1609,7 @@ issues a warning otherwise. This ensures that the parser always terminates.
\paragraph{Error-related keywords}
A couple of error-related keywords are made available to semantic actions.
The following keyword is made available to semantic actions.
When the \verb+$syntaxerror+ keyword is evaluated, evaluation of the semantic
action is aborted, so that the current reduction is abandoned; the current
......@@ -1619,12 +1619,6 @@ handling mode is entered. Note that there is no mechanism for inserting an
might also be desirable. It is unclear whether this keyword is useful; it
might be suppressed in the future.
The \verb+$previouserror+ keyword evaluates to an integer value, and indicates
how many tokens were successfully shifted since the last \error token was
shifted. This allows heuristics such as \textit{``when a new error is detected, do not
display a new error message unless the previous error is ancient enough''} to
be implemented if and where desired.
\paragraph{When are errors detected?}
An error is detected when the current state of the automaton has no action on
......
......@@ -167,9 +167,6 @@ let rec print f action =
in
P.expr action.expr
let has_previouserror action =
KeywordSet.mem PreviousError (keywords action)
let has_syntaxerror action =
KeywordSet.mem SyntaxError (keywords action)
......
......@@ -44,9 +44,6 @@ val print: out_channel -> t -> unit
(** [from_stretch s] builds an action out of a textual piece of code. *)
val from_stretch: Stretch.t -> t
(** Check whether the keyword $previouserror is used in the action. *)
val has_previouserror: t -> bool
(** Check whether the keyword $syntaxerror is used in the action. *)
val has_syntaxerror: t -> bool
......
......@@ -186,17 +186,6 @@ open Interface
were the default behavior; however, recall that error recovery is
disabled unless [--error-recovery] was specified.
When an error is detected and an error production is reduced, the
user might like to know how recent the previous error was, so as
(for instance) to suppress diagnostic messages if it was too
recent. (yacc and ocamlyacc have their own, hard-wired,
idiosyncratic mechanism for that.) We provide access to this
information as follows. When a new error is detected and
[env.shifted] is set to -1, the previous value of [env.shifted] is
saved to [env.previouserror]. Thus, the number of tokens that were
shifted between the two errors is recorded. This information is
then made available to the user via the $previouserror keyword.
I note that error recovery, case (a) above, can cause the parser to
enter an infinite loop. Indeed, the token stream is in principle
infinite -- for instance, many lexers will return an EOF token
......@@ -328,9 +317,6 @@ let fstartp =
let fendp =
prefix "endp"
let fpreviouserror =
prefix "previouserror"
(* The type variable that represents the stack tail. *)
let tvtail =
......@@ -422,14 +408,6 @@ let auto2scheme t =
scheme [ tvtail; tvresult ] t
(* ------------------------------------------------------------------------ *)
(* Determine whether at least one semantic action mentions $previouserror. *)
let previouserror_required : bool =
Production.foldx (fun prod accu ->
accu || Action.has_previouserror (Production.action prod)
) false
(* ------------------------------------------------------------------------ *)
(* Determine whether the [goto] function for nonterminal [nt] will push
a new cell onto the stack. If it doesn't, then that job is delegated
to the [run] functions called by [goto].
......@@ -604,7 +582,7 @@ let envtypedef = {
typename = tcenv;
typeparams = [];
typerhs =
TDefRecord ([
TDefRecord [
(* The lexer itself. *)
......@@ -635,14 +613,7 @@ let envtypedef = {
field true fshifted tint;
] @
(* If at least one semantic action mentions $previouserror, then we keep
track of this information. *)
insertif previouserror_required (field true fpreviouserror tint)
);
];
typeconstraint = None
}
......@@ -1146,11 +1117,7 @@ let defaultreductioncomment toks e =
(* This produces some bookkeeping code that is used when initiating
error handling.
First, we copy [env.shifted] to [env.previouserror]. Of course,
this is done only if at least one semantic action uses the
[$previouserror] keyword.
Then, we reset the count of tokens shifted since the last error to
We reset the count of tokens shifted since the last error to
-1, so that it becomes zero *after* the error token itself is
shifted. By convention, when [shifted] is -1, the field [env.token]
becomes meaningless and one considers that the first token on the
......@@ -1163,8 +1130,6 @@ let errorbookkeeping e =
tracecomment
"Initiating error handling"
(blet (
concatif previouserror_required
[ PUnit, ERecordWrite (EVar env, fpreviouserror, ERecordAccess (EVar env, fshifted)) ] @
[ PUnit, ERecordWrite (EVar env, fshifted, EIntConst (-1)) ],
e
))
......@@ -1446,7 +1411,7 @@ let reducebody prod =
(pat, EVar stack) ::
unitbindings @
posbindings action @
extrabindings fpreviouserror action,
extrabindings action,
(* If the semantic action is susceptible of raising [Error],
use a [let/unless] construct, otherwise use [let]. *)
......@@ -1801,8 +1766,7 @@ let initenvdef =
(fstartp, ERecordAccess (EVar lexbuf, "Lexing.lex_start_p"));
(fendp, ERecordAccess (EVar lexbuf, "Lexing.lex_curr_p"));
(fshifted, EMaxInt)
] @
insertif previouserror_required (fpreviouserror, EMaxInt)
]
)
)
),
......
......@@ -192,18 +192,15 @@ let destructuretokendef name codomain bindsemv branch = {
(* Bindings for exotic keywords. *)
(* [extrabindings fpreviouserror action] provides definitions for the
[$startofs], [$endofs], and [$previouserror] keywords, if required
by a semantic action. The parameter [fpreviouserror] is the name of
the [previouserror] field in the environment -- the table-based and
code-based back-ends use different names. The parameter [action] is
the semantic action within which these keywords might be used. *)
(* [extrabindings action] provides definitions for the [$startofs] and
[$endofs] keywords, if required by a semantic action. The parameter
[action] is the semantic action within which these keywords might be
used. *)
(* The [ofs] keyword family is defined in terms of the [pos] family by
accessing the [pos_cnum] field. The [$previouserror] keyword simply
provides access to the current value of [env.previouserror]. *)
accessing the [pos_cnum] field. *)
let extrabindings fpreviouserror action =
let extrabindings action =
Keyword.KeywordSet.fold (fun keyword bindings ->
match keyword with
| Keyword.Dollar _
......@@ -213,8 +210,6 @@ let extrabindings fpreviouserror action =
| Keyword.Position (s, w, (Keyword.FlavorOffset as f)) ->
(PVar (Keyword.posvar s w f),
ERecordAccess (EVar (Keyword.posvar s w Keyword.FlavorPosition), "Lexing.pos_cnum")) :: bindings
| Keyword.PreviousError ->
(PVar "_previouserror", ERecordAccess (EVar env, fpreviouserror)) :: bindings
) (Action.keywords action) []
(* ------------------------------------------------------------------------ *)
......
......@@ -108,13 +108,11 @@ val destructuretokendef: string -> typ -> bool -> (Terminal.t -> expr) -> valdef
(* Bindings for exotic keywords. *)
(* This provides definitions for the [$startofs], [$endofs], and
[$previouserror] keywords, if required by a semantic action. The
[ofs] keyword family is defined in terms of the [pos] family by
accessing the [pos_cnum] field. The [$previouserror] keyword simply
provides access to the current value of [env.previouserror]. *)
(* This provides definitions for the [$startofs] and [$endofs] keywords, if
required by a semantic action. The [ofs] keyword family is defined in terms
of the [pos] family by accessing the [pos_cnum] field. *)
val extrabindings: string -> Action.t -> (pattern * expr) list
val extrabindings: Action.t -> (pattern * expr) list
(* ------------------------------------------------------------------------ *)
......
......@@ -69,10 +69,10 @@ module Run (T: sig end) = struct
| Some _ -> ());
Production.iterx (fun prod ->
let act = Production.action prod in
if Action.has_previouserror act || Action.has_syntaxerror act ||
if Action.has_syntaxerror act ||
Action.has_leftstart act || Action.has_leftend act ||
Action.use_dollar act then
Error.error [] ("$previouserror, $syntaxerror, $start, $end, $i are not "^
Error.error [] ("$syntaxerror, $start, $end, $i are not "^
"supported by the coq back-end"))
end;
......
......@@ -231,7 +231,6 @@ module Make (T : TABLE) = struct
and errorbookkeeping env =
Log.initiating_error_handling();
env.previouserror <- env.shifted;
env.shifted <- (-1);
error env
......@@ -329,7 +328,6 @@ module Make (T : TABLE) = struct
lexbuf = lexbuf;
token = token;
shifted = max_int;
previouserror = max_int;
stack = empty;
current = s;
} in
......
......@@ -67,12 +67,6 @@ type ('state, 'semantic_value, 'token) env = {
mutable shifted: int;
(* A copy of the value of [shifted] just before the most recent error
was detected. This value is not used by the automaton itself, but
is made accessible to semantic actions. *)
mutable previouserror: int;
(* The stack. In [CodeBackend], it is passed around on its own,
whereas, here, it is accessed via the environment. *)
......
/* This is the fancy version of the parser, to be processed by menhir.
It is kept in sync with [Parser], but exercises menhir's features. */
/* As of 2014/12/02, the $previouserror keyword and the --error-recovery
mode no longer exists. Thus, we replace all calls to [Error.signal]
with calls to [Error.error], and report just one error. */
/* ------------------------------------------------------------------------- */
/* Imports. */
......@@ -79,12 +83,11 @@ declaration:
| TOKEN OCAMLTYPE? clist(terminal) error
| TOKEN OCAMLTYPE? error
{ Error.signal (Positions.two $startpos $endpos) "\
{ Error.error (Positions.two $startpos $endpos) "\
Syntax error in a %token declaration.
Here are sample valid declarations:
%token DOT SEMICOLON
%token <string> LID UID";
[]
%token <string> LID UID"
}
| START t = OCAMLTYPE? nts = clist(nonterminal) %prec decl
......@@ -100,12 +103,11 @@ Here are sample valid declarations:
| START OCAMLTYPE? clist(nonterminal) error
| START OCAMLTYPE? error
{ Error.signal (Positions.two $startpos $endpos) "\
{ Error.error (Positions.two $startpos $endpos) "\
Syntax error in a %start declaration.
Here are sample valid declarations:
%start expression phrase
%start <int> date time";
[]
%start <int> date time"
}
| TYPE t = OCAMLTYPE ss = clist(actual_parameter) %prec decl
......@@ -115,12 +117,11 @@ Here are sample valid declarations:
| TYPE OCAMLTYPE clist(actual_parameter) error
| TYPE OCAMLTYPE error
| TYPE error
{ Error.signal (Positions.two $startpos $endpos) "\
{ Error.error (Positions.two $startpos $endpos) "\
Syntax error in a %type declaration.
Here are sample valid declarations:
%type <Syntax.expression> expression
%type <int> date time";
[]
%type <int> date time"
}
| k = priority_keyword ss = clist(symbol) %prec decl
......@@ -129,34 +130,26 @@ Here are sample valid declarations:
| priority_keyword clist(symbol) error
| priority_keyword error
{ Error.signal (Positions.two $startpos $endpos) "\
{ Error.error (Positions.two $startpos $endpos) "\
Syntax error in a precedence declaration.
Here are sample valid declarations:
%left PLUS TIMES
%nonassoc unary_minus
%right CONCAT";
[]
%right CONCAT"
}
| PARAMETER t = OCAMLTYPE
{ [ with_poss $startpos $endpos (DParameter t) ] }
| PARAMETER error
{ Error.signal (Positions.two $startpos $endpos) "\
{ Error.error (Positions.two $startpos $endpos) "\
Syntax error in a %parameter declaration.
Here is a sample valid declaration:
%parameter <X : sig type t end>";
[]
%parameter <X : sig type t end>"
}
/* This error production should lead to resynchronization on the next %something.
The use of $previouserror prevents reporting errors that are too close to one
another -- presumably, the second error only means that we failed to properly
recover after the first error. */
| error
{ if $previouserror >= 3 then
Error.signal (Positions.two $startpos $endpos) "Syntax error inside a declaration.";
[] }
{ Error.error (Positions.two $startpos $endpos) "Syntax error inside a declaration." }
/* This production recognizes tokens that are valid in the rules section,
but not in the declarations section. This is a hint that a %% was
......@@ -164,15 +157,9 @@ Here is a sample valid declaration:
| rule_specific_token
{
if $previouserror >= 3 then
Error.signal (Positions.two $startpos $endpos)
"Syntax error inside a declaration.\n\
Did you perhaps forget the %% that separates declarations and rules?";
(* Do not attempt to perform error recovery. There is no way of
forcing the automaton into a state where rules are expected. *)
exit 1
Error.error (Positions.two $startpos $endpos)
"Syntax error inside a declaration.\n\
Did you perhaps forget the %% that separates declarations and rules?"
}
priority_keyword:
......@@ -250,9 +237,7 @@ rule:
| error
/* This error production should lead to resynchronization on the next
well-formed rule. */
{ if $previouserror >= 3 then
Error.signal (Positions.two $startpos $endpos) "Syntax error inside the definition of a nonterminal symbol.";
[] }
{ Error.error (Positions.two $startpos $endpos) "Syntax error inside the definition of a nonterminal symbol." }
flags:
/* epsilon */
......@@ -296,9 +281,7 @@ production_group:
/* This error production should lead to resynchronization on the next
semantic action, unless the end of file is reached before a semantic
action is found. */
{ if $previouserror >= 3 then
Error.signal (Positions.two $startpos($1) $endpos($1)) "Syntax error inside a production.";
[] }
{ Error.error (Positions.two $startpos($1) $endpos($1)) "Syntax error inside a production." }
%inline precedence:
PREC symbol = symbol
......
......@@ -100,7 +100,6 @@ let actiondef grammar symbol branch =
right-hand side. *)
let formals =
PAnnot (PVar "_previouserror", tint) ::
PAnnot (PVar "_eRR", texn) ::
PAnnot (PVar "_startpos", tposition) ::
PAnnot (PVar "_endpos", tposition) ::
......
......@@ -646,7 +646,6 @@ let () =
KeywordSet.iter (function
| Dollar _
| PreviousError
| SyntaxError ->
()
| Position (Left, where, _) ->
......
......@@ -34,7 +34,6 @@ type subject =
type keyword =
| Dollar of int
| Position of subject * where * flavor
| PreviousError
| SyntaxError
(* ------------------------------------------------------------------------- *)
......
......@@ -31,7 +31,6 @@ type subject =
type keyword =
| Dollar of int
| Position of subject * where * flavor
| PreviousError
| SyntaxError
(* This maps a [Position] keyword to the name of the variable that the
......
......@@ -60,8 +60,7 @@
overwrite content ofs '$' '_';
match keyword with
| Keyword.Dollar _
| Keyword.Position (Keyword.Left, _, _)
| Keyword.PreviousError ->
| Keyword.Position (Keyword.Left, _, _) ->
()
| Keyword.SyntaxError ->
(* $syntaxerror is replaced with
......@@ -374,8 +373,7 @@ and action percent openingpos pkeywords = parse
{ let pkeyword = mk_keyword lexbuf w f n id in
action percent openingpos (pkeyword :: pkeywords) lexbuf }
| previouserror
{ let pkeyword = with_cpos lexbuf Keyword.PreviousError in
action percent openingpos (pkeyword :: pkeywords) lexbuf }
{ error1 (lexeme_start_p lexbuf) "$previouserror is no longer supported." }
| syntaxerror
{ let pkeyword = with_cpos lexbuf Keyword.SyntaxError in
action percent openingpos (pkeyword :: pkeywords) lexbuf }
......@@ -413,8 +411,7 @@ and parentheses openingpos pkeywords = parse
{ let pkeyword = mk_keyword lexbuf w f n id in
parentheses openingpos (pkeyword :: pkeywords) lexbuf }
| previouserror
{ let pkeyword = with_cpos lexbuf Keyword.PreviousError in
parentheses openingpos (pkeyword :: pkeywords) lexbuf }
{ error1 (lexeme_start_p lexbuf) "$previouserror is no longer supported." }
| syntaxerror
{ let pkeyword = with_cpos lexbuf Keyword.SyntaxError in
parentheses openingpos (pkeyword :: pkeywords) lexbuf }
......
......@@ -614,7 +614,6 @@ let check_keywords grammar producers action =
Error.errorp keyword
(Printf.sprintf "%s refers to a nonexistent symbol." id)
| Position (Left, _, _)
| PreviousError
| SyntaxError ->
()
) (Action.pkeywords action)
......
......@@ -55,9 +55,6 @@ let fcurrent =
let flexbuf =
field "lexbuf"
let fpreviouserror =
field "previouserror"
let flex_start_p =
"Lexing.lex_start_p"
......@@ -202,7 +199,7 @@ let reducebody prod =
(pat, EVar stack) :: (* destructure the stack *)
casts @ (* perform type casts *)
posbindings @ (* bind [startp] and [endp] *)
extrabindings fpreviouserror action @ (* add bindings for the weird keywords *)
extrabindings action @ (* add bindings for the weird keywords *)
[ PVar semv, act ], (* run the user's code and bind [semv] *)
ERecordWrite (
......
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