Path: csiph.com!aioe.org!.POSTED!not-for-mail From: Victor Porton Newsgroups: comp.lang.java.programmer Subject: Re: Two exceptions Date: Sat, 09 Dec 2017 01:55:42 +0200 Organization: Aioe.org NNTP Server Lines: 107 Message-ID: References: NNTP-Posting-Host: Sz6TxwyziwPWhj5bu0SdBw.user.gioia.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7Bit X-Complaints-To: abuse@aioe.org User-Agent: KNode/4.14.10 X-Notice: Filtered by postfilter v. 0.8.2 Xref: csiph.com comp.lang.java.programmer:37740 Eric Sosman wrote: > On 12/8/2017 5:53 PM, Victor Porton wrote: >> I am writing something like a recursive descent parser: That is, I >> inspect object and its parts. When a part of an object is wrong, my >> method parse() throws my exception ParseException. It is sometimes >> handled in parse() of a higher-level object. >> >> Example: >> >> An object X may be either X1 or X2 or X3 class. >> >> I try to call parse() for an object of X1 class. If it parses, the higher >> level parse() (for X) return X1 casted to X. If it fails with exception >> ParseException, X2 is tried, and if that fails too X3 is tried. >> >> Or for an object X I try calling parse() for subobjects Y and Z. If >> either throws ParseException, the parse exception is propagated for >> parse() of X. >> >> In this way, I consider an object and its possible parts. This is >> sometimes called recursive descent. >> >> But I want also FatalParseException meant to stop parsing of a file >> altogether if it happens in the object or its subobject. >> >> Human logic suggests that FatalParseException is a kind of ParseException >> and so should be its subclass. But this way handling ParseException we >> would also handle FatalParseException what is wrong, because >> FatalParseException is meant to be handled only in the outer method, >> outside of all parse() methods. >> >> So I have two alternatives: >> >> 1. Derive ParseException from FatalParseException what seems to do the >> right thing but seems illogical. >> >> 2. Not derive either of these two exceptions from each other. >> >> By the way, I am to rewrite an Ada project in Java (because the Ada >> compiler is too buggy and I can't work with it). In Ada all exceptions >> are independent (no exception is a subclass of another one). > > Alternative #1 seems preferable (to me). Perhaps you would find it > more palatable if you renamed FatalParseException to ParseFailure and > ParseException to ParseMismatch. > > However, I feel you may be misusing exceptions. They are supposed > to be, well, "exceptional" rather than "normal control flow." In a > recursive descent parser you *expect* many matching failures, just in > the ordinary course of events; a matching failure is not "exceptional." > (Also, building a Throwable can be rather expensive, especially if it > is thrown from a deep point in the call stack and must fill in a long > stack trace. Java's optimizations tend to focus on the "normal" cases > rather than on the "exceptional" ones, so throwing and catching, even > though much improved since Java 1.0, still involves a lot of work.) > > Instead of announcing a "venial" mismatch by throwing an exception, > consider returning a status value from each parse method. This might > be a boolean ("It's an X1" / "It's not an X1") or a reference value > ("It's an X1 and here it is" / "It's not an X1 and here's a null"), > or something more structured ("Here's a status-and-result-and-info > object; look at its fields to find out what happened"). Not only is > this likely to produce faster code, but it may also simplify > > X result; > try { > result = X1.parse(); > } catch (ParseMismatch ex1) { > try { > result = X2.parse(); > } catch (ParseMismatch ex2) { > try { > result = X3.parse(); > } catch (ParseMismatch ex3) { > ... > } > > to something more like > > X result = X1.parse(); > if (result == null) > result = X2.parse(); > if (result == null) > result = X3.parse(); > ... The main reason I chose to use exceptions for this, is to allow parse() method to return the result of parsing (not a boolean value). For example result of parsing an integer may return "long". Can you propose another alternative? It is to be easily programmable (if I find handling exceptions too slow, I always can rewrite my program). Oh, I see, you proposed to return "null" instead of my ParseException. It however also seems to me not a quite good solution, because returning null may be a non-exceptionable situation (as for a missing optional object in the parsed resource). > (You could, of course, nest these differently.) > > Perhaps the structure of the existing Ada code is not amenable > to this sort of transformation -- but if I were you I'd give it > some consideration. > -- Victor Porton - http://portonvictor.org