//===- Nodes.td - Node types in the Syntax Tree grammar -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines concrete nodes in the syntax tree.
// The archetypes they fall into (Sequence, List etc) are defined in Syntax.td.
//
// The C++ classes for the archetypes themselves are written by hand, and the
// concrete node classes will be generated. Migration to TableGen is not
// complete, so currently there is a mix of generated and hand-authored code.
//
//===----------------------------------------------------------------------===//
include "clang/Tooling/Syntax/Syntax.td"
def TranslationUnit : Unconstrained {
let documentation = [{
A root node for a translation unit. Parent is always null.
}];
}
def UnqualifiedId : External<Tree> {}
// Lists
def List : External<Tree> {}
def DeclaratorList : External<List> {}
def ParameterDeclarationList : External<List> {}
def CallArguments : External<List> {}
def NestedNameSpecifier : External<List> {}
def Expression : Alternatives {
let documentation = [{
A base class for all expressions. Note that expressions are not statements,
even though they are in clang.
}];
}
def UnknownExpression : External<Expression> {}
def UnaryOperatorExpression : External<Tree> {}
def PrefixUnaryOperatorExpression : External<UnaryOperatorExpression> {}
def PostfixUnaryOperatorExpression : External<UnaryOperatorExpression> {}
def BinaryOperatorExpression : External<Expression> {}
def ParenExpression : Sequence<Expression> {
let documentation = [{
Models a parenthesized expression `(E)`. C++ [expr.prim.paren]
e.g. `(3 + 2)` in `a = 1 + (3 + 2);`
}];
let children = [
Role<"OpenParen", Token<"l_paren">>,
Role<"SubExpression", Expression>,
Role<"CloseParen", Token<"r_paren">>,
];
}
def LiteralExpression : Alternatives<Expression> {
let documentation = [{
Expression for literals. C++ [lex.literal]
}];
}
def IntegerLiteralExpression : Sequence<LiteralExpression> {
let documentation = [{
Expression for integer literals. C++ [lex.icon]
}];
let children = [
Role<"LiteralToken", Token<"numeric_constant">>,
];
}
defvar AnyCharacterLiteral = AnyToken<[
"char_constant", "wide_char_constant", "utf8_char_constant",
"utf16_char_constant", "utf32_char_constant"
]>;
def CharacterLiteralExpression : Sequence<LiteralExpression> {
let documentation = [{
Expression for character literals. C++ [lex.ccon]
}];
let children = [
Role<"LiteralToken", AnyCharacterLiteral>,
];
}
def FloatingLiteralExpression : Sequence<LiteralExpression> {
let documentation = [{
Expression for floating-point literals. C++ [lex.fcon]
}];
let children = [
Role<"LiteralToken", Token<"numeric_constant">>,
];
}
defvar AnyStringLiteral = AnyToken<[
"string_literal", "wide_string_literal", "utf8_string_literal",
"utf16_string_literal", "utf32_string_literal"
]>;
def StringLiteralExpression : Sequence<LiteralExpression> {
let documentation = [{
Expression for string-literals. C++ [lex.string]
}];
// FIXME: string literals may consist of multiple tokens.
// These are merged in phase 6, but tokens are captured after phase 4.
// The child here should be a list of literal tokens instead.
let children = [
Role<"LiteralToken", AnyStringLiteral>,
];
}
def BoolLiteralExpression : Sequence<LiteralExpression> {
let documentation = [{
Expression for boolean literals. C++ [lex.bool]
}];
let children = [
Role<"LiteralToken", AnyToken<["kw_false","kw_true"]>>,
];
}
def CxxNullPtrExpression : Sequence<LiteralExpression> {
let documentation = [{
Expression for the `nullptr` literal. C++ [lex.nullptr]
}];
let children = [
Role<"LiteralToken", Keyword<"nullptr">>,
];
}
def UserDefinedLiteralExpression : Alternatives<LiteralExpression> {
let documentation = [{
Expression for user-defined literal. C++ [lex.ext]
user-defined-literal:
user-defined-integer-literal
user-defined-floating-point-literal
user-defined-string-literal
user-defined-character-literal
}];
}
def IntegerUserDefinedLiteralExpression : Sequence<UserDefinedLiteralExpression> {
let documentation = [{
Expression for user-defined-integer-literal. C++ [lex.ext]
}];
let children = [
Role<"LiteralToken", Keyword<"numeric_constant">>,
];
}
def FloatUserDefinedLiteralExpression : Sequence<UserDefinedLiteralExpression> {
let documentation = [{
Expression for user-defined-floating-point-literal. C++ [lex.ext]
}];
let children = [
Role<"LiteralToken", Keyword<"numeric_constant">>,
];
}
def CharUserDefinedLiteralExpression : Sequence<UserDefinedLiteralExpression> {
let documentation = [{
Expression for user-defined-character-literal. C++ [lex.ext]
}];
let children = [
Role<"LiteralToken", AnyCharacterLiteral>,
];
}
def StringUserDefinedLiteralExpression : Sequence<UserDefinedLiteralExpression> {
let documentation = [{
Expression for user-defined-string-literal. C++ [lex.ext]
}];
let children = [
Role<"LiteralToken", AnyStringLiteral>,
];
}
def IdExpression : Sequence<Expression> {
let documentation = [{
Models an `id-expression`, e.g. `std::vector<int>::size`.
C++ [expr.prim.id]
id-expression:
unqualified-id
qualified-id
qualified-id:
nested-name-specifier template_opt unqualified-id
}];
let children = [
Role<"Qualifier", Optional<NestedNameSpecifier>>,
Role<"TemplateKeyword", Optional<Keyword<"template">>>,
Role<"UnqualifiedId", UnqualifiedId>,
];
}
def MemberExpression : Sequence<Expression> {
let documentation = [{
Models a class member access. C++ [expr.ref]
member-expression:
expression -> template_opt id-expression
expression . template_opt id-expression
e.g. `x.a`, `xp->a`
Note: An implicit member access inside a class, i.e. `a` instead of
`this->a`, is an `id-expression`.
}];
let children = [
Role<"Object", Expression>,
Role<"AccessToken", AnyToken<["period","arrow"]>>,
Role<"TemplateKeyword", Optional<Keyword<"template">>>,
Role<"Member", IdExpression>,
];
}
def ThisExpression : Sequence<Expression> {
let documentation = [{
Models a this expression `this`. C++ [expr.prim.this]
}];
let children = [
Role<"IntroducerKeyword", Keyword<"this">>,
];
}
def CallExpression : Sequence<Expression> {
let documentation = [{
A function call. C++ [expr.call]
call-expression:
expression '(' call-arguments ')'
e.g `f(1, '2')` or `this->Base::f()`
}];
let children = [
Role<"Callee", Expression>,
Role<"OpenParen", Token<"l_paren">>,
Role<"Arguments", CallArguments>,
Role<"CloseParen", Token<"r_paren">>,
];
}
// Statements.
def Statement : External<Tree> {}
def UnknownStatement : External<Statement> {}
def DeclarationStatement : External<Statement> {}
def EmptyStatement : External<Statement> {}
def SwitchStatement : External<Statement> {}
def CaseStatement : External<Statement> {}
def DefaultStatement : External<Statement> {}
def IfStatement : External<Statement> {}
def ForStatement : External<Statement> {}
def WhileStatement : External<Statement> {}
def ContinueStatement : External<Statement> {}
def BreakStatement : External<Statement> {}
def ReturnStatement : External<Statement> {}
def RangeBasedForStatement : External<Statement> {}
def ExpressionStatement : External<Statement> {}
def CompoundStatement : External<Statement> {}
// Declarations.
def Declaration : External<Tree> {}
def UnknownDeclaration : External<Declaration> {}
def EmptyDeclaration : External<Declaration> {}
def StaticAssertDeclaration : External<Declaration> {}
def LinkageSpecificationDeclaration : External<Declaration> {}
def SimpleDeclaration : External<Declaration> {}
def TemplateDeclaration : External<Declaration> {}
def ExplicitTemplateInstantiation : External<Declaration> {}
def NamespaceDefinition : External<Declaration> {}
def NamespaceAliasDefinition : External<Declaration> {}
def UsingNamespaceDirective : External<Declaration> {}
def UsingDeclaration : External<Declaration> {}
def TypeAliasDeclaration : External<Declaration> {}
// Declarators.
def Declarator : External<Tree> {}
def SimpleDeclarator : External<Declarator> {}
def ParenDeclarator : External<Declarator> {}
def ArraySubscript : External<Tree> {}
def TrailingReturnType : External<Tree> {}
def ParametersAndQualifiers : External<Tree> {}
def MemberPointer : External<Tree> {}
// Name Specifiers.
def NameSpecifier : Alternatives {
let documentation = [{
A sequence of these specifiers make a `nested-name-specifier`.
e.g. the `std` or `vector<int>` in `std::vector<int>::size`.
}];
}
def GlobalNameSpecifier : Unconstrained<NameSpecifier> {
let documentation = [{
The global namespace name specifier, this specifier doesn't correspond to a
token instead an absence of tokens before a `::` characterizes it, in
`::std::vector<int>` it would be characterized by the absence of a token
before the first `::`
}];
}
def DecltypeNameSpecifier : Unconstrained<NameSpecifier> {
let documentation = [{
A name specifier holding a decltype, of the form: `decltype ( expression ) `
e.g. the `decltype(s)` in `decltype(s)::size`.
}];
}
def IdentifierNameSpecifier : Unconstrained<NameSpecifier> {
let documentation = [{
A identifier name specifier, of the form `identifier`
e.g. the `std` in `std::vector<int>::size`.
}];
}
def SimpleTemplateNameSpecifier : Unconstrained<NameSpecifier> {
let documentation = [{
A name specifier with a simple-template-id, of the form `template_opt
identifier < template-args >` e.g. the `vector<int>` in
`std::vector<int>::size`.
}];
}