Home | History | Annotate | Download | only in Java
      1 /*
      2  [The "BSD license"]
      3  Copyright (c) 2005-2006 Terence Parr
      4  All rights reserved.
      5 
      6  Redistribution and use in source and binary forms, with or without
      7  modification, are permitted provided that the following conditions
      8  are met:
      9  1. Redistributions of source code must retain the above copyright
     10     notice, this list of conditions and the following disclaimer.
     11  2. Redistributions in binary form must reproduce the above copyright
     12     notice, this list of conditions and the following disclaimer in the
     13     documentation and/or other materials provided with the distribution.
     14  3. The name of the author may not be used to endorse or promote products
     15     derived from this software without specific prior written permission.
     16 
     17  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 */
     28 /** Template overrides to add debugging to normal Java output;
     29  *  If ASTs are built, then you'll also get ASTDbg.stg loaded.
     30  */
     31 @outputFile.imports() ::= <<
     32 <@super.imports()>
     33 import org.antlr.runtime.debug.*;
     34 import java.io.IOException;
     35 >>
     36 
     37 @genericParser.members() ::= <<
     38 <if(grammar.grammarIsRoot)>
     39 public static final String[] ruleNames = new String[] {
     40     "invalidRule", <grammar.allImportedRules:{rST | "<rST.name>"}; wrap="\n    ", separator=", ">
     41 };<\n>
     42 <endif>
     43 public static final boolean[] decisionCanBacktrack = new boolean[] {
     44     false, // invalid decision
     45     <grammar.decisions:{d | <d.dfa.hasSynPred; null="false">}; wrap="\n    ", separator=", ">
     46 };<\n>
     47 <if(grammar.grammarIsRoot)> <! grammar imports other grammar(s) !>
     48     public int ruleLevel = 0;
     49     public int getRuleLevel() { return ruleLevel; }
     50     public void incRuleLevel() { ruleLevel++; }
     51     public void decRuleLevel() { ruleLevel--; }
     52 <if(profile)>
     53     <ctorForProfilingRootGrammar()>
     54 <else>
     55     <ctorForRootGrammar()>
     56 <endif>
     57 <ctorForPredefinedListener()>
     58 <else> <! imported grammar !>
     59     public int getRuleLevel() { return <grammar.delegators:{g| <g:delegateName()>}>.getRuleLevel(); }
     60     public void incRuleLevel() { <grammar.delegators:{g| <g:delegateName()>}>.incRuleLevel(); }
     61     public void decRuleLevel() { <grammar.delegators:{g| <g:delegateName()>}>.decRuleLevel(); }
     62     <ctorForDelegateGrammar()>
     63 <endif>
     64 <if(profile)>
     65 public boolean alreadyParsedRule(IntStream input, int ruleIndex) {
     66 	int stopIndex = getRuleMemoization(ruleIndex, input.index());
     67     ((Profiler)dbg).examineRuleMemoization(input, ruleIndex, stopIndex, <grammar.composite.rootGrammar.recognizerName>.ruleNames[ruleIndex]);
     68     return super.alreadyParsedRule(input, ruleIndex);
     69 }<\n>
     70 public void memoize(IntStream input,
     71                     int ruleIndex,
     72                     int ruleStartIndex)
     73 {
     74     ((Profiler)dbg).memoize(input, ruleIndex, ruleStartIndex, <grammar.composite.rootGrammar.recognizerName>.ruleNames[ruleIndex]);
     75     super.memoize(input, ruleIndex, ruleStartIndex);
     76 }<\n>
     77 <endif>
     78 protected boolean evalPredicate(boolean result, String predicate) {
     79     dbg.semanticPredicate(result, predicate);
     80     return result;
     81 }<\n>
     82 >>
     83 
     84 ctorForRootGrammar() ::= <<
     85 <! bug: can't use <@super.members()> cut-n-paste instead !>
     86 <! Same except we add port number and profile stuff if root grammar !>
     87 public <name>(<inputStreamType> input) {
     88     this(input, DebugEventSocketProxy.DEFAULT_DEBUGGER_PORT, new RecognizerSharedState());
     89 }
     90 public <name>(<inputStreamType> input, int port, RecognizerSharedState state) {
     91     super(input, state);
     92     <parserCtorBody()>
     93     <createListenerAndHandshake()>
     94     <grammar.directDelegates:{g|<g:delegateName()> = new <g.recognizerName>(input, dbg, this.state, this<grammar.delegators:{g|, <g:delegateName()>}>);}; separator="\n">
     95     <@finally()>
     96 }<\n>
     97 >>
     98 
     99 ctorForProfilingRootGrammar() ::= <<
    100 <! bug: can't use <@super.members()> cut-n-paste instead !>
    101 public <name>(<inputStreamType> input) {
    102     this(input, new Profiler(null), new RecognizerSharedState());
    103 }
    104 public <name>(<inputStreamType> input, DebugEventListener dbg, RecognizerSharedState state) {
    105     super(input, dbg, state);
    106     Profiler p = (Profiler)dbg;
    107     p.setParser(this);
    108     <parserCtorBody()>
    109     <grammar.directDelegates:
    110      {g|<g:delegateName()> = new <g.recognizerName>(input, dbg, this.state, this<grammar.delegators:{g|, <g:delegateName()>}>);}; separator="\n">
    111     <@finally()>
    112 }
    113 <\n>
    114 >>
    115 
    116 /** Basically we don't want to set any dbg listeners are root will have it. */
    117 ctorForDelegateGrammar() ::= <<
    118 public <name>(<inputStreamType> input, DebugEventListener dbg, RecognizerSharedState state<grammar.delegators:{g|, <g.recognizerName> <g:delegateName()>}>) {
    119     super(input, dbg, state);
    120     <parserCtorBody()>
    121     <grammar.directDelegates:
    122      {g|<g:delegateName()> = new <g.recognizerName>(input, this, this.state<grammar.delegators:{g|, <g:delegateName()>}>);}; separator="\n">
    123 }<\n>
    124 >>
    125 
    126 ctorForPredefinedListener() ::= <<
    127 public <name>(<inputStreamType> input, DebugEventListener dbg) {
    128     <@superClassRef>super(input, dbg, new RecognizerSharedState());<@end>
    129 <if(profile)>
    130     Profiler p = (Profiler)dbg;
    131     p.setParser(this);
    132 <endif>
    133     <parserCtorBody()>
    134     <grammar.directDelegates:{g|<g:delegateName()> = new <g.recognizerName>(input, dbg, this.state, this<grammar.delegators:{g|, <g:delegateName()>}>);}; separator="\n">
    135     <@finally()>
    136 }<\n>
    137 >>
    138 
    139 createListenerAndHandshake() ::= <<
    140 <if(TREE_PARSER)>
    141 DebugEventSocketProxy proxy =
    142     new DebugEventSocketProxy(this, port, input.getTreeAdaptor());<\n>
    143 <else>
    144 DebugEventSocketProxy proxy =
    145     new DebugEventSocketProxy(this, port, null);<\n>
    146 <endif>
    147 setDebugListener(proxy);
    148 try {
    149     proxy.handshake();
    150 }
    151 catch (IOException ioe) {
    152     reportError(ioe);
    153 }
    154 >>
    155 
    156 @genericParser.superClassName() ::= "Debug<@super.superClassName()>"
    157 
    158 @rule.preamble() ::= <<
    159 try { dbg.enterRule(getGrammarFileName(), "<ruleName>");
    160 if ( getRuleLevel()==0 ) {dbg.commence();}
    161 incRuleLevel();
    162 dbg.location(<ruleDescriptor.tree.line>, <ruleDescriptor.tree.charPositionInLine>);<\n>
    163 >>
    164 
    165 @rule.postamble() ::= <<
    166 dbg.location(<ruleDescriptor.EORNode.line>, <ruleDescriptor.EORNode.charPositionInLine>);<\n>
    167 }
    168 finally {
    169     dbg.exitRule(getGrammarFileName(), "<ruleName>");
    170     decRuleLevel();
    171     if ( getRuleLevel()==0 ) {dbg.terminate();}
    172 }<\n>
    173 >>
    174 
    175 @synpred.start() ::= "dbg.beginBacktrack(state.backtracking);"
    176 
    177 @synpred.stop() ::= "dbg.endBacktrack(state.backtracking, success);"
    178 
    179 // Common debug event triggers used by region overrides below
    180 
    181 enterSubRule() ::=
    182     "try { dbg.enterSubRule(<decisionNumber>);<\n>"
    183 
    184 exitSubRule() ::=
    185     "} finally {dbg.exitSubRule(<decisionNumber>);}<\n>"
    186 
    187 enterDecision() ::=
    188     "try { dbg.enterDecision(<decisionNumber>, decisionCanBacktrack[<decisionNumber>]);<\n>"
    189 
    190 exitDecision() ::=
    191     "} finally {dbg.exitDecision(<decisionNumber>);}<\n>"
    192 
    193 enterAlt(n) ::= "dbg.enterAlt(<n>);<\n>"
    194 
    195 // Region overrides that tell various constructs to add debugging triggers
    196 
    197 @block.predecision() ::= "<enterSubRule()><enterDecision()>"
    198 
    199 @block.postdecision() ::= "<exitDecision()>"
    200 
    201 @block.postbranch() ::= "<exitSubRule()>"
    202 
    203 @ruleBlock.predecision() ::= "<enterDecision()>"
    204 
    205 @ruleBlock.postdecision() ::= "<exitDecision()>"
    206 
    207 @ruleBlockSingleAlt.prealt() ::= "<enterAlt(n=\"1\")>"
    208 
    209 @blockSingleAlt.prealt() ::= "<enterAlt(n=\"1\")>"
    210 
    211 @positiveClosureBlock.preloop() ::= "<enterSubRule()>"
    212 
    213 @positiveClosureBlock.postloop() ::= "<exitSubRule()>"
    214 
    215 @positiveClosureBlock.predecision() ::= "<enterDecision()>"
    216 
    217 @positiveClosureBlock.postdecision() ::= "<exitDecision()>"
    218 
    219 @positiveClosureBlock.earlyExitException() ::=
    220     "dbg.recognitionException(eee);<\n>"
    221 
    222 @closureBlock.preloop() ::= "<enterSubRule()>"
    223 
    224 @closureBlock.postloop() ::= "<exitSubRule()>"
    225 
    226 @closureBlock.predecision() ::= "<enterDecision()>"
    227 
    228 @closureBlock.postdecision() ::= "<exitDecision()>"
    229 
    230 @altSwitchCase.prealt() ::= "<enterAlt(altNum)>" // altNum is arg of altSwitchCase
    231 
    232 @element.prematch() ::=
    233     "dbg.location(<e.line>,<e.pos>);" // e is arg of element
    234 
    235 @matchSet.mismatchedSetException() ::=
    236     "dbg.recognitionException(mse);"
    237 
    238 @dfaState.noViableAltException() ::= "dbg.recognitionException(nvae);"
    239 
    240 @dfaStateSwitch.noViableAltException() ::= "dbg.recognitionException(nvae);"
    241 
    242 dfaDecision(decisionNumber,description) ::= <<
    243 try {
    244     isCyclicDecision = true;
    245     <super.dfaDecision(...)>
    246 }
    247 catch (NoViableAltException nvae) {
    248     dbg.recognitionException(nvae);
    249     throw nvae;
    250 }
    251 >>
    252 
    253 @cyclicDFA.errorMethod() ::= <<
    254 public void error(NoViableAltException nvae) {
    255     dbg.recognitionException(nvae);
    256 }
    257 >>
    258 
    259 /** Force predicate validation to trigger an event */
    260 evalPredicate(pred,description) ::= <<
    261 evalPredicate(<pred>,"<description>")
    262 >>
    263