static Lexem ParseNumericConstant( const std::string& file_data, std::string::const_iterator& it ) { Lexem result; result.file_position= it - file_data.begin(); // Hex if( *it == '0' && (it+1) < file_data.end() && *(it+1) == 'x' ) { if( it+2 == file_data.end() || !IsHexDigit(*it) ) throw LexicalError( it - file_data.begin() ); result.text+= "0x"; it+= 2; while( it != file_data.end() && IsHexDigit(*it) ) { result.text+= *it; it++; } } else while( it != file_data.end() && isdigit(*it) ) { result.text+= *it; it++; } if( it != file_data.end() && isalpha(*it) ) throw LexicalError( it - file_data.begin() ); result.type= Lexem::Type::NumericConstant; return result; }
static BinaryOperationsChain ParseBinaryOperatorsChain( const Lexems& lexems, Lexems::const_iterator& it ) { BinaryOperationsChain result; while( it < lexems.end() ) { BinaryOperationsChain::ComponentWithOperator comp; switch (it->type) { case Lexem::Type::Identifier: case Lexem::Type::Scope: { std::unique_ptr<BinaryOperationsChain::Variable> var( new BinaryOperationsChain::Variable ); var->name= ParseCombinedName( lexems, it ); comp.component= std::move(var); } break; case Lexem::Type::BracketLeft: { it++; if( it == lexems.end()) throw LexicalError(lexems.back().file_position); std::unique_ptr<BinaryOperationsChain::BracketExpression> subexpr( new BinaryOperationsChain::BracketExpression ); subexpr->subexpression.reset( new BinaryOperationsChain(ParseBinaryOperatorsChain( lexems, it )) ); comp.component= std::move(subexpr); if( it->type != Lexem::Type::BracketRight ) throw LexicalError( it->file_position); it++; } break; case Lexem::Type::NumericConstant: { std::unique_ptr<BinaryOperationsChain::NumericConstant> num( new BinaryOperationsChain::NumericConstant ); num->value= it->text; it++; comp.component= std::move(num); } break; default: goto end; }; BinaryOperationsChain::Operator op= ParseBinaryOperator( it ); comp.op= op; result.components.push_back(std::move(comp)); if( op == BinaryOperationsChain::Operator::NoOperator ) break; } end:; return result; }
Token Source::read_chars(size_t number, bool escape) { Info start = this->get_info(); std::string s; char c; while(s.size() < number && ! this->eof()) { c = this->current(); if(escape && c == string::ESCAPE) { s += c; // ... this->consume(); s += this->current(); } else if(c == 0) { throw LexicalError(DEBUG_INFO, this, this->get_info(), "EOF found during scanning"); } else { s += c; } this->consume(); } return Token(start, this->get_info(), s); }
Token Source::read_up_to_delimiters(std::string delimiters, bool escape, bool include_delimiter) { Info start = this->get_info(); std::string s; while(true) { char c = this->current(); if(delimiters.find(c) != delimiters.npos) { if(include_delimiter) { s += c; } break; } else if(escape && c == string::ESCAPE) { //s += c; // ... this->consume(); s += this->current(); } else if(c == 0) { throw LexicalError(DEBUG_INFO, this, this->get_info(), "EOF found during scanning"); } else { s += c; } this->consume(); } return Token(start, this->get_info(), s); }
Token Source::read_up_to_delimiter(std::string substring, bool escape, bool include_delimiter) { Info start = this->get_info(); std::string s; size_t s_pos = 0; size_t s_len = substring.size(); //char s_c; char c; std::string s_s; while(true) { //s_c = substring[s_pos]; c = this->current(); if(escape && c == string::ESCAPE) { s += c; //... this->consume(); s += this->current(); s_pos = 0; } else if(c == substring[s_pos]) { s_s += c; ++s_pos; if(s_pos == s_len) { break; } } else if(s_pos > 0) { s_s.clear(); s_pos = 0; continue; } else if(c == 0) { throw LexicalError(DEBUG_INFO, this, this->get_info(), "EOF found during scanning"); } else { s += c; } this->consume(); } if(include_delimiter) { s += s_s; } return Token(start, this->get_info(), s); }
bool SimpleParser::Parse(const GPSTR_T &source, GPSTR_T &msgOut, bool trimReductions) { /* This procedure starts the GOLD Parser Engine and handles each of the messages it returns. Each time a reduction is made, you can create new custom object and reassign the .CurrentReduction property. Otherwise, the system will use the Reduction object that was returned. The resulting tree will be a pure representation of the language and will be ready to implement. */ ParseMessage response; bool done; //Controls when we leave the loop bool accepted = false; //Was the parse successful? parser_->Open(source); parser_->TrimReductions = trimReductions; //Please read about this feature before enabling done = false; while (!done) { response = parser_->Parse(); switch (response) { case ParseMessage::LexicalError: //Cannot recognize token msgOut = LexicalError(this, parser_); done = true; break; case ParseMessage::SyntaxError: //Expecting a different token msgOut = SyntaxError(this, parser_); done = true; break; case ParseMessage::Reduction: parser_->SetCurrentReduction(Reduce(this, parser_->GetCurrentReduction())); break; case ParseMessage::Accept: //Accepted! Root = parser_->GetCurrentReduction(); //The root node! done = true; accepted = true; break; case ParseMessage::TokenRead: //You don't have to do anything here. break; case ParseMessage::InternalError: //INTERNAL ERROR! Something is horribly wrong. msgOut = InternalError(this); done = true; break; case ParseMessage::NotLoadedError: //This error occurs if the EGT was not loaded. msgOut = TablesNotLoaded(this); done = true; break; case ParseMessage::GroupError: //GROUP ERROR! Unexpected end of file msgOut = Runaway(this); done = true; break; } } //while return accepted; }