diff -r 2fe1408b6811 -r e1b950c65cb4 epoc32/include/mw/cbnfparser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/epoc32/include/mw/cbnfparser.h Wed Mar 31 12:27:01 2010 +0100 @@ -0,0 +1,557 @@ +// Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" to Symbian Foundation members and "Symbian Foundation End User License Agreement v1.0" to non-members +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/licencesv10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// This class provides a mechanism to use a BNF tree to parse an input stream. +// The notation of the EBNF is based upon that described in the XML1.0 specification. +// The BNF tree form used is a variation on Extended BNF and has the following rule types, +// where the input stream must: +// , Exact - match exactly with the provided string. +// , Range - next character must be in the specified range. +// , Select - next character must exist in the selected string. +// If the select string starts with ^ it is a NOT Select. +// , And - match all of the given sub rules +// , Or - match one of the given sub rules +// , NMore - match N or more times the the SINGLE subrule. +// , Optional - match 0/1 times to the SINGLE subrule. +// , Without - match the first subrule but NOT the second. +// , Reference - match the referred to rule. +// The iterative parser not only validates an input stream against the +// BNF grammer but allows pre/post actions to be performed during the parsing. +// Partial parsing is also allowed in that the input stream does not have to +// completed before parsing can begin. As soon as data is added the parser +// attempts to parse it. +// Numerous methods are provided to assist in the building of the BNF Tree this parser uses. +// To use this class: +// Create a derivation and implement the virtual method TreeL() to creat a BNF rule tree +// (the assistance methods NewBNF/NewRule etc should be used) - see DTDModel +// To use your new parser invoke Reset and pass input data using the ProcessData method. +// +// + +#ifndef __CBNFPARSER_H__ +#define __CBNFPARSER_H__ + +#include +#include +#include +#include +#include + +// +// forward class declarations +// +class CAttributeLookupTable; + + +// Rule Tree node type definitions +/** Defines types of node in a BNF tree (CBNFParser). + +Except for ERoot, EIncomplete, EReference, and ELastParserNodeType, the +types define different types of rule that the input stream must meet to +satisfy the grammar. */ +enum TParserNodeTypes + { + /** Root node. */ + ERoot, + /** Incomplete node. */ + EIncomplete, + /** Exact rule: match exactly with the provided string. */ + EExact, + /** Range rule: next character must be in the specified range. + + The start of the range is specified by a CBNFNode::KRangeStart() + attribute; the end by a CBNFNode::KRangeEnd() attribute. */ + ERange, + /** Select rule: next character must exist in the selected string. + + If the select string starts with ^, it is a NOT Select. */ + ESelect, + /** And rule: match all of the given sub-rules. + + Sub-rules are defined by the child nodes of the AND rule node. */ + EAnd, + /** Or rule: match one of the given sub-rules. + + Sub-rules are defined by the child nodes of the OR rule node. */ + EOr, + /** NMore rule: match a single subrule N or more times. + + A minimum is specified by a CBNFNode::KNMoreMinimum() attribute; a maximum by + a CBNFNode::KNMoreMaximum() attribute; an exact figure by a CBNFNode::KNMoreCount() attribute. */ + ENMore, + /** Optional rule: match a single sub-rule 0/1 times. + + A sub-rule is defined by the child node of the Optional rule node. */ + EOptional, + /** Without rule: match the first sub-rule but not the second. + + Sub-rules are defined by the child nodes of the Without rule node. */ + EWithout, + /** Reference rule: match the referred to rule. + + The target rule name is identified by a CBNFNode::KReference() attribute. */ + EReference, + /** Indicates final node type. */ + ELastParserNodeType + }; + +// Parser states +// +// When a the state is EActive. +// Setting the parser state to something else in a pre-/post-rule callback function +// causes the parser to exit on next loop in ParseL. If the state is set to EStopped +// we have finished the parser operation (e.g. in event of an error), in state EPaused +// we are likely to resume the parser operation after some external operations. +/** CBNFParser parser states. */ +enum TParseState + { + /** Parser has stopped. */ + EStopped, + /** Rarser is running. */ + EActive, + /** Parser has paused: e.g. waiting for further input to continue. */ + EPaused + }; + + + +class CBNFParser : public CBase, public MDataProviderObserver +/** Base class for parsers that use a BNF tree to parse an input stream. + +The BNF tree form used is a variation on Extended BNF described in the XML1.0 +specification. The general form of the tree is as follows: + +Each node in the tree defines a rule that the input stream must meet to satisfy the grammar. + +1. a node type is set to the rule type, as defined in TParserNodeTypes + +2. node data stores any string required by the rule: e.g. for a comparison rule, the string + to match against + +3. the parser allows callback functions to be called either before or after the rule is processed. + If these are present, they are stored as attributes of the node. + +4. some rules allow sub-rules: for example, the AND rule expects a number of sub-rules, all + of which must be successful if the AND rule itself is to succeed. Each sub-rule is + represented as a child node of the parent rule. Sub-rules in turn can have sub-rules. + +5. reference rule nodes are also allowed: these do not define themselves rules, but direct the + parser to another rule. They can link rules to each other and so build rule sequences more + complex than a simple tree. + +All the top-level rules are stored as attributes of the root node. The attribute type is a string + that names the rule; the attribute value is a pointer to the node that implements the rule. + +The class supplies functions that encapsulate adding rules appropriately to the tree. The parser +provider creates a derived class that implements the virtual method TreeL() that uses these +functions to create a BNF rule tree. + +The user of the parser initialises the parser with ResetL(), and then passes input data to the +parser using ProcessData(). The parser supports partial parsing: the input stream does not have +to completed before parsing can begin. As soon as data is added, the parser attempts to parse it. + + @publishedAll + @released + +*/ + { +protected: + /** Defines a type to handle a stack of rules. */ + typedef CStack CRuleStack; + + /** Type definition for a callback function pointer + Callback functions need to get a reference to the parser as parameter + and they need to be static. */ + typedef void (TRuleCallback)(CBNFParser&); + +public: + // Constructor for a new parser instance + // + // Input: + // aLUT - reference to attribute lookuptable; used to store all the stuff in the parser rule tree + // + //##ModelId=3B6669EA00F8 + IMPORT_C static CBNFParser* NewL(CAttributeLookupTable& aLUT); + + //##ModelId=3B6669EA00F7 + IMPORT_C virtual ~CBNFParser(); + + // Prepare the parser to take in fresh stream of data. + // THIS METHOD MUST BE CALLED BEFORE DATA CAN BE PROCESSED BY THE PARSER!! + // Calls TreeL in order to create the parsing rule tree if no tree already + // exists. + //##ModelId=3B6669EA00EF + IMPORT_C virtual void ResetL(); + + /** Checks if the input stream was completely processed + @return ETrue if all of the data was processed, EFalse if the data didn't match to the parsing rules + */ + //##ModelId=3B6669EA00EE + TBool Valid() const { return iStringComplete && (iString.Length() == 0); } + + /** Concatenates the rest of the input stream (which hasn't yet been processed) + into a single string. The ownership of the string is given to the caller. + @return String containing the remaining data to be parsed. OWNERSHIP PASSED TO CALLED. */ + //##ModelId=3B6669EA00ED + HBufC* StringL() const { return iString.StringL(); } + + /** Gets a pointer to the rule node currently being processed. + @return Rule node */ + //##ModelId=3B6669EA00E3 + CBNFNode* CurrentRule() { return iCurrentRule; } + + // Set reference to an attribute lookup table + //##ModelId=3B6669EA00C5 + void SetAttributeLookupTable(CAttributeLookupTable& aAttributeLookupTable); + + // methods to allow the input stream to be marked so that the callbacks + // can determine those parts which successfully matched + + /** Set a mark to the current position of the input stream. + + The mark acts as a tag in the stream currently being processed. + As we process further along the stream after adding the mark, we can perform + a rollback to the most previously set mark and start processing again (e.g. OR rule + works this way). The string fragments won't be consumed (deleted) until + all the marks on a fragment (and fragments before that) are deleted. */ + //##ModelId=3B6669EA00BC + void Mark() { iString.Mark(); }; // **Mark can leave** + + /** Get string between the "cursor position" and the latest mark on the stream. + + @return Pointer to the string from the previous mark on to the current position + of processed string. OWNERSHIP OF THE STRING GIVEN TO THE CALLER. */ + //##ModelId=3B6669EA00BB + HBufC* MarkedL() { return iString.MarkedL(); }; + + /** Gets the marked string with a string added before the mached string. + @see MarkedL() + @return A string cosisting of aInitialText appended with the marked string. + OWNERSHIP OF THE CONSTRUCTED STRING IS GIVEN TO THE CALLER. */ + //##ModelId=3B6669EA009E + HBufC* MarkedWithInitialTextL(const TDesC& aInitialText) { return iString.MarkedWithInitialTextL(aInitialText); }; + + /** Removes the latest mark. All the marks are stored in a stack and this removes + the topmost mark.*/ + //##ModelId=3B6669EA009D + void DeleteMark() { iString.DeleteMark(); }; + + // methods to determine it the used rule actually matched (typically used in post callbacks) + /** Tests if the used rule matched. + + This is typically used in post-rule callbacks. + + @return True if the used rule matched; otherwise false + */ + //##ModelId=3B6669EA0094 + TBool RuleMatched() const { return iSubRuleMatched; }; + /** Tests if an Optional node sub-rule matched. + + @return True if the sub- rule matched; otherwise false + */ + //##ModelId=3B6669EA0093 + TBool OptionalMatched() const { return iOptionalMatched; }; + + // Create new rule tree root node. + // This method creates a new single instance of CBNFNode, which shall act as the root + // node of the rule tree, which implements the BNF rules for parsing the input stream. + // All the other rules are attached as attributes to this node. + // The root node should have single child node, which should be a reference to the + // "logical root" of the rule tree. This can be done be attaching the logical root + // rule as a component to the root rule. + //##ModelId=3B6669EA0089 + IMPORT_C CBNFNode* NewBNFL(); + + // Add a new rule to a rule tree. + // + // Input: + // aRootRule - Pointer to the root bnf node (created with NewBNFL() ). + // aRuleName - Reference to a string identifying this rule. The string is used + // to make references to this rule from other rule's subtrees. + // aData - Pointer to a data string; used with EExact and ESelect type rules + // to match actual text strings. + // aPreRule - Function pointer to a prerule function that gets called _BEFORE_ + // we start processing this rule and its children (i.e. the rule subtree) + // aPostRule - Function pointer to a postrule function which is called _AFTER_ + // we have processed this rule (i.e. when we return up from the subtree + // and this rule is finished). + // + // Return: + // CBNFNode& - Reference to the newly created rule node in the rule tree + // + //##ModelId=3B6669E90326 + IMPORT_C CBNFNode& NewRuleL(CBNFNode* aRootRule, + const TDesC& aRuleName, + TParserNodeTypes aRuleType, + HBufC* aData, + TRuleCallback* aPreRule, + TRuleCallback* aPostRule); + + // Overridden version of the NewRuleL. Takes reference to the data instead of owning it. + //##ModelId=3B6669E903D1 + IMPORT_C CBNFNode& NewRuleL(CBNFNode* aRootRule, + const TDesC& aRuleName, + TParserNodeTypes aRuleType, + const TDesC& aData, + TRuleCallback* aPreRule, + TRuleCallback* aPostRule); + + // construct a new rule component not attached to a rule. + //##ModelId=3B6669E9018C + IMPORT_C CBNFNode* NewComponentL(TParserNodeTypes aRuleType, const TDesC& aData); + //##ModelId=3B6669E901B4 + IMPORT_C CBNFNode* NewComponentL(TParserNodeTypes aRuleType, HBufC* aData = NULL, TRuleCallback* aPreRule = NULL, TRuleCallback* aPostRule = NULL); + + // create a reference component to the rule of the given name + // which is not attached to any rule. + //##ModelId=3B6669E90204 + IMPORT_C CBNFNode* NewComponentL(CBNFNode* aRootRule, const TDesC& aRuleName); + + // Methods to create a new subrule to the given parent rule. + // These methods can be used to build the subtrees to the "main rules" attached to the root node. + // + // Input: + // aParentRule - The rule for which the new rule shall be added as a child + // aRuleType - Type of the new rule + // aData - Data for the rule; the string to match for an EExact rule, the selection character set for ESelect + // + // aPreRule - Pre rule callback function pointer + // aPostRule - Post rule callback function pointer + // Return: + // CBNFNode& - reference to the new rule + // + //##ModelId=3B6669E9022C + IMPORT_C CBNFNode& NewComponentL(CBNFNode &aParentRule, TParserNodeTypes aRuleType, const TDesC& aData); + //##ModelId=3B6669E90268 + IMPORT_C CBNFNode& NewComponentL(CBNFNode &aParentRule, TParserNodeTypes aRuleType, HBufC* aData = NULL, TRuleCallback* aPreRule = NULL, TRuleCallback* aPostRule = NULL); + + // Create a reference to another rule and attach this reference as a child of the given parent. + // Creates a child node of type EReference for the parent. This reference node + // hold the pointer to the rule we are refering to. + // Using references we can link rules to each other and build complex rule trees + // even though they don't physically form a complete tree. + // Notice, that the rule we are refering to does not necessarily need to exist, yet! + // + // Input: + // aRootRule - The Root node to the rule tree (created with NewBNFL). This is needed to + // find the rule we are refering to with the string. + // aParentRule - The parent rule of the newly created reference + // aRuleName - The "id string" of the rule we are refering to. + //##ModelId=3B6669E902CC + IMPORT_C CBNFNode& NewComponentL(CBNFNode* aRootRule, CBNFNode &aParentRule, const TDesC& aRuleName); + + // add additional attributes to components of rules (i.e. range values) + //##ModelId=3B6669E900F6 + IMPORT_C void AddComponentAttributeL(CBNFNode& aRule, CBNFNodeAttributeType aAttribute, TInt aInt); + + // re-implementations of MDataProviderObserver methods + //##ModelId=3B6669E900D8 + IMPORT_C virtual void ProcessDataL(HBufC8& aData); + //##ModelId=3B6669E900AF + IMPORT_C virtual void SetStatus(TInt aStatus = KErrNone); + //##ModelId=3B6669E90069 + IMPORT_C virtual void SetDocumentTypeL(const TDesC&); + //##ModelId=3B6669E90087 + IMPORT_C virtual void SetDocumentTypeL(const TDesC&, const TDesC&); + //##ModelId=3B6669E90055 + IMPORT_C virtual void SetDataExpected(TInt); + //##ModelId=3B6669E90041 + IMPORT_C virtual void SetBaseUriL(const TDesC* aBaseUri); + //##ModelId=3B6669E90038 + IMPORT_C virtual void MDataProviderObserverReserved1(); + //##ModelId=3B6669E90037 + IMPORT_C virtual void MDataProviderObserverReserved2(); + + // Tell the parser, that we all the data has been passed in. + // This method attempts to parse what ever is left of the input stream if it wasn't + // already finished. + //##ModelId=3B6669E9002E + IMPORT_C void CommitL(); + + /** Get the current state of the parser. + @return Parser state */ + //##ModelId=3B6669E9002D + TParseState State() const {return(iParsing);}; + +protected: + IMPORT_C CBNFParser(CAttributeLookupTable& aLUT); + + // Each of the following functions is a handler method for a specific type of a rule + // node. For example, ReferenceL handles reference nodes etc. + // These methods are called by PerformRuleL. + // + // Input: + // aRule - reference to the rule being processed + // aMatched - reference to a CFragmentedString::TStringMatch variable, which holds + // the information if the string or character we previously were trying to + // match actually matched. + // Return: + // TBool - We return ETrue if we have completed processing this node. If the processing + // still continues we return EFalse. For example, an EAnd rule would return + // ETrue if all of its chidren had matched or if a rule didn't match. In the first + // case the EAnd rule would have turned out to be true (aMatched = EMatched) since + // all of its children were true, but in the latter case we can stop processing the + // EAnd rule, since a subrule to the And didn't match and this means that the And + // expression can not be true. Either way, the processing of the And ends and we + // may return ETrue; + // + //##ModelId=3B6669E90005 + IMPORT_C virtual TBool ReferenceL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched); + //##ModelId=3B6669E803BB + IMPORT_C virtual TBool ExactL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched); + //##ModelId=3B6669E80389 + IMPORT_C virtual TBool RangeL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched); + //##ModelId=3B6669E80343 + IMPORT_C virtual TBool SelectL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched); + //##ModelId=3B6669E80311 + IMPORT_C virtual TBool WithoutL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched); + //##ModelId=3B6669E802D5 + IMPORT_C virtual TBool AndL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched); + //##ModelId=3B6669E80299 + IMPORT_C virtual TBool OrL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched); + //##ModelId=3B6669E80271 + IMPORT_C virtual TBool OptionalL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched); + //##ModelId=3B6669E8023F + IMPORT_C virtual TBool NMoreL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched); + + // A method to add a callback to a rule + // + // Input: + // aRule - The rule to which the callback is to be added + // aCallbackID - Either CBNFNode::KPreRuleCallback() or CBNFNode::KPostRuleCallback() + // Defines the type of the callback function (i.e. is it to be called before + // or after the rule has been processed). + // aCallback - The callback function pointer + // + //##ModelId=3B6669E80203 + IMPORT_C virtual void AddRuleCallbackL(CBNFNode& aRule, const TDesC* aCallbackID, TRuleCallback* aCallback); + //##ModelId=3B6669E801EF + IMPORT_C virtual void ExecutePreRuleCallbackL(CBNFNode& aRule); + //##ModelId=3B6669E801D1 + IMPORT_C virtual void ExecutePostRuleCallbackL(CBNFNode& aRule); + + // the method TreeL() should be reimplemented to generate a BNF rule tree and return + // ownership of it. This is the rule tree which will be to parse the input stream. + // See XmlPars.cpp or DTDMDL.cpp for example. + //##ModelId=3B6669E801D0 + IMPORT_C virtual CBNFNode* TreeL(); + + // methods which are invoked when the parser encounters a conditional + // point in the BNF grammar (i.e. And/Or) + //##ModelId=3B6669E801B2 + IMPORT_C virtual void StartConditional(TParserNodeTypes aRuleType); + //##ModelId=3B6669E80180 + IMPORT_C virtual void EndConditional(TParserNodeTypes aRuleType, TBool aSuccess); + + // A callback function to insert a mark to the current position of the stream + // being processed. Adding mark is a very common callback operation befor starting + // to process a rule, hence the method is provided by the parser. + //##ModelId=3B6669E8016C + IMPORT_C static void MarkCallback(CBNFParser& aParser); + + // returns the LUT used by this parser. + //##ModelId=3B6669E80163 + IMPORT_C CAttributeLookupTable& AttributeLUT() const; + + // method which does the actual iterative parsing + //##ModelId=3B6669E80162 + IMPORT_C TBool ParseL(); + + // A rule to handle a node in the rule tree. This method just calls the appropriate + // handler method according to the rule type. + //##ModelId=3B6669E8013A + IMPORT_C virtual TBool PerformRuleL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched); + + //##ModelId=3B6669E8011C + /** Sets the parser state. + + @param aState Parser state + */ + void SetState(TParseState aState) {iParsing=aState;}; + +protected: + /** Storage object for all the attributes and identifiers in a tree */ + //##ModelId=3B6669E80108 + CAttributeLookupTable& iLUT; + + /** An utility object which stores all the buffers passed into the parser + and represents them as if they would form a single, continuous string. + This class also performs the actual physical matching/selection of the strings + and holds the marks set onto the string.*/ + //##ModelId=3B6669E800EA + CFragmentedString iString; + /** Flag indicating if the input stream has been completely processed. */ + //##ModelId=3B6669E800D6 + TBool iStringComplete; // more input stream has completed + + /** The BNF tree the parser is using to parse the input stream.*/ + //##ModelId=3B6669E800C2 + CBNFNode* iTree; // the BNF tree we are using to parse the input stream + + /** A stack of rules from iTree which are waiting to be completed. + The stack basically holds the path along the rule tree. */ + //##ModelId=3B6669E800AE + CRuleStack iRuleStack; + /** The BNF rule that is currently being processed. */ + //##ModelId=3B6669E80090 + CBNFNode* iCurrentRule; // the BNF rule we are currently using + + // when returning to a rule in the rulestack this indicates + // if the child rule matched correctly + /** Flag that indicates when returning to a rule in the rulestack if the child rule matched correctly. */ + //##ModelId=3B6669E8007C + TBool iSubRuleMatched; + /** Flag that indicates when returning to a rule in the rulestack if an optional rule matched correctly. */ + //##ModelId=3B6669E8006A + TBool iOptionalMatched; + + /** The child rule we are returning from (if any). + If this is NULL we are new to this BNF rule.*/ + //##ModelId=3B6669E80054 + CBNFNode* iSubRule; + + /** Parser state. */ + //##ModelId=3B6669E8004A + TParseState iParsing; + /** Input stream matched rule flag. */ + //##ModelId=3B6669E80038 + CFragmentedString::TStringMatch iMatched; + + // Storage pointers for strings identifying certain attributes on the rule nodes + /** Stores attribute identifier for reference string attributes. */ + //##ModelId=3B6669E8002C + const TDesC* iReferenceString; + /** Stores attribute identifier for range start attributes. */ + //##ModelId=3B6669E8001A + const TDesC* iRangeStart; + /** Stores attribute identifier for range end attributes. */ + //##ModelId=3B6669E80010 + const TDesC* iRangeEnd; + /** Stores attribute identifier for nmore minimum attributes. */ + //##ModelId=3B6669E80006 + const TDesC* iMoreMinimum; + /** Stores attribute identifier for nmore count attributes. */ + //##ModelId=3B6669E703DA + const TDesC* iMoreCount; + /** Stores attribute identifier for nmore maximum attributes. */ + //##ModelId=3B6669E703D0 + const TDesC* iMoreMaximum; + /** Stores attribute identifier for pre-rule callback attributes. */ + //##ModelId=3B6669E703C6 + const TDesC* iPreRuleCallback; + /** Stores attribute identifier for post-rule callback attributes. */ + //##ModelId=3B6669E703BC + const TDesC* iPostRuleCallback; + }; + +#endif