Click here to Skip to main content
15,885,869 members
Articles / Programming Languages / C++

Parsing XML in C++ using the YARD Parser

Rate me:
Please Sign up or sign in to vote.
4.79/5 (23 votes)
21 Dec 20046 min read 87.2K   1.2K   39  
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


Written By
Software Developer Ara 3D
Canada Canada
I am the designer of the Plato programming language and I am the founder of Ara 3D. I can be reached via email at cdiggins@gmail.com

Comments and Discussions