[antlr-interest] how do i throw my exception and get the rule text and line number

Adam Connelly adam.rpconnelly at googlemail.com
Thu Apr 3 03:32:39 PDT 2008


Ok, here's an example grammar:

prog:line+;

line: reportStat | indexStat;

reportStat :  a=ID '=' '[' b=ID ']'  ( a=ID '=' '[' b=ID ']' )*
              {
                     reportMap.put($a.text, $b.text);
              };
indexStat
    :    (a=ID '(' b=INT ',' c=INT ')' '=' d=INT)
{!reportMap.containsKey($a.text)}?
    ;
catch [FailedPredicateException e]
{
    // e.line is the line that the predicate failed at
    // e.charPositionInLine is the position in the line
}

In the indexStat rule, I've written "{!reportMap.containsKey($a.text)}?".
What this means is "stop parsing if the condition inside the braces fails"
(more or less).  So although reportMap.containsKey() only returns a boolean,
because of the {}? around it a FailedPredicateException is thrown if the
condition evaluates to false.

If you generate the parser code and go to the indexStat method you can see
how it works.  You should see some code along the lines of:

if ( !(!reportMap.ContainsKey(a.getText())) ) {
                throw new FailedPredicateException(input, "indexStat",
"!reportMap.ContainsKey($a.text)");
            }

Now you can just leave it like that and you'll get a default error message
if the collection already contains the specified key.  If you want to alter
the exception that gets thrown by the rule when your predicate fails you can
use the optional catch block of the rule (which comes after the last ";" of
the rule) to catch the FailedPredicateException and potentially re-throw it
as your own exception.  I guess you'd have to add a throws clause to your
rule in that case (although since I'm not a big Java person I'm not 100%).

Next, if you want to actually alter the error message that's displayed you
can override the getErrorMessage(RecognitionException e, String[]
tokenNames) method of BaseRecognizer.  To do this you simply write a method
in the members section of the grammar.  It would probably be something like
this:

@members
{
  public String getErrorMessage(RecognitionException e, String[] tokenNames)
  {
    if(e instanceof FailedPredicateException)
    {
      // cast e to FPE and extract whatever data you need from it
      return myNewErrorMessage;
    }

    return super.getErrorMessage(e, tokenNames);
  }
}

Hope that's a help - I think it should do what you need (obviously you'll
need to fill in the blanks and change things here and there).  Below are
some links to the API specs for some of the classes I mentioned.

Cheers,
Adam

http://www.antlr.org/api/Java/classorg_1_1antlr_1_1runtime_1_1_base_recognizer.html
http://www.antlr.org/api/Java/classorg_1_1antlr_1_1runtime_1_1_recognition_exception.html
http://www.antlr.org/api/Java/classorg_1_1antlr_1_1runtime_1_1_failed_predicate_exception.html

On 03/04/2008, hardaway <hardawaycg at gmail.com> wrote:
>
> i 'm new to antlr and maybe my questions are very stupid.
>   just like my question,
> 1: if i have text like those in red
>  *a = [REPA], b=[REPB], c=[REPC]*
>  *a(1,1)=100*
>  b(1,4)=19
>  e(1,1)=100
> when i'm parsing the text,i'll put the first line to a map ,just like
> map.put(a,REPA),map.put(b,REPB)....and when parsing line2-4,just like
> a(1,1).i'll scan the map whether the variable has been defined,just like
> map.containsKey(a),if it is ,i'll do some operations.and just like the above
> text,when it turn to line 4: "map.containsKey(e)".obviously it'll return a
> false to me.and i want to throw my custom Excpetion to warning the text
> writer to do some correct.and i want to throw some custom messages with the
> full text of  "e(1,1)=100" and the line number: 4,maybe message like this
> "REPORT HAS NOT BEEN DEFINED WITH THE TEXT:  e(1,1)=100  in line 4.how can i
> get the full text and the line number.
> indexStat : a=ID '(' b=INT ',' c=INT ')'' '=' d=INT.
> i only know that writing like this: $a.text + '(" + $b.text + ',' +
> $c.text + ')=' + $d.text to combine e '(' 1 ',' 1 ')=' 100 .but is it too
> complicate?is there any way to get e(1,1)=100 as easy as possible?
>
> and in your replys ,firstly a big thank to ur replays.u mentioned that use
> the FailedPredicateException.but i'm afraid map.containsKey(e) returns only
> true or false, it wont throw any exception.how can i catch it??
>
> and the last question.i googled some pages that in an older version of
> antlr,wen can write rule like this to throws Exception:
> indexStat returns[String value] throws MyException   but in antlr 3,does
> the format change? when i write like that,i got an tip and "indexStat  is
> not a rule"...
> and if in an action,i write ... throw new MyException()..i have to modify
> the generated parser java file with the sentence like
> public String indexStat() throws RecoginitionException
> to
>  public String indexStat() throws RecoginitionException, MyException..
> to make the java code compileable.what is the right way to handle this?
>
> thanks to ur help again
>
> hardaway
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org/pipermail/antlr-interest/attachments/20080403/46d4d5f9/attachment.html 


More information about the antlr-interest mailing list