aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/parser
diff options
context:
space:
mode:
authorMaximilian Goldstein <max.goldstein@qt.io>2019-11-29 16:52:16 +0100
committerMaximilian Goldstein <max.goldstein@qt.io>2019-12-05 14:28:47 +0100
commit8fadf5d374936e50b8bce5adb1f10da2f66eac2b (patch)
tree9fa8808718e47673413980aa4448fe8d11dde0c7 /src/qml/parser
parent79166592d17135309a070065e7cb947ffa293828 (diff)
qml/parser: Implement nullish coalescing
Implements the '??' operator as specified in https://github.com/tc39/proposal-nullish-coalescing. Also adds a few tests. Task-number: QTBUG-77926 Change-Id: I3993450c192d11bf1ade0662d945c1553b4c6976 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/parser')
-rw-r--r--src/qml/parser/qqmljs.g44
-rw-r--r--src/qml/parser/qqmljsast_p.h1
-rw-r--r--src/qml/parser/qqmljslexer.cpp9
3 files changed, 49 insertions, 5 deletions
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g
index ea105e7e22..6fbb9df164 100644
--- a/src/qml/parser/qqmljs.g
+++ b/src/qml/parser/qqmljs.g
@@ -80,6 +80,7 @@
%token T_COMMENT "comment"
%token T_COMPATIBILITY_SEMICOLON
%token T_ARROW "=>"
+%token T_QUESTION_QUESTION "??"
%token T_ENUM "enum"
%token T_ELLIPSIS "..."
%token T_YIELD "yield"
@@ -2638,13 +2639,48 @@ LogicalORExpression_In: LogicalORExpression_In T_OR_OR LogicalANDExpression_In;
} break;
./
+CoalesceExpression: LogicalORExpression;
+CoalesceExpression_In: LogicalORExpression_In;
-ConditionalExpression: LogicalORExpression;
-ConditionalExpression_In: LogicalORExpression_In;
+CoalesceExpression: CoalesceExpression T_QUESTION_QUESTION LogicalORExpression;
+/. case $rule_number: Q_FALLTHROUGH(); ./
+CoalesceExpression_In: CoalesceExpression_In T_QUESTION_QUESTION LogicalORExpression_In;
+/.
+ case $rule_number: {
+
+ auto *lhs = sym(1).Expression;
+ auto *rhs = sym(3).Expression;
+
+ // Check if lhs or rhs contain || or &&
+
+ if (lhs->binaryExpressionCast() != nullptr) {
+ auto *binaryExpr = lhs->binaryExpressionCast();
+ if (binaryExpr->op == QSOperator::And || binaryExpr->op == QSOperator::Or) {
+ syntaxError(binaryExpr->operatorToken, "Left-hand side may not contain || or &&");
+ return false;
+ }
+ }
+
+ if (rhs->binaryExpressionCast() != nullptr) {
+ auto *binaryExpr = rhs->binaryExpressionCast();
+ if (binaryExpr->op == QSOperator::And || binaryExpr->op == QSOperator::Or) {
+ syntaxError(binaryExpr->operatorToken, "Right-hand side may not contain || or &&");
+ return false;
+ }
+ }
+
+ AST::BinaryExpression *node = new (pool) AST::BinaryExpression(lhs, QSOperator::Coalesce, rhs);
+ node->operatorToken = loc(2);
+ sym(1).Node = node;
+ } break;
+./
+
+ConditionalExpression: CoalesceExpression;
+ConditionalExpression_In: CoalesceExpression_In;
-ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression_In T_COLON AssignmentExpression;
+ConditionalExpression: CoalesceExpression T_QUESTION AssignmentExpression_In T_COLON AssignmentExpression;
/. case $rule_number: Q_FALLTHROUGH(); ./
-ConditionalExpression_In: LogicalORExpression_In T_QUESTION AssignmentExpression_In T_COLON AssignmentExpression_In;
+ConditionalExpression_In: CoalesceExpression_In T_QUESTION AssignmentExpression_In T_COLON AssignmentExpression_In;
/.
case $rule_number: {
AST::ConditionalExpression *node = new (pool) AST::ConditionalExpression(sym(1).Expression, sym(3).Expression, sym(5).Expression);
diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h
index bc0a467f40..aa355fed85 100644
--- a/src/qml/parser/qqmljsast_p.h
+++ b/src/qml/parser/qqmljsast_p.h
@@ -105,6 +105,7 @@ enum Op {
InplaceURightShift,
InplaceXor,
As,
+ Coalesce,
Invalid
};
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index 443e1a7476..80d883e52f 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -580,7 +580,14 @@ again:
case ']': return T_RBRACKET;
case '[': return T_LBRACKET;
- case '?': return T_QUESTION;
+ case '?': {
+ if (_char == QLatin1Char('?')) {
+ scanChar();
+ return T_QUESTION_QUESTION;
+ }
+
+ return T_QUESTION;
+ }
case '>':
if (_char == QLatin1Char('>')) {