applayerprotocols/wapbase/bnf/CBNFParser.cpp
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <cbnfparser.h>
       
    17 
       
    18 #include <cnodeleteattribute.h>
       
    19 #include <attrlut.h>
       
    20 #include <estatus.h>
       
    21 #include <e32base.h>
       
    22 
       
    23 #include "BNFPanicCodes.h"
       
    24 
       
    25 
       
    26 /** Allocates and constructs a new BNF parser.
       
    27 
       
    28 @return New parser
       
    29 @param aLUT Attribute lookup table in which to store attributes for 
       
    30 the rule tree
       
    31 */
       
    32 EXPORT_C CBNFParser* CBNFParser::NewL(CAttributeLookupTable& aLUT)
       
    33 	{
       
    34 	CBNFParser* model = new (ELeave) CBNFParser(aLUT);
       
    35 	return (model);
       
    36 	}
       
    37 
       
    38 /** Constructor.
       
    39 
       
    40 @param aLUT Attribute lookup table
       
    41 */
       
    42 EXPORT_C CBNFParser::CBNFParser(CAttributeLookupTable& aLUT)
       
    43     : iLUT(aLUT)
       
    44 	{
       
    45 // store pointers to these to avoid continual unnecessary calls to the CBNFNode DLL
       
    46 	iReferenceString=CBNFNode::KReference();
       
    47 	iRangeStart=CBNFNode::KRangeStart();
       
    48 	iRangeEnd=CBNFNode::KRangeEnd();
       
    49 	iMoreMinimum=CBNFNode::KNMoreMinimum();
       
    50 	iMoreCount=CBNFNode::KNMoreCount();
       
    51 	iMoreMaximum=CBNFNode::KNMoreMaximum();
       
    52 	iPreRuleCallback=CBNFNode::KPreRuleCallback();
       
    53 	iPostRuleCallback=CBNFNode::KPostRuleCallback();
       
    54 	}
       
    55 
       
    56 /** Destructor.
       
    57 */
       
    58 EXPORT_C CBNFParser::~CBNFParser()
       
    59 	{
       
    60 	delete iTree;
       
    61 	}
       
    62 
       
    63 /**  Reset the parser to a state where it can accept and parse new input.
       
    64 
       
    65 If no BNF tree yet exists the virtual method TreeL() is called to obtain the BNF tree for this parser.
       
    66 Any existing state of parsing and input data is destroyed. */
       
    67 EXPORT_C void CBNFParser::ResetL()
       
    68 	{
       
    69 	if (iTree == NULL)
       
    70 		iTree = TreeL();
       
    71 
       
    72 	iRuleStack.Clear();
       
    73 	iRuleStack.PushL(iTree);
       
    74 
       
    75 	iSubRuleMatched = EFalse;
       
    76 	iSubRule = NULL;
       
    77 	iStringComplete = EFalse;
       
    78 	iString.Reset();
       
    79 	}
       
    80 
       
    81 /** Gets the attribute look-up table used by this parser.
       
    82 
       
    83 @return Attribute look-up table
       
    84 */
       
    85 EXPORT_C CAttributeLookupTable& CBNFParser::AttributeLUT() const
       
    86     {
       
    87 	return iLUT;
       
    88 	}
       
    89 
       
    90 /** Processes a reference rule node.
       
    91 
       
    92 It is called by PerformRuleL().
       
    93 
       
    94 @return ETrue if the function completed processing this node, otherwise EFalse
       
    95 @param aRule The rule node being processed
       
    96 @param aMatched On return, flag indicating if input stream matched the rule
       
    97 */
       
    98 EXPORT_C TBool CBNFParser::ReferenceL(CBNFNode& aRule, CFragmentedString::TStringMatch& /*aMatched*/)
       
    99 // Handle a reference node.
       
   100 // The pointer to the refered rule is stored as an attribute to a node which
       
   101 // is stored as an attribute to the reference node. Nice and simple, isn't it? :-)
       
   102     {
       
   103     // new to this Reference, or returning from a sub match?
       
   104     if (iSubRule)
       
   105 		// No operation is required when returning from the refered rule - continue up.
       
   106         return ETrue;
       
   107     else
       
   108         {
       
   109         CNoDeleteAttributeT<CBNFNode*>* attributeNode = REINTERPRET_CAST(CNoDeleteAttributeT<CBNFNode*>*, aRule.Attribute(iReferenceString));
       
   110 //        iRuleStack.Pop(); //Optimisation not possible as other bnf parts use this 'rule' node to find the next sibling (i.e. And, Or etc)
       
   111         iRuleStack.PushL(attributeNode->Attribute());
       
   112         }
       
   113     return EFalse;
       
   114     }
       
   115 
       
   116 /** Processes an EExact rule node.
       
   117 
       
   118 It is called by PerformRuleL().
       
   119 
       
   120 @return ETrue if the function completed processing this node, otherwise EFalse
       
   121 @param aRule The rule node being processed
       
   122 @param aMatched On return, flag indicating if input stream matched the rule
       
   123 */
       
   124 EXPORT_C TBool CBNFParser::ExactL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched)
       
   125 // Handle an EExact rule
       
   126 // Attempts to match a string with the stream.
       
   127     {
       
   128     if ((aMatched=iString.Match(REINTERPRET_CAST(HBufC*, aRule.Data())->Des()))==CFragmentedString::EMatch)
       
   129         iString.ConsumeMatched();
       
   130     return ETrue;
       
   131     }
       
   132 
       
   133 /** Processes an ERange rule node.
       
   134 
       
   135 It is called by PerformRuleL().
       
   136 
       
   137 @return ETrue if the function completed processing this node, otherwise EFalse
       
   138 @param aRule The rule node being processed
       
   139 @param aMatched On return, flag indicating if input stream matched the rule
       
   140 */
       
   141 EXPORT_C TBool CBNFParser::RangeL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched)
       
   142 // Handle ERange rule
       
   143 // Checks if the next character in the stream fits into the chracter range defined by the rule
       
   144     {
       
   145     CNoDeleteAttributeT<TInt>* rangeStartAttribute = REINTERPRET_CAST(CNoDeleteAttributeT<TInt>*, aRule.Attribute(iRangeStart));
       
   146     TInt rangeStart;
       
   147     if (rangeStartAttribute)
       
   148         rangeStart = rangeStartAttribute->Attribute();
       
   149     else
       
   150         rangeStart = 0;
       
   151     
       
   152     CNoDeleteAttributeT<TInt>* rangeEndAttribute = REINTERPRET_CAST(CNoDeleteAttributeT<TInt>*, aRule.Attribute(iRangeEnd));
       
   153     TInt rangeEnd;
       
   154     if (rangeEndAttribute)
       
   155         rangeEnd = rangeEndAttribute->Attribute();
       
   156     else
       
   157         rangeEnd = 0;
       
   158     
       
   159     if ((aMatched = iString.MatchRange(rangeStart, rangeEnd)) == CFragmentedString::EMatch)
       
   160         iString.ConsumeMatched();
       
   161     return ETrue;
       
   162     }
       
   163 
       
   164 
       
   165 /** Processes an ESelect rule node.
       
   166 
       
   167 It is called by PerformRuleL().
       
   168 
       
   169 @return ETrue if the function completed processing this node, otherwise EFalse
       
   170 @param aRule The rule node being processed
       
   171 @param aMatched On return, flag indicating if input stream matched the rule
       
   172 */
       
   173 EXPORT_C TBool CBNFParser::SelectL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched)
       
   174 // Handle Select rule
       
   175 // Check if the next character in the stream matches to any of the chracters included
       
   176 // into the set defined by the select rule.
       
   177 // The selection can also be performed as inverted selection (by using "^" as the first char)
       
   178 // in which case all the other characters but the ones defined in the set match correctly to the stream.
       
   179     {
       
   180     if ((*aRule.Data())[0] == '^')
       
   181         aMatched = iString.MatchNotSelect((*REINTERPRET_CAST(HBufC*, aRule.Data())).Mid(1));
       
   182     else
       
   183         aMatched = iString.MatchSelect(*REINTERPRET_CAST(HBufC*, aRule.Data()));
       
   184 
       
   185 //!	if (aMatched == CFragmentedString::EMatch)
       
   186     iString.ConsumeMatched();
       
   187     return ETrue;
       
   188     }
       
   189 
       
   190 /** Processes an EWithout rule node.
       
   191 
       
   192 It is called by PerformRuleL().
       
   193 
       
   194 @return ETrue if the function completed processing this node, otherwise EFalse
       
   195 @param aRule The rule node being processed
       
   196 @param aMatched On return, flag indicating if input stream matched the rule
       
   197 */
       
   198 EXPORT_C TBool CBNFParser::WithoutL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched)
       
   199 // Handle EWithout rule
       
   200 // An example Without rule: [A-Z] - B
       
   201 // Here we are trying to match all characters from A-Z except character B.
       
   202 // The rule is performed here by first executing the latter part of the rule (in the example
       
   203 // by trying to match B). If the latter rule matches, then the stream contains the chracter
       
   204 // string we didn't want it to include and hence the Without rule is false. However, if the
       
   205 // latter rule doesn't match we proceed to matching the first part of the rule and if it
       
   206 // does match the whole Without rule is true.
       
   207 // The Without rule node has two children of which the first one (child on index 0)
       
   208 // is the rule we are trying to match and the second child is the "except" part of the rule.
       
   209     {
       
   210     TBool performedMatch = EFalse;
       
   211     // new to this Without, or returning from a sub match?
       
   212     CBNFNode* newRule = NULL;
       
   213     if (iSubRule)
       
   214         {
       
   215         if (iSubRule == aRule.Child(1))
       
   216             {
       
   217             iString.ResetToMark();
       
   218             iString.DeleteMark();
       
   219             if (!iSubRuleMatched)
       
   220                 newRule = REINTERPRET_CAST(CBNFNode*, aRule.Child(0));
       
   221             else
       
   222                 aMatched = CFragmentedString::ENoMatch;
       
   223             }
       
   224         }
       
   225     else
       
   226         {
       
   227         iString.Mark(); // Mark can leave
       
   228         StartConditional((enum TParserNodeTypes)aRule.Type());
       
   229         newRule = REINTERPRET_CAST(CBNFNode*, aRule.Child(1));
       
   230         }
       
   231     if (newRule)
       
   232         {
       
   233         iRuleStack.PushL(newRule);
       
   234         iSubRule = NULL; // going down
       
   235         }
       
   236     else
       
   237         {
       
   238         EndConditional((enum TParserNodeTypes)aRule.Type(), iSubRuleMatched);
       
   239         performedMatch = ETrue;
       
   240         }
       
   241     return performedMatch;
       
   242     }
       
   243 
       
   244 /** Processes an EAnd rule node.
       
   245 
       
   246 It is called by PerformRuleL().
       
   247 
       
   248 @return ETrue if the function completed processing this node, otherwise EFalse
       
   249 @param aRule The rule node being processed
       
   250 @param aMatched On return, flag indicating if input stream matched the rule
       
   251 */
       
   252 EXPORT_C TBool CBNFParser::AndL(CBNFNode& aRule, CFragmentedString::TStringMatch& /*aMatched*/)
       
   253 // Handle And rule
       
   254 // An EAnd rule is true if all of its children are true. Processing the child nodes of
       
   255 // the And rule continues until all the children has been processed of one of them doesn't
       
   256 // match. Notice, that the order of the child rules has signifigance, since we are
       
   257 // matching a chracter stream and the first child is matched first, followed by the second etc.
       
   258     {
       
   259     TBool performedMatch = EFalse;
       
   260     // new to this And, or returning from a sub match?
       
   261     CBNFNode* newRule = NULL;
       
   262     if (iSubRule)
       
   263         {
       
   264         if (iSubRuleMatched)
       
   265             {
       
   266             newRule = REINTERPRET_CAST(CBNFNode*, iSubRule->NextSibling());
       
   267             if (!newRule)
       
   268                 performedMatch = ETrue;
       
   269             }
       
   270         else
       
   271             performedMatch = ETrue;
       
   272         }
       
   273     else
       
   274         {
       
   275         newRule = REINTERPRET_CAST(CBNFNode*, aRule.Child(0));
       
   276         StartConditional((enum TParserNodeTypes)aRule.Type());
       
   277         }
       
   278     if (newRule)
       
   279         {
       
   280         iRuleStack.PushL(newRule);
       
   281         iSubRule = NULL; // going down
       
   282         }
       
   283     else
       
   284 		{
       
   285         EndConditional((enum TParserNodeTypes)aRule.Type(), iSubRuleMatched);
       
   286 //!		performedMatch = ETrue;
       
   287 		}
       
   288     return performedMatch;
       
   289     }
       
   290 
       
   291 
       
   292 /** Processes an EOr rule node.
       
   293 
       
   294 It is called by PerformRuleL().
       
   295 
       
   296 @return ETrue if the function completed processing this node, otherwise EFalse
       
   297 @param aRule The rule node being processed
       
   298 @param aMatched On return, flag indicating if input stream matched the rule
       
   299 */
       
   300 EXPORT_C TBool CBNFParser::OrL(CBNFNode& aRule, CFragmentedString::TStringMatch& /*aMatched*/)
       
   301 // Handle Or rule
       
   302 // We attempt to match the child rules of the Or node and stop when we have the first match.
       
   303 // With the Or type rule each of the child rules are matched agaist the same bit of input
       
   304 // stream. Before we start processing the first child rule we set a mark to the input stream
       
   305 // and if a child rule doesn't match, we rollback the input stream to the mark and try
       
   306 // to match the next child.
       
   307     {
       
   308     TBool performedMatch = EFalse;
       
   309     CBNFNode* newRule = NULL;
       
   310     // new to this Or, or returning from a sub match?
       
   311     if (iSubRule)
       
   312         {
       
   313         if (!iSubRuleMatched)
       
   314             {
       
   315             newRule = REINTERPRET_CAST(CBNFNode*, iSubRule->NextSibling());
       
   316             }
       
   317         EndConditional((enum TParserNodeTypes)aRule.Type(), iSubRuleMatched);
       
   318         }
       
   319     else
       
   320         {
       
   321         newRule = REINTERPRET_CAST(CBNFNode*, aRule.Child(0));
       
   322         iString.Mark(); // Mark can leave
       
   323         }
       
   324     if (newRule)
       
   325         {
       
   326         iRuleStack.PushL(newRule);
       
   327         iSubRule = NULL; // going down
       
   328         iString.ResetToMark();
       
   329         StartConditional((enum TParserNodeTypes)aRule.Type());
       
   330         }
       
   331     else
       
   332         {
       
   333         performedMatch = ETrue;
       
   334         if (!iSubRuleMatched)
       
   335             iString.ResetToMark();
       
   336         iString.DeleteMark();
       
   337         }
       
   338     return performedMatch;
       
   339     }
       
   340 
       
   341 EXPORT_C TBool CBNFParser::OptionalL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched)
       
   342 // Handle Optional rule
       
   343 // Process the subrule attached to the optional rule.
       
   344 // An optional rule is always successfully processed regardless to success or failure of matching
       
   345 // the subrule. This is because of the nature of the optional rule - the subrule here either may
       
   346 // or may not be there.
       
   347     {
       
   348     TBool performedMatch = EFalse;
       
   349     // new to this Optional, or returning from a sub match?
       
   350     if (iSubRule)
       
   351         {
       
   352         performedMatch = ETrue;
       
   353         aMatched = CFragmentedString::EMatch;
       
   354         iOptionalMatched = iSubRuleMatched;
       
   355         if (!iSubRuleMatched)
       
   356             iString.ResetToMark();
       
   357         iString.DeleteMark();
       
   358         }
       
   359     else
       
   360         {
       
   361         iString.Mark(); // Mark can leave
       
   362         iRuleStack.PushL(REINTERPRET_CAST(CBNFNode*, aRule.Child(0)));
       
   363         iSubRule = NULL;
       
   364         }
       
   365     return performedMatch;
       
   366     }    
       
   367 
       
   368 
       
   369 
       
   370 /** Processes an ENMore rule node.
       
   371 
       
   372 It is called by PerformRuleL().
       
   373 
       
   374 @return ETrue if the function completed processing this node, otherwise EFalse
       
   375 @param aRule The rule node being processed
       
   376 @param aMatched On return, flag indicating if input stream matched the rule
       
   377 */
       
   378 EXPORT_C TBool CBNFParser::NMoreL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched)
       
   379 // Handle NMore rule
       
   380 // NMore rule implements the "multiplier" elements of BNF (* and +).
       
   381 // We attempt to match the subrule and if it matches we try again until it doesn't match
       
   382 // or we run into the upperlimit set to this rule.
       
   383 // An NMore rule may contain lower and upper limits for the number of times the matching
       
   384 // can or needs to be done. These are included as attributes to the NMore node. The NMore
       
   385 // node also holds a counter attribute, which holds the amount of times this rule has been
       
   386 // matched.
       
   387     {
       
   388     TBool performedMatch = EFalse;
       
   389     // new to this NMore, or returning from a sub match?
       
   390     if (iSubRule)
       
   391         {
       
   392         CNoDeleteAttributeT<TInt>* countAttribute = REINTERPRET_CAST(CNoDeleteAttributeT<TInt>*, aRule.Attribute(iMoreCount));
       
   393         CNoDeleteAttributeT<TInt>* maxCountAttribute = REINTERPRET_CAST(CNoDeleteAttributeT<TInt>*, aRule.Attribute(iMoreMaximum));
       
   394         
       
   395         if (iSubRuleMatched)
       
   396             countAttribute->SetAttribute(countAttribute->Attribute()+1);
       
   397         else
       
   398             {
       
   399             performedMatch = ETrue;
       
   400             CNoDeleteAttributeT<TInt>* minCountAttribute = REINTERPRET_CAST(CNoDeleteAttributeT<TInt>*, aRule.Attribute(iMoreMinimum));
       
   401             if ((minCountAttribute == NULL) || (countAttribute->Attribute() >= minCountAttribute->Attribute()))
       
   402                 aMatched = CFragmentedString::EMatch;
       
   403             iString.ResetToMark();
       
   404             }
       
   405         
       
   406         if ((maxCountAttribute) && (countAttribute->Attribute() >= maxCountAttribute->Attribute()))
       
   407             performedMatch = ETrue;
       
   408         
       
   409         iString.DeleteMark();
       
   410         }
       
   411     else
       
   412         {
       
   413         aRule.DeleteAttribute(iMoreCount);
       
   414         CNoDeleteAttributeT<TInt>* countAttribute = new (ELeave) CNoDeleteAttributeT<TInt>(0);
       
   415         CleanupStack::PushL(countAttribute);
       
   416         aRule.AddAttributeL(iMoreCount, countAttribute);
       
   417         CleanupStack::Pop();
       
   418         }
       
   419     if (!performedMatch)
       
   420         {
       
   421         iRuleStack.PushL(REINTERPRET_CAST(CBNFNode*, aRule.Child(0)));
       
   422         iSubRule = NULL;
       
   423         iString.Mark(); // Mark can leave
       
   424         }
       
   425     return performedMatch;
       
   426     }
       
   427 
       
   428 /** Executes a pre-rule callback function.
       
   429 
       
   430 @param aRule Node specifying the callback
       
   431 */
       
   432 EXPORT_C
       
   433 void
       
   434 CBNFParser::ExecutePreRuleCallbackL(CBNFNode& aRule)
       
   435     {
       
   436     CNoDeleteAttributeT<TRuleCallback*>* preRuleAttribute;
       
   437     if ((preRuleAttribute= REINTERPRET_CAST(CNoDeleteAttributeT<TRuleCallback*>*, aRule.Attribute(iPreRuleCallback)))!=NULL)
       
   438         (*preRuleAttribute->Attribute())(*this);
       
   439     }
       
   440 
       
   441 /** Executes a post-rule callback function.
       
   442 
       
   443 @param aRule Node specifying the callback
       
   444 */
       
   445 EXPORT_C
       
   446 void
       
   447 CBNFParser::ExecutePostRuleCallbackL(CBNFNode& aRule)
       
   448     {
       
   449     CNoDeleteAttributeT<TRuleCallback*>* postRuleAttribute;
       
   450     if ((postRuleAttribute = REINTERPRET_CAST(CNoDeleteAttributeT<TRuleCallback*>*, aRule.Attribute(iPostRuleCallback)))!=NULL)
       
   451         (*postRuleAttribute->Attribute())(*this);
       
   452     }
       
   453 
       
   454 /** Handles a node in the rule tree.
       
   455 
       
   456 It calls the appropriate handler method for the rule type.
       
   457 
       
   458 @return ETrue if the function completed processing this node, otherwise EFalse
       
   459 @param aRule Rule node
       
   460 @param aMatched On return, flag indicating if input stream matched the rule
       
   461 */
       
   462 EXPORT_C
       
   463 TBool
       
   464 CBNFParser::PerformRuleL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched)
       
   465 // Dispatches a rule node of given type to the appropriate handler
       
   466 	{
       
   467     TBool performedMatch;
       
   468     switch (aRule.Type())
       
   469         {
       
   470     case EReference:
       
   471         performedMatch = ReferenceL(aRule, aMatched);
       
   472         break;
       
   473     case EExact:
       
   474         performedMatch = ExactL(aRule, aMatched);
       
   475         break;
       
   476     case ERange:
       
   477         performedMatch = RangeL(aRule, aMatched);
       
   478         break;
       
   479     case ESelect:
       
   480         performedMatch = SelectL(aRule, aMatched);
       
   481         break;
       
   482     case EWithout:
       
   483         performedMatch = WithoutL(aRule, aMatched);
       
   484         break;
       
   485     case ERoot:
       
   486     case EAnd:
       
   487         performedMatch = AndL(aRule, aMatched);
       
   488         break;
       
   489     case EOr:
       
   490         performedMatch = OrL(aRule, aMatched);
       
   491         break;
       
   492     case EOptional:
       
   493         performedMatch = OptionalL(aRule, aMatched);
       
   494         break;
       
   495     case ENMore:
       
   496         performedMatch = NMoreL(aRule, aMatched);
       
   497         break;
       
   498     case EIncomplete:
       
   499     default:
       
   500         __ASSERT_DEBUG(EFalse, User::Panic(_L("CBNFPARSE"), 1));
       
   501         // Oh dear an incomplete node in the rule tree. FAIL NOW!!!
       
   502         performedMatch = ETrue;
       
   503         aMatched = CFragmentedString::ENoMatch;
       
   504         break;
       
   505         }
       
   506     return performedMatch;
       
   507     }
       
   508 
       
   509 EXPORT_C TBool CBNFParser::ParseL()
       
   510 // Performs the actual parsing.
       
   511 // Consumes as much of the input data as it can using the iTree BNF tree.
       
   512 // Whilst parsing the appropriate callbacks are invoked on the parsed rules allowing actions to be performed.
       
   513 // Should the input data be fully consumed and the parser has not been notified that there is no more input data
       
   514 // this method returns leaving the parser in a state waiting for more input.
       
   515 	{
       
   516 	iParsing = EActive;
       
   517 	while ((State() == EActive) && (!iRuleStack.IsEmpty()))
       
   518 		{
       
   519 		// find next rule
       
   520 		CBNFNode *currentRule = iRuleStack.Head();
       
   521 
       
   522 		// are we going up or down the tree?
       
   523  		if (iSubRule == NULL)
       
   524             ExecutePreRuleCallbackL(*currentRule);
       
   525 
       
   526         if (PerformRuleL(*currentRule, iMatched))
       
   527 			{
       
   528 			switch (iMatched)
       
   529 				{
       
   530             case CFragmentedString::EMatch:
       
   531                 // we matched take ourselves off the stack
       
   532                 iRuleStack.Pop();
       
   533                 iSubRuleMatched = ETrue;
       
   534                 iSubRule = currentRule;
       
   535                 break;
       
   536             case CFragmentedString::EInsufficientData:
       
   537                 // we ran out of data doing the match, should we try again later or is it a no match
       
   538                 if (!iStringComplete)
       
   539                     {
       
   540                     iParsing= EStopped;
       
   541                     break;
       
   542                     }
       
   543             case CFragmentedString::ENoMatch:
       
   544                 // we didn't match take ourselves off the stack
       
   545                 iRuleStack.Pop();
       
   546                 iSubRuleMatched = EFalse;
       
   547                 iSubRule = currentRule;
       
   548                 break;
       
   549             default:
       
   550                 // naughty, naughty.
       
   551                 break;
       
   552 				}
       
   553             if( iMatched != CFragmentedString::EInsufficientData || iStringComplete)
       
   554 				ExecutePostRuleCallbackL(*currentRule);
       
   555 			}
       
   556 		// have we finished all the rules!?!?!
       
   557 		if (iRuleStack.IsEmpty())
       
   558 			iParsing= EStopped;
       
   559 		}
       
   560 	return (iSubRuleMatched);
       
   561 	}
       
   562 
       
   563 
       
   564 //
       
   565 // assist BNF tree building
       
   566 /** Creates a new rule tree root node.
       
   567 
       
   568 It creates a new single instance of CBNFNode as the root node of the rule tree. 
       
   569 All the top-level rules are attached as attributes to this node. The root node 
       
   570 should have single child node, which should be a reference to the logical root 
       
   571 of the rule tree. This can be done be attaching the logical root rule as a component 
       
   572 to the root rule.
       
   573 
       
   574 @return New rule tree root node
       
   575 */
       
   576 EXPORT_C CBNFNode* CBNFParser::NewBNFL()
       
   577 // Generate a new ROOT node for a BNF tree.
       
   578 	{
       
   579 	return CBNFNode::NewL(ERoot);
       
   580 	}
       
   581 
       
   582 /** Creates a new rule node and adds it to the root of the rule tree. 
       
   583 
       
   584 This overload takes ownership of the node data.
       
   585 
       
   586 @return The newly created rule node in the rule tree
       
   587 @param aRootRule Pointer to the root BNF node, created with NewBNFL()
       
   588 @param aRuleName Reference to a string identifying this rule. The string is used to make references to this rule from other rule's subtrees.
       
   589 @param aRuleType Rule type
       
   590 @param aData Rule data pointer. This is used with EExact and ESelect type rules to match actual text strings.
       
   591 @param aPreRule Function pointer to a pre-rule function that gets called before the parser starts processing this rule and its children (i.e. the rule subtree).
       
   592 @param aPostRule Function pointer to a post-rule function that gets called after the parser has processed this rule and its subtree.
       
   593 */
       
   594 EXPORT_C CBNFNode&  CBNFParser::NewRuleL(CBNFNode* aRootRule, const TDesC& aRuleName, TParserNodeTypes aRuleType, HBufC* aData, TRuleCallback* aPreRule, TRuleCallback* aPostRule)
       
   595 // Add a new rule to the BNF tree, the new rule is given the name aRuleName (so it can be referred by another rule).
       
   596 // The parameter aData is used by the RuleTypes: Exact & Select.
       
   597 	{
       
   598 	// taken ownership of aData
       
   599 	CleanupStack::PushL(aData);
       
   600 	const HBufC* id = iLUT.Des2IDL(aRuleName);
       
   601 
       
   602 	CBNFNode* terminal = REINTERPRET_CAST(CBNFNode*, aRootRule->Attribute(id));
       
   603 
       
   604 	if (terminal)
       
   605 		terminal->SetType(aRuleType);
       
   606 	else
       
   607 		{
       
   608 		terminal = CBNFNode::NewL(aRuleType);
       
   609         CleanupStack::PushL(terminal);
       
   610 		aRootRule->AddAttributeL(id, terminal);
       
   611         CleanupStack::Pop();
       
   612 		}
       
   613 
       
   614 	if (aData)
       
   615 		terminal->SetDataL(aData);
       
   616 	CleanupStack::Pop();
       
   617 
       
   618     AddRuleCallbackL(*terminal, iPreRuleCallback, aPreRule);
       
   619     AddRuleCallbackL(*terminal, iPostRuleCallback, aPostRule);
       
   620 
       
   621 	return *terminal;
       
   622 	}
       
   623 
       
   624 /** Creates a new rule node and adds it to the root of the rule tree. 
       
   625 
       
   626 This overload takes a reference to the node data instead of owning it.
       
   627 
       
   628 @return The newly created rule node in the rule tree
       
   629 @param aRootRule Pointer to the root BNF node, created with NewBNFL()
       
   630 @param aRuleName Reference to a string identifying this rule. The string is used to make references to this rule from other rule's subtrees.
       
   631 @param aRuleType Rule type
       
   632 @param aData Rule data pointer. This is used with EExact and ESelect type rules to match actual text strings.
       
   633 @param aPreRule Function pointer to a pre-rule function that gets called before the parser starts processing this rule and its children (i.e. the rule subtree).
       
   634 @param aPostRule Function pointer to a post-rule function that gets called after the parser has processed this rule and its subtree.
       
   635 */
       
   636 EXPORT_C CBNFNode& CBNFParser::NewRuleL(CBNFNode* aRootRule, const TDesC& aRuleName, TParserNodeTypes aRuleType, const TDesC& aData, TRuleCallback* aPreRule, TRuleCallback* aPostRule)
       
   637 	{
       
   638     return NewRuleL(aRootRule, aRuleName, aRuleType, aData.AllocL(), aPreRule, aPostRule);
       
   639 	}
       
   640 
       
   641 /** Adds a callback to a rule.
       
   642 
       
   643 @param aRule The rule to which the callback is to be added
       
   644 @param aCallbackID Callback type: either CBNFNode::KPreRuleCallback() or CBNFNode::KPostRuleCallback()
       
   645 @param aCallback Callback function
       
   646 */
       
   647 EXPORT_C void CBNFParser::AddRuleCallbackL(CBNFNode& aRule, const TDesC* aCallbackID, TRuleCallback* aCallback)
       
   648     {
       
   649     if (aCallback)
       
   650         {
       
   651         CNoDeleteAttributeT<TRuleCallback*>* ruleAttribute = new (ELeave) CNoDeleteAttributeT<TRuleCallback*>(aCallback);
       
   652         CleanupStack::PushL(ruleAttribute);
       
   653         aRule.AddAttributeL(aCallbackID, ruleAttribute);
       
   654         CleanupStack::Pop();
       
   655         }
       
   656     }
       
   657 
       
   658 /** Creates a new reference rule node.
       
   659 
       
   660 @return The new reference rule node
       
   661 @param aRootRule Root node
       
   662 @param aRuleName Rule name
       
   663 */
       
   664 EXPORT_C CBNFNode* CBNFParser::NewComponentL(CBNFNode* aRootRule, const TDesC& aRuleName)
       
   665 	{
       
   666 	CBNFNode *terminalNode = (CBNFNode*)aRootRule->Attribute(iLUT.Des2IDL(aRuleName));
       
   667 	if (terminalNode == NULL)
       
   668 		terminalNode = &NewRuleL(aRootRule, aRuleName, EIncomplete, NULL, NULL, NULL);
       
   669 
       
   670 	CBNFNode* rule = CBNFNode::NewL(EReference);
       
   671 	CleanupStack::PushL(rule);
       
   672 	CNoDeleteAttributeT<CBNFNode*>* attributeNode = new (ELeave) CNoDeleteAttributeT<CBNFNode*>(terminalNode);
       
   673     CleanupStack::PushL(attributeNode);
       
   674 	rule->AddAttributeL(iReferenceString, attributeNode);
       
   675 	CleanupStack::Pop(2);
       
   676 
       
   677 	return rule;
       
   678 	}
       
   679 
       
   680 
       
   681 /** Creates a new rule node, but does not add it to the tree.
       
   682 
       
   683 This overload sets no rule callbacks.
       
   684 
       
   685 @return The new rule node
       
   686 @param aRuleType Rule type
       
   687 @param aData Rule data reference. This is used with EExact and ESelect type rules to match actual text strings.
       
   688 */
       
   689 EXPORT_C CBNFNode* CBNFParser::NewComponentL(TParserNodeTypes aRuleType, const TDesC& aData)
       
   690 // Adds a new rule component to the given ParentRule.
       
   691 	{
       
   692     return NewComponentL(aRuleType, aData.AllocL());
       
   693 	}
       
   694 
       
   695 /** Creates a new rule node, but does not add it to the tree.
       
   696 
       
   697 This overload allows rule callbacks to be set.
       
   698 
       
   699 @return The new rule node
       
   700 @param aRuleType Rule type
       
   701 @param aData Rule data pointer. This is used with EExact and ESelect type rules to match actual text strings.
       
   702 @param aPreRule Function pointer to a pre-rule function that gets called before the parser starts processing this rule and its subtree.
       
   703 @param aPostRule The new rule node
       
   704 */
       
   705 EXPORT_C CBNFNode* CBNFParser::NewComponentL(TParserNodeTypes aRuleType, HBufC* aData/*=NULL*/, TRuleCallback* aPreRule/*=NULL*/, TRuleCallback* aPostRule/*=NULL*/)
       
   706 	{
       
   707 	// taken ownership of aData
       
   708 	CleanupStack::PushL(aData);
       
   709 	CBNFNode* terminal = CBNFNode::NewL(aRuleType);
       
   710 	CleanupStack::PushL(terminal);
       
   711 	if (aData)
       
   712 		terminal->SetDataL(aData);
       
   713 	// correct cleanupstack
       
   714 	CleanupStack::Pop(2);
       
   715 	CleanupStack::PushL(terminal);
       
   716 
       
   717     AddRuleCallbackL(*terminal, iPreRuleCallback, aPreRule);
       
   718     AddRuleCallbackL(*terminal, iPostRuleCallback, aPostRule);
       
   719 
       
   720 	CleanupStack::Pop(); //terminal
       
   721 	return terminal;
       
   722 	}
       
   723 
       
   724 
       
   725 /** Creates a new sub-rule, and makes it a child of a specified parent rule.
       
   726 
       
   727 This overload sets no rule callbacks.
       
   728 
       
   729 @return The new sub-rule node
       
   730 @param aParentRule The rule to the new sub-rule shall be added as a child
       
   731 @param aRuleType Rule type
       
   732 @param aData Rule data reference. This is used with EExact and ESelect type rules to match actual text strings.
       
   733 */
       
   734 EXPORT_C CBNFNode&  CBNFParser::NewComponentL(CBNFNode &aParentRule, TParserNodeTypes aRuleType, const TDesC& aData)
       
   735 // Adds a new rule component to the given ParentRule.
       
   736 	{
       
   737     return NewComponentL(aParentRule, aRuleType, aData.AllocL());
       
   738 	}
       
   739 
       
   740 /** Creates a new sub-rule, and makes it a child of a specified parent rule.
       
   741 
       
   742 This overload sets rule callbacks.
       
   743 
       
   744 @return The new sub-rule node
       
   745 @param aParentRule The rule to the new sub-rule shall be added as a child
       
   746 @param aRuleType Rule type
       
   747 @param aData Rule data pointer. This is used with EExact and ESelect type rules to match actual text strings.
       
   748 @param aPreRule Function pointer to a pre-rule function that gets called before the parser starts processing this rule and its subtree.
       
   749 @param aPostRule Function pointer to a post-rule function that gets called after the parser has processed this rule and its subtree.
       
   750 */
       
   751 EXPORT_C CBNFNode&  CBNFParser::NewComponentL(CBNFNode &aParentRule, TParserNodeTypes aRuleType, HBufC* aData, TRuleCallback* aPreRule, TRuleCallback* aPostRule)
       
   752 	{
       
   753 	// take ownership of aData
       
   754     CleanupStack::PushL(aData);
       
   755 	CBNFNode& terminal = REINTERPRET_CAST(CBNFNode&, aParentRule.AppendNodeL(aRuleType));
       
   756     AddRuleCallbackL(terminal, iPreRuleCallback, aPreRule);
       
   757     AddRuleCallbackL(terminal, iPostRuleCallback, aPostRule);
       
   758 
       
   759 	if (aData)
       
   760 		terminal.SetDataL(aData);
       
   761     CleanupStack::Pop();
       
   762 
       
   763 	return terminal;
       
   764 	}
       
   765 
       
   766 
       
   767 /** Creates a new reference rule node, and adds it as a child of the specified parent.
       
   768 
       
   769 Note that the function succeeds even if the target rule aRuleName does not yet exist.
       
   770 
       
   771 @return The new reference rule node
       
   772 @param aRootRule Root node: the function needs this to find the target rule identified by aRuleName
       
   773 @param aParentRule Parent rule to which to attach the new rule as a child
       
   774 @param aRuleName The name of the rule that the new node refers to
       
   775 */
       
   776 EXPORT_C CBNFNode&  CBNFParser::NewComponentL(CBNFNode* aRootRule, CBNFNode &aParentRule, const TDesC& aRuleName)
       
   777     {
       
   778 	CBNFNode *terminalNode = (CBNFNode*)aRootRule->Attribute(iLUT.Des2IDL(aRuleName));
       
   779 	if (terminalNode == NULL)
       
   780 		terminalNode = &NewRuleL(aRootRule, aRuleName, EIncomplete, NULL, NULL, NULL);
       
   781 
       
   782 	CBNFNode& rule = REINTERPRET_CAST(CBNFNode&, aParentRule.AppendNodeL(EReference));
       
   783 	CNoDeleteAttributeT<CBNFNode*>* attributeNode = new (ELeave) CNoDeleteAttributeT<CBNFNode*>(terminalNode);
       
   784     CleanupStack::PushL(attributeNode);
       
   785 	rule.AddAttributeL(iReferenceString, attributeNode);
       
   786     CleanupStack::Pop();
       
   787 
       
   788 	return rule;
       
   789 	}
       
   790 
       
   791 /** Adds an additional attribute to an existing rule node.
       
   792 
       
   793 For example, this is used with range rules, which specify the range boundaries using start and end attributes.
       
   794 
       
   795 @param aRule Rule node on which to set the attribute
       
   796 @param aAttribute Attribute type
       
   797 @param aInt Attribute value
       
   798 */
       
   799 EXPORT_C void CBNFParser::AddComponentAttributeL(CBNFNode& aRule, CBNFNodeAttributeType aAttribute, TInt aInt)
       
   800 // Adds a restriction to a rule component, this is used for instance with Range restrictions (Start/End)
       
   801 	{
       
   802 	CNoDeleteAttributeT<TInt>* aTIntAttribute = new (ELeave) CNoDeleteAttributeT<TInt>(aInt);
       
   803     CleanupStack::PushL(aTIntAttribute);
       
   804 	aRule.AddAttributeL(aAttribute, aTIntAttribute);
       
   805     CleanupStack::Pop();
       
   806 	}
       
   807 
       
   808 /** Inserts a mark to the current position of the stream being processed.
       
   809 
       
   810 Adding a mark is a very common callback operation before starting to process a rule, so the method is provided by the parser.
       
   811 
       
   812 @param aParser Parser processing the stream
       
   813 */
       
   814 EXPORT_C void CBNFParser::MarkCallback(CBNFParser& aParser)
       
   815 // Provide a very common preaction callback to mark the input stream before the next rule attempts to parse it.
       
   816 	{// static
       
   817 	aParser.Mark(); // Mark can leave
       
   818 	}
       
   819 
       
   820 
       
   821 //
       
   822 // Data Provider access
       
   823 /** Called by the data provider to add data for the parser to process.
       
   824 
       
   825 This implements MDataProviderObserver::ProcessDataL().
       
   826 
       
   827 @param aData The data to process
       
   828 */
       
   829 EXPORT_C void CBNFParser::ProcessDataL(HBufC8& aData)
       
   830 // Add new data as the input to the parser, ownership is taken of the aData.
       
   831 	{
       
   832 	HBufC* newData = HBufC::NewL(aData.Length());
       
   833 	newData->Des().Copy(aData.Des());
       
   834 	
       
   835 	iString.AddStringL(newData);
       
   836 
       
   837 	ParseL();
       
   838 	}
       
   839 
       
   840 /** Called by the data provider to report its status to its observer.
       
   841 
       
   842 This implements MDataProviderObserver::SetStatus().
       
   843 
       
   844 @param aStatusCode Status code
       
   845 */
       
   846 EXPORT_C void CBNFParser::SetStatus(TInt aStatusCode)
       
   847 // Notify the parser that there is no more (new) input data to be added/parsed.
       
   848 	{
       
   849 	if (aStatusCode == EPluginComplete)
       
   850 		{
       
   851 		// No more data will be pushed at us
       
   852 		// so do what we need to finish and set our
       
   853 		// status
       
   854 		iStringComplete = ETrue;
       
   855 		}
       
   856 	}
       
   857 
       
   858 EXPORT_C void CBNFParser::SetDocumentTypeL(const TDesC& /*aDocType*/)
       
   859     {
       
   860     }
       
   861 
       
   862 EXPORT_C void CBNFParser::SetDocumentTypeL(const TDesC&, const TDesC&)
       
   863     {
       
   864     }
       
   865 
       
   866 EXPORT_C void CBNFParser::SetDataExpected(TInt)
       
   867     {
       
   868     }
       
   869 
       
   870 EXPORT_C void CBNFParser::SetBaseUriL(const TDesC* /*aBaseUri*/)
       
   871 	{
       
   872 	}
       
   873 
       
   874 /** Notifies the parser that all the data has been passed in.
       
   875 
       
   876 It causes the parser to parse any of the input stream not already parsed.
       
   877 */
       
   878 EXPORT_C void CBNFParser::CommitL()
       
   879 	{
       
   880 	if (iStringComplete)
       
   881 	    ParseL();
       
   882 	}
       
   883 
       
   884 EXPORT_C  CBNFNode* CBNFParser::TreeL()
       
   885     {
       
   886     return NULL;
       
   887     }
       
   888 
       
   889 EXPORT_C void CBNFParser::StartConditional(TParserNodeTypes /*aRuleType*/)
       
   890     {
       
   891     }
       
   892 
       
   893 EXPORT_C void CBNFParser::EndConditional(TParserNodeTypes /*aRuleType*/, TBool /*aSuccess*/)
       
   894     {
       
   895     }
       
   896 
       
   897 
       
   898 // Provide an implementation for the interface class
       
   899 EXPORT_C void CBNFParser::MDataProviderObserverReserved1() 
       
   900 	{
       
   901 	User::Panic(_L("Reserved"),KErrNotSupported);
       
   902 	}
       
   903 
       
   904 EXPORT_C void CBNFParser::MDataProviderObserverReserved2()
       
   905 	{
       
   906 	User::Panic(_L("Reserved"),KErrNotSupported);
       
   907 	}