4141#include " absl/strings/ascii.h"
4242#include " absl/strings/str_format.h"
4343#include " absl/strings/string_view.h"
44+ #include " absl/strings/strip.h"
4445#include " base/japanese_util.h"
4546#include " base/number_util.h"
4647
@@ -327,17 +328,12 @@ std::optional<std::string> Calculator::CalculateString(
327328 std::string normalized_key =
328329 japanese_util::FullWidthAsciiToHalfWidthAscii (key);
329330
330- absl::string_view expression_body;
331- if (normalized_key.front () == ' =' ) {
332- // Expression starts with '='.
333- expression_body =
334- absl::string_view (normalized_key.data () + 1 , normalized_key.size () - 1 );
335- } else if (normalized_key.back () == ' =' ) {
336- // Expression is ended with '='.
337- expression_body =
338- absl::string_view (normalized_key.data (), normalized_key.size () - 1 );
339- } else {
340- // Expression does not start nor end with '='.
331+ if (normalized_key.starts_with (' =' ) && normalized_key.ends_with (' =' )) {
332+ return std::nullopt ;
333+ }
334+ absl::string_view expression_body = normalized_key;
335+ if (!absl::ConsumePrefix (&expression_body, " =" ) &&
336+ !absl::ConsumeSuffix (&expression_body, " =" )) {
341337 return std::nullopt ;
342338 }
343339
@@ -358,72 +354,80 @@ std::optional<std::string> Calculator::CalculateString(
358354
359355std::optional<Calculator::TokenSequence> Calculator::Tokenize (
360356 absl::string_view expression_body) const {
361- const char * current = expression_body.data ();
362- const char * end = expression_body.data () + expression_body.size ();
363357 int num_operator = 0 ; // Number of operators or functions appeared
364358 int num_value = 0 ; // Number of values appeared
365359
366360 TokenSequence tokens;
361+ absl::string_view rest = expression_body;
367362
368- while (current < end ) {
363+ while (!rest. empty () ) {
369364 // Skip spaces
370- while ((*current == ' ' ) || (*current == ' \t ' )) {
371- ++current;
365+ while (!rest.empty () && (rest.front () == ' ' || rest.front () == ' \t ' )) {
366+ rest.remove_prefix (1 );
367+ }
368+ if (rest.empty ()) {
369+ break ;
372370 }
373- const char * token_begin = current;
374371
375372 // Read value token
376- while (((*current >= ' 0' ) && (*current <= ' 9' )) || (*current == ' .' )) {
377- ++current;
373+ size_t value_len = 0 ;
374+ while (value_len < rest.size () &&
375+ (absl::ascii_isdigit (rest[value_len]) ||
376+ rest[value_len] == ' .' )) {
377+ ++value_len;
378378 }
379- if (token_begin < current ) {
380- std::string number_token (token_begin, current - token_begin );
379+ if (value_len > 0 ) {
380+ const absl::string_view number_token = rest. substr ( 0 , value_len );
381381 double value = 0.0 ;
382382 if (!NumberUtil::SafeStrToDouble (number_token, &value)) {
383383 return std::nullopt ;
384384 }
385385 tokens.push_back ({TokenType::INTEGER, value});
386386 ++num_value;
387+ rest.remove_prefix (value_len);
387388 continue ;
388389 }
389390
390391 // Read alphabetical function name token
391- if (absl::ascii_isalpha (*current)) {
392- while (current < end && absl::ascii_isalpha (*current)) {
393- ++current;
392+ if (absl::ascii_isalpha (rest.front ())) {
393+ size_t func_len = 0 ;
394+ while (func_len < rest.size () && absl::ascii_isalpha (rest[func_len])) {
395+ ++func_len;
394396 }
395- std::string name (token_begin, current - token_begin );
397+ std::string name (rest. data (), func_len );
396398 absl::AsciiStrToLower (&name);
397399 const auto func_it = operator_map_.find (name);
398400 if (func_it != operator_map_.end ()) {
399401 tokens.push_back ({func_it->second , 0.0 });
402+ rest.remove_prefix (func_len);
400403 ++num_operator;
401404 continue ;
402405 }
403406 return std::nullopt ;
404407 }
405408
406409 // Read operator token
410+ bool matched_operator = false ;
407411 for (size_t length = 1 ; length <= kMaxLengthOfOperator ; ++length) {
408- if (current + length > end) {
409- // Invalid token
410- return std::nullopt ;
412+ if (length > rest.size ()) {
413+ break ;
411414 }
412- absl::string_view window (current , length);
415+ const absl::string_view window = rest. substr ( 0 , length);
413416 const auto op_it = operator_map_.find (window);
414417 if (op_it == operator_map_.end ()) {
415418 continue ;
416419 }
417420 tokens.push_back ({op_it->second , 0.0 });
418- current += length;
421+ rest.remove_prefix (length);
422+ matched_operator = true ;
419423 // Does not count parenthesis as an operator.
420424 if ((op_it->second != TokenType::LP) &&
421425 (op_it->second != TokenType::RP)) {
422426 ++num_operator;
423427 }
424428 break ;
425429 }
426- if (token_begin < current ) {
430+ if (matched_operator ) {
427431 continue ;
428432 }
429433
0 commit comments