Skip to content

Commit 34d9a84

Browse files
committed
Synthesize >= the same as we already do >> and >>=
Closes #1162 This synthesizes>>= in relational-expression, the same way we already do for >> in shift-expression and >>= in assignment-expression This allows code like `x: std::vector<int>=(1,2,3);` without the spaces, and avoids max munch misinterpreting the >= as a single token
1 parent 8168a2d commit 34d9a84

File tree

4 files changed

+39
-10
lines changed

4 files changed

+39
-10
lines changed

regression-tests/test-results/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
cppfront compiler v0.7.1 Build 9714:0930
2+
cppfront compiler v0.7.1 Build 9715:1523
33
Copyright(c) Herb Sutter All rights reserved
44

55
SPDX-License-Identifier: CC-BY-NC-ND-4.0

source/build.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"9714:0930"
1+
"9715:1523"

source/lex.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,7 @@ auto lex_line(
13521352
}
13531353
else { store(1, lexeme::Less); }
13541354

1355-
// Note: >> and >>= are not source tokens, they are synthesized from > > and > >= where legal
1355+
// Note: >= and >> and >>= synthesized from > = and > > and > >= where legal
13561356
//G '>>=' '>>' '>=' '>'
13571357
break;case '>':
13581358
//---------------------------------------------------------
@@ -1362,10 +1362,10 @@ auto lex_line(
13621362
// if (peek2 == '=') { store(3, lexeme::RightShiftEq); }
13631363
// else { store(2, lexeme::RightShift); }
13641364
//}
1365+
//else if (peek1 == '=') { store(2, lexeme::GreaterEq); }
13651366
//else
13661367
//---------------------------------------------------------
1367-
if (peek1 == '=') { store(2, lexeme::GreaterEq); }
1368-
else { store(1, lexeme::Greater); }
1368+
{ store(1, lexeme::Greater); }
13691369

13701370
//G '++' '+=' '+'
13711371
break;case '+':

source/parse.h

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6157,6 +6157,26 @@ class parser
61576157
next();
61586158
}
61596159

6160+
// And for assignment-expression we may synthesize >>= from > > =
6161+
// which will return a token* == a valid operator for this production
6162+
// (possibly a synthesized new token) or nullptr otherwise
6163+
else if constexpr (requires{ validate_op(curr(), *peek(1), *peek(2)); }) {
6164+
if (
6165+
peek(1) == nullptr
6166+
|| peek(2) == nullptr
6167+
|| (t.op = validate_op(curr(), *peek(1), *peek(2))) == nullptr
6168+
)
6169+
{
6170+
break;
6171+
}
6172+
// If we didn't consume the next token, we consumed the next three
6173+
if (t.op != &curr()) {
6174+
next();
6175+
next();
6176+
}
6177+
next();
6178+
}
6179+
61606180
// And it shouldn't be anything else
61616181
else {
61626182
assert (!"ICE: validate_op should take one token and return bool, or two tokens and return token const* ");
@@ -6269,12 +6289,20 @@ class parser
62696289
{
62706290
if (allow_angle_operators) {
62716291
return binary_expression<relational_expression_node> (
6272-
[](token const& t, token const& next) -> token const* {
6292+
[this](token const& t, token const& next) -> token const* {
6293+
if (
6294+
t.type() == lexeme::Greater
6295+
&& next.type() == lexeme::Assignment
6296+
&& t.position() == source_position{ next.position().lineno, next.position().colno - 1 }
6297+
)
6298+
{
6299+
generated_tokens->emplace_back(">=", t.position(), lexeme::GreaterEq);
6300+
return &generated_tokens->back();
6301+
}
62736302
if (
62746303
t.type() == lexeme::Less
62756304
|| t.type() == lexeme::LessEq
6276-
|| (t.type() == lexeme::Greater && next.type() != lexeme::GreaterEq)
6277-
|| t.type() == lexeme::GreaterEq
6305+
|| t.type() == lexeme::Greater
62786306
) {
62796307
return &t;
62806308
}
@@ -6394,13 +6422,14 @@ class parser
63946422
if (allow_angle_operators)
63956423
{
63966424
ret = binary_expression<assignment_expression_node> (
6397-
[this](token const& t, token const& next) -> token const* {
6425+
[this](token const& t, token const& next, token const& third) -> token const* {
63986426
if (is_assignment_operator(t.type())) {
63996427
return &t;
64006428
}
64016429
if (
64026430
t.type() == lexeme::Greater
6403-
&& next.type() == lexeme::GreaterEq
6431+
&& next.type() == lexeme::Greater
6432+
&& third.type() == lexeme::Assignment
64046433
&& t.position() == source_position{ next.position().lineno, next.position().colno-1 }
64056434
)
64066435
{

0 commit comments

Comments
 (0)