diff --git a/clang/include/clang/Tooling/Syntax/Nodes.h b/clang/include/clang/Tooling/Syntax/Nodes.h --- a/clang/include/clang/Tooling/Syntax/Nodes.h +++ b/clang/include/clang/Tooling/Syntax/Nodes.h @@ -45,6 +45,7 @@ BinaryOperatorExpression, CxxNullPtrExpression, IntegerLiteralExpression, + IdExpression, // Statements. UnknownStatement, @@ -84,7 +85,10 @@ ArraySubscript, TrailingReturnType, ParametersAndQualifiers, - MemberPointer + MemberPointer, + NestedNameSpecifier, + NameSpecifier, + UnqualifiedId }; /// For debugging purposes. llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeKind K); @@ -150,7 +154,10 @@ ArraySubscript_sizeExpression, TrailingReturnType_declarator, ParametersAndQualifiers_parameter, - ParametersAndQualifiers_trailingReturn + ParametersAndQualifiers_trailingReturn, + IdExpression_id, + IdExpression_qualifier, + NestedNameSpecifier_specifier }; /// For debugging purposes. llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeRole R); @@ -177,6 +184,55 @@ } }; +/// A sequence of these specifiers make a `nested-name-specifier` +class NameSpecifier final : public Tree { +public: + NameSpecifier() : Tree(NodeKind::NameSpecifier) {} + static bool classof(const Node *N) { + return N->kind() == NodeKind::NameSpecifier; + } +}; + +/// Models a `nested-name-specifier` as defined in the grammar. +/// C++ [expr.prim.id.qual] +class NestedNameSpecifier final : public Tree { +public: + NestedNameSpecifier() : Tree(NodeKind::NestedNameSpecifier) {} + static bool classof(const Node *N) { + return N->kind() <= NodeKind::NestedNameSpecifier; + } + std::vector specifiers(); +}; + +/// Models an `unqualified-id`, e.g. in `std::vector::size` it is `size`. +/// C++ [expr.prim.id.unqual] +class UnqualifiedId final : public Tree { +public: + UnqualifiedId() : Tree(NodeKind::UnqualifiedId) {} + static bool classof(const Node *N) { + return N->kind() == NodeKind::UnqualifiedId; + } +}; + +/// Models an `id-expression`, e.g. `std::vector::size`. +/// C++ [expr.prim.id] +/// id-expression: +/// unqualified-id +/// qualified-id +/// qualified-id: +/// nested-name-specifier template_opt unqualified-id +class IdExpression final : public Expression { +public: + IdExpression() : Expression(NodeKind::IdExpression) {} + static bool classof(const Node *N) { + return N->kind() == NodeKind::IdExpression; + } + syntax::NestedNameSpecifier *qualifier(); + // TODO after Expose `id-expression` from `DependentScopeDeclRefExpr`: + // Add accessor for `template_opt` + syntax::UnqualifiedId *unqualifiedId(); +}; + /// An expression of an unknown kind, i.e. one not currently handled by the /// syntax tree. class UnknownExpression final : public Expression { diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -608,6 +608,45 @@ return true; } + syntax::NestedNameSpecifier * + BuildNestedNameSpecifier(NestedNameSpecifierLoc QualifierLoc) { + if (!QualifierLoc) + return nullptr; + for (auto it = QualifierLoc; it; it = it.getPrefix()) { + auto *NS = new (allocator()) syntax::NameSpecifier; + Builder.foldNode(Builder.getRange(it.getLocalSourceRange()), NS, nullptr); + Builder.markChild(NS, syntax::NodeRole::NestedNameSpecifier_specifier); + } + auto *NNS = new (allocator()) syntax::NestedNameSpecifier; + Builder.foldNode(Builder.getRange(QualifierLoc.getSourceRange()), NNS, + nullptr); + return NNS; + } + + bool WalkUpFromDeclRefExpr(DeclRefExpr *S) { + if (auto *NNS = BuildNestedNameSpecifier(S->getQualifierLoc())) + Builder.markChild(NNS, syntax::NodeRole::IdExpression_qualifier); + + auto *unqualifiedId = new (allocator()) syntax::UnqualifiedId; + // Get `UnqualifiedId` from `DeclRefExpr` + // FIXME: Extract this logic so that it can be used by `MemberExpr`, + // and other semantic constructs, now it is tied to `DeclRefExpr` + if (!S->hasExplicitTemplateArgs()) { + Builder.foldNode(Builder.getRange(S->getNameInfo().getSourceRange()), + unqualifiedId, nullptr); + } else { + auto templateIdSourceRange = + SourceRange(S->getBeginLoc(), S->getRAngleLoc()); + Builder.foldNode(Builder.getRange(templateIdSourceRange), unqualifiedId, + nullptr); + } + Builder.markChild(unqualifiedId, syntax::NodeRole::IdExpression_id); + + Builder.foldNode(Builder.getExprRange(S), + new (allocator()) syntax::IdExpression, S); + return true; + } + bool WalkUpFromIntegerLiteral(IntegerLiteral *S) { Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken); Builder.foldNode(Builder.getExprRange(S), diff --git a/clang/lib/Tooling/Syntax/Nodes.cpp b/clang/lib/Tooling/Syntax/Nodes.cpp --- a/clang/lib/Tooling/Syntax/Nodes.cpp +++ b/clang/lib/Tooling/Syntax/Nodes.cpp @@ -28,6 +28,10 @@ return OS << "PostfixUnaryOperatorExpression"; case NodeKind::BinaryOperatorExpression: return OS << "BinaryOperatorExpression"; + case NodeKind::UnqualifiedId: + return OS << "UnqualifiedId"; + case NodeKind::IdExpression: + return OS << "IdExpression"; case NodeKind::UnknownStatement: return OS << "UnknownStatement"; case NodeKind::DeclarationStatement: @@ -94,6 +98,10 @@ return OS << "ParametersAndQualifiers"; case NodeKind::MemberPointer: return OS << "MemberPointer"; + case NodeKind::NameSpecifier: + return OS << "NameSpecifier"; + case NodeKind::NestedNameSpecifier: + return OS << "NestedNameSpecifier"; } llvm_unreachable("unknown node kind"); } @@ -158,10 +166,35 @@ return OS << "ParametersAndQualifiers_parameter"; case syntax::NodeRole::ParametersAndQualifiers_trailingReturn: return OS << "ParametersAndQualifiers_trailingReturn"; + case syntax::NodeRole::IdExpression_id: + return OS << "IdExpression_id"; + case syntax::NodeRole::IdExpression_qualifier: + return OS << "IdExpression_qualifier"; + case syntax::NodeRole::NestedNameSpecifier_specifier: + return OS << "NestedNameSpecifier_specifier"; } llvm_unreachable("invalid role"); } +std::vector syntax::NestedNameSpecifier::specifiers() { + std::vector Children; + for (auto *C = firstChild(); C; C = C->nextSibling()) { + if (C->role() == syntax::NodeRole::NestedNameSpecifier_specifier) + Children.push_back(llvm::cast(C)); + } + return Children; +} + +syntax::NestedNameSpecifier *syntax::IdExpression::qualifier() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::IdExpression_qualifier)); +} + +syntax::UnqualifiedId *syntax::IdExpression::unqualifiedId() { + return llvm::cast_or_null( + findChild(syntax::NodeRole::IdExpression_id)); +} + syntax::Leaf *syntax::IntegerLiteralExpression::literalToken() { return llvm::cast_or_null( findChild(syntax::NodeRole::LiteralToken)); diff --git a/clang/unittests/Tooling/Syntax/TreeTest.cpp b/clang/unittests/Tooling/Syntax/TreeTest.cpp --- a/clang/unittests/Tooling/Syntax/TreeTest.cpp +++ b/clang/unittests/Tooling/Syntax/TreeTest.cpp @@ -485,8 +485,9 @@ | | |-SimpleDeclarator | | | `-x | | `-: - | |-UnknownExpression - | | `-a + | |-IdExpression + | | `-UnqualifiedId + | | `-a | |-) | `-EmptyStatement | `-; @@ -662,8 +663,9 @@ |-{ |-ExpressionStatement | |-UnknownExpression - | | |-UnknownExpression - | | | `-test + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-test | | |-( | | `-) | `-; @@ -675,16 +677,18 @@ | |-) | |-ExpressionStatement | | |-UnknownExpression - | | | |-UnknownExpression - | | | | `-test + | | | |-IdExpression + | | | | `-UnqualifiedId + | | | | `-test | | | |-( | | | `-) | | `-; | |-else | `-ExpressionStatement | |-UnknownExpression - | | |-UnknownExpression - | | | `-test + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-test | | |-( | | `-) | `-; @@ -692,6 +696,464 @@ )txt")); } +TEST_P(SyntaxTreeTest, UnqualifiedId) { + if (!GetParam().isCXX11OrLater()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +struct X { + // TODO: Expose `id-expression` from `Declarator` + friend X operator+(const X&, const X&); + operator int(); +}; +unsigned operator "" _w(long long unsigned); +template +void f(T&); +void test(X x) { + x; // identifier + operator+(x, x); // operator-function-id + operator "" _w(1llu); // literal-operator-id + + f(x); // template-id + + // TODO: Expose `id-expression` from `MemberExpr` + x.operator int(); // conversion-funtion-id + x.~X(); // ~type-name + x.~decltype(x)(); // ~decltype-specifier +} +)cpp", + R"txt( +*: TranslationUnit +|-SimpleDeclaration +| |-struct +| |-X +| |-{ +| |-UnknownDeclaration +| | `-SimpleDeclaration +| | |-friend +| | |-X +| | |-SimpleDeclarator +| | | |-operator +| | | |-+ +| | | `-ParametersAndQualifiers +| | | |-( +| | | |-SimpleDeclaration +| | | | |-const +| | | | |-X +| | | | `-SimpleDeclarator +| | | | `-& +| | | |-, +| | | |-SimpleDeclaration +| | | | |-const +| | | | |-X +| | | | `-SimpleDeclarator +| | | | `-& +| | | `-) +| | `-; +| |-SimpleDeclaration +| | |-SimpleDeclarator +| | | |-operator +| | | |-int +| | | `-ParametersAndQualifiers +| | | |-( +| | | `-) +| | `-; +| |-} +| `-; +|-SimpleDeclaration +| |-unsigned +| |-SimpleDeclarator +| | |-operator +| | |-"" +| | |-_w +| | `-ParametersAndQualifiers +| | |-( +| | |-SimpleDeclaration +| | | |-long +| | | |-long +| | | `-unsigned +| | `-) +| `-; +|-TemplateDeclaration +| |-template +| |-< +| |-UnknownDeclaration +| | |-typename +| | `-T +| |-> +| `-SimpleDeclaration +| |-void +| |-SimpleDeclarator +| | |-f +| | `-ParametersAndQualifiers +| | |-( +| | |-SimpleDeclaration +| | | |-T +| | | `-SimpleDeclarator +| | | `-& +| | `-) +| `-; +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-X + | | `-SimpleDeclarator + | | `-x + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-IdExpression + | | `-UnqualifiedId + | | `-x + | `-; + |-ExpressionStatement + | |-UnknownExpression + | | |-IdExpression + | | | `-UnqualifiedId + | | | |-operator + | | | `-+ + | | |-( + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-x + | | |-, + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-x + | | `-) + | `-; + |-ExpressionStatement + | |-UnknownExpression + | | |-IdExpression + | | | `-UnqualifiedId + | | | |-operator + | | | |-"" + | | | `-_w + | | |-( + | | |-IntegerLiteralExpression + | | | `-1llu + | | `-) + | `-; + |-ExpressionStatement + | |-UnknownExpression + | | |-IdExpression + | | | `-UnqualifiedId + | | | |-f + | | | |-< + | | | |-X + | | | `-> + | | |-( + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-x + | | `-) + | `-; + |-ExpressionStatement + | |-UnknownExpression + | | |-UnknownExpression + | | | |-IdExpression + | | | | `-UnqualifiedId + | | | | `-x + | | | |-. + | | | |-operator + | | | `-int + | | |-( + | | `-) + | `-; + |-ExpressionStatement + | |-UnknownExpression + | | |-UnknownExpression + | | | |-IdExpression + | | | | `-UnqualifiedId + | | | | `-x + | | | |-. + | | | |-~ + | | | `-X + | | |-( + | | `-) + | `-; + |-ExpressionStatement + | |-UnknownExpression + | | |-UnknownExpression + | | | |-IdExpression + | | | | `-UnqualifiedId + | | | | `-x + | | | |-. + | | | `-~ + | | |-decltype + | | |-( + | | |-x + | | |-) + | | |-( + | | `-) + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, QualifiedId) { + if (!GetParam().isCXX()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +namespace a { + struct S { + static void f(){} + }; +} +void test() { + :: // global-namespace-specifier + a:: // namespace-specifier + S:: // type-name-specifier + f(); +} +)cpp", + R"txt( +*: TranslationUnit +|-NamespaceDefinition +| |-namespace +| |-a +| |-{ +| |-SimpleDeclaration +| | |-struct +| | |-S +| | |-{ +| | |-SimpleDeclaration +| | | |-static +| | | |-void +| | | |-SimpleDeclarator +| | | | |-f +| | | | `-ParametersAndQualifiers +| | | | |-( +| | | | `-) +| | | `-CompoundStatement +| | | |-{ +| | | `-} +| | |-} +| | `-; +| `-} +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-UnknownExpression + | | |-IdExpression + | | | |-NestedNameSpecifier + | | | | |-NameSpecifier + | | | | | `-:: + | | | | |-NameSpecifier + | | | | | |-a + | | | | | `-:: + | | | | `-NameSpecifier + | | | | |-S + | | | | `-:: + | | | `-UnqualifiedId + | | | `-f + | | |-( + | | `-) + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, QualifiedIdWithTemplate) { + if (!GetParam().isCXX()) { + return; + } + if (GetParam().hasDelayedTemplateParsing()) { + // FIXME: Make this test work on Windows by generating the expected syntax + // tree when `-fdelayed-template-parsing` is active. + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( +struct X { + template static void f(); + template + struct Y { + static void f(); + }; +}; +template void test() { + // TODO: Expose `id-expression` from `DependentScopeDeclRefExpr` + T::template f<0>(); // nested-name-specifier template unqualified-id + T::template Y<0>::f(); // nested-name-specifier template :: unqualified-id +} +)cpp", + R"txt( +*: TranslationUnit +|-SimpleDeclaration +| |-struct +| |-X +| |-{ +| |-TemplateDeclaration +| | |-template +| | |-< +| | |-SimpleDeclaration +| | | `-int +| | |-> +| | `-SimpleDeclaration +| | |-static +| | |-void +| | |-SimpleDeclarator +| | | |-f +| | | `-ParametersAndQualifiers +| | | |-( +| | | `-) +| | `-; +| |-TemplateDeclaration +| | |-template +| | |-< +| | |-SimpleDeclaration +| | | `-int +| | |-> +| | `-SimpleDeclaration +| | |-struct +| | |-Y +| | |-{ +| | |-SimpleDeclaration +| | | |-static +| | | |-void +| | | |-SimpleDeclarator +| | | | |-f +| | | | `-ParametersAndQualifiers +| | | | |-( +| | | | `-) +| | | `-; +| | |-} +| | `-; +| |-} +| `-; +`-TemplateDeclaration + |-template + |-< + |-UnknownDeclaration + | |-typename + | `-T + |-> + `-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-UnknownExpression + | | |-UnknownExpression + | | | |-T + | | | |-:: + | | | |-template + | | | |-f + | | | |-< + | | | |-IntegerLiteralExpression + | | | | `-0 + | | | `-> + | | |-( + | | `-) + | `-; + |-ExpressionStatement + | |-UnknownExpression + | | |-UnknownExpression + | | | |-T + | | | |-:: + | | | |-template + | | | |-Y + | | | |-< + | | | |-IntegerLiteralExpression + | | | | `-0 + | | | |-> + | | | |-:: + | | | `-f + | | |-( + | | `-) + | `-; + `-} +)txt")); +} + +TEST_P(SyntaxTreeTest, DecltypeQualifiedId) { + if (!GetParam().isCXX11OrLater()) { + return; + } + EXPECT_TRUE(treeDumpEqual( + R"cpp( + struct S { + static void f(){} + }; +void test(S s) { + decltype(s):: // decltype-specifier + f(); +} +)cpp", + R"txt( +*: TranslationUnit +|-SimpleDeclaration +| |-struct +| |-S +| |-{ +| |-SimpleDeclaration +| | |-static +| | |-void +| | |-SimpleDeclarator +| | | |-f +| | | `-ParametersAndQualifiers +| | | |-( +| | | `-) +| | `-CompoundStatement +| | |-{ +| | `-} +| |-} +| `-; +`-SimpleDeclaration + |-void + |-SimpleDeclarator + | |-test + | `-ParametersAndQualifiers + | |-( + | |-SimpleDeclaration + | | |-S + | | `-SimpleDeclarator + | | `-s + | `-) + `-CompoundStatement + |-{ + |-ExpressionStatement + | |-UnknownExpression + | | |-IdExpression + | | | |-NestedNameSpecifier + | | | | `-NameSpecifier + | | | | |-decltype + | | | | |-( + | | | | |-IdExpression + | | | | | `-UnqualifiedId + | | | | | `-s + | | | | |-) + | | | | `-:: + | | | `-UnqualifiedId + | | | `-f + | | |-( + | | `-) + | `-; + `-} +)txt")); +} + TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) { if (!GetParam().isCXX11OrLater()) { return; @@ -889,14 +1351,16 @@ |-{ |-ExpressionStatement | |-PostfixUnaryOperatorExpression - | | |-UnknownExpression - | | | `-a + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-a | | `-++ | `-; |-ExpressionStatement | |-PostfixUnaryOperatorExpression - | | |-UnknownExpression - | | | `-a + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-a | | `--- | `-; `-} @@ -941,62 +1405,72 @@ |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |--- - | | `-UnknownExpression - | | `-a + | | `-IdExpression + | | `-UnqualifiedId + | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-++ - | | `-UnknownExpression - | | `-a + | | `-IdExpression + | | `-UnqualifiedId + | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-~ - | | `-UnknownExpression - | | `-a + | | `-IdExpression + | | `-UnqualifiedId + | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-- - | | `-UnknownExpression - | | `-a + | | `-IdExpression + | | `-UnqualifiedId + | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-+ - | | `-UnknownExpression - | | `-a + | | `-IdExpression + | | `-UnqualifiedId + | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-& - | | `-UnknownExpression - | | `-a + | | `-IdExpression + | | `-UnqualifiedId + | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-* - | | `-UnknownExpression - | | `-ap + | | `-IdExpression + | | `-UnqualifiedId + | | `-ap | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-! - | | `-UnknownExpression - | | `-a + | | `-IdExpression + | | `-UnqualifiedId + | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-__real - | | `-UnknownExpression - | | `-a + | | `-IdExpression + | | `-UnqualifiedId + | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-__imag - | | `-UnknownExpression - | | `-a + | | `-IdExpression + | | `-UnqualifiedId + | | `-a | `-; `-} )txt")); @@ -1036,14 +1510,16 @@ |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-compl - | | `-UnknownExpression - | | `-a + | | `-IdExpression + | | `-UnqualifiedId + | | `-a | `-; |-ExpressionStatement | |-PrefixUnaryOperatorExpression | | |-not - | | `-UnknownExpression - | | `-b + | | `-IdExpression + | | `-UnqualifiedId + | | `-b | `-; `-} )txt")); @@ -1095,16 +1571,18 @@ | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression - | | | `-a + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-a | | |-= | | `-IntegerLiteralExpression | | `-1 | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression - | | | `-a + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-a | | |-<<= | | `-IntegerLiteralExpression | | `-1 @@ -1127,8 +1605,9 @@ | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression - | | | `-a + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-a | | |-^= | | `-IntegerLiteralExpression | | `-3 @@ -1191,8 +1670,9 @@ | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression - | | | `-a + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-a | | |-xor_eq | | `-IntegerLiteralExpression | | `-3 @@ -1257,23 +1737,27 @@ |-ExpressionStatement | |-BinaryOperatorExpression | | |-BinaryOperatorExpression - | | | |-UnknownExpression - | | | | `-a + | | | |-IdExpression + | | | | `-UnqualifiedId + | | | | `-a | | | |-+ - | | | `-UnknownExpression - | | | `-b + | | | `-IdExpression + | | | `-UnqualifiedId + | | | `-b | | |-+ | | `-IntegerLiteralExpression | | `-42 | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression - | | | `-a + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-a | | |-= | | `-BinaryOperatorExpression - | | |-UnknownExpression - | | | `-b + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-b | | |-= | | `-IntegerLiteralExpression | | `-42 @@ -1281,12 +1765,14 @@ |-ExpressionStatement | |-BinaryOperatorExpression | | |-BinaryOperatorExpression - | | | |-UnknownExpression - | | | | `-a + | | | |-IdExpression + | | | | `-UnqualifiedId + | | | | `-a | | | |-+ | | | `-BinaryOperatorExpression - | | | |-UnknownExpression - | | | | `-b + | | | |-IdExpression + | | | | `-UnqualifiedId + | | | | `-b | | | |-* | | | `-IntegerLiteralExpression | | | `-4 @@ -1297,15 +1783,17 @@ |-ExpressionStatement | |-BinaryOperatorExpression | | |-BinaryOperatorExpression - | | | |-UnknownExpression - | | | | `-a + | | | |-IdExpression + | | | | `-UnqualifiedId + | | | | `-a | | | |-% | | | `-IntegerLiteralExpression | | | `-2 | | |-+ | | `-BinaryOperatorExpression - | | |-UnknownExpression - | | | `-b + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-b | | |-* | | `-IntegerLiteralExpression | | `-42 @@ -1415,31 +1903,40 @@ |-{ |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression - | | | `-x - | | |-UnknownExpression - | | | `-= - | | `-UnknownExpression - | | `-y + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-x + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-= + | | `-IdExpression + | | `-UnqualifiedId + | | `-y | `-; |-ExpressionStatement | |-BinaryOperatorExpression | | |-UnknownExpression - | | | `-UnknownExpression - | | | `-x - | | |-UnknownExpression - | | | `-+ - | | `-UnknownExpression - | | `-y + | | | `-IdExpression + | | | `-UnqualifiedId + | | | `-x + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-+ + | | `-IdExpression + | | `-UnqualifiedId + | | `-y | `-; |-ExpressionStatement | |-BinaryOperatorExpression - | | |-UnknownExpression - | | | `-x - | | |-UnknownExpression - | | | `-< - | | `-UnknownExpression - | | `-y + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-x + | | |-IdExpression + | | | `-UnqualifiedId + | | | `-< + | | `-IdExpression + | | `-UnqualifiedId + | | `-y | `-; `-} )txt"));