搞定symbian的http 和xml, xml采用sdk自带的cparser

    最近弄的东西太杂了. symbian os的sdk确实不是一般的难用, 顺便更正了以前写的symbian下的支持注释和section的ini类...
    顺便发泄下. 跟人合作做东西, 如果涉及到经济利益的话确实很麻烦. 本来这些东西都不是我来做的. 只是对方对源码遮遮掩掩的. 而且类封装的也很牵强.所以我才得做大量的工作...
    symbian阵营里面这些程序员对自己的源码还是看得很重的... 很怀念linux
   
关于xml的代码. 我记得没错的话, s60 2.3以后的sdk中才提供的cparser , 如果你要使用其代码, 请确认自己的sdk是2nd fp3 或以上, 否则, 请自行查阅mozilla的xml解析包的symbian移植版本


// --------------------------------------------------------------------------
// XmlHandler.h
//
// Copyright 2007, Antony Pranata
// http://www.antonypranata.com
//
// Example how to parse XML file using SAX on Symbian OS.
//
// There are two methods to parse XML document, i.e.;
//   - StartParsingL() -> parse XML document without active object.
//     The whole file content is read at once. It is simple, but suitable
//     for relatively small file only.
//   - StartParsingWithAoL() -> parse XML document with active object.
// --------------------------------------------------------------------------

#ifndef __XMLHANDLER_H__
#define __XMLHANDLER_H__

// INCLUDE FILES
#include <e32base.h>
#include <xml/contenthandler.h> // for MContentHandler
#include <xml/parser.h> // for CParser

// CLASS DECLARATION

using namespace Xml;

/**
 * MXmlHandlerObserver, an observer to CXmlHandler class.
 */
class MXmlHandlerObserver
{
  public:
    virtual void OnParseCompleted( TInt aError ) = 0;

};

/**
 * CXmlHandler, a class to parse XML file and then output log information
 * to a buffer.
 */
class CXmlHandler: public CActive, MContentHandler
{
    enum TState
    {
        EIdle,
        EReadingFile
    };
       
  public: // Constructors and destructor
   
    static CXmlHandler* NewL( MXmlHandlerObserver& aObserver );
   
    static CXmlHandler* NewLC( MXmlHandlerObserver& aObserver );
   
    virtual ~CXmlHandler();
   
  public: // Public methods
    void StartParsingL( const TDesC8& aBody );
    void StartParsingFL( const TDesC& aFileName );
   
    void StartParsingWithAoL( const TDesC& aFileName );
   
    TPtr8 DisplayResult() { return iDisplayResult->Des(); }

  private: // Constructors

    CXmlHandler( MXmlHandlerObserver& aObserver );
   
    void ConstructL();

  private: // from CActive
   
    void DoCancel();
   
    void RunL();
   
  private: // from MContentHandler

    void OnStartDocumentL( const RDocumentParameters &aDocParam, TInt aErrorCode );
   
    void OnEndDocumentL( TInt aErrorCode );
   
    void OnStartElementL( const RTagInfo &aElement, const RAttributeArray &aAttributes, TInt aErrorCode );
       
    void OnEndElementL( const RTagInfo &aElement, TInt aErrorCode );
   
    void OnContentL( const TDesC8 &aBytes, TInt aErrorCode );
   
    void OnStartPrefixMappingL( const RString &aPrefix, const RString &aUri, TInt aErrorCode );
       
    void OnEndPrefixMappingL( const RString &aPrefix, TInt aErrorCode );
   
    void OnIgnorableWhiteSpaceL( const TDesC8 &aBytes, TInt aErrorCode );
   
    void OnSkippedEntityL( const RString &aName, TInt aErrorCode );
   
    void OnProcessingInstructionL( const TDesC8 &aTarget, const TDesC8 &aData, TInt aErrorCode);
       
    void OnError( TInt aErrorCode );
   
    TAny *GetExtendedInterface( const TInt32 aUid );
   
  private: // Private methods

    void AppendText( const TDesC8& aText );
   
    void AppendTag( const TDesC8& aTag, TBool aIsClosingTag );

  private: // Private data

    MXmlHandlerObserver& iObserver;
    CParser*             iParser;
    HBufC8*              iBuffer;
    HBufC8*              iDisplayResult;
    TState               iState;
    RFile                iFile;

};

#endif /* __XMLHANDLER_H__ */

// End of File

 

 

 

 

// --------------------------------------------------------------------------
// XmlHandler.cpp
//
// Copyright 2007, Antony Pranata
// http://www.antonypranata.com
//
// Example how to parse XML file using SAX on Symbian OS.
//
// There are two methods to parse XML document, i.e.;
//   - StartParsingL() -> parse XML document without active object.
//     The whole file content is read at once. It is simple, but suitable
//     for relatively small file only.
//   - StartParsingWithAoL() -> parse XML document with active object.
// --------------------------------------------------------------------------

// INCLUDE FILES
#include <coemain.h>
#include <f32file.h>
#include "XmlHandler.h"

// CONSTANTS
const TInt KBufferSize     = 1024; // buffer size to store the result of
                                   // XML parsing -> the actual buffer size
                                   // can expand if needed (see AppendText())
                                  
const TInt KFileBufferSize = 1024; // buffer size for file reading

const TInt KOverheadLen    = 4; // length of (KOpeningTag + KClosingTag
                                //            + KSlash + KEndOfLine)

_LIT8(KOpeningTag, "<" );
_LIT8(KClosingTag, ">" );
_LIT8(KSlash,      "/" );
//_LIT8(KEndOfLine,  "/f" ); // CEikEdwin uses '/f' as EOF mark.

_LIT8( KXmlMimeType, "text/xml" );

 

// METHODS DEFINITION

// --------------------------------------------------------------------------

CXmlHandler* CXmlHandler::NewL( MXmlHandlerObserver& aObserver )
{
    CXmlHandler* self = CXmlHandler::NewLC( aObserver );
    CleanupStack::Pop();
    return self;
}

// --------------------------------------------------------------------------

CXmlHandler* CXmlHandler::NewLC( MXmlHandlerObserver& aObserver )
{
    CXmlHandler* self = new ( ELeave ) CXmlHandler( aObserver );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
}

// --------------------------------------------------------------------------

CXmlHandler::~CXmlHandler()
{
    Cancel();
    delete iParser;
    delete iDisplayResult;
    delete iBuffer;
}

// --------------------------------------------------------------------------

CXmlHandler::CXmlHandler( MXmlHandlerObserver& aObserver ):CActive( EPriorityStandard ),
    iObserver( aObserver ), iParser( 0 ), iDisplayResult( 0 ), iState( EIdle )
{
    CActiveScheduler::Add( this );
}

// --------------------------------------------------------------------------

void CXmlHandler::DoCancel()
{
    iParser->ParseEndL();
    iFile.Close();
    delete iBuffer;
    iBuffer = 0;
}

// --------------------------------------------------------------------------

void CXmlHandler::RunL()
{
    if ( KErrNone == iStatus.Int() )
    {
        // If the buffe length is zero, it means if we have reached
        // the end of the file.
        if ( iBuffer->Length() == 0)
        {
            iParser->ParseEndL();
            iFile.Close();
            delete iBuffer;
            iBuffer = 0;
        }
           
        // Otherwise, we continue reading the next chunk of the XML file.
        else
        {
            // Parse the next "part" of the XML document.
            iParser->ParseL( *iBuffer );
           
            // Read the next chunk of the file.
            TPtr8 bufferPtr( iBuffer->Des() );
            iFile.Read( bufferPtr, KFileBufferSize, iStatus );
           
            // Don't forget to call this... :)
            SetActive();
        }
    }
    else
    {
        iObserver.OnParseCompleted( iStatus.Int() );
    }
}

// --------------------------------------------------------------------------

void CXmlHandler::ConstructL()
{
    iParser = CParser::NewL( KXmlMimeType, *this );
    iDisplayResult = HBufC8::NewL( KBufferSize );
}

// --------------------------------------------------------------------------
  
  
void CXmlHandler::StartParsingL( const TDesC8& aBody )
{
    iDisplayResult->Des().Zero();
   
    delete iBuffer;
    iBuffer = 0;
    iBuffer = HBufC8::NewL( aBody.Length() );
   
    iBuffer->Des().Copy(aBody);
   
    iParser->ParseBeginL();
    iParser->ParseL( *iBuffer );
   
    iParser->ParseEndL();
}


void CXmlHandler::StartParsingFL( const TDesC& aFileName )
{
    // Read the whole content of aFileName into iBuffer.
    // IMPORTANT: This example reads the whole content within
    // one-shot for simplicity reason.
    // In reality, you have to read it chunk by chunk
    // using active object so that your application doesn't block.
    RFile file;
    User::LeaveIfError( file.Open( CCoeEnv::Static()->FsSession(), aFileName, EFileRead ) );
    CleanupClosePushL( file );
   
    iDisplayResult->Des().Zero();
    TInt size;
    User::LeaveIfError( file.Size( size ) );
    delete iBuffer;
    iBuffer = 0;
    iBuffer = HBufC8::NewL( size );
    TPtr8 bufferPtr( iBuffer->Des() );
    User::LeaveIfError( file.Read( bufferPtr ) );
   
    CleanupStack::PopAndDestroy(); // file
   
    // Now, we have the whole file content in iBuffer.
    // We are ready to parse the XML content.
    iParser->ParseBeginL();
    iParser->ParseL( *iBuffer );
   
    // Since we read the whole file contents within one-shot,
    // we can call ParseEndL() right after calling ParseL().
    iParser->ParseEndL();
}

// --------------------------------------------------------------------------
  
void CXmlHandler::StartParsingWithAoL( const TDesC& aFileName )
{
     // Remember to cancel any outstanding request first.
    if ( IsActive() )
    {
        Cancel();
    }
       
    User::LeaveIfError( iFile.Open( CCoeEnv::Static()->FsSession(), aFileName, EFileRead ) );

    // Create a buffer to store the file content.
    // Note that this method uses active object to read the file.
    // So we have to call SetActive() at the end. Then we call CParser::ParseL()
    // in RunL() method.
    iDisplayResult->Des().Zero();
    delete iBuffer;
    iBuffer = 0;
    iBuffer = HBufC8::NewL( KFileBufferSize );
    TPtr8 bufferPtr( iBuffer->Des() );
    iFile.Read( bufferPtr, KFileBufferSize, iStatus );
    SetActive();

    // Tell the parser that we are about to parse a XML document.   
    iParser->ParseBeginL();
}

// --------------------------------------------------------------------------

void CXmlHandler::OnStartDocumentL( const RDocumentParameters& /*aDocParam*/, TInt aErrorCode )
{
    _LIT8( KOnStartDocumentL, "*** OnStartDocumentL ***/f" );
    AppendText( KOnStartDocumentL );
   
    if ( KErrNone == aErrorCode )
    {
       //可以在这里解析xml头
    }
    else
    {
        iObserver.OnParseCompleted( aErrorCode );
    }
}

 

// --------------------------------------------------------------------------
   
void CXmlHandler::OnEndDocumentL( TInt aErrorCode )
{
    //_LIT8( KOnEndDocumentL, "*** OnEndDocumentL ***/f" );
    //AppendText( KOnEndDocumentL );
   
    if ( KErrNone == aErrorCode )
    {
        // Do something here if needed....
    }
       
    iObserver.OnParseCompleted( aErrorCode );
}

// --------------------------------------------------------------------------

void CXmlHandler::OnStartElementL( const RTagInfo& aElement, const RAttributeArray& aAttributes, TInt aErrorCode )
{
    if ( KErrNone == aErrorCode )
    {
        // If we find the start of an element, we write to the screen,
        // for example: "<tag>"
        //AppendTag( aElement.LocalName().DesC(), EFalse );
        for(TInt i = 0; i<aAttributes.Count(); i++)
        {
            RAttribute ra = aAttributes[i];
            if( ra.Attribute().LocalName().DesC() == _L8("id") 
              || ra.Attribute().LocalName().DesC() == _L8("name") )
            {
                //AppendText(ra.Attribute().LocalName().DesC());
                AppendText(aElement.LocalName().DesC());
                AppendText(_L8(" "));
                AppendText(ra.Value().DesC());
                AppendText(_L8(" "));
            }

        }
        AppendText(_L8("/r/n"));
 
    }
    else
    {
        iObserver.OnParseCompleted( aErrorCode );
    }
}
       
// --------------------------------------------------------------------------

void CXmlHandler::OnEndElementL( const RTagInfo& /*aElement*/, TInt aErrorCode )
{
    if ( KErrNone == aErrorCode )
    {
        // If we find the end of an element, we write it to the screen,
        // for example: "</tag>"
        //AppendTag( aElement.LocalName().DesC(), ETrue );
    }
    else
    {
        iObserver.OnParseCompleted( aErrorCode );
    }
}
   
// --------------------------------------------------------------------------

void CXmlHandler::OnContentL( const TDesC8 &aBytes, TInt aErrorCode )
{
    if ( KErrNone == aErrorCode )
    {
        // Display aBytes on the screen.
        // Before we can display it, we have to convert the content
        // from TDesC8 to TDesC16.
        HBufC8* buffer = HBufC8::NewLC( aBytes.Length() + 1 );
        TPtr8 bufferPtr( buffer->Des() );
        bufferPtr.Copy( aBytes );
        bufferPtr.Trim();
        AppendText( *buffer );
        CleanupStack::PopAndDestroy(); // buffer
    }
    else
    {
        iObserver.OnParseCompleted( aErrorCode );
    }
}
   
// --------------------------------------------------------------------------

void CXmlHandler::OnStartPrefixMappingL( const RString& /*aPrefix*/, const RString& /*aUri*/, TInt aErrorCode )
{
    if ( KErrNone == aErrorCode )
    {
        // Do something here...
       
    }
    else
    {
        iObserver.OnParseCompleted( aErrorCode );
    }
}
       
// --------------------------------------------------------------------------

void CXmlHandler::OnEndPrefixMappingL( const RString& /*aPrefix*/, TInt aErrorCode )
{
    if ( KErrNone == aErrorCode )
    {
        // Do something here...
        //AppendText(aPrefix.DesC());
    }
    else
    {
        iObserver.OnParseCompleted( aErrorCode );
    }
}
   
// --------------------------------------------------------------------------

void CXmlHandler::OnIgnorableWhiteSpaceL( const TDesC8& /*aBytes*/, TInt aErrorCode )
{
    if ( KErrNone == aErrorCode )
    {
        // Do something here...
    }
    else
    {
        iObserver.OnParseCompleted( aErrorCode );
    }
}
   
// --------------------------------------------------------------------------

void CXmlHandler::OnSkippedEntityL( const RString& /*aName*/, TInt aErrorCode )
{
    if ( KErrNone == aErrorCode )
    {
        // Do something here...
    }
    else
    {
        iObserver.OnParseCompleted( aErrorCode );
    }
}

// --------------------------------------------------------------------------

void CXmlHandler::OnProcessingInstructionL( const TDesC8& /*aTarget*/, const TDesC8& /*aData*/, TInt aErrorCode )
{
    if ( KErrNone == aErrorCode )
    {
        // Do something here...
    }
    else
    {
        iObserver.OnParseCompleted( aErrorCode );
    }
}

// --------------------------------------------------------------------------

void CXmlHandler::OnError( TInt aErrorCode )
{
    //_LIT8( KErrorMessage, "*** OnError ***/f" );
    //AppendText( KErrorMessage );
    iObserver.OnParseCompleted( aErrorCode );
}

// --------------------------------------------------------------------------

TAny* CXmlHandler::GetExtendedInterface( const TInt32 /*aUid*/ )
{
    return 0;
}

// --------------------------------------------------------------------------

void CXmlHandler::AppendText( const TDesC8& aText )
{
    TPtr8 displayResultPtr( iDisplayResult->Des() );
    if ( displayResultPtr.Length() + aText.Length() > displayResultPtr.MaxLength() )
    {
        iDisplayResult = iDisplayResult->ReAllocL( displayResultPtr.MaxLength() + KBufferSize );
        displayResultPtr.Set( iDisplayResult->Des() );
    }   
    displayResultPtr.Append( aText );
}

// --------------------------------------------------------------------------

void CXmlHandler::AppendTag( const TDesC8& aTag, TBool aIsClosingTag )
{
    // Instantiate buffer to display tag information.
    HBufC8* buffer = HBufC8::NewLC( aTag.Length() + ( ( aIsClosingTag ) ? KOverheadLen : KOverheadLen - 1 ) );
    TPtr8 bufferPtr( buffer->Des() );
       
    // Convert tag name from TDesC8 to TDesC16.
    bufferPtr.Copy( aTag );
       
    // Add opening tag.
    if ( aIsClosingTag )
    {
        bufferPtr.Insert( 0, KSlash );
    }
    bufferPtr.Insert( 0, KOpeningTag );
       
    // Add closing tag.
    bufferPtr.Append( KClosingTag );
    //bufferPtr.Append( KEndOfLine );
       
    // Add to the result text and then destroy it.
    AppendText( *buffer );
    CleanupStack::PopAndDestroy(); // buffer
}

// End of File

 

 

 

 

 


//CHttpEngine.h

 

#ifndef _CHTTPENGINE_H_
#define _CHTTPENGINE_H_

#include <e32base.h>                // CBase
#include <MHTTPAuthenticationCallback.h>    // MHTTPAuthenticationCallback

#include <MHttpTransactionCallback.h>        // MHTTPTransactionCallback
#include <RHTTPSession.h>            // RHTTPSession
#include <RHTTPTransaction.h>            // RHTTPTransaction

#include <MHttpDataSupplier.h>

#include "NewCommon.h"

class CHTTPFormEncoder;

enum
{
    EMaxUrlLength = 128,
    EMaxNameLength = 32
};

 

//抽象的数据接口, 回调函数
class MHttpEngineObserver
{
  public:
    //返回链接状态
    virtual void ResponseStatusL(TInt aStatusCode, const TDesC8& aStatusText, TNewHeader& newheader) = 0;
   
    //返回数据
    virtual void ResponseReceivedL( const TDesC8& aResponseBuffer) = 0;
    //virtual void ResponseNewStatusL()=0;
};

 

class CHttpEngine : public CBase, MHTTPTransactionCallback, MHTTPDataSupplier
    {
    public:
      static CHttpEngine* NewL(MHttpEngineObserver& aObserver);
      static CHttpEngine* NewLC(MHttpEngineObserver& aObserver);

        ~CHttpEngine();

        void GetRequestL(const TDesC8& aUri);
        void PostRequestL(const TDesC8& aPostUri, const TDesC8& aName);

        // Cancel an outstanding transaction
        void Cancel();

    private: // from MHTTPTransactionCallback
        virtual void MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent);
        virtual TInt MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent);

    private:
        CHttpEngine(MHttpEngineObserver& aObserver);
        void ConstructL();

        void ParseUriL(const TDesC8& aUri);
        void AddHeaderL(RHTTPHeaders aHeaders, TInt aHeaderField, const TDesC8& aHeaderValue);
        void AddHeaderExL(RHTTPHeaders aHeaders, const TDesC8 &aHeaderField, const TDesC8 &aHeaderValue);
        TInt GetHeaderL(RHTTPHeaders aHeaders, const TDesC8 &aHeaderField, THTTPHdrVal &aHeaderValue);
        void DumpRespHeadersL(RHTTPTransaction& aTrans);
    private://from MHTTPDataSupplier
          TBool GetNextDataPart(TPtrC8& aDataPart);
          void ReleaseData();
          TInt OverallDataSize();
          TInt Reset();
         
    private://data
        RHTTPSession          iSession;
        RHTTPTransaction      iTransaction;
        HBufC8*               iPostData;    // Data for HTTP POST
        HBufC8*               iResponseBuffer;

        CHTTPFormEncoder*     iFormEncoder;
       
        MHttpEngineObserver&  iObserver;
    };

#endif //_CHTTPENGINE_H_

 

//CHttpEngine.cpp


#include <chttpformencoder.h>    // CHTTPFormEncoder
#include <httpstringconstants.h>  // HTTP string table
#include <rhttpheaders.h>      // RHTTPHeaders
#include <mhttpdatasupplier.h>    // MHTTPDataSupplier

#include "CHttpEngine.h"

 

// CONSTANTS
// HTTP header values
_LIT8(KUserAgent, "NewEyes(1.0)");  // Name of this client app
_LIT8(KAccept, "*/*");        // Accept any (but only) text content
_LIT8(KPostParamName, "NAME");      // Name of the parameter sent in a POST request
_LIT8(KPostContentType, "text/plain");  // Content type sent in a POST request
_LIT8(KXHost,"X-Online-Host:");
_LIT8(KIP,"222.66.92.54");

 

CHttpEngine* CHttpEngine::NewL(MHttpEngineObserver& aObserver)
{
  CHttpEngine* self = CHttpEngine::NewLC(aObserver);
  CleanupStack::Pop(self);
  return self;
}

 

CHttpEngine* CHttpEngine::NewLC(MHttpEngineObserver& aObserver)
{
  CHttpEngine* self = new (ELeave) CHttpEngine(aObserver);
  CleanupStack::PushL(self);
  self->ConstructL();
  return self;
}

 

CHttpEngine::CHttpEngine(MHttpEngineObserver& aObserver): iObserver(aObserver)
{
}

 

CHttpEngine::~CHttpEngine()
{
  // Close session
  iSession.Close();  // Will also close any open transactions
  delete iResponseBuffer;
  delete iFormEncoder;
  //delete iUri;
}

 

void CHttpEngine::ConstructL()
{
    TRAPD( err, iSession.OpenL() );//创建会话并捕获异常
    if( err != KErrNone ) {
        iFormEncoder = CHTTPFormEncoder::NewL();
        User::Leave( err );
    }
}

 

 


/**
* Override of pure virtual method in MHTTPTransactionCallback.
* Called to report progress by a currently outstanding transaction.
*
* @param aTransaction The transaction reporting progress
* @param aEvent The event being notified
*/
void CHttpEngine::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent)
{
  switch (aEvent.iStatus)
  {
    case THTTPEvent::EGotResponseHeaders:
    {
      // HTTP response headers have been received. Pass status information to observer.
      RHTTPResponse resp = aTransaction.Response();

      TInt statusCode = resp.StatusCode();
     
      RHTTPHeaders headers = resp.GetHeaderCollection();

      TNewHeader aNewHeader;
     
      THTTPHdrVal aHeaderValue;
      GetHeaderL(headers, _L8("Content-Length"), aHeaderValue);
      aNewHeader._data_len = aHeaderValue.Int();
     
      GetHeaderL(headers, _L8("Text-content-length"), aHeaderValue);
     
      RStringPool strP = aTransaction.Session().StringPool();
      RStringF fieldValStr = strP.StringF(aHeaderValue.StrF());
      const TDesC8& fieldValDesC = fieldValStr.DesC();

      TLex8 iLex(fieldValDesC);
      TInt iNum2;
      iLex.Val(iNum2);
     
      aNewHeader._xml_len = iNum2;
     
      fieldValStr.Close();
      //strP.Close();
     
      // Get status text
      RStringF statusStr = resp.StatusText();

      // Inform observer 调用返回链接状态的用户接口
      iObserver.ResponseStatusL(statusCode, statusStr.DesC(), aNewHeader);
      statusStr.Close();
    }
      break;


    case THTTPEvent::EGotResponseBodyData:
    {
      //dataSupplier
      // Get text of response body
      MHTTPDataSupplier* abody = aTransaction.Response().Body();
      TPtrC8 ptr;
      TBool isLast = abody->GetNextDataPart(ptr);

      // Append to iResponseBuffer
      if (!iResponseBuffer)
      {
        iResponseBuffer = ptr.Alloc();
      }
      else
      {
        iResponseBuffer = iResponseBuffer->ReAllocL(iResponseBuffer->Length() + ptr.Length());
        iResponseBuffer->Des().Append(ptr);
      }
     
      // Release the body data
      abody->ReleaseData();
    }
      break;

    case THTTPEvent::EResponseComplete:
    {
      // Pass the response buffer by reference to the observer
      iObserver.ResponseReceivedL(*iResponseBuffer);
      if(iResponseBuffer != NULL)
      {
          delete iResponseBuffer;
          iResponseBuffer = NULL;
      }
       
    }
      break;
    case THTTPEvent::ESucceeded:
    {
    }
      break;

    case THTTPEvent::EFailed:
    {
    }
      break;

    default:
    {
      TBuf8<64> text;
      if (aEvent.iStatus < 0)
      {
        _LIT8(KErrorStr, "Error: %d");
        text.Format(KErrorStr, aEvent.iStatus);
        // Just close the transaction on errors
        aTransaction.Close();
      }
      else
      {
        // Other events are not errors (e.g. permanent and temporary redirections)
        _LIT8(KUnrecognisedEvent, "Unrecognised event: %d");
        text.Format(KUnrecognisedEvent, aEvent.iStatus);
      }
      //iObserver.DataReceived(6, text);
    }
      break;
  }
}

 


TInt CHttpEngine::MHFRunError(TInt aError, RHTTPTransaction /*aTransaction*/, const THTTPEvent& /*aEvent*/)
{
  return aError;
}

 

void CHttpEngine::GetRequestL(const TDesC8& aUri)
{
  TUriParser8 uri;
  uri.Parse(aUri);

  // Create the transaction
  iTransaction = iSession.OpenTransactionL(uri, *this, iSession.StringPool().StringF(HTTP::EGET, RHTTPSession::GetTable()));

  // Set transaction headers
  RHTTPHeaders headers = iTransaction.Request().GetHeaderCollection();
  AddHeaderL(headers, HTTP::EUserAgent, KUserAgent);
  AddHeaderL(headers, HTTP::EAccept, KAccept);
  AddHeaderExL(headers,KXHost,KIP);
  // Submit the request
  iTransaction.SubmitL();
}

 

void CHttpEngine::PostRequestL(const TDesC8& aPostUri, const TDesC8& aBody)
{
  // Build form encoder
  // Start by removing any previous content
  /*
  delete iFormEncoder;
  iFormEncoder = NULL;
  iFormEncoder = CHTTPFormEncoder::NewL();
  TBuf8<EMaxNameLength> buf8;
  buf8.Copy(aName);
  iFormEncoder->AddFieldL(KPostParamName, buf8);
*/
  // Create transaction
  TUriParser8 uri;
  uri.Parse(aPostUri);

 
  delete iPostData;
  iPostData = aBody.AllocL();
 
  iTransaction = iSession.OpenTransactionL(uri, *this, iSession.StringPool().StringF(HTTP::EPOST, RHTTPSession::GetTable()));

  // Set transaction headers
  RHTTPHeaders headers = iTransaction.Request().GetHeaderCollection();
  AddHeaderL(headers, HTTP::EUserAgent, KUserAgent);
  AddHeaderL(headers, HTTP::EAccept, KAccept);
  AddHeaderL(headers, HTTP::EContentType, KPostContentType);
  AddHeaderExL(headers,KXHost,KIP);

  MHTTPDataSupplier* dataSupplier = this;
  iTransaction.Request().SetBody(*dataSupplier);
  // Set the form encoder as the data supplier
  //iTransaction.Request().SetBody(*iFormEncoder);

  // Submit the request
  iTransaction.SubmitL();
}

 

TBool CHttpEngine::GetNextDataPart(TPtrC8& aDataPart)
{

    if(iPostData){
        aDataPart.Set(iPostData->Des());
    }
    return ETrue;
}


void CHttpEngine::ReleaseData()
{
    // It's safe to delete iPostData now.
    delete iPostData;
    iPostData = NULL;
}


TInt CHttpEngine::OverallDataSize()
{
    if(iPostData)
        return iPostData->Length();
    else
        return KErrNotFound ;
}

 


TInt CHttpEngine::Reset()
{
    return KErrNone;
}


TInt CHttpEngine::GetHeaderL(RHTTPHeaders aHeaders, const TDesC8 &aHeaderField, THTTPHdrVal &aHeaderValue)
{
  RStringPool string_pool = iSession.StringPool();
  RStringF contLength = string_pool.OpenFStringL(aHeaderField);
 
  TInt err = aHeaders.GetField(contLength,0,aHeaderValue);

  contLength.Close();
  return err;
}


void CHttpEngine::AddHeaderL(RHTTPHeaders aHeaders, TInt aHeaderField, const TDesC8& aHeaderValue)
{
  RStringPool stringPool = iSession.StringPool();
  RStringF valStr = stringPool.OpenFStringL(aHeaderValue);
  THTTPHdrVal headerVal(valStr);
  aHeaders.SetFieldL(stringPool.StringF(aHeaderField, RHTTPSession::GetTable()), headerVal);
  valStr.Close();
}


void CHttpEngine::AddHeaderExL(RHTTPHeaders aHeaders, const TDesC8 &aHeaderField, const TDesC8 &aHeaderValue)
{
    RStringPool stringPool = iSession.StringPool();
    RStringF valStr = stringPool.OpenFStringL(aHeaderValue);
    THTTPHdrVal headerVal(valStr);
    RStringF sHeaderField = stringPool.OpenFStringL(aHeaderField);
    aHeaders.SetFieldL(sHeaderField, headerVal);
    valStr.Close();
    sHeaderField.Close();
}

/**
* Cancel any outstanding transaction
*/
void CHttpEngine::Cancel()
{
  iTransaction.Cancel();
}

 

 

 

void CHttpEngine::DumpRespHeadersL(RHTTPTransaction& aTrans)
{
    TBuf<64> fieldName16;
    TBuf<128> fieldVal16;
   
    RHTTPResponse resp = aTrans.Response();
    RStringPool strP = aTrans.Session().StringPool();
    RHTTPHeaders hdr = resp.GetHeaderCollection();
    // Get an iterator for the collection of response headers
    THTTPHdrFieldIter it = hdr.Fields();
    while (it.AtEnd() == EFalse)
    {
        // Get name of next header field
        RStringTokenF fieldName = it();
        RStringF fieldNameStr = strP.StringF(fieldName);
        // Get the field value
        THTTPHdrVal fieldVal;
        if (hdr.GetField(fieldNameStr,0,fieldVal) == KErrNone)
        {
            const TDesC8& fieldNameDesC = fieldNameStr.DesC();
            fieldName16.Copy(fieldNameDesC.Left(fieldNameDesC.Length()));
            switch (fieldVal.Type())
            {
                case THTTPHdrVal::KTIntVal:
                    //Printf(_L("%S: %d/n"), &fieldName16, fieldVal.Int());
                    break;
                case THTTPHdrVal::KStrFVal:
                    {
                    RStringF fieldValStr = strP.StringF(fieldVal.StrF());
                    const TDesC8& fieldValDesC = fieldValStr.DesC();
                    fieldVal16.Copy(fieldValDesC.Left(fieldValDesC.Length()));
                    //Printf(_L("%S: %S/n"), &fieldName16, &fieldVal16);
                    }
                    break;
                case THTTPHdrVal::KStrVal:
                    {
                    RString fieldValStr = strP.String(fieldVal.Str());
                    const TDesC8& fieldValDesC = fieldValStr.DesC();
                    fieldVal16.Copy(fieldValDesC.Left(fieldValDesC.Length()));
                    //Printf(_L("%S: %S/n"), &fieldName16, &fieldVal16);
                    }
                    break;
                case THTTPHdrVal::KDateVal:
                    {
                    TDateTime date = fieldVal.DateTime();
                    TBuf<40> dateTimeString;
                    TTime t(date);
                    t.FormatL(dateTimeString,_L("%H:%T:%S on %E, %F%D-%*M-%Y"));
                    //Printf(_L("%S: %S/n"), &fieldName16, &dateTimeString);
                    }
                    break;
                default:
                    //Printf(_L("%S: <unrecognised value type>/n"), &fieldName16);
                    break;
            }
           
           
           
        }
            // Advance the iterator to get the next field
        ++it;
    }
}

 

 

 

 


调用他们的程序需要实现那些虚接口.

/* ====================================================================
 * File: NewEyesAppUi.h
 * Created: 12/14/07
 * Author: Khan.Lau
 * Copyright (c): 2007, All rights reserved
 * ==================================================================== */

#ifndef __NEWEYES_APPUI_H__
#define __NEWEYES_APPUI_H__

#include <aknappui.h>

#include "CHttpEngine.h"
#include "XmlHandler.h"


// Forward reference
class CNewEyesAppView;


class CAknNavigationDecorator;
class CAknTabGroup;
class CHttpEngine;
//class CXmlHandler;

/*!
  @class CNewEyesAppUi
 
  @discussion An instance of class CNewEyesAppUi is the UserInterface part of the AVKON
  application framework for the NewEyes example application
  */
class CNewEyesAppUi : public CAknAppUi,
                      public MHttpEngineObserver,
                      public MXmlHandlerObserver
    {
public:
    void ConstructL();

    CNewEyesAppUi();

 

    ~CNewEyesAppUi();


public: // from CAknAppUi
    void HandleCommandL(TInt aCommand);
   
private://CEikServAppUiBase
    TKeyResponse HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);

private: // from MHttpEngineObserver
    virtual void ResponseStatusL(TInt aStatusCode, const TDesC8& aStatusText, TNewHeader& newheader);
    virtual void ResponseReceivedL(const TDesC8& aResponse);

   
private://MXmlHandlerObserver
    virtual void OnParseCompleted( TInt aError );

private:
    void InitNaviPane();
   
    void ConvUni2Gbk(TDesC& original, TDes8& res) ;

private:
    CNewEyesAppView* iAppView;
    CAknNavigationDecorator *iNaviDecorator;
    CAknTabGroup* iTabGroup;
   
   
    CXmlHandler* iXmlHandler;
   
    CHttpEngine* iEngine;
    TNewHeader iNewheader;
    TInt    iIndex;
    };


#endif // __NEWEYES_APPUI_H__

 

 

 

 

/* ====================================================================
 * File: NewEyesAppUi.cpp
 * Created: 12/14/07
 * Author: Khan.Lau
 * Copyright (c): 2007 All rights reserved
 * ==================================================================== */

#include <avkon.hrh>
#include <aknnotewrappers.h>

#include <aknnavi.h>               // for CAknNavigationControlContainer
#include <eikspane.h>              // for CEikStatusPane
#include <aknnavide.h>             // for CAknNavigationDecorator
#include <akntabgrp.h>             // CAknTabGroup
#include <akntitle.h>

#include <e32base.h>
//#include <utf.h>
#include <charconv.h>

#include "NewEyes.pan"
#include "NewEyesAppUi.h"
#include "NewEyesAppView.h"
#include "NewEyes.hrh"

#include "CFile.h"

 

const TInt KStatusCodeLength = 10;  // Enough room in a descriptor for code + ": "


// ConstructL is called by the application framework
void CNewEyesAppUi::ConstructL()
{
    BaseConstructL();
    iIndex = 0;
   
   
    iEngine = CHttpEngine::NewL(*this);
   
    iXmlHandler = CXmlHandler::NewL( *this );
   
    InitNaviPane();
   
    if(iAppView)
    {
        RemoveFromStack(iAppView);
        delete iAppView;
        iAppView = NULL;
    }
   

    TUid muid;
    muid.iUid = iIndex;
    iAppView = CNewEyesAppView::NewL(ClientRect(), muid);   
    AddToStackL(iAppView);
}

 

CNewEyesAppUi::CNewEyesAppUi()                             
{
    this->iNewheader._data_len = 0;
    this->iNewheader._xml_len = 0;
}

 

CNewEyesAppUi::~CNewEyesAppUi()
{
    delete iNaviDecorator;
    delete iXmlHandler;
    delete iEngine;
}

// handle any menu commands
void CNewEyesAppUi::HandleCommandL(TInt aCommand)
{
    switch(aCommand)
    {
        case EEikCmdExit:
        case EAknSoftkeyExit:
            Exit();
            break;

        case ENewEyesCommand1:
        {
             iEngine->GetRequestL(_L8("http://222.66.92.54:8080/cmcc/phone?c=as"));
        }
            break;

        default:
            Panic(ENewEyesBasicUi);
            break;
    }
}


void CNewEyesAppUi::InitNaviPane()
{
    CEikStatusPane* statusPane = StatusPane();

    CEikStatusPaneBase::TPaneCapabilities subPane = statusPane->PaneCapabilities(TUid::Uid(EEikStatusPaneUidNavi));


    if (subPane.IsPresent() && subPane.IsAppOwned())
    {

        CAknNavigationControlContainer* naviPane =(CAknNavigationControlContainer *) statusPane->ControlL(TUid::Uid(EEikStatusPaneUidNavi));

        delete iNaviDecorator;
        iNaviDecorator = NULL;

        iNaviDecorator = naviPane->CreateTabGroupL();

        iTabGroup = (CAknTabGroup*) iNaviDecorator->DecoratedControl();

        iTabGroup->SetTabFixedWidthL(KTabWidthWithTwoTabs);

        TInt tabId = 0;


        iTabGroup->AddTabL(tabId++, _L("aaaaaaaaa"));
        iTabGroup->AddTabL(tabId++, _L("bbbbbbbbb"));
        iTabGroup->AddTabL(tabId++, _L("ccccccccc"));
       
        iTabGroup->SetActiveTabByIndex(iIndex);
        naviPane->PushL(*iNaviDecorator);
    }
}

 

TKeyResponse CNewEyesAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType){
    if(iTabGroup == NULL){
        return EKeyWasNotConsumed;
    }
    //如果按下的是左方向键或右方向键
    if(aKeyEvent.iCode==EKeyLeftArrow || aKeyEvent.iCode == EKeyRightArrow){
   
        TUid muid;
        muid.iUid = iTabGroup->ActiveTabIndex();
        if(aKeyEvent.iCode==EKeyLeftArrow)
        {
            if(muid.iUid > 0)
            {
                //ActivateLocalViewL(TUid::Uid(ViewId));
                muid.iUid--;
            }
        }
        else
        {
            if(muid.iUid < iTabGroup->TabCount() - 1)
            {
                //ActivateLocalViewL(TUid::Uid(ViewId));
                muid.iUid++;
            }
        }
       
        if(    muid.iUid != iTabGroup->ActiveTabIndex())
        {
            if(iAppView)
            {
                RemoveFromStack(iAppView);
                delete iAppView;
                iAppView = NULL;
            }
            CEikStatusPane* statusPane = StatusPane();
            CAknTitlePane* aTitlePane=(CAknTitlePane*)statusPane->ControlL(TUid::Uid(EEikStatusPaneUidTitle));
           
           
            aTitlePane->SetTextL(_L("453543634") );
            iAppView = CNewEyesAppView::NewL(ClientRect(), muid);   
            AddToStackL(iAppView);
        }
       
        return iTabGroup->OfferKeyEventL(aKeyEvent, aType);
    } else {
        return EKeyWasNotConsumed;
    }
}

 

 

void CNewEyesAppUi::ResponseStatusL(TInt aStatusCode, const TDesC8& aStatusText, TNewHeader& newheader)
{
    iNewheader._data_len = newheader._data_len;
    iNewheader._xml_len = newheader._xml_len;
   
   
    HBufC* buf = HBufC::NewLC(aStatusText.Length() + KStatusCodeLength);
    buf->Des().Format(_L("%d: %S"), aStatusCode, &aStatusText);
    CAknInformationNote* note = new (ELeave) CAknInformationNote;
    note->ExecuteLD(*buf);
    CleanupStack::PopAndDestroy(buf);
}

 

/**
* Callback from engine invoked when the complete response has been received.
*
* @param aResponse Text of the HTTP response
*/
void CNewEyesAppUi::ResponseReceivedL(const TDesC8& aResponse)
{

  if(iNewheader._data_len > 0 && iNewheader._xml_len < iNewheader._data_len)
  {
      HBufC8* buf8 = HBufC8::NewLC(iNewheader._xml_len);
    buf8->Des().Copy(aResponse.Left( iNewheader._xml_len));

    //CFile::LogToFile(_L("c://debug.txt"), (TDes8&)buf8->Des());
    buf8->Des().TrimAll();
    iXmlHandler->StartParsingL(buf8->Des());
    CleanupStack::PopAndDestroy(buf8);
  }

  iNewheader._data_len = 0;
  iNewheader._xml_len = 0;
}


void CNewEyesAppUi::OnParseCompleted( TInt aError )
    {
    if ( KErrNone == aError )
        {
        TPtr8 resultPtr( iXmlHandler->DisplayResult() );
        //iXmlHandlerp->
       
        //HBufC* buffer = HBufC::NewLC(resultPtr.Length());
        //buffer->Des().Copy(resultPtr);
        //iAppView->SetTextL( buffer->Des() );
       
        //CleanupStack::PopAndDestroy(); // buffer
        CFile::LogToFile(_L("c://debug.txt"), resultPtr);
        }
    else
        {
        TBuf8<50> buffer;
        buffer.Append( _L("Error: " ) );
        buffer.AppendNum( aError );
        CFile::LogToFile(_L("c://debug.txt"), (TDes8&)buffer);
        //iAppView->SetTextL( buffer );
        }
    }

 


本例中是将http发过来的文档解析后. 存入log

mmp中需要引入的lib
LIBRARY     aknicon.lib
LIBRARY     fbscli.lib
LIBRARY     eikcoctl.lib
LIBRARY     http.lib
LIBRARY     InetProtUtil.lib    // TUriParser
LIBRARY     bafl.lib            // String pool APIs
LIBRARY     charconv.lib
LIBRARY     efsrv.lib           // Rfs
LIBRARY     xmlframework.lib


以上内容, 转载请注明出处. 本人保留所有权利, 如果对代码有修改, 请在版权信息中注明.


发表于 2007-12-19 14:11 Khan's Notebook 阅读(5407) 评论(13)  编辑 收藏 引用 所属分类: GCC/G++
 
 
评论
# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser[未登录]
大哥,能不能换个背景色,
看着真的很压抑


robin 评论于 2008-01-06 15:21  回复  更多评论   
# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
@robin
嘿嘿. 个人爱好. 你帖到editplus或者vim里面看吧


Khan's Notebook 评论于 2008-04-01 10:41  回复  更多评论   
# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
你好,你的文章很好,但是为什么CHttpEngine文件编译不过,你的LIB文件我都已经包含了。


diyer 评论于 2008-05-10 16:56  回复  更多评论   
# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
@diyer

这个...不清楚你的编程环境.... 也不清楚你的RP.... 仅仅凭借一句编译不过我很难解释的哦....
代码确定没问题的...


思春贴调查员 评论于 2008-05-21 12:08  回复  更多评论   
# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
where is "NewCommon.h"?
ouccomputer 评论于 2008-07-04 17:51  回复  更多评论   


# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
@ouccomputer
NewCommon.h 里没有跟你相关的东西
Khan's Notebook 评论于 2008-07-07 10:21  回复  更多评论   

 
# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
知道了,3q~
ouccomputer 评论于 2008-07-08 12:59  回复  更多评论   


# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
太强悍了。。。小弟佩服佩服。。。
Airon 评论于 2008-07-26 16:37  回复  更多评论   


# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
使用你设计的类如果解析<a>1234</a>Xml文件,在哪个函数或方法中能取得
"1234"的值,谢谢指点,!!!!

在OnStartElementL函数中通过 aElement.LocalName().DesC()取得

tag <a> 但是怎么取得1234那???

缘分天空 评论于 2008-09-14 13:09  回复  更多评论   


# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
@缘分天空
代码实在太久了. 我不太记得了. 你自己查查sdk吧.... 我已经好久不碰symbian了
Khan's Notebook 评论于 2008-09-16 10:22  回复  更多评论   


# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
NewCommon.h文件里是不是这样的啊
struct TNewHeader
{
TInt _data_len;
TInt _xml_len;
};
另外,要增加System includes,包含epoc32/include/http和epoc32/include/ecom
要不然编译不过去啊
Youngmingxin 评论于 2008-10-22 10:31  回复  更多评论  

 
# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
大哥,mobile中的ini怎么用啊,是sdk。现成的API函数都用不了,自己封装的老说是文件报错说2,系统找不到指定的文件。if( (stream = fopen( lpFileName, "r" )) != NULL ) // 根据所指定的路径和名字打开文件

mobile,vs2005中,怎么用ini呢
adler0518 评论于 2008-11-24 15:58  回复  更多评论   

 
# re: 搞定symbian的http 和xml, xml采用sdk自带的cparser
我这段代码就是在wm5下用的
找不到指定文件就说明你路径错了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个关于使用LEX和YACC实现C语言词法和语法分析的基本步骤: 1. 定义词法规则:使用LEX定义C语言的词法规则,包括关键字、操作符、标识符、常量等。 2. 编写语法规则:使用YACC编写C语言的语法规则,包括程序结构、数据类型、表达式、语句等。 3. 链接LEX和YACC:将LEX和YACC生成的词法和语法分析程序进行链接,生成最终的C语言解析器。 4. 测试解析器:编写一些C语言代码,用生成的解析器进行测试,检查是否能正确地解析出代码中的词法和语法错误。 下面是一个简单的示例: 首先,我们需要创建一个名为“cparser”的文件夹,然后在该文件夹中创建三个文件:lex.l、yacc.y和main.c。 在lex.l文件中,我们定义C语言的词法规则,可以包含以下内容: ```c %{ #include "yacc.tab.h" %} %% "auto" { return AUTO; } "break" { return BREAK; } "case" { return CASE; } "char" { return CHAR; } "const" { return CONST; } "continue" { return CONTINUE; } "default" { return DEFAULT; } "do" { return DO; } "double" { return DOUBLE; } "else" { return ELSE; } "enum" { return ENUM; } "extern" { return EXTERN; } "float" { return FLOAT; } "for" { return FOR; } "goto" { return GOTO; } "if" { return IF; } "int" { return INT; } "long" { return LONG; } "register" { return REGISTER; } "return" { return RETURN; } "short" { return SHORT; } "signed" { return SIGNED; } "sizeof" { return SIZEOF; } "static" { return STATIC; } "struct" { return STRUCT; } "switch" { return SWITCH; } "typedef" { return TYPEDEF; } "union" { return UNION; } "unsigned" { return UNSIGNED; } "void" { return VOID; } "volatile" { return VOLATILE; } "while" { return WHILE; } "+" { return PLUS; } "-" { return MINUS; } "*" { return TIMES; } "/" { return DIVIDE; } "=" { return ASSIGN; } "==" { return EQ; } "!=" { return NEQ; } ">" { return GT; } ">=" { return GE; } "<" { return LT; } "<=" { return LE; } "(" { return LPAREN; } ")" { return RPAREN; } "{" { return LBRACE; } "}" { return RBRACE; } ";" { return SEMICOLON; } "," { return COMMA; } %% ``` 在yacc.y文件中,我们定义C语言的语法规则,可以包含以下内容: ```c %{ #include <stdio.h> #include <stdlib.h> void yyerror(const char *msg); int yylex(void); %} %token AUTO BREAK CASE CHAR CONST CONTINUE DEFAULT DO DOUBLE ELSE ENUM EXTERN FLOAT FOR GOTO IF INT LONG REGISTER RETURN SHORT SIGNED SIZEOF STATIC STRUCT SWITCH TYPEDEF UNION UNSIGNED VOID VOLATILE WHILE %token PLUS MINUS TIMES DIVIDE ASSIGN EQ NEQ GT GE LT LE LPAREN RPAREN LBRACE RBRACE SEMICOLON COMMA %token ID NUM %start program %% program: /* empty */ | program external_declaration ; external_declaration: function_definition ; function_definition: type_specifier declarator compound_statement ; type_specifier: INT | VOID ; declarator: ID | LPAREN declarator RPAREN | declarator LBRACE RBRACE | declarator LPAREN parameter_list RPAREN | declarator LPAREN RPAREN ; parameter_list: parameter_declaration | parameter_list COMMA parameter_declaration ; parameter_declaration: type_specifier declarator ; compound_statement: LBRACE RBRACE | LBRACE statement_list RBRACE ; statement_list: statement | statement_list statement ; statement: expression_statement ; expression_statement: expression SEMICOLON ; expression: ID ASSIGN expression | ID | NUM ; %% void yyerror(const char *msg) { fprintf(stderr, "error: %s\n", msg); } int main(int argc, char **argv) { yyparse(); return 0; } ``` 在main.c文件中,我们将使用解析器来读取C语言代码: ```c #include <stdio.h> #include <stdlib.h> void yyerror(const char *msg); int yyparse(void); int main(int argc, char **argv) { yyparse(); return 0; } void yyerror(const char *msg) { fprintf(stderr, "error: %s\n", msg); } ``` 现在,我们可以使用以下命令来编译和运行解析器: ```sh $ lex lex.l $ yacc -d yacc.y $ gcc lex.yy.c yacc.tab.c main.c -o cparser $ ./cparser ``` 输入一些C语言代码,例如: ```c int main() { return 0; } ``` 解析器应该能够正确地解析该代码,不会提示任何错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值