Click here to Skip to main content
12,398,225 members (62,087 online)
Click here to Skip to main content

Stats

68.7K views
1.1K downloads
39 bookmarked
Posted

Parsing XML in C++ using the YARD Parser

, 21 Dec 2004
Provides a set of tools for building XML parsers in C++ using the YARD recursive descent parser.
// released into the public domain 
// by Christopher Diggins 2004 
// http://www.cdiggins.com 

#ifndef REOPS_HPP_INCLUDED
#define REOPS_HPP_INCLUDED 

#include "parser_input_stream.hpp"

namespace yard 
{
  // in order execute semantic actions, this class simply needs to be specialized by the user 
  // for the Rules_T type
  template<typename Iter_T, typename Rules_T> 
  struct Actor {
    static void OnBefore(Iter_T pos) { }
    static void OnSuccess(Iter_T begin, Iter_T end) { }
    static void OnFailure(Iter_T pos) { }
  };      

  // this function attempts to match the pattern, but failing it backs the stream up to before failing 
  template<typename Rules_T, typename Stream_T>
  bool match(Stream_T& stream) {
    // store stream position
    Stream_T::iter_type pos = stream.GetPos();
    // notify of attempt to parse
    Actor<Stream_T::iter_type, Rules_T>::OnBefore(pos);     
    // try to match 
    if (Rules_T::Accept(stream)) { 
      // if successful trigger action ( this either goes to the default implementation at semantic_actions.hpp
      // or it calls a user defined actor ( this is done through specialization )
      Actor<Stream_T::iter_type, Rules_T>::OnSuccess(pos, stream.GetPos()); 
      return true; 
    } 
    // notify of failure parsing
    Actor<Stream_T::iter_type, Rules_T>::OnFailure(stream.GetPos());     
    // restore stream position
    stream.SetPos(pos);    
    return false;  
  };
  
  template<typename T0, typename T1> 
  struct re_or {
    // attempts to match T0, failing that it attempt to match T1
    template<typename Elem_T>
    static bool Accept(ParserInputStream<Elem_T>& stream) {
      return (match<T0>(stream) || match<T1>(stream));
    }
  };

  template<typename T0, typename T1, typename T2> 
  struct re_or3 {
    // attempts to match T0, failing that it attempt to match T1
    template<typename Elem_T>
    static bool Accept(ParserInputStream<Elem_T>& stream) {
      return (match<T0>(stream) || match<T1>(stream) || match<T2>(stream));
    }
  };

  template<typename T0, typename T1> 
  struct re_and {
    // matches T0 then T1 
    template<typename Elem_T>
    static bool Accept(ParserInputStream<Elem_T>& stream) {
      return (match<T0>(stream) && match<T1>(stream));
    }
  };

  template<typename T0, typename T1, typename T2> 
  struct re_and3 {
    // matches T0 then T1 
    template<typename Elem_T>
    static bool Accept(ParserInputStream<Elem_T>& stream) {
      return (match<T0>(stream) && match<T1>(stream) && match<T2>(stream));
    }
  };
  
  template<typename T> 
  struct re_star {
    // matches 0 or more times the pattern represented by T 
    template<typename Elem_T>
    static bool Accept(ParserInputStream<Elem_T>& stream) {
      while (match<T>(stream)) 
      { }
      return true;                 
    }
  };

  template<typename T> 
  struct re_plus {
    // matches 1 or more times the pattern represented by T 
    template<typename Elem_T>
    static bool Accept(ParserInputStream<Elem_T>& stream) {
      if (match<T>(stream)) { 
        while (match<T>(stream))
        { } 
        return true;                 
      }
      else {
        return false;
      }
    }
  };

  template<typename T> 
  struct re_opt {
    // matches 0 or 1 times the pattern represented by T
    template<typename Elem_T>
    static bool Accept(ParserInputStream<Elem_T>& stream) {
      match<T>(stream); 
      return true;                 
    }
  };

  template<typename T, unsigned int N> 
  struct re_repeat {
    // matches exactly N times the pattern represented by T
    template<typename Elem_T>
    static bool Accept(ParserInputStream<Elem_T>& stream) {
      for (int i=0; i < N; ++i) {
        if (!match<T>(stream)) {
          return false;
        }
      }
      return true;                 
    }
  };
  
  template<typename T>
  struct re_until {
    template<typename Elem_T>
    static bool Accept(ParserInputStream<Elem_T>& stream) {
      if (stream.AtEnd()) return false;
      while (!match<T>(stream)) {
        if (stream.AtEnd()) return false;
        stream.GotoNext();
      }
      return true;                 
    }
  };
}

#endif // #ifndef REOPS_HPP_INCLUDED

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Christopher Diggins
Software Developer Autodesk
Canada Canada
This article was written by Christopher Diggins, a computer science nerd who currently works at Autodesk as an SDK specialist.

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160721.1 | Last Updated 21 Dec 2004
Article Copyright 2004 by Christopher Diggins
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid