TokenPtr Scanner::ScanNumber() { if (!std::isdigit(UChr())) Error("expected digit"); /* Take first number (literals like ".0" are not allowed) */ std::string spell; const auto startChr = TakeIt(); spell += startChr; /* Parse integer or floating-point number */ auto type = Token::Types::IntLiteral; ScanDecimalLiteral(spell); if (Is('.')) { spell += TakeIt(); if (std::isdigit(UChr())) ScanDecimalLiteral(spell); else Error("floating-point literals must have a decimal on both sides of the dot (e.g. '0.0' but not '0.' or '.0')"); type = Token::Types::FloatLiteral; } if (std::isalpha(UChr()) || Is('.')) ErrorLetterInNumber(); /* Create number token */ return Make(type, spell); }
TokenPtr SLScanner::ScanIdentifier() { /* Scan identifier string */ std::string spell; spell += TakeIt(); while (std::isalnum(UChr()) || Is('_')) spell += TakeIt(); /* Scan identifier or keyword */ return ScanIdentifierOrKeyword(std::move(spell)); }
void Scanner::ErrorUnexpected(char expectedChar) { auto chr = TakeIt(); if (chr != 0 && chr != '\n') Error("invalid character '" + std::string(1, chr) + "' (expected '" + std::string(1, expectedChar) + "')"); else ErrorEOF(); }
TokenPtr Scanner::ScanIdentifier() { /* Scan identifier string */ std::string spell; spell += TakeIt(); while (std::isalnum(UChr()) || Is('_')) spell += TakeIt(); /* Scan reserved words */ if (spell == "mod") return Make(Token::Types::DivOp, spell); if (spell == "sum" || spell == "product") return Make(Token::Types::FoldFunc, spell); /* Return as identifier */ return Make(Token::Types::Ident, spell); }
TokenPtr Scanner::ScanShiftOperator(const char chr) { std::string spell; spell += TakeIt(); spell += Take(chr); return Make(Token::Types::ShiftOp, spell); }
TokenPtr Scanner::Make(const Token::Types& type, bool takeChr) { if (takeChr) { std::string spell; spell += TakeIt(); return std::make_shared<Token>(Pos(), type, std::move(spell)); } return std::make_shared<Token>(Pos(), type); }
HBITMAP CPlayGif::NextImage(void) { if(m_pcGif==NULL)return 0; l1: if(m_iTotalReadByte>m_iGifSize){m_pcGifTrack=m_pcGif;m_iTotalReadByte=0;return 0;} m_iTotalReadByte++; switch(*m_pcGifTrack++) { case 0x2C: return TakeIt(); break; case 0x21: BYTE cSize; m_iTotalReadByte++; switch(*m_pcGifTrack++) { case 0xF9: m_pcGifTrack++; m_iDisposalMethod=(*m_pcGifTrack)&28; m_bTransparentIndex=(*m_pcGifTrack++)&1; m_iDelayTime=*(WORD*)m_pcGifTrack; m_pcGifTrack+=2; m_iTransparentIndex=*m_pcGifTrack++; m_iTotalReadByte+=5; break; case 0xFE: while((cSize=*m_pcGifTrack)!=0){m_pcGifTrack+=cSize+1;m_iTotalReadByte+=cSize+1;if(m_iTotalReadByte>m_iGifSize)return 0;} break; case 0x01: m_pcGifTrack+=13; m_iTotalReadByte+=13; while((cSize=*m_pcGifTrack)!=0){m_pcGifTrack+=cSize+1;m_iTotalReadByte+=cSize+1;if(m_iTotalReadByte>m_iGifSize)return 0;} break; case 0xFF: m_pcGifTrack+=12; m_iTotalReadByte+=12; while((cSize=*m_pcGifTrack)!=0){m_pcGifTrack+=cSize+1;m_iTotalReadByte+=cSize+1;if(m_iTotalReadByte>m_iGifSize)return 0;} break; default: return FALSE; } m_pcGifTrack++; m_iTotalReadByte++; if(m_iTotalReadByte>m_iGifSize)return 0; goto l1; break; case 0x3B: m_pcGifTrack=m_pcGif; m_iTotalReadByte=0; goto l1; case 0: goto l1; default: return FALSE; } }
TokenPtr SLScanner::ScanAssignShiftRelationOp(const char chr) { std::string spell; spell += TakeIt(); if (Is(chr)) { spell += TakeIt(); if (Is('=')) return Make(Tokens::AssignOp, spell, true); return Make(Tokens::BinaryOp, spell); } if (Is('=')) spell += TakeIt(); return Make(Tokens::BinaryOp, spell); }
TokenPtr SLScanner::ScanMinusOp() { std::string spell; spell += TakeIt(); if (Is('-')) return Make(Tokens::UnaryOp, spell, true); else if (Is('=')) return Make(Tokens::AssignOp, spell, true); return Make(Tokens::BinaryOp, spell); }
bool Scanner::Scan(const std::shared_ptr<ExprStream>& stream) { if (stream && stream->IsValid()) { /* Store source stream and take first character */ stream_ = stream; TakeIt(); succeeded_ = true; return true; } succeeded_ = false; return false; }
TokenPtr SLScanner::ScanDirective() { std::string spell; /* Take directive begin '#' */ Take('#'); /* Ignore white spaces (but not new-lines) */ IgnoreWhiteSpaces(false); /* Scan identifier string */ StoreStartPos(); while (std::isalpha(UChr())) spell += TakeIt(); /* Return as identifier */ return Make(Token::Types::Directive, spell); }
TokenPtr Scanner::Make(const Token::Types& type, std::string& spell, const StreamPosition& pos, bool takeChr) { if (takeChr) spell += TakeIt(); return std::make_shared<Token>(pos, type, std::move(spell)); }
TokenPtr SLScanner::ScanToken() { std::string spell; /* Scan directive (beginning with '#') */ if (Is('#')) return ScanDirective(); /* Scan identifier */ if (std::isalpha(UChr()) || Is('_')) return ScanIdentifier(); /* Scan number */ if (Is('.')) return ScanNumberOrDot(); if (std::isdigit(UChr())) return ScanNumber(); /* Scan string literal */ if (Is('\"')) return ScanStringLiteral(); /* Scan operators */ if (Is('=')) { spell += TakeIt(); if (Is('=')) return Make(Tokens::BinaryOp, spell, true); return Make(Tokens::AssignOp, spell); } if (Is('~')) return Make(Tokens::UnaryOp, spell, true); if (Is('!')) { spell += TakeIt(); if (Is('=')) return Make(Tokens::BinaryOp, spell, true); return Make(Tokens::UnaryOp, spell); } if (Is('%')) { spell += TakeIt(); if (Is('=')) return Make(Tokens::AssignOp, spell, true); return Make(Tokens::BinaryOp, spell); } if (Is('*')) { spell += TakeIt(); if (Is('=')) return Make(Tokens::AssignOp, spell, true); return Make(Tokens::BinaryOp, spell); } if (Is('^')) { spell += TakeIt(); if (Is('=')) return Make(Tokens::AssignOp, spell, true); return Make(Tokens::BinaryOp, spell); } if (Is('+')) return ScanPlusOp(); if (Is('-')) return ScanMinusOp(); if (Is('<') || Is('>')) return ScanAssignShiftRelationOp(Chr()); if (Is('&')) { spell += TakeIt(); if (Is('=')) return Make(Tokens::AssignOp, spell, true); if (Is('&')) return Make(Tokens::BinaryOp, spell, true); return Make(Tokens::BinaryOp, spell); } if (Is('|')) { spell += TakeIt(); if (Is('=')) return Make(Tokens::AssignOp, spell, true); if (Is('|')) return Make(Tokens::BinaryOp, spell, true); return Make(Tokens::BinaryOp, spell); } if (Is(':')) { spell += TakeIt(); if (Is(':')) return Make(Tokens::DColon, spell, true); return Make(Tokens::Colon, spell); } /* Scan punctuation, special characters and brackets */ switch (Chr()) { case ';': return Make(Tokens::Semicolon, true); break; case ',': return Make(Tokens::Comma, true); break; case '?': return Make(Tokens::TernaryOp, true); break; case '(': return Make(Tokens::LBracket, true); break; case ')': return Make(Tokens::RBracket, true); break; case '{': return Make(Tokens::LCurly, true); break; case '}': return Make(Tokens::RCurly, true); break; case '[': return Make(Tokens::LParen, true); break; case ']': return Make(Tokens::RParen, true); break; } ErrorUnexpected(); return nullptr; }
char Scanner::Take(char chr) { if (chr_ != chr) ErrorUnexpected(chr); return TakeIt(); }
void Scanner::ScanDecimalLiteral(std::string& spell) { while (std::isdigit(UChr())) spell += TakeIt(); }
/* ------------------------------------------------------------------------------------ */ bool CAnimGif::GetImage(bool repeat) { if(!pcGif) return false; l1: if(TotalReadByte > GifSize) { pcGifTrack = pcGif; TotalReadByte = 0; return false; } TotalReadByte++; switch(*pcGifTrack++) { case 0x2C: return TakeIt(); break; case 0x21: BYTE cSize; TotalReadByte++; switch(*pcGifTrack++) { case 0xF9: pcGifTrack++;//block size DisposalMethod = (*pcGifTrack)&28; bTransparentIndex = (*pcGifTrack++)&1; DelayTime = *(WORD*)pcGifTrack; pcGifTrack += 2; TransparentIndex = *pcGifTrack++; TotalReadByte += 5; break; case 0xFE: while((cSize = *pcGifTrack) != 0) { pcGifTrack += cSize+1; TotalReadByte += cSize+1; if(TotalReadByte > GifSize) return false; } break; case 0x01: pcGifTrack += 13; TotalReadByte += 13; while((cSize = *pcGifTrack) != 0) { pcGifTrack += cSize+1; TotalReadByte += cSize+1; if(TotalReadByte > GifSize) return false; } break; case 0xFF: pcGifTrack += 12; TotalReadByte += 12; while((cSize = *pcGifTrack) != 0) { pcGifTrack += cSize+1; TotalReadByte += cSize+1; if(TotalReadByte > GifSize) return false; } break; default: return false; } pcGifTrack++; TotalReadByte++; if(TotalReadByte > GifSize) return false; goto l1; break; case 0x3B: pcGifTrack = pcGif; TotalReadByte = 0; return false; case 0: pcGifTrack = pcGif; TotalReadByte = 0; return false; default: return false; } }
void Scanner::Ignore(const std::function<bool (char)>& pred) { while (pred(chr_)) TakeIt(); }