/** Skips whitespace (including lineBreaks, if desired) & comments, then reads one token. A token can be: - a string ("" delimited; ignores readToEOL) - whitespace-delimited (if readToEOL == false) - EOL- or comment-delimited (if readToEOL == true); i.e. reads to end of line or the first // or /* @param text adjusted to start beyond the read token */ static gsl::cstring_view GetToken( gsl::cstring_view& text, bool allowLineBreaks, bool readToEOL = false ) { skipWhitespaceAndComments( text, allowLineBreaks ); // EOF if( text.empty() ) { return{}; } // string. ignores readToEOL. if( text[ 0 ] == '"' ) { // there are no escapes, string just ends at the next " auto tokenEnd = std::find( text.begin() + 1, text.end(), '"' ); if( tokenEnd == text.end() ) { gsl::cstring_view token = { text.begin() + 1, text.end() }; text = { text.end(), text.end() }; return token; } else { gsl::cstring_view token = { text.begin() + 1, tokenEnd }; text = { tokenEnd + 1, text.end() }; return token; } } else if( readToEOL ) { // find the first of '\n', "//" or "/*"; that's end of token auto tokenEnd = std::find( text.begin(), text.end(), '\n' ); static const std::array< char, 2 > commentPatterns[]{ { { '/', '*' } }, { { '/', '/' } } }; for( auto& pattern : commentPatterns ) { tokenEnd = std::min( tokenEnd, std::search( text.begin(), tokenEnd, pattern.begin(), pattern.end() ) ); } gsl::cstring_view token{ text.begin(), tokenEnd }; text = { tokenEnd, text.end() }; return removeTrailingWhitespace( token ); } else { // consume until first whitespace (if allowLineBreaks == false, that may be text.begin(); in that case token is empty.) auto tokenEnd = std::find_if( text.begin(), text.end(), static_cast< int( *)( int ) >( std::isspace ) ); gsl::cstring_view token{ text.begin(), tokenEnd }; text = { tokenEnd, text.end() }; return token; } }
static void closeLineEndingAndAdjustRuns(LineState& line, Layout::RunVector& runs, unsigned previousRunCount, unsigned& lineCount, const TextFragmentIterator& textFragmentIterator) { if (previousRunCount == runs.size()) return; ASSERT(runs.size()); removeTrailingWhitespace(line, runs, textFragmentIterator); if (!runs.size()) return; // Adjust runs' position by taking line's alignment into account. if (float lineLogicalLeft = computeLineLeft(textFragmentIterator.style().textAlign, line.availableWidth(), line.width(), line.logicalLeftOffset())) { for (unsigned i = previousRunCount; i < runs.size(); ++i) { runs[i].logicalLeft += lineLogicalLeft; runs[i].logicalRight += lineLogicalLeft; } } runs.last().isEndOfLine = true; ++lineCount; }
vector <string> parseLine(string line, int line_number, string filename, bool allowError=true) { // Cleanup the input line before using... line=removeLeadingWhitespace(line); line=removeTrailingWhitespace(line); if (show_debug) { //cout << "ParseLine: Parsing line '" << line << "'" << endl; } // Break the line into a series of vectors vector<string> result; string origLine = line; size_t space=line.find_first_of(" "); // Only one item on line - a single command if(space==string::npos) { result.push_back(line); return result; } // Put the command as the first item result.push_back(line.substr(0,space)); line.erase(0,space); while(line.length()>0){ // Need to remove any leading spaces while((line.at(0)==' ')||(line.at(0)=='\t')) { line.erase(0,1); } if(line.length()==0) break; if(line.at(0)=='"') { // A string //cout << "looking for string..." << endl; space=1; space=line.find_first_of("\"",space); while((space!=string::npos)){ if (verbose_parse_output==true){ DisplayOnConsole("normal","Line length is: "+IntToString(line.length())); } if (show_debug){cout << "Char is at " << space << endl;} if (space!=1) { if (line.length()>4) { if (line.at(space-2)!='\\'){ if (show_debug){ cout << "string is not double escaped (\\)" << endl; } if (line.at(space-1)!='\\'){ if (show_debug){ cout << "string is not single escaped\nnot a \"" << endl; } break; } else { if (show_debug){cout << "Single escaped char!" << endl;} space=line.find_first_of("\"",space+1); if (space==string::npos) { break; } } } else { // scan for a new " character unsigned int space_old = space; space=line.find_first_of("\"",space); if (space == space_old) { // there must not be another " on the line, return as it is... break; } } } else { space=line.find_first_of("\"",space); break; } } else { break; } } //cout << "found at " << space << endl; if (space==string::npos){ // unable to find a closing quote! if (allowError){parse_error("Error: Missing closing quote!",line_number,filename);} } result.push_back(line.substr(0,space+1)); line.erase(0,space+1); } else if (line.at(0)=='(') { space=1; if (GetCount(line,")") > 1) { space=line.find_last_of(")"); } else { space=line.find_first_of(")",space); } if (space==string::npos){ // unable to find a closing bracket! if(allowError){parse_error("Error: Missing closing bracket!",line_number,filename);} } result.push_back(line.substr(0,space+1)); line.erase(0,space+1); } else { space=line.find_first_of(" "); if(space==string::npos) { // Last one on the line result.push_back(line); line.clear(); } else { result.push_back(line.substr(0,space)); line.erase(0,space); } } } for(unsigned int i=1;i!=result.size()-1;i++) { //if (show_debug){cout << "replacing \\\" in '" << result[i] << "' with \"..." << endl;} result[i]=replaceAll(result[i],"\\\"","\""); } return result; }