Skip to content

Commit b6a8f3a

Browse files
authored
Merge pull request #2291 from guwirth/fix-2286
fix parsing error with right angle bracket detection
2 parents b5befbf + 6f8edd1 commit b6a8f3a

File tree

4 files changed

+66
-30
lines changed

4 files changed

+66
-30
lines changed

cxx-squid/src/main/java/org/sonar/cxx/channels/RightAngleBracketsChannel.java

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -43,29 +43,45 @@
4343
*/
4444
public class RightAngleBracketsChannel extends Channel<Lexer> {
4545

46-
private int angleBracketLevel = 0;
47-
private int parentheseLevel = 0;
46+
private int angleBracketLevel = 0; // angle brackets < >
47+
private int parentheseLevel = 0; // parentheses / round brackets ( )
4848

4949
@Override
5050
public boolean consume(CodeReader code, Lexer output) {
5151
var ch = (char) code.peek();
5252
var consumed = false;
5353

54-
if (ch == '<') {
55-
if (parentheseLevel == 0) {
56-
var next = code.charAt(1);
57-
if ((next != '<') && (next != '=')) { // not <<, <=, <<=, <=>,
58-
angleBracketLevel++;
54+
switch (ch) {
55+
case '(':
56+
parentheseLevel++;
57+
break;
58+
case ')':
59+
if (parentheseLevel > 0) {
60+
parentheseLevel--;
5961
}
60-
}
61-
} else if (angleBracketLevel > 0) {
62-
switch (ch) {
63-
case ';': // end of expression => reset
64-
angleBracketLevel = 0;
65-
parentheseLevel = 0;
66-
break;
67-
case '>':
68-
if (parentheseLevel == 0) {
62+
break;
63+
case ';': // end of expression => reset
64+
angleBracketLevel = 0;
65+
parentheseLevel = 0;
66+
break;
67+
68+
case '<':
69+
if (parentheseLevel == 0) {
70+
var next = code.charAt(1);
71+
if ((next != '<') && (next != '=')) { // not <<, <=, <<=, <=>
72+
angleBracketLevel++;
73+
}
74+
}
75+
break;
76+
77+
case '>':
78+
if (angleBracketLevel > 0) {
79+
var consume = parentheseLevel == 0;
80+
var next = code.charAt(1);
81+
consume = consume && !(next == '='); // not >=
82+
consume = consume && !((next == '>') && (angleBracketLevel == 1)); // not dangling >>
83+
84+
if (consume) {
6985
output.addToken(Token.builder()
7086
.setLine(code.getLinePosition())
7187
.setColumn(code.getColumnPosition())
@@ -74,20 +90,12 @@ public boolean consume(CodeReader code, Lexer output) {
7490
.setType(CxxPunctuator.GT)
7591
.build());
7692
code.pop();
93+
94+
angleBracketLevel--;
7795
consumed = true;
7896
}
79-
angleBracketLevel = Math.max(0, angleBracketLevel - 1);
80-
if (angleBracketLevel == 0) {
81-
parentheseLevel = 0;
82-
}
83-
break;
84-
case '(':
85-
parentheseLevel++;
86-
break;
87-
case ')':
88-
parentheseLevel = Math.max(0, parentheseLevel - 1);
89-
break;
90-
}
97+
}
98+
break;
9199
}
92100

93101
return consumed;

cxx-squid/src/main/java/org/sonar/cxx/parser/CxxGrammarImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ private static void expressions(LexerfulGrammarBuilder b) {
713713
).skipIfOneChild();
714714

715715
b.rule(cudaKernel).is(
716-
b.sequence("<<", "<", b.optional(expressionList), ">", ">>") // CUDA
716+
b.sequence("<<", "<", b.optional(expressionList), ">>", ">") // CUDA
717717
);
718718

719719
b.rule(typeIdEnclosed).is( // todo

cxx-squid/src/test/java/org/sonar/cxx/parser/StatementTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,28 @@ public void statement_reallife() {
7171
.matches("friend class SmartPtr<T>;");
7272
}
7373

74+
@Test
75+
public void expressionStatement_reallife() {
76+
setRootRule(CxxGrammarImpl.expressionStatement);
77+
78+
assertThatParser()
79+
// fix #2286: use expressionStatement with ; at the end to reset RightAngleBracketsChannel after each matches
80+
.matches("a() < 0 || c >= 1;")
81+
.matches("a() < 0 || c > 1;")
82+
.matches("a() < 0 || c >> 1;");
83+
}
84+
85+
@Test
86+
public void selectionStatement_reallife() {
87+
setRootRule(CxxGrammarImpl.selectionStatement);
88+
89+
assertThatParser()
90+
// fix #2286
91+
.matches("if(a() < 0 || c >= 1) {}")
92+
.matches("if(a() < 0 || c > 1) {}")
93+
.matches("if(a() < 0 || c >> 1) {}");
94+
}
95+
7496
@Test
7597
public void labeledStatement() {
7698
setRootRule(CxxGrammarImpl.labeledStatement);

cxx-squid/src/test/java/org/sonar/cxx/parser/TemplatesTest.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,13 @@ public void simpleTemplateId_reallife() {
199199
.matches("A<(X>Y)>")
200200
.matches("A<(X<Y)>")
201201
.matches("vector<std::vector<bool>>")
202-
.matches("Y<X<(6>>1)>>");
202+
.matches("Y<X<(6>1)>>")
203+
.matches("Y<X<(6<1)>>")
204+
.matches("Y<X<(6>=1)>>")
205+
.matches("Y<X<(6<=1)>>")
206+
.matches("Y<X<(6>>1)>>")
207+
.matches("Y<X<(6<<1)>>")
208+
.matches("Y<X<(6<=>1)>>");
203209
}
204210

205211
@Test

0 commit comments

Comments
 (0)