chollida
chollida

Reputation: 7894

What is the Antlr3 C runtime equivalent of throwing an exception for error reporting

I'm pretty familiar with Antlr 2.X and the Antlr 3.1.X CSharp and python targets.

However I'm now forced to use the Antlr 3 C target for a project.

My issue is how do I report errors in my grammar, or tree grammar.

Consider a rule that matches a token and we put it into a map. We want to ensure the token is unique. Normally I'd throw an exception if the token was already in the map and catch the exception outside of hte parser to report the error.

What is Antlr C runtime equivalent of the following rule?

token_match: ID 
{
    if(mp.find($ID.Text))
        throw std::exception("Non unique token found");
}

Upvotes: 2

Views: 1125

Answers (1)

user597225
user597225

Reputation:

I'd recommend using your own methods to display semantic errors. But if you need to stay in ANTLR for this:

First you have to create your own error handler if you want to create custom exception types. Look at antlr3baserecognizer.c:1000 for the original.

static void         
displayRecognitionErrorNew  (pANTLR3_BASE_RECOGNIZER recognizer,
                             pANTLR3_UINT8 * tokenNames)
{
...
    switch  (ex->type)
    {
    case    ANTLR3_UNWANTED_TOKEN_EXCEPTION:
...
    case    NUTF_EXCEPTION:
      printf("Non unique token found");
      break;

Then code some function or rule code to process an exception structure. Look at antlr3baserecognizer.c:325 to setup your exception.

ex = antlr3ExceptionNew(ANTLR3_RECOGNITION_EXCEPTION,
                       (void *)ANTLR3_RECOGNITION_EX_NAME,
                       NULL,
                       ANTLR3_FALSE);

ex->type                = NUTF_EXCEPTION
ex->line                = ins->getLine (ins);
ex->charPositionInLine  = ins->getCharPositionInLine    (ins);  
ex->index               = is->index (is);
ex->streamName          = ins->fileName;
ex->message             = "That was totally unexpected";

Next you need to actually throw your exception when you detect the error. I think the only way to do this is to override mismatch() adding in your code and calling it from your rule.

static  void
mismatchNew(pANTLR3_BASE_RECOGNIZER recognizer, ANTLR3_UINT32 ttype, pANTLR3_BITSET_LIST follow)
{
  ...
}

Finally tell ANTLR to use your new functions.

@parser::apifuncs {
  RECOGNIZER->displayRecognitionError       = displayRecognitionErrorNew;
  RECOGNIZER->antlr3RecognitionExceptionNew = antlr3RecognitionExceptionNewNew;
  RECOGNIZER->mismatch                      = mismatchNew;
}

Upvotes: 2

Related Questions