Skip to content

Commit

Permalink
Trigger calculation for inputs start with '='
Browse files Browse the repository at this point in the history
In the current implementation, calculation rewriter is triggered only for
inputs end with "=", e.g. "1+1=".

With this CL, inputs start with "=" such as "=1+1" also trigger
calculation rewriter.

BUG=
TEST=unittest
REF_BUG=20315815
REF_CL=91563543
  • Loading branch information
kohyatoh authored and yukawa committed Dec 20, 2015
1 parent b499f9e commit 5d423b0
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/mozc_version_template.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MAJOR=2
MINOR=17
BUILD=2243
BUILD=2244
REVISION=102
# NACL_DICTIONARY_VERSION is the target version of the system dictionary to be
# downloaded by NaCl Mozc.
Expand Down
30 changes: 19 additions & 11 deletions src/rewriter/calculator/calculator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "base/logging.h"
#include "base/number_util.h"
#include "base/singleton.h"
#include "base/string_piece.h"
#include "base/util.h"

// parser.c is a source file auto-generated by Lemon Parser. It is not compiled
Expand Down Expand Up @@ -80,11 +81,11 @@ class CalculatorImpl : public CalculatorInterface {
static const size_t kMaxLengthOfOperator = 3;
static const size_t kBufferSizeOfOutputNumber = 32;

// Tokenizes |input| and sets the tokens into |tokens|.
// It returns false if |input| includes an invalid token or does not include
// both of a number token and an operator token. Parenthesis is not
// considered as an operator.
bool Tokenize(const string &input, TokenSequence *tokens) const;
// Tokenizes |expression_body| and sets the tokens into |tokens|.
// It returns false if |expression_body| includes an invalid token or
// does not include both of a number token and an operator token.
// Parenthesis is not considered as an operator.
bool Tokenize(StringPiece expression_body, TokenSequence *tokens) const;

// Perform calculation with a given sequence of token.
bool CalculateTokens(const TokenSequence &tokens,
Expand Down Expand Up @@ -122,14 +123,21 @@ bool CalculatorImpl::CalculateString(const string &key, string *result) const {
string normalized_key;
Util::FullWidthAsciiToHalfWidthAscii(key, &normalized_key);

// Expression is ended with '='.
if (normalized_key[normalized_key.size() - 1] != '=') {
StringPiece expression_body;
if (normalized_key.front() == '=') {
// Expression starts with '='.
expression_body.set(normalized_key.data() + 1, normalized_key.size() - 1);
} else if (normalized_key.back() == '=') {
// Expression is ended with '='.
expression_body.set(normalized_key.data(), normalized_key.size() - 1);
} else {
// Expression does not start nor end with '='.
result->clear();
return false;
}

TokenSequence tokens;
if (!Tokenize(normalized_key, &tokens)) {
if (!Tokenize(expression_body, &tokens)) {
// normalized_key is not valid sequence of tokens
result->clear();
return false;
Expand All @@ -148,10 +156,10 @@ bool CalculatorImpl::CalculateString(const string &key, string *result) const {
return true;
}

bool CalculatorImpl::Tokenize(const string &input,
bool CalculatorImpl::Tokenize(StringPiece expression_body,
TokenSequence *tokens) const {
const char *current = input.data();
const char *end = input.data() + input.size() - 1; // omit '='
const char *current = expression_body.data();
const char *end = expression_body.data() + expression_body.size();
int num_operator = 0; // Number of operators appeared
int num_value = 0; // Number of values appeared

Expand Down
4 changes: 4 additions & 0 deletions src/rewriter/calculator/calculator_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ TEST(CalculatorTest, BasicTest) {
VerifyRejection(calculator, "(5)=");
// Expression must include at least one number.
VerifyRejection(calculator, "()=");
// Expression with both heading and tailing '='s should be rejected.
VerifyRejection(calculator, "=(0-0)=");

// Test for each operators
VerifyCalculation(calculator, "38+2.5=", "40.5");
Expand All @@ -108,6 +110,8 @@ TEST(CalculatorTest, BasicTest) {
VerifyCalculation(calculator, "2^10=", "1024");
VerifyCalculation(calculator, "4*-2=", "-8");
VerifyCalculation(calculator, "-10.3+3.5=", "-6.8");
// Expression can starts with '=' instead of ending with '='.
VerifyCalculation(calculator, "=-10.3+3.5", "-6.8");

// Full width cases (some operators may appear as full width character).
// "12345+67890="
Expand Down
14 changes: 12 additions & 2 deletions src/rewriter/calculator_rewriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,18 @@ bool CalculatorRewriter::InsertCandidate(const string &value,
candidate->value = value;
candidate->content_value = value;
} else { // with expression
candidate->value = expression + value;
candidate->content_value = expression + value;
DCHECK(!expression.empty());
if (expression.front() == '=') {
// Expression starts with '='.
// Appends value to the left of expression.
candidate->value = value + expression;
candidate->content_value = value + expression;
} else {
// Expression ends with '='.
// Appends value to the right of expression.
candidate->value = expression + value;
candidate->content_value = expression + value;
}
}
}

Expand Down
21 changes: 21 additions & 0 deletions src/rewriter/calculator_rewriter_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,27 @@ TEST_F(CalculatorRewriterTest, SeparatedSegmentsTest) {
EXPECT_EQ("1+1=2", segments.segment(0).candidate(index + 1).value);
}

// CalculatorRewriter should convert an expression starting with '='.
TEST_F(CalculatorRewriterTest, ExpressionStartingWithEqualTest) {
// Pretend "=1+1" is calculated to "2".
calculator_mock().SetCalculatePair("=1+1", "2", true);

std::unique_ptr<CalculatorRewriter> calculator_rewriter(
BuildCalculatorRewriterWithConverterMock());
const ConversionRequest request;

Segments segments;
SetSegment("=1+1", "=1+1", &segments);
calculator_rewriter->Rewrite(request, &segments);
int index = GetIndexOfCalculatedCandidate(segments);
EXPECT_NE(-1, index);
EXPECT_EQ("2", segments.segment(0).candidate(index).value);
EXPECT_TRUE(ContainsCalculatedResult(
segments.segment(0).candidate(index + 1)));
// CalculatorRewriter should append the result to the side '=' exists.
EXPECT_EQ("2=1+1", segments.segment(0).candidate(index + 1).value);
}

// Verify the description of calculator candidate.
TEST_F(CalculatorRewriterTest, DescriptionCheckTest) {
// "5・(8/4)ー7%3+6^−1*9="
Expand Down

0 comments on commit 5d423b0

Please sign in to comment.