Skip to content

Commit 8638a77

Browse files
authored
Improving grammar (#20)
Improved grammar
1 parent 0b2b74a commit 8638a77

File tree

12 files changed

+1558
-53
lines changed

12 files changed

+1558
-53
lines changed

rust-frontend/src/main/java/org/sonar/rust/RustGrammar.java

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
* Sonar Rust Plugin (Community)
33
* Copyright (C) 2021 Eric Le Goff
44
* http://github.com/elegoff/sonar-rust
5-
*
5+
* <p>
66
* This program is free software; you can redistribute it and/or
77
* modify it under the terms of the GNU Lesser General Public
88
* License as published by the Free Software Foundation; either
99
* version 3 of the License, or (at your option) any later version.
10-
*
10+
* <p>
1111
* This program is distributed in the hope that it will be useful,
1212
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1313
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1414
* Lesser General Public License for more details.
15-
*
15+
* <p>
1616
* You should have received a copy of the GNU Lesser General Public License
1717
* along with this program; if not, write to the Free Software Foundation,
1818
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -60,6 +60,7 @@ public enum RustGrammar implements GrammarRuleKey {
6060
BLOCK_EXPRESSION,
6161
BOOLEAN_LITERAL,
6262
BORROW_EXPRESSION,
63+
BOX_EXPRESSION,
6364
BREAK_EXPRESSION,
6465
BYTE_ESCAPE,
6566
BYTE_LITERAL,
@@ -344,7 +345,7 @@ public static LexerlessGrammarBuilder create() {
344345
LexerlessGrammarBuilder b = LexerlessGrammarBuilder.create();
345346

346347

347-
b.rule(COMPILATION_UNIT).is(SPC, b.zeroOrMore(INNER_ATTRIBUTE), SPC, b.zeroOrMore(STATEMENT, SPC), EOF);
348+
b.rule(COMPILATION_UNIT).is(SPC, b.zeroOrMore(INNER_ATTRIBUTE, SPC), SPC, b.zeroOrMore(STATEMENT, SPC), EOF);
348349

349350
punctuators(b);
350351
keywords(b);
@@ -385,29 +386,34 @@ private static void literals(LexerlessGrammarBuilder b) {
385386
b.token(GenericTokenType.UNKNOWN_CHAR, b.regexp("(?s).")),
386387
SPC).skip();
387388

388-
389389
b.rule(CHAR_LITERAL).is(b.token(RustTokenType.CHARACTER_LITERAL,
390-
b.firstOf(b.regexp("^\\'[^\\\r\\n\\t\\'].*\\'"),
391-
b.sequence("'", UNICODE_ESCAPE, "'"),
392-
b.sequence("'", QUOTE_ESCAPE, "'"),
393-
b.sequence("'", ASCII_ESCAPE, "'")))).skip();
390+
b.sequence("'",
391+
b.firstOf(
392+
UNICODE_ESCAPE,
393+
QUOTE_ESCAPE,
394+
ASCII_ESCAPE,
395+
b.regexp("[\\x00-\\x08\\x11-\\x12\\x14-\\x26\\x28-x5b\\x5d-\\x{1ffff}]")
396+
), "'"
397+
398+
))).skip();
394399

395400
b.rule(STRING_CONTENT).is(b.oneOrMore(b.regexp("[\\x{0000}-\\x{0021}\\x{0023}-\\x{005b}\\x{005d}-\\x{1ffff}]")));
396401

397402
b.rule(STRING_LITERAL).is(b.token(RustTokenType.STRING_LITERAL,
398-
b.firstOf(
399-
"\"\\\\\"",
400-
b.sequence(
401-
"\"", b.zeroOrMore(b.firstOf(
402-
"\\n//",
403-
QUOTE_ESCAPE
404-
, ASCII_ESCAPE
405-
, UNICODE_ESCAPE
406-
, STRING_CONTINUE
407-
, STRING_CONTENT
408-
), SPC),
409-
"\""
410-
))
403+
b.sequence(
404+
"\"", b.zeroOrMore(b.firstOf(
405+
UNICODE_ESCAPE,
406+
"\\n//",
407+
"\\\\",
408+
QUOTE_ESCAPE
409+
410+
, ASCII_ESCAPE
411+
412+
, STRING_CONTINUE
413+
, STRING_CONTENT
414+
), SPC),
415+
"\""
416+
)
411417
));
412418

413419

@@ -713,7 +719,7 @@ private static void implItem(LexerlessGrammarBuilder b) {
713719

714720
b.rule(TRAIT_IMPL).is(
715721
b.optional(RustKeyword.KW_UNSAFE, SPC), RustKeyword.KW_IMPL, SPC, b.optional(GENERIC_PARAMS, SPC),
716-
b.optional(RustPunctuator.NOT), TYPE_PATH, SPC, RustKeyword.KW_FOR, SPC, TYPE,
722+
b.optional(RustPunctuator.NOT), TYPE_PATH, SPC, RustKeyword.KW_FOR, SPC, TYPE, SPC,
717723
b.optional(WHERE_CLAUSE, SPC), "{", SPC,
718724
b.zeroOrMore(b.firstOf(INNER_ATTRIBUTE, OUTER_ATTRIBUTE), SPC),
719725
b.zeroOrMore(ASSOCIATED_ITEM, SPC), "}"
@@ -928,6 +934,7 @@ private static void patterns(LexerlessGrammarBuilder b) {
928934
TUPLE_STRUCT_PATTERN,
929935
STRUCT_PATTERN,
930936
MACRO_INVOCATION,
937+
b.sequence(LITERAL_PATTERN, b.nextNot(RustPunctuator.DOTDOT)),
931938

932939

933940
//unambigous PATH_PATTERN,
@@ -950,9 +957,9 @@ private static void patterns(LexerlessGrammarBuilder b) {
950957

951958
TUPLE_PATTERN,
952959
GROUPED_PATTERN,
953-
SLICE_PATTERN,
960+
SLICE_PATTERN
961+
954962

955-
LITERAL_PATTERN
956963
));
957964
b.rule(LITERAL_PATTERN).is(b.firstOf(
958965
BOOLEAN_LITERAL,
@@ -1016,7 +1023,7 @@ private static void patterns(LexerlessGrammarBuilder b) {
10161023
b.rule(STRUCT_PATTERN_ETCETERA).is(b.zeroOrMore(OUTER_ATTRIBUTE, SPC), RustPunctuator.DOTDOT);
10171024

10181025
b.rule(TUPLE_STRUCT_PATTERN).is(
1019-
PATH_IN_EXPRESSION, "(", b.optional(TUPLE_STRUCT_ITEMS), ")"
1026+
PATH_IN_EXPRESSION, "(", SPC, b.optional(RustKeyword.KW_BOX, SPC), b.optional(TUPLE_STRUCT_ITEMS), ")"
10201027
);
10211028
b.rule(TUPLE_STRUCT_ITEMS).is(seq(b, PATTERN, RustPunctuator.COMMA));
10221029

@@ -1031,8 +1038,8 @@ private static void patterns(LexerlessGrammarBuilder b) {
10311038
));
10321039

10331040
b.rule(GROUPED_PATTERN).is("(", SPC, PATTERN, SPC, ")");
1034-
b.rule(SLICE_PATTERN).is("[", SPC, PATTERN, SPC,
1035-
b.zeroOrMore(b.sequence(RustPunctuator.COMMA, SPC, PATTERN)), b.optional(RustPunctuator.COMMA, SPC), SPC, "]"
1041+
1042+
b.rule(SLICE_PATTERN).is("[", b.optional(seq(b, PATTERN, RustPunctuator.COMMA)), "]"
10361043
);
10371044
b.rule(PATH_PATTERN).is(b.firstOf(PATH_IN_EXPRESSION, QUALIFIED_PATH_IN_EXPRESSION));
10381045
}
@@ -1137,6 +1144,7 @@ public static void expressions(LexerlessGrammarBuilder b) {
11371144
b.firstOf(
11381145
b.sequence(LITERAL_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)),
11391146
b.sequence(BREAK_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)),
1147+
b.sequence(BOX_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)),
11401148
b.sequence(RustPunctuator.DOTDOT, b.next(b.firstOf(")", "]", "}"))),
11411149
b.sequence(RANGE_TO_INCLUSIVE_EXPR, b.zeroOrMore(SPC, EXPRESSION_TERM)),
11421150
b.sequence(RustPunctuator.DOTDOT, b.nextNot(RustPunctuator.EQ), b.endOfInput()),
@@ -1169,6 +1177,7 @@ public static void expressions(LexerlessGrammarBuilder b) {
11691177
b.zeroOrMore(OUTER_ATTRIBUTE, SPC),
11701178
b.firstOf(
11711179
b.sequence(BREAK_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)),
1180+
b.sequence(BOX_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)),
11721181
b.sequence(CONTINUE_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)),
11731182
b.sequence(RustPunctuator.DOTDOT, b.next(")")),
11741183
b.sequence(RANGE_TO_INCLUSIVE_EXPR, b.zeroOrMore(SPC, EXPRESSION_TERM_EXCEPT_STRUCT)),
@@ -1362,6 +1371,7 @@ public static void expressions(LexerlessGrammarBuilder b) {
13621371
b.rule(EXPRESSION_WITHOUT_BLOCK).is(b.zeroOrMore(OUTER_ATTRIBUTE, SPC),
13631372
b.firstOf(
13641373
b.sequence(BREAK_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)),
1374+
b.sequence(BOX_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)),
13651375
b.sequence(CONTINUE_EXPRESSION, b.zeroOrMore(SPC, EXPRESSION_TERM)),
13661376
b.sequence(EXPRESSION_WITH_BLOCK, b.oneOrMore(SPC, EXPRESSION_TERM)),
13671377

@@ -1502,6 +1512,7 @@ private static void loops(LexerlessGrammarBuilder b) {
15021512
);
15031513
b.rule(LOOP_LABEL).is(LIFETIME_OR_LABEL, SPC, RustPunctuator.COLON);
15041514
b.rule(BREAK_EXPRESSION).is(RustKeyword.KW_BREAK, SPC, b.optional(LIFETIME_OR_LABEL, SPC), b.optional(EXPRESSION, SPC));
1515+
b.rule(BOX_EXPRESSION).is(RustKeyword.KW_BOX, SPC, EXPRESSION);
15051516
b.rule(CONTINUE_EXPRESSION).is(
15061517
RustKeyword.KW_CONTINUE, b.optional(SPC, LIFETIME_OR_LABEL));
15071518

@@ -1803,8 +1814,8 @@ public static void struct(LexerlessGrammarBuilder b) {
18031814

18041815
b.rule(STRUCT_EXPR_FIELD).is(b.firstOf(
18051816

1806-
b.sequence(b.firstOf(IDENTIFIER, TUPLE_INDEX), SPC, RustPunctuator.COLON, SPC, EXPRESSION),
1807-
IDENTIFIER
1817+
b.sequence(b.optional(OUTER_ATTRIBUTE, SPC), b.firstOf(IDENTIFIER, TUPLE_INDEX), SPC, RustPunctuator.COLON, SPC, EXPRESSION),
1818+
b.sequence(b.optional(OUTER_ATTRIBUTE, SPC), IDENTIFIER)
18081819

18091820
));
18101821

@@ -2063,7 +2074,8 @@ private static void bytes(LexerlessGrammarBuilder b) {
20632074

20642075
b.rule(BYTE_LITERAL).is(b.token(RustTokenType.BYTE_LITERAL,
20652076
b.firstOf(
2066-
b.regexp("^b\\'" + "[^\\'\\n\\r\\t\\\\].*" + "\\'"),
2077+
"b'\\''",
2078+
b.sequence("b'", b.regexp("[\\x00-\\x08\\x11-\\x12\\x14-\\x26\\x28-x5b\\x5d-\\x7f]"), "'"),
20672079
b.sequence("b'", BYTE_ESCAPE, "'")
20682080
)));
20692081

@@ -2133,7 +2145,7 @@ private static void characters(LexerlessGrammarBuilder b) {
21332145

21342146
b.rule(QUOTE_ESCAPE).is(b.firstOf("\\'", "\\\""));
21352147
b.rule(ASCII_ESCAPE).is(b.firstOf(b.sequence("\\x", OCT_DIGIT, HEX_DIGIT),
2136-
"\\n", "\\r", "\\t", "\\", "\0"));
2148+
"\\n", "\\r", "\\t", "\\\\", "\\0"));
21372149
b.rule(UNICODE_ESCAPE).is("\\u{", b.oneOrMore(b.sequence(HEX_DIGIT, b.zeroOrMore(RustPunctuator.UNDERSCORE))), "}");
21382150
b.rule(STRING_CONTINUE).is("\\\n");
21392151

rust-frontend/src/test/java/org/sonar/rust/RustLexerTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ public void testTokens() {
6969
public void testParsing() {
7070

7171

72-
String sexpr = "#![feature(const_fn_fn_ptr_basics)]";
72+
String sexpr = "let missing_key = GlyphKey { character: '\\0', ..glyph_key };";
73+
7374

7475

7576
//Print out Ast node content for debugging purpose

rust-frontend/src/test/java/org/sonar/rust/parser/attributes/AttributeTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public void testOuterAttribute() {
5454
.matches("#[cfg(feature = \"serde\")]")
5555
.matches("#[inline]")
5656
.matches("#[allow(unrooted_must_root)]")
57+
.matches("#[cfg(not(any(target_os = \"macos\", windows)))]")
5758
;
5859
}
5960
}

rust-frontend/src/test/java/org/sonar/rust/parser/expressions/ExpressionWithoutBlockTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public void testExpressionWithoutBlock() {
120120

121121
.matches("async move {}\n" +
122122
" .boxed()")
123+
.matches("'b'")
123124

124125

125126
;

rust-frontend/src/test/java/org/sonar/rust/parser/expressions/LiteralExpressionTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ public class LiteralExpressionTest {
2929
@Test
3030
public void testLiteralExpression() {
3131
assertThat(RustGrammar.create().build().rule(RustGrammar.LITERAL_EXPRESSION))
32-
.matches("'foo'")
33-
.matches("'foo''bar'")
32+
.matches("'f'")
3433
.matches("\"b\"")
3534
.matches("\"52\"")
3635
.matches("r\"foo\"")

rust-frontend/src/test/java/org/sonar/rust/parser/expressions/MatchExpressionTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ public void tesMatchArm() {
5757
.matches("1 | _ if { i.set(i.get() + 1); false }")
5858
.matches("(a,_)")
5959
.matches("(a,b)")
60+
.matches("'c'")
61+
.matches("b'c'")
6062

6163
;
6264
}
@@ -102,6 +104,11 @@ public void tesMatchArms() {
102104
.matches("(&http::Method::GET, \"/json\") => {\n" +
103105
" handle_json_request(inspector_map.clone())\n" +
104106
" }")
107+
.matches("'c' => ClipboardType::Clipboard")
108+
.matches("b'c' => ClipboardType::Clipboard")
109+
.matches("42 => 'b'")
110+
.matches("'a' => 'b'")
111+
105112

106113
;
107114

rust-frontend/src/test/java/org/sonar/rust/parser/expressions/OperatorExpressionTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@
2727
public class OperatorExpressionTest {
2828

2929

30+
@Test
31+
public void testBoxExpression() {
32+
assertThat(RustGrammar.create().build().rule(RustGrammar.BOX_EXPRESSION))
33+
.matches("box 42")
34+
.matches("box foo")
35+
.matches("box a.method()")
36+
.matches("box Ok(Poll::Pending)")
37+
;
38+
}
39+
40+
3041
@Test
3142
public void testBorrowExpression() {
3243
assertThat(RustGrammar.create().build().rule(RustGrammar.BORROW_EXPRESSION))
@@ -136,7 +147,7 @@ public void testTypeCastExpression() {
136147
assertThat(RustGrammar.create().build().rule(RustGrammar.EXPRESSION))
137148
.matches("value as f64")
138149
.matches("{} as i32")
139-
.matches("'test' as i32")
150+
.matches("test as i32")
140151
.matches("self.len() as u32")
141152
.matches("abc() as i32")
142153
.matches("len(vals) as f64")

rust-frontend/src/test/java/org/sonar/rust/parser/expressions/StructExpressionTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,27 @@ public void testStructExprStruct() {
7373
.matches("TuplePoint { .. bar}")
7474
.matches("TuplePoint { age :35,.. structbase}")
7575
.matches("Point {x: 10, y: 20}")
76+
.matches("Self {\n" +
77+
" current_mouse_cursor,\n" +
78+
" mouse_visible: true,\n" +
79+
" windowed_context,\n" +
80+
" #[cfg(not(any(target_os = \"macos\", windows)))]\n" +
81+
" should_draw: Arc::new(AtomicBool::new(true)),\n" +
82+
" #[cfg(all(feature = \"wayland\", not(any(target_os = \"macos\", windows))))]\n" +
83+
" wayland_surface,\n" +
84+
" dpr,\n" +
85+
" }")
86+
.matches("Self {\n" +
87+
" current_mouse_cursor,\n" +
88+
" mouse_visible: true,\n" +
89+
" windowed_context,\n" +
90+
" #[cfg(not(any(target_os = \"macos\", windows)))]\n" +
91+
" should_draw: Arc::new(AtomicBool::new(true)),\n" +
92+
" #[cfg(all(feature = \"wayland\", not(any(target_os = \"macos\", windows))))]\n" +
93+
" wayland_surface,\n" +
94+
" dpr,\n" +
95+
" }")
96+
7697
;
7798
}
7899

@@ -141,6 +162,16 @@ public void testStructExpression() {
141162
"frames: js_error.frames.clone(),\n" +
142163
"stack: None,\n" +
143164
"}")
165+
.matches("Self {\n" +
166+
" current_mouse_cursor,\n" +
167+
" mouse_visible: true,\n" +
168+
" windowed_context,\n" +
169+
" #[cfg(not(any(target_os = \"macos\", windows)))]\n" +
170+
" should_draw: Arc::new(AtomicBool::new(true)),\n" +
171+
" #[cfg(all(feature = \"wayland\", not(any(target_os = \"macos\", windows))))]\n" +
172+
" wayland_surface,\n" +
173+
" dpr,\n" +
174+
" }")
144175

145176

146177

rust-frontend/src/test/java/org/sonar/rust/parser/items/EnumerationTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public void testEnumerationItem() {
5656
" }")
5757

5858

59+
5960
;
6061
}
6162

0 commit comments

Comments
 (0)