1 | //===--- DisambiguateTest.cpp ---------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "clang-pseudo/Disambiguate.h" |
10 | #include "clang-pseudo/Forest.h" |
11 | #include "clang-pseudo/Token.h" |
12 | #include "clang/Basic/TokenKinds.h" |
13 | #include "gmock/gmock.h" |
14 | #include "gtest/gtest.h" |
15 | #include <vector> |
16 | |
17 | namespace clang { |
18 | namespace pseudo { |
19 | namespace { |
20 | using testing::ElementsAre; |
21 | using testing::Pair; |
22 | using testing::UnorderedElementsAre; |
23 | |
24 | // Common disambiguation test fixture. |
25 | // This is the ambiguous forest representing parses of 'a * b;'. |
26 | class DisambiguateTest : public ::testing::Test { |
27 | protected: |
28 | // Greatly simplified C++ grammar. |
29 | enum Symbol : SymbolID { |
30 | Statement, |
31 | Declarator, |
32 | Expression, |
33 | DeclSpecifier, |
34 | Type, |
35 | Template, |
36 | }; |
37 | enum Rule : RuleID { |
38 | /* LHS__RHS1_RHS2 means LHS := RHS1 RHS2 */ |
39 | Statement__DeclSpecifier_Declarator_Semi, |
40 | Declarator__Star_Declarator, |
41 | Declarator__Identifier, |
42 | Statement__Expression_Semi, |
43 | Expression__Expression_Star_Expression, |
44 | Expression__Identifier, |
45 | DeclSpecifier__Type, |
46 | DeclSpecifier__Template, |
47 | Type__Identifier, |
48 | Template__Identifier, |
49 | }; |
50 | |
51 | ForestArena Arena; |
52 | ForestNode &A = Arena.createTerminal(TK: tok::identifier, Start: 0); |
53 | ForestNode &Star = Arena.createTerminal(TK: tok::star, Start: 1); |
54 | ForestNode &B = Arena.createTerminal(TK: tok::identifier, Start: 2); |
55 | ForestNode &Semi = Arena.createTerminal(TK: tok::semi, Start: 3); |
56 | |
57 | // Parse as multiplication expression. |
58 | ForestNode &AExpr = |
59 | Arena.createSequence(SID: Expression, RID: Expression__Identifier, Elements: &A); |
60 | ForestNode &BExpr = |
61 | Arena.createSequence(SID: Expression, RID: Expression__Identifier, Elements: &B); |
62 | ForestNode &Expr = |
63 | Arena.createSequence(SID: Expression, RID: Expression__Expression_Star_Expression, |
64 | Elements: {&AExpr, &Star, &BExpr}); |
65 | ForestNode &ExprStmt = Arena.createSequence( |
66 | SID: Statement, RID: Statement__Expression_Semi, Elements: {&Expr, &Semi}); |
67 | // Parse as declaration (`a` may be CTAD or not). |
68 | ForestNode &AType = |
69 | Arena.createSequence(SID: DeclSpecifier, RID: DeclSpecifier__Type, |
70 | Elements: &Arena.createSequence(SID: Type, RID: Type__Identifier, Elements: &A)); |
71 | ForestNode &ATemplate = Arena.createSequence( |
72 | SID: DeclSpecifier, RID: DeclSpecifier__Template, |
73 | Elements: &Arena.createSequence(SID: Template, RID: Template__Identifier, Elements: &A)); |
74 | ForestNode &DeclSpec = |
75 | Arena.createAmbiguous(SID: DeclSpecifier, Alternatives: {&AType, &ATemplate}); |
76 | ForestNode &BDeclarator = |
77 | Arena.createSequence(SID: Declarator, RID: Declarator__Identifier, Elements: &B); |
78 | ForestNode &BPtr = Arena.createSequence( |
79 | SID: Declarator, RID: Declarator__Star_Declarator, Elements: {&Star, &BDeclarator}); |
80 | ForestNode &DeclStmt = |
81 | Arena.createSequence(SID: Statement, RID: Statement__DeclSpecifier_Declarator_Semi, |
82 | Elements: {&DeclSpec, &Star, &BDeclarator}); |
83 | // Top-level ambiguity |
84 | ForestNode &Stmt = Arena.createAmbiguous(SID: Statement, Alternatives: {&ExprStmt, &DeclStmt}); |
85 | }; |
86 | |
87 | TEST_F(DisambiguateTest, Remove) { |
88 | Disambiguation D; |
89 | D.try_emplace(Key: &Stmt, Args: 1); // statement is a declaration, not an expression |
90 | D.try_emplace(Key: &DeclSpec, Args: 0); // a is a type, not a (CTAD) template |
91 | ForestNode *Root = &Stmt; |
92 | removeAmbiguities(Root, Disambig: D); |
93 | |
94 | EXPECT_EQ(Root, &DeclStmt); |
95 | EXPECT_THAT(DeclStmt.elements(), ElementsAre(&AType, &Star, &BDeclarator)); |
96 | } |
97 | |
98 | TEST_F(DisambiguateTest, DummyStrategy) { |
99 | Disambiguation D = disambiguate(Root: &Stmt, Params: {}); |
100 | EXPECT_THAT(D, UnorderedElementsAre(Pair(&Stmt, 1), Pair(&DeclSpec, 1))); |
101 | |
102 | ForestNode *Root = &Stmt; |
103 | removeAmbiguities(Root, Disambig: D); |
104 | EXPECT_EQ(Root, &DeclStmt); |
105 | EXPECT_THAT(DeclStmt.elements(), |
106 | ElementsAre(&ATemplate, &Star, &BDeclarator)); |
107 | } |
108 | |
109 | } // namespace |
110 | } // namespace pseudo |
111 | } // namespace clang |
112 | |