/* * A push-model scanner example for re2c -f * Written Mon Apr 11 2005 by mgix@mgix.com * This file is in the public domain. * */ // ---------------------------------------------------------------------- #include #include #include #include #include #if defined(WIN32) typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #else #include #include #ifndef O_BINARY #define O_BINARY 0 #endif #endif // ---------------------------------------------------------------------- #define TOKENS \ \ TOK(kEOF) \ TOK(kEOL) \ TOK(kUnknown) \ TOK(kIdentifier) \ TOK(kDecimalConstant) \ \ TOK(kEqual) \ TOK(kLeftParen) \ TOK(kRightParen) \ TOK(kMinus) \ TOK(kPlus) \ TOK(kStar) \ TOK(kSlash) \ \ TOK(kIf) \ TOK(kFor) \ TOK(kElse) \ TOK(kGoto) \ TOK(kBreak) \ TOK(kWhile) \ TOK(kReturn) \ // ---------------------------------------------------------------------- static const char *tokenNames[] = { #define TOK(x) #x, TOKENS #undef TOK }; // ---------------------------------------------------------------------- class PushScanner { public: enum Token { #define TOK(x) x, TOKENS #undef TOK }; private: bool eof; int32_t state; uint8_t *limit; uint8_t *start; uint8_t *cursor; uint8_t *marker; uint8_t *buffer; uint8_t *bufferEnd; uint8_t yych; uint32_t yyaccept; public: // ---------------------------------------------------------------------- PushScanner() { limit = 0; start = 0; state = -1; cursor = 0; marker = 0; buffer = 0; eof = false; bufferEnd = 0; } // ---------------------------------------------------------------------- ~PushScanner() { } // ---------------------------------------------------------------------- void send( Token token ) { size_t tokenSize = cursor-start; const char *tokenName = tokenNames[token]; printf( "scanner is pushing out a token of type %d (%s)", token, tokenName ); if(token==kEOF) putchar('\n'); else { size_t tokenNameSize = strlen(tokenNames[token]); size_t padSize = 20-(20"); fwrite( start, tokenSize, 1, stdout ); printf("<----\n"); } } // ---------------------------------------------------------------------- uint32_t push( const void *input, ssize_t inputSize ) { printf( "scanner is receiving a new data batch of length %d\n" "scanner continues with saved state = %d\n", inputSize, state ); /* * Data source is signaling end of file when batch size * is less than maxFill. This is slightly annoying because * maxFill is a value that can only be known after re2c does * its thing. Practically though, maxFill is never bigger than * the longest keyword, so given our grammar, 32 is a safe bet. */ uint8_t null[64]; const ssize_t maxFill = 32; if(inputSize