/////////////////////////////////////////////////////////////////////////// All arguments must be individually and wholly recognized by the Lexer. Any argument not recognized is considered a Lexer::Type::word. As a side effect, tags all arguments after a terminator ('--') with TERMINATED.
| 333 | // As a side effect, tags all arguments after a terminator ('--') with |
| 334 | // TERMINATED. |
| 335 | void CLI2::lexArguments() { |
| 336 | // Note: Starts iterating at index 1, because ::handleArg0 has already |
| 337 | // processed it. |
| 338 | bool terminated = false; |
| 339 | for (unsigned int i = 1; i < _original_args.size(); ++i) { |
| 340 | bool quoted = Lexer::wasQuoted(_original_args[i].attribute("raw")); |
| 341 | |
| 342 | // Process single-token arguments. |
| 343 | std::string lexeme; |
| 344 | Lexer::Type type; |
| 345 | Lexer lex(_original_args[i].attribute("raw")); |
| 346 | if (lex.token(lexeme, type) && |
| 347 | (lex.isEOS() || // Token goes to EOS |
| 348 | (quoted && type == Lexer::Type::pair))) // Quoted pairs automatically go to EOS |
| 349 | { |
| 350 | if (!terminated && type == Lexer::Type::separator) |
| 351 | terminated = true; |
| 352 | else if (terminated) |
| 353 | type = Lexer::Type::word; |
| 354 | |
| 355 | A2 a(_original_args[i].attribute("raw"), type); |
| 356 | if (terminated) a.tag("TERMINATED"); |
| 357 | if (quoted) a.tag("QUOTED"); |
| 358 | |
| 359 | if (_original_args[i].hasTag("ORIGINAL")) a.tag("ORIGINAL"); |
| 360 | |
| 361 | _args.push_back(a); |
| 362 | } |
| 363 | |
| 364 | // Process multiple-token arguments. |
| 365 | else { |
| 366 | const std::string quote = "'"; |
| 367 | |
| 368 | // Escape unescaped single quotes |
| 369 | std::string escaped = ""; |
| 370 | |
| 371 | // For performance reasons. The escaped string is as long as the original. |
| 372 | escaped.reserve(_original_args[i].attribute("raw").size()); |
| 373 | |
| 374 | std::string::size_type cursor = 0; |
| 375 | bool nextEscaped = false; |
| 376 | while (int num = utf8_next_char(_original_args[i].attribute("raw"), cursor)) { |
| 377 | std::string character = utf8_character(num); |
| 378 | if (!nextEscaped && (character == "\\")) |
| 379 | nextEscaped = true; |
| 380 | else { |
| 381 | if (character == quote && !nextEscaped) escaped += "\\"; |
| 382 | nextEscaped = false; |
| 383 | } |
| 384 | escaped += character; |
| 385 | } |
| 386 | |
| 387 | cursor = 0; |
| 388 | std::string word; |
| 389 | if (Lexer::readWord(quote + escaped + quote, quote, cursor, word)) { |
| 390 | Lexer::dequote(word); |
| 391 | A2 unknown(word, Lexer::Type::word); |
| 392 | if (lex.wasQuoted(_original_args[i].attribute("raw"))) unknown.tag("QUOTED"); |