⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 errorrecovery.html

📁 This a JavaCC documentation.
💻 HTML
字号:
<HTML><!--Copyright 漏 2002 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,California 95054, U.S.A. All rights reserved.  Sun Microsystems, Inc. hasintellectual property rights relating to technology embodied in the productthat is described in this document. In particular, and without limitation,these intellectual property rights may include one or more of the U.S.patents listed at http://www.sun.com/patents and one or more additionalpatents or pending patent applications in the U.S. and in other countries.U.S. Government Rights - Commercial software. Government users are subjectto the Sun Microsystems, Inc. standard license agreement and applicableprovisions of the FAR and its supplements.  Use is subject to license terms.Sun,  Sun Microsystems,  the Sun logo and  Java are trademarks or registeredtrademarks of Sun Microsystems, Inc. in the U.S. and other countries.  Thisproduct is covered and controlled by U.S. Export Control laws and may besubject to the export or import laws in other countries.  Nuclear, missile,chemical biological weapons or nuclear maritime end uses or end users, whetherdirect or indirect, are strictly prohibited.  Export or reexport to countriessubject to U.S. embargo or to entities identified on U.S. export exclusionlists, including, but not limited to, the denied persons and speciallydesignated nationals lists is strictly prohibited.--><HEAD> <title>JavaCC: Error Reporting and Recovery</title><!-- Changed by: Michael Van De Vanter, 14-Jan-2003 --></HEAD><BODY bgcolor="#FFFFFF" ><H1>JavaCC [tm]: Error Reporting and Recovery</H1><PRE>This is a rough document describing the new error recovery features inVersion 0.7.1.  This document also describes how features have changedsince Version 0.6.The first change (from 0.6) is that we have two new exceptions:    . ParseException    . TokenMgrErrorWhenever the token manager detects a problem, it throws the exceptionTokenMgrError.  Previously, it used to print the message:  Lexical Error ...following which it use to throw the exception ParseError.Whenever the parser detects a problem, it throws the exceptionParseException.  Previously, it used to print the message:  Encountered ... Was expecting one of ...following which it use to throw the exception ParseError.In Version 0.7.1, error messages are never printed explicitly,rather this information is stored inside the exception objects thatare thrown.  Please see the classes ParseException.java andTokenMgrError.java (that get generated by JavaCC [tm] during parsergeneration) for more details.If the thrown exceptions are never caught, then a standard action istaken by the virtual machine which normally includes printing thestack trace and also the result of the "toString" method in theexception.  So if you do not catch the JavaCC exceptions, a messagequite similar to the ones in Version 0.6.But if you catch the exception, you must print the message yourself.Exceptions in the Java [tm] programming language are all subclasses oftype Throwable.  Furthermore, exceptions are divided into two broadcategories - ERRORS and other exceptions.Errors are exceptions that one is not expected to recover from -examples of these are ThreadDeath or OutOfMemoryError.  Errors areindicated by subclassing the exception "Error".  Exceptions subclassedfrom Error need not be specified in the "throws" clause of methoddeclarations.Exceptions other than errors are typically defined by subclassing theexception "Exception".  These exceptions are typically handled by theuser program and must be declared in throws clauses of methoddeclarations (if it is possible for the method to throw thatexception).The exception TokenMgrError is a subclass of Error, while theexception ParseException is a subclass of Exception.  The reasoninghere is that the token manager is never expected to throw an exception- you must be careful in defining your token specifications such thatyou cover all cases.  Hence the suffix "Error" in TokenMgrError.  Youdo not have to worry about this exception - if you have designed yourtokens well, it should never get thrown.  Whereas it is typical toattempt recovery from Parser errors - hence the name "ParseException".(Although if you still want to recover from token manager errors, youcan do it - it's just that you are not forced to catch them.)In Version 0.7.1, we have added a syntax to specify additional exceptionsthat may be thrown by methods corresponding to non-terminals.  Thissyntax is identical to the Java "throws ..." syntax.  Here's anexample of how you use this:  void VariableDeclaration() throws SymbolTableException, IOException :  {...}  {    ...  }Here, VariableDeclaration is defined to throw exceptionsSymbolTableException and IOException in addition to ParseException.Error Reporting:The scheme for error reporting is simpler in Version 0.7.1 (as comparedto Version 0.6) - simply modify the file ParseException.java to dowhat you want it to do.  Typically, you would modify the getMessagemethod to do your own customized error reporting.  All informationregarding these methods can be obtained from the comments in thegenerated files ParseException.java and TokenMgrError.java.  It willalso help to understand the functionality of the class Throwable (reada Java book for this).There is a method in the generated parser called"generateParseException".  You can call this method anytime you wishto generate an object of type ParseException.  This object willcontain all the choices that the parser has attempted since the lastsuccessfully consumed token.Error Recovery:JavaCC offers two kinds of error recovery - shallow recovery and deeprecovery.  Shallow recovery recovers if none of the current choiceshave succeeded in being selected, while deep recovery is when a choiceis selected, but then an error happens sometime during the parsing ofthis choice.Shallow Error Recovery:We shall explain shallow error recovery using the following example:void Stm() :{}{  IfStm()|  WhileStm()}Let's assume that IfStm starts with the reserved word "if" and WhileStmstarts with the reserved word "while".  Suppose you want to recover byskipping all the way to the next semicolon when neither IfStm nor WhileStmcan be matched by the next input token (assuming a lookahead of 1).  Thatis the next token is neither "if" nor "while".What you do is write the following:void Stm() :{}{  IfStm()|  WhileStm()|  error_skipto(SEMICOLON)}But you have to define "error_skipto" first.  So far as JavaCC is concerned,"error_skipto" is just like any other non-terminal.  The following is oneway to define "error_skipto" (here we use the standard JAVACODE production):JAVACODEvoid error_skipto(int kind) {  ParseException e = generateParseException();  // generate the exception object.  System.out.println(e.toString());  // print the error message  Token t;  do {    t = getNextToken();  } while (t.kind != kind);    // The above loop consumes tokens all the way up to a token of    // "kind".  We use a do-while loop rather than a while because the    // current token is the one immediately before the erroneous token    // (in our case the token immediately before what should have been    // "if"/"while".}That's it for shallow error recovery.  In a future version of JavaCCwe will have support for modular composition of grammars.  When thishappens, one can place all these error recovery routines into aseparate module that can be "imported" into the main grammar module.We intend to supply a library of useful routines (for error recoveryand otherwise) when we implement this capability.Deep Error Recovery:Let's use the same example that we did for shallow recovery:void Stm() :{}{  IfStm()|  WhileStm()}In this case we wish to recover in the same way.  However, we wish torecover even when there is an error deeper into the parse.  Forexample, suppose the next token was "while" - therefore the choice"WhileStm" was taken.  But suppose that during the parse of WhileStmsome error is encountered - say one has "while (foo { stm; }" - i.e., theclosing parentheses has been missed.  Shallow recovery will not workfor this situation.  You need deep recovery to achieve this.  For this,we offer a new syntactic entity in JavaCC - the try-catch-finally block.First, let us rewrite the above example for deep error recovery and thenexplain the try-catch-finally block in more detail:void Stm() :{}{  try {    (      IfStm()    |      WhileStm()    )  catch (ParseException e) {    error_skipto(SEMICOLON);  }}That's all you need to do.  If there is any unrecovered error during theparse of IfStm or WhileStm, then the catch block takes over.  You canhave any number of catch blocks and also optionally a finally block(just as with Java errors).  What goes into the catch blocks is *Java code*,not JavaCC expansions.  For example, the above example could have beenrewritten as:void Stm() :{}{  try {    (      IfStm()    |      WhileStm()    )  catch (ParseException e) {    System.out.println(e.toString());    Token t;    do {      t = getNextToken();    } while (t.kind != SEMICOLON);  }}Our belief is that it's best to avoid placing too much Java code in thecatch and finally blocks since it overwhelms the grammar reader.  Its bestto define methods that you can then call from the catch blocks.Note that in the second writing of the example, we essentially copiedthe code out of the implementation of error_skipto.  But we left out thefirst statement - the call to generateParseException.  That's because inthis case, the catch block already provides us with the exception.  Buteven if you did call this method, you will get back an identical object.</PRE><P></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -