diff --git a/src/parser/GraphScanner.h b/src/parser/GraphScanner.h
index 6323b662bad81c62e4fd42c160e8863a73111f70..429c46f5f3e358ce1187a8fb1a35528ae41a8c74 100644
--- a/src/parser/GraphScanner.h
+++ b/src/parser/GraphScanner.h
@@ -88,6 +88,79 @@ protected:
return sbuf_.get();
}
+ using TokenType = nebula::GraphParser::token;
+ auto parseDecimal() const {
+ try {
+ folly::StringPiece text(yytext, yyleng);
+ uint64_t val = folly::to<uint64_t>(text);
+ if (val > MAX_ABS_INTEGER) {
+ throw GraphParser::syntax_error(*yylloc, "Out of range:");
+ }
+ if (val == MAX_ABS_INTEGER && !hasUnaryMinus()) {
+ throw GraphParser::syntax_error(*yylloc, "Out of range:");
+ }
+ yylval->intval = val;
+ } catch (...) {
+ throw GraphParser::syntax_error(*yylloc, "Out of range:");
+ }
+ return TokenType::INTEGER;
+ }
+
+ auto parseDouble() const {
+ try {
+ folly::StringPiece text(yytext, yyleng);
+ yylval->doubleval = folly::to<double>(text);
+ } catch (...) {
+ throw GraphParser::syntax_error(*yylloc, "Out of range:");
+ }
+ return TokenType::DOUBLE;
+ }
+
+ auto parseHex() const {
+ if (yyleng > 18) {
+ auto i = 2;
+ while (i < yyleng && yytext[i] == '0') {
+ i++;
+ }
+ if (yyleng - i > 16) {
+ throw GraphParser::syntax_error(*yylloc, "Out of range:");
+ }
+ }
+ uint64_t val = 0;
+ sscanf(yytext, "%lx", &val);
+ if (val > MAX_ABS_INTEGER) {
+ throw GraphParser::syntax_error(*yylloc, "Out of range:");
+ }
+ if (val == MAX_ABS_INTEGER && !hasUnaryMinus()) {
+ throw GraphParser::syntax_error(*yylloc, "Out of range:");
+ }
+ yylval->intval = static_cast<int64_t>(val);
+ return TokenType::INTEGER;
+ }
+
+ auto parseOct() const {
+ if (yyleng > 22) {
+ auto i = 1;
+ while (i < yyleng && yytext[i] == '0') {
+ i++;
+ }
+ if (yyleng - i > 22 ||
+ (yyleng - i == 22 && yytext[i] != '1')) {
+ throw GraphParser::syntax_error(*yylloc, "Out of range:");
+ }
+ }
+ uint64_t val = 0;
+ sscanf(yytext, "%lo", &val);
+ if (val > MAX_ABS_INTEGER) {
+ throw GraphParser::syntax_error(*yylloc, "Out of range:");
+ }
+ if (val == MAX_ABS_INTEGER && !hasUnaryMinus()) {
+ throw GraphParser::syntax_error(*yylloc, "Out of range:");
+ }
+ yylval->intval = static_cast<int64_t>(val);
+ return TokenType::INTEGER;
+ }
+
private:
friend class Scanner_Basic_Test;
int yylex() override;
diff --git a/src/parser/parser.yy b/src/parser/parser.yy
index af4dc6421e6647f3184102e239e0701d60f57447..accf788bfd29bb63e409ac0e574050bac1da54d1 100644
--- a/src/parser/parser.yy
+++ b/src/parser/parser.yy
@@ -158,7 +158,7 @@ static constexpr size_t MAX_ABS_INTEGER = 9223372036854775808ULL;
/* symbols */
%token L_PAREN R_PAREN L_BRACKET R_BRACKET L_BRACE R_BRACE COMMA
%token PIPE ASSIGN
-%token DOT COLON SEMICOLON L_ARROW R_ARROW AT
+%token DOT DOT_DOT COLON SEMICOLON L_ARROW R_ARROW AT
%token ID_PROP TYPE_PROP SRC_ID_PROP DST_ID_PROP RANK_PROP INPUT_REF DST_REF SRC_REF
/* token type specification */
@@ -1145,14 +1145,14 @@ match_step_range
| STAR legal_integer {
$$ = new MatchStepRange($2, $2);
}
- | STAR DOT DOT legal_integer {
- $$ = new MatchStepRange(1, $4);
+ | STAR DOT_DOT legal_integer {
+ $$ = new MatchStepRange(1, $3);
}
- | STAR legal_integer DOT DOT {
+ | STAR legal_integer DOT_DOT {
$$ = new MatchStepRange($2);
}
- | STAR legal_integer DOT DOT legal_integer {
- $$ = new MatchStepRange($2, $5);
+ | STAR legal_integer DOT_DOT legal_integer {
+ $$ = new MatchStepRange($2, $4);
}
;
diff --git a/src/parser/scanner.lex b/src/parser/scanner.lex
index db5a55125cfd4364f7c1142696cee6145415cba9..e7eb4321e4f5b5b1781ce8ea33058b8b9afdae71 100644
--- a/src/parser/scanner.lex
+++ b/src/parser/scanner.lex
@@ -13,8 +13,6 @@
yylloc->step(); \
yylloc->columns(yyleng);
-using TokenType = nebula::GraphParser::token;
-
static constexpr size_t MAX_STRING = 4096;
%}
@@ -364,6 +362,7 @@ FORMAT ([Ff][Oo][Rr][Mm][Aa][Tt])
{FALSE} { yylval->boolval = false; return TokenType::BOOL; }
"." { return TokenType::DOT; }
+".." { return TokenType::DOT_DOT; }
"," { return TokenType::COMMA; }
":" { return TokenType::COLON; }
";" { return TokenType::SEMICOLON; }
@@ -433,75 +432,29 @@ FORMAT ([Ff][Oo][Rr][Mm][Aa][Tt])
return TokenType::IPV4;
}
0[Xx]{HEX}+ {
- if (yyleng > 18) {
- auto i = 2;
- while (i < yyleng && yytext[i] == '0') {
- i++;
- }
- if (yyleng - i > 16) {
- throw GraphParser::syntax_error(*yylloc, "Out of range:");
- }
- }
- uint64_t val = 0;
- sscanf(yytext, "%lx", &val);
- if (val > MAX_ABS_INTEGER) {
- throw GraphParser::syntax_error(*yylloc, "Out of range:");
- }
- if (val == MAX_ABS_INTEGER && !hasUnaryMinus()) {
- throw GraphParser::syntax_error(*yylloc, "Out of range:");
- }
- yylval->intval = static_cast<int64_t>(val);
- return TokenType::INTEGER;
+ return parseHex();
}
0{OCT}+ {
- if (yyleng > 22) {
- auto i = 1;
- while (i < yyleng && yytext[i] == '0') {
- i++;
- }
- if (yyleng - i > 22 ||
- (yyleng - i == 22 && yytext[i] != '1')) {
- throw GraphParser::syntax_error(*yylloc, "Out of range:");
- }
- }
- uint64_t val = 0;
- sscanf(yytext, "%lo", &val);
- if (val > MAX_ABS_INTEGER) {
- throw GraphParser::syntax_error(*yylloc, "Out of range:");
- }
- if (val == MAX_ABS_INTEGER && !hasUnaryMinus()) {
- throw GraphParser::syntax_error(*yylloc, "Out of range:");
- }
- yylval->intval = static_cast<int64_t>(val);
- return TokenType::INTEGER;
+ return parseOct();
+ }
+
+{DEC}+\.\. {
+ yyless(yyleng - 2);
+ return parseDecimal();
}
{DEC}+ {
- try {
- folly::StringPiece text(yytext, yyleng);
- uint64_t val = folly::to<uint64_t>(text);
- if (val > MAX_ABS_INTEGER) {
- throw GraphParser::syntax_error(*yylloc, "Out of range:");
- }
- if (val == MAX_ABS_INTEGER && !hasUnaryMinus()) {
- throw GraphParser::syntax_error(*yylloc, "Out of range:");
- }
- yylval->intval = val;
- } catch (...) {
- throw GraphParser::syntax_error(*yylloc, "Out of range:");
- }
- return TokenType::INTEGER;
+ return parseDecimal();
}
-{DEC}+\.{DEC}+ {
- try {
- folly::StringPiece text(yytext, yyleng);
- yylval->doubleval = folly::to<double>(text);
- } catch (...) {
- throw GraphParser::syntax_error(*yylloc, "Out of range:");
- }
- return TokenType::DOUBLE;
+
+{DEC}*\.{DEC}+ |
+{DEC}+\.{DEC}* {
+ return parseDouble();
}
-\${LABEL} { yylval->strval = new std::string(yytext + 1, yyleng - 1); return TokenType::VARIABLE; }
+\${LABEL} {
+ yylval->strval = new std::string(yytext + 1, yyleng - 1);
+ return TokenType::VARIABLE;
+ }
\" { BEGIN(DQ_STR); sbufPos_ = 0; }
diff --git a/src/parser/test/ScannerTest.cpp b/src/parser/test/ScannerTest.cpp
index fb664ee8b41b560197ac35300ec3f54e99569c58..59e0cd4a73a6236c87dea488c1bdc721ebbdc03a 100644
--- a/src/parser/test/ScannerTest.cpp
+++ b/src/parser/test/ScannerTest.cpp
@@ -134,6 +134,7 @@ TEST(Scanner, Basic) {
std::vector<Validator> validators = {
CHECK_SEMANTIC_TYPE(".", TokenType::DOT),
+ CHECK_SEMANTIC_TYPE("..", TokenType::DOT_DOT),
CHECK_SEMANTIC_TYPE(",", TokenType::COMMA),
CHECK_SEMANTIC_TYPE(":", TokenType::COLON),
CHECK_SEMANTIC_TYPE(";", TokenType::SEMICOLON),
@@ -468,6 +469,8 @@ TEST(Scanner, Basic) {
CHECK_SEMANTIC_VALUE("0x123", TokenType::INTEGER, 0x123),
CHECK_SEMANTIC_VALUE("0xdeadbeef", TokenType::INTEGER, 0xdeadbeef),
CHECK_SEMANTIC_VALUE("0123", TokenType::INTEGER, 0123),
+ CHECK_SEMANTIC_VALUE("123.", TokenType::DOUBLE, 123.),
+ CHECK_SEMANTIC_VALUE(".123", TokenType::DOUBLE, 0.123),
CHECK_SEMANTIC_VALUE("123.456", TokenType::DOUBLE, 123.456),
CHECK_SEMANTIC_VALUE("0x7FFFFFFFFFFFFFFF", TokenType::INTEGER, 0x7FFFFFFFFFFFFFFFL),
diff --git a/src/validator/test/YieldValidatorTest.cpp b/src/validator/test/YieldValidatorTest.cpp
index 405fd9ae3a171e05ff2c31a0504f98b2a41fb1b3..88087a25d08320870b0050141ab3d6566d8b2f92 100644
--- a/src/validator/test/YieldValidatorTest.cpp
+++ b/src/validator/test/YieldValidatorTest.cpp
@@ -135,6 +135,10 @@ TEST_F(YieldValidatorTest, TypeCastTest) {
std::string query = "YIELD (INT)1.23";
EXPECT_TRUE(checkResult(query, expected_));
}
+ {
+ std::string query = "YIELD (INT).123";
+ EXPECT_TRUE(checkResult(query, expected_));
+ }
{
std::string query = "YIELD (INT)123";
EXPECT_TRUE(checkResult(query, expected_));