Home | History | Annotate | Download | only in ObjC
      1 /*
      2  [The "BSD license"]
      3  Copyright (c) 2006 Kay Roepke 2010 Alan Condit
      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 Objective-C output;
     29  *  If ASTs are built, then you'll also get ASTDbg.stg loaded.
     30  */
     31 @headerFile.imports() ::= <<
     32 <@super.imports()>
     33 #import \<ANTLR/ANTLRDebug.h>
     34 >>
     35 
     36 @parserHeaderFile.memVars() ::= <<
     37 NSInteger ruleLevel;
     38 NSArray *ruleNames;
     39 >>
     40 
     41 @parserHeaderFile.methodsDecl() ::= <<
     42 -(BOOL) evalPredicate:(NSString *)predicate matched:(BOOL)result;<\n>
     43 >>
     44 
     45 @genericParser.methods() ::= <<
     46 <if(grammar.grammarIsRoot)>
     47 AMutableArray *ruleNames = [AMutableArray arrayWithArray:{
     48     @"invalidRule", <grammar.allImportedRules:{rST | @"<rST.name>"}; wrap=@"\n    ", separator=", ">
     49 };<\n>
     50 <endif>
     51 <if(grammar.grammarIsRoot)> <! grammar imports other grammar(s) !>
     52     ruleLevel = 0;
     53 - (NSInteger) getRuleLevel { return ruleLevel; }
     54 - (void) incRuleLevel { ruleLevel++; }
     55 - (void) decRuleLevel { ruleLevel--; }
     56 <if(profile)>
     57     <ctorForProfilingRootGrammar()>
     58 <else>
     59     <ctorForRootGrammar()>
     60 <endif>
     61 <ctorForPredefinedListener()>
     62 <else> <! imported grammar !>
     63 - (NSInteger) getRuleLevel
     64 {
     65     return <grammar.delegators:{g| <g:delegateName()>}>.getRuleLevel();
     66 }<\n>
     67 
     68 - (void) incRuleLevel
     69 {
     70     <grammar.delegators:{g| <g:delegateName()>}>.incRuleLevel();
     71 }<\n>
     72 - (void) decRuleLevel
     73 {
     74     <grammar.delegators:{g| <g:delegateName()>}>.decRuleLevel();
     75 }<\n>
     76     <ctorForDelegateGrammar()>
     77 <endif>
     78 <if(profile)>
     79 - (BOOL) alreadyParsedRule:(id<IntStream>) input Index:(NSInteger) ruleIndex
     80 {
     81     [(Profiler)dbg examineRuleMemoization:input, ruleIndex, <grammar.composite.rootGrammar.recognizerName>.ruleNames objectAtIndex:ruleIndex];
     82     return super.alreadyParsedRule(input, ruleIndex);
     83 }<\n>
     84 - (void) memoize:(id<ANTLRIntStream>)input RuleIndex:(NSInteger)ruleIndex StartIndex:(NSInteger)ruleStartIndex
     85 {
     86     [((Profiler)dbg) memoize:input RuleIndex:ruleIndex StartIndex:ruleStartIndex [<grammar.composite.rootGrammar.recognizerName> ruleNames[ruleIndex]];
     87     [super memoize:input RuleIndex:ruleIndex StartIndex:ruleStartIndex];
     88 }<\n>
     89 <endif>
     90 - (BOOL) evalPredicate:(BOOL)result Pred:(NSString *)predicate
     91 {
     92     [dbg semanticPredicate:result Pred:predicate];
     93     return result;
     94 }<\n>
     95 >>
     96 
     97 @genericParser.init() ::= <<
     98 ruleNames = [NSArray arrayWithObjects:<rules:{rST | @"<rST.ruleName>"}; separator=", ", wrap="\n	">, nil];<\n>
     99 >>
    100 
    101 @genericParser.dealloc() ::= <<
    102 [ruleNames release];<\n>
    103 >>
    104 
    105 @genericParser.methods() ::= <<
    106 -(BOOL) evalPredicate:(NSString *)predicate matched:(BOOL)result
    107 {
    108 	[debugListener semanticPredicate:predicate matched:result];
    109 	return result;
    110 }<\n>
    111 >>
    112 
    113 /* bug: can't use @super.superClassName()> */
    114 @parserHeaderFile.superClassName() ::= "ANTLRDebug<if(TREE_PARSER)>Tree<endif>Parser"
    115 
    116 @rule.preamble() ::= <<
    117 @try { [debugListener enterRule:@"<ruleName>"];
    118 if ( ruleLevel==0 ) [debugListener commence];
    119 ruleLevel++;
    120 [debugListener locationLine:<ruleDescriptor.tree.line> column:<ruleDescriptor.tree.column>];<\n>
    121 >>
    122 
    123 @rule.postamble() ::= <<
    124 [debugListener locationLine:<ruleDescriptor.EORNode.line> column:<ruleDescriptor.EORNode.column>];<\n>
    125 }
    126 @finally {
    127     [debugListener exitRule:@"<ruleName>"];
    128     ruleLevel--;
    129     if ( ruleLevel==0 ) [debugListener terminate];
    130 }<\n>
    131 >>
    132 
    133 /* these are handled in the runtime for now.
    134  * stinks, but that's the easiest way to avoid having to generate two
    135  * methods for each synpred
    136 
    137 @synpred.start() ::= "[debugListener beginBacktrack:state.backtracking];"
    138 
    139 @synpred.stop() ::= "[debugListener endBacktrack:state.backtracking wasSuccessful:success];"
    140 
    141  */
    142 
    143 // Common debug event triggers used by region overrides below
    144 
    145 enterSubRule() ::=
    146     "@try { [debugListener enterSubRule:<decisionNumber>];<\n>"
    147 
    148 exitSubRule() ::=
    149     "} @finally { [debugListener exitSubRule:<decisionNumber>]; }<\n>"
    150 
    151 enterDecision() ::=
    152     "@try { [debugListener enterDecision:<decisionNumber>];<\n>"
    153 
    154 exitDecision() ::=
    155     "} @finally { [debugListener exitDecision:<decisionNumber>]; }<\n>"
    156 
    157 enterAlt(n) ::= "[debugListener enterAlt:<n>];<\n>"
    158 
    159 // Region overrides that tell various constructs to add debugging triggers
    160 
    161 @block.predecision() ::= "<enterSubRule()><enterDecision()>"
    162 
    163 @block.postdecision() ::= "<exitDecision()>"
    164 
    165 @block.postbranch() ::= "<exitSubRule()>"
    166 
    167 @ruleBlock.predecision() ::= "<enterDecision()>"
    168 
    169 @ruleBlock.postdecision() ::= "<exitDecision()>"
    170 
    171 @ruleBlockSingleAlt.prealt() ::= "<enterAlt(n=\"1\")>"
    172 
    173 @blockSingleAlt.prealt() ::= "<enterAlt(n=\"1\")>"
    174 
    175 @positiveClosureBlock.preloop() ::= "<enterSubRule()>"
    176 
    177 @positiveClosureBlock.postloop() ::= "<exitSubRule()>"
    178 
    179 @positiveClosureBlock.predecision() ::= "<enterDecision()>"
    180 
    181 @positiveClosureBlock.postdecision() ::= "<exitDecision()>"
    182 
    183 @positiveClosureBlock.earlyExitException() ::=
    184     "[debugListener recognitionException:eee];<\n>"
    185 
    186 @closureBlock.preloop() ::= "<enterSubRule()>"
    187 
    188 @closureBlock.postloop() ::= "<exitSubRule()>"
    189 
    190 @closureBlock.predecision() ::= "<enterDecision()>"
    191 
    192 @closureBlock.postdecision() ::= "<exitDecision()>"
    193 
    194 @altSwitchCase.prealt() ::= "<enterAlt(n=i)>"
    195 
    196 @element.prematch() ::=
    197     "[debugListener locationLine:<it.line> column:<it.pos>];"
    198 
    199 @matchSet.mismatchedSetException() ::=
    200     "[debugListener recognitionException:mse];"
    201 
    202 @dfaState.noViableAltException() ::= "[debugListener recognitionException:nvae];"
    203 
    204 @dfaStateSwitch.noViableAltException() ::= "[debugListener recognitionException:nvae];"
    205 
    206 dfaDecision(decisionNumber,description) ::= <<
    207 @try {
    208     // isCyclicDecision is only necessary for the Profiler. Which I didn't do, yet.
    209     // isCyclicDecision = YES;
    210     <super.dfaDecision(...)>
    211 }
    212 @catch (ANTLRNoViableAltException *nvae) {
    213     [debugListener recognitionException:nvae];
    214     @throw nvae;
    215 }
    216 >>
    217 
    218 @cyclicDFA.errorMethod() ::= <<
    219 -(void) error:(ANTLRNoViableAltException *)nvae
    220 {
    221     [[recognizer debugListener] recognitionException:nvae];
    222 }
    223 >>
    224 
    225 /** Force predicate validation to trigger an event */
    226 evalPredicate(pred,description) ::= <<
    227 [self evalPredicate:@"<description>" result:<pred>];
    228 >>
    229