From: <bl...@us...> - 2003-05-04 18:19:30
|
Update of /cvsroot/cpptool/rfta/include/xtl In directory sc8-pr-cvs1:/tmp/cvs-serv31091/include/xtl Added Files: MiniParser.h Log Message: * experimenting with implementation of a simplistic parser framework (akin to Boost.Spirit, but much more simple). Still need to devise how matched parts are returned... --- NEW FILE: MiniParser.h --- #ifndef XTL_MINIPARSER_H_INCLUDED #define XTL_MINIPARSER_H_INCLUDED #include <xtl/CStringView.h> #include <stdexcept> namespace Xtl { template<typename LeftParserType ,typename RightParserType> class SequenceMiniParser; template<typename ParserType> class OptionalMiniParser; template<typename LeftParserType ,typename RightParserType> class AlternativeMiniParser; class Scanner { public: typedef const char *Iterator; explicit Scanner( const Xtl::CStringView &content ) : start_( content.getStart() ) , end_( content.getEnd() ) , current_( start_ ) { } Scanner( const char *first, const char *last ) : start_( first ) , end_( last ) , current_( start_ ) { } bool hasNext() const { return current_ != end_; } bool isAtEnd() const { return current_ == end_; } char operator *() const { #ifndef NDEBUG if ( isAtEnd() ) throw std::logic_error( "Scanner::operator *() called at end of content." ); #endif return *current_; } Scanner &operator ++() { #ifndef NDEBUG if ( isAtEnd() ) throw std::logic_error( "Scanner::operator ++() called at end of content." ); #endif ++current_; return *this; } Scanner::Iterator current() const { return current_; } void backtrack( Scanner::Iterator rollback ) { current_ = rollback; } private: const Iterator start_; const Iterator end_; Iterator current_; }; struct ParseResult { ParseResult() : matched_( false ) { } ParseResult( Scanner::Iterator start, Scanner::Iterator end ) : matched_( true ) , matchStart_( start ) , matchEnd_( end ) { } bool matched_; Scanner::Iterator matchStart_; Scanner::Iterator matchEnd_; }; struct MandatoryMiniParserCategory { enum { isOptional = false }; }; struct OptionalMiniParserCategory { enum { isOptional = true }; }; class MiniParser { public: typedef MandatoryMiniParserCategory Category; virtual ParseResult parse( Scanner &scanner ) const = 0; ParseResult noMatch() const { return ParseResult(); } ParseResult matched( Scanner::Iterator start, const Scanner &scanner ) const { return ParseResult( start, scanner.current() ); } ParseResult concatResult( const ParseResult &left, const ParseResult &right ) const { return ParseResult( left.matchStart_, right.matchEnd_ ); } ParseResult emptyMatch( Scanner::Iterator start ) const { return ParseResult( start, start ); } }; template<typename DerivedParserType> class MiniParserBase : public MiniParser { public: template<typename RightParserType> SequenceMiniParser<DerivedParserType,RightParserType> operator >>( const RightParserType &parser) const { return makeSequenceParser( static_cast<const DerivedParserType &>(*this), parser ); } template<typename RightParserType> AlternativeMiniParser<DerivedParserType,RightParserType> operator |( const RightParserType &parser) const { return makeAlternativeParser( static_cast<const DerivedParserType &>(*this), parser ); } OptionalMiniParser<DerivedParserType> operator !() const { return makeOptionalParser( static_cast<const DerivedParserType &>(*this) ); } }; class CharMiniParser : public MiniParserBase<CharMiniParser> { public: CharMiniParser( char ch ) : ch_( ch ) { } ParseResult parse( Scanner &scanner ) const { if ( scanner.hasNext() ) { if ( *scanner == ch_ ) { Scanner::Iterator start = scanner.current(); ++scanner; return matched( start, scanner ); } } return noMatch(); } private: char ch_; }; class StringMiniParser : public MiniParserBase<StringMiniParser> { public: StringMiniParser( const std::string &text ) : text_( text ) , first_( text_.c_str() ) , last_( text_.c_str() + text_.length() ) { } ParseResult parse( Scanner &scanner ) const { Scanner::Iterator start = scanner.current(); const char *str = first_; while ( str != last_ ) { if ( scanner.isAtEnd() || *scanner != *str ) return noMatch(); ++str; ++scanner; } return matched( start, scanner ); } private: std::string text_; const char *first_; const char *last_; }; struct CppIdentifierTraits { inline static bool isIdentifierFirstLetter( char letter ) { return (letter >= 'a' && letter <= 'z' ) || (letter >= 'A' && letter <= 'Z' ) || letter == '_'; } inline static bool isIdentifierLetter( char letter ) { return (letter >= 'a' && letter <= 'z' ) || (letter >= 'A' && letter <= 'Z' ) || (letter >= '0' && letter <= '9' ) || letter == '_'; } }; struct MacroIdentifierTraits { inline static bool isIdentifierFirstLetter( char letter ) { return (letter >= 'A' && letter <= 'Z' ) || letter == '_'; } inline static bool isIdentifierLetter( char letter ) { return (letter >= 'A' && letter <= 'Z' ) || (letter >= '0' && letter <= '9' ) || letter == '_'; } }; template<typename IdentifierTraits> class IdentifierMiniParser : public MiniParserBase< IdentifierMiniParser<IdentifierTraits> > { public: ParseResult parse( Scanner &scanner ) const { Scanner::Iterator start = scanner.current(); if ( scanner.hasNext() && IdentifierTraits::isIdentifierFirstLetter( *scanner ) ) { ++scanner; while ( scanner.hasNext() && IdentifierTraits::isIdentifierLetter( *scanner ) ) ++scanner; return matched( start, scanner ); } return noMatch(); } }; typedef IdentifierMiniParser<CppIdentifierTraits> CppIdentifierMiniParser; typedef IdentifierMiniParser<MacroIdentifierTraits> MacroIdentifierMiniParser; template<typename ParserType ,typename DerivedParserType> class UnaryMiniParser : public MiniParserBase<DerivedParserType> { public: typedef ParserType Parser; UnaryMiniParser( const Parser &parser ) : parser_( parser ) { } protected: Parser parser_; }; template<typename LeftParserType ,typename RightParserType ,typename DerivedParserType> class BinaryMiniParser : public MiniParserBase<DerivedParserType> { public: typedef LeftParserType LeftParser; typedef RightParserType RightParser; BinaryMiniParser( const LeftParser &left, const RightParser &right ) : leftParser_( left ) , rightParser_( right ) { } protected: LeftParser leftParser_; RightParser rightParser_; }; template<typename LeftParserType ,typename RightParserType> class SequenceMiniParser : public BinaryMiniParser<LeftParserType ,RightParserType ,SequenceMiniParser<LeftParserType ,RightParserType> > { public: typedef BinaryMiniParser<LeftParserType ,RightParserType ,SequenceMiniParser<LeftParserType ,RightParserType> > SuperClass; SequenceMiniParser( const LeftParser &left, const RightParser &right ) : SuperClass( left, right ) { } ParseResult parse( Scanner &scanner ) const { ParseResult leftResult = leftParser_.parse( scanner ); if ( leftResult.matched_ ) { ParseResult rightResult = rightParser_.parse( scanner ); if ( rightResult.matched_ ) return concatResult( leftResult, rightResult ); } return noMatch(); } }; template<typename LeftParserType ,typename RightParserType> SequenceMiniParser<LeftParserType,RightParserType> makeSequenceParser( const LeftParserType &left, const RightParserType &right ) { return SequenceMiniParser<LeftParserType,RightParserType>( left, right ); } template<typename ParserType> class OptionalMiniParser : public UnaryMiniParser<ParserType ,OptionalMiniParser<ParserType> > { public: typedef UnaryMiniParser<ParserType,OptionalMiniParser<ParserType> > SuperClass; typedef OptionalMiniParserCategory Category; OptionalMiniParser( const ParserType &parser ) : SuperClass( parser ) { } ParseResult parse( Scanner &scanner ) const { Scanner::Iterator rollback = scanner.current(); ParseResult result = parser_.parse( scanner ); if ( result.matched_ ) return result; scanner.backtrack( rollback ); return emptyMatch( rollback ); } }; template<typename ParserType> OptionalMiniParser<ParserType> makeOptionalParser( const ParserType &parser ) { return OptionalMiniParser<ParserType>( parser ); } template<typename LeftParserType ,typename RightParserType> class AlternativeMiniParser : public BinaryMiniParser<LeftParserType ,RightParserType ,AlternativeMiniParser<LeftParserType ,RightParserType> > { public: typedef BinaryMiniParser<LeftParserType ,RightParserType ,AlternativeMiniParser<LeftParserType ,RightParserType> > SuperClass; AlternativeMiniParser( const LeftParser &left, const RightParser &right ) : SuperClass( left, right ) { } ParseResult parse( Scanner &scanner ) const { Scanner::Iterator initial = scanner.current(); ParseResult leftResult = leftParser_.parse( scanner ); if ( leftResult.matched_ ) return leftResult; scanner.backtrack( initial ); return rightParser_.parse( scanner ); } }; template<typename LeftParserType ,typename RightParserType> AlternativeMiniParser<LeftParserType,RightParserType> makeAlternativeParser( const LeftParserType &left, const RightParserType &right ) { return AlternativeMiniParser<LeftParserType,RightParserType>( left, right ); } } // namespace Xtl #endif // XTL_MINIPARSER_H_INCLUDED |