|
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
|