Loading ...
Sorry, an error occurred while loading the content.

Re: Manually generating parsing exceptions

Expand Messages
  • pete@xxxxxx.xxxxx.xx.xxxxxxxxxxxxxx)
    Hi ... This wasn t very easy to track down, I have to admit. ... The problem is in the catch clause right after the user-generated throw. In that, there is a
    Message 1 of 2 , Dec 22, 1998
    • 0 Attachment

      > I'm sending this to you as a last resort since I've spent way too
      > much time in the VC++ 6.0 debugger trying to track down a nasty exception.
      > Unfortunately I'm an ANTLR tenderfoot and I'm not smart enough to help
      > myself. :-(

      This wasn't very easy to track down, I have to admit.

      > You'll note in the attached grammar that I'm generating to C++. The
      > interesting stuff is in the "funcExpr" rule in the parser grammar.
      > Essentially I want the parser to recognize anything that *looks* like a
      > function call (e.g., f(foo, bar, baz)) but I want the parser to reject (with
      > a meaningful message) any function call that (a) is not a recognized or
      > supported function (e.g. bat(...)) or (b) has the wrong number of arguments
      > (e.g., sin(1.1, 2.2)).
      > To accomplish this I examine the function name token text and
      > argument count manually and throw a ParserException as a semantic action if
      > either of conditions (a) or (b) are encountered. Well this generates a most
      > heinous unhandled exception in the bowels of the generated parser (it looks
      > like a RefToken is being munched somewhere).

      The problem is in the catch clause right after the user-generated throw.
      In that, there is a call to consume(), which removes the next token from
      the token queue. Unfortunately, in this case, there are no tokens in the
      queue, and we end up trying to remove the first element from an empty
      container. Some platforms don't seem to care, but MS does.

      I think this is also a problem in Java mode (not a crash but incorrect
      behaviour). I've boiled it down to a really simple test case, described

      There seems to be a problem with throwing a ParserException from an
      action, where an extra token is skipped from the input.

      Here's a simple grammar file, which parses a stream of letters. If it
      meets the letter Z, it throws an exception. But the following letter is
      then skipped.

      class SimpleParser extends Parser;

      : (identifier)* EOF!

      : n:ALPHA
      if (n.getText().equals("Z"))
      throw new ParserException("Please don't use the letter Z");
      System.out.println("The letter "+n.getText()+" is OK");

      class SimpleLexer extends Lexer;

      : 'a'..'z' | 'A'..'Z'

      : ( ' '
      | '\t'
      | '\r' ('\n')?
      | '\n'
      { _ttype = Token.SKIP; }

      Again, the problem is in the call to consume() in the catch clause after
      the user-generated throw. At this point, there is no token to consume,
      so the TokenQueue sets nbrEntries to -1, so the next token gets skipped.

      My question, then, is this:

      Should TokenQueue.removeFirst() check for nbrEntries==0 and do nothing
      in that case? It feels like a bit of a hack, but is there a better way
      to avoid this problem?

    Your message has been successfully submitted and would be delivered to recipients shortly.