#ifndef __JLANG__JCPPFACET__ #define __JLANG__JCPPFACET__ #include #include #include #include #include #include #include "JLang/JStringFacet.hh" /** * \author mdejong */ namespace JLANG {} namespace JPP { using namespace JLANG; } namespace JLANG { /** * Facet class to specify parsing of a C[++] variable name. */ class JCppFacet: public JStringFacet { public: /** * Constructor. */ JCppFacet() {} /** * Clone this facet. * * \return pointer to newly created facet */ virtual JCppFacet* clone() const override { return new JCppFacet(); } static inline bool is_eol (const char c) { return c == ';'; } static inline bool is_begin_single_line_comment(const char c1, const char c2) { return c1 == '/' && c2 == '/'; } static inline bool is_begin_multi_line_comment (const char c1, const char c2) { return c1 == '/' && c2 == '*'; } static inline bool is_end_single_line_comment (const char c1) { return c1 == '\n'; } static inline bool is_end_multi_line_comment (const char c1, const char c2) { return c1 == '*' && c2 == '/'; } /** * Get string. * * \param __begin begin position of input stream * \param __end end position of input stream * \param format format * \param result status after input operation * \param buffer output string * \return position of input stream */ istreambuf_iterator get(const istreambuf_iterator __begin, const istreambuf_iterator __end, const std::ios_base& format, std::ios_base::iostate& result, std::string& buffer) const { return do_get(__begin, __end, format, result, buffer); } /** * Put string. * * \param out begin position of output stream * \param format format * \param c fill character * \param buffer input string * \return position of output stream buffer */ ostreambuf_iterator put(ostreambuf_iterator out, const std::ios_base& format, const char c, const std::string& buffer) const { return do_put(out, format, c, buffer); } protected: /** * Get string. * * \param __begin begin position of input stream * \param __end end position of input stream * \param format format * \param result status after input operation * \param buffer output string * \return position of input stream */ virtual istreambuf_iterator do_get(const istreambuf_iterator __begin, const istreambuf_iterator __end, const std::ios_base& format, std::ios_base::iostate& result, std::string& buffer) const override { using namespace std; result = (ios_base::iostate) 0; // reset I/O status streamsize n = format.width(); // number of characters to read if (n == 0) { n = numeric_limits::max(); } istreambuf_iterator i = __begin; if (i == __end || (i = do_ignore(i, __end)) == __end) { result |= ios_base::failbit; result |= ios_base::eofbit; } else { char c = *i; for (++i; i != __end; c = *i, ++i) { // skip comment line(s) if (is_begin_single_line_comment(c,*i)) i = do_ignore_single_line_comment(i, __end); else if (is_begin_multi_line_comment (c,*i)) i = do_ignore_multi_line_comment (i, __end); else if (c == '_' || isalpha(c)) // first character must be letter or underscore break; i = do_ignore(i, __end); } if (i == __end) { result |= ios_base::failbit; result |= ios_base::eofbit; } else { buffer.clear(); buffer.push_back(c); for (--n; i != __end && n != 0 && (*i == '_' || isalnum(*i)); // following characters may also be digits ++i, --n) { buffer.push_back(*i); } if (i == __end) { result |= ios_base::eofbit; } } } return i; } /** * Put string. * * \param out begin position of output stream * \param format format * \param c fill character * \param buffer input string * \return current position of output stream */ virtual ostreambuf_iterator do_put(ostreambuf_iterator out, const std::ios_base& format, const char c, const std::string& buffer) const override { using namespace std; if (format.flags() & ios_base::right) { for (streamsize i = buffer.size(); i < format.width(); ++i, ++out) { *out = c; } } for (string::const_iterator i = buffer.begin(); i != buffer.end(); ++i, ++out) { *out = *i; } if (format.flags() & ios_base::left) { for (streamsize i = buffer.size(); i < format.width(); ++i, ++out) { *out = c; } } return out; } /** * Ignore white space and end of line characters. * * \param __begin begin position of input stream * \param __end end position of input stream * \return position of input stream */ virtual istreambuf_iterator do_ignore(const istreambuf_iterator __begin, const istreambuf_iterator __end) const override { istreambuf_iterator i = __begin; while (i != __end && (isspace(*i) || is_eol(*i))) { ++i; } return i; } /** * Ignore characters until end of line. * * \param __begin begin position of input stream * \param __end end position of input stream * \return position of input stream */ virtual istreambuf_iterator do_ignore_single_line_comment(const istreambuf_iterator __begin, const istreambuf_iterator __end) const { istreambuf_iterator i = __begin; for ( ; i != __end && !is_end_single_line_comment(*i); ++i) {} if (i != __end) { ++i; // skip end of line } return i; } /** * Ignore characters until next end of comment. * * \param __begin begin position of input stream * \param __end end position of input stream * \return position of input stream */ virtual istreambuf_iterator do_ignore_multi_line_comment(const istreambuf_iterator __begin, const istreambuf_iterator __end) const { istreambuf_iterator i = __begin; if (i != __end) { char c = *i; for (++i; i != __end && !is_end_multi_line_comment(c,*i); c = *i, ++i) {} if (i != __end) { ++i; // skip end of line } } return i; } private: JCppFacet(const JCppFacet&); // not defined void operator=(const JCppFacet&); // not defined }; } #endif