This is all code from the C# port of the tool, but the application of it
to the Java version should be reasonably straightforward. Bear in mind
that the C# port uses v3 grammars, so the grammar changes will need to
be applied relevant to the v2 grammars in use by the Java version of the
tool. Note that there is heavy use of HTML formatting in this message
for highlighting.

 


Part 1: Supporting throwsSpec in the AST. Here is the rewrite rule for
the 'rule' rule in ANTLR.g3. All comments were stripped from this except
for the one indicating the alteration.


 

->      ^(      RULE["rule"]

                ^($ruleName)

                $p1? $p2? $p3? $p4?

                ^(ARG["ARG"] $aa?)

                ^(RET["RET"] $rt?)

                throwsSpec? // <-- this line was added

                optionsSpec?

                ^($scopes)

                ruleActions?

                altList

                $ex?

                EOR[$SEMI,"<end-of-rule>"])

 

In addition, the throwsSpec rule was altered by adding the ^ and ! as
shown here:

 

throwsSpec

        :       'throws'^ id ( COMMA! id )*

        ;

 

The 'rule' rule in each of the tree parsers needs "(throwsSpec)?" added
before "(optionsSpec)?", with this declaration of throwsSpec:

 

throwsSpec

        :       ^('throws' ID+)

        ;

 

Note that other places where a 'rule' is matched, such as the
"test*AsSet" rules do not need to be changed.

 


Part 2: Implement throwsSpec in the codegen and update the Java target.


 


Step A: Add a member field after Rule.useScopes:


 

/** Exceptions that this rule can throw */

public HashSet<string> throwsSpec;

 

and initialize it in the constructor:

 

throwsSpec = new HashSet<string>() { "RecognitionException" };

 


Step B: After the listed code in DefineGrammarItemsWalker.g3 action in
the rule 'rule', add the exceptions to the rule:


 

// this code is already in the action:

if ( $ret!=null )

{

        r.returnScope = grammar.createReturnScope(name,$ret.token);

        r.returnScope.addAttributes($ret.text, ',');

}

// this code must be added to the action

if ( $throwsSpec.exceptions != null )

{

        foreach ( string exception in $throwsSpec.exceptions )

                r.throwsSpec.Add( exception );

}

 

Also update the throwsSpec rule in this grammar:

 

throwsSpec returns [HashSet<string> exceptions]

@init

{

        $exceptions = new HashSet<string>();

}

        :       ^('throws' (ID {$exceptions.Add($ID.text);})+ )

        ;

 


Part 3: Update the Java target in Java.stg. Replace all instances of
"throws RecognitionException", except the one that's part of the mTokens
template, with the following:


 

throws <ruleDescriptor.throwsSpec:{<it>}; separator=", ">

 


Part 4: Add a unit test at the end of TestJavaCodeGeneration:


 

[TestMethod]

public void TestUserExceptionInParser()

{

    string grammar =

        "grammar T;\n" +

        "@parser::header {import java.io.IOException;}" +

        "a throws IOException : 'x' {throw new IOException();};\n";

 

    bool found = rawGenerateAndBuildRecognizer( "T.g", grammar,
"TParser", "TLexer", false );

    bool expecting = true;

    Assert.AreEqual( expecting, found );

}

 

Sam

_______________________________________________
antlr-dev mailing list
[email protected]
http://www.antlr.org/mailman/listinfo/antlr-dev

Reply via email to