blob: ce7620b505dabf14df58b36300c4388550599e07 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_FIDL_FIDLC_INCLUDE_FIDL_RAW_AST_H_
#define TOOLS_FIDL_FIDLC_INCLUDE_FIDL_RAW_AST_H_
#include <cassert>
#include <memory>
#include <optional>
#include <utility>
#include <variant>
#include <vector>
#include "source_span.h"
#include "token.h"
#include "types.h"
#include "utils.h"
// ASTs fresh out of the oven. This is a tree-shaped bunch of nodes
// pretty much exactly corresponding to the grammar of a single fidl
// file. File is the root of the tree, and consists of lists of
// Declarations, and so on down to individual SourceSpans.
// See
// https://fuchsia.dev/fuchsia-src/development/languages/fidl/reference/compiler#compiler_internals
// for additional context
// Each node owns its children via unique_ptr and vector. All tokens
// here, like everywhere in the fidl compiler, are backed by a string
// view whose contents are owned by a SourceManager.
// This class has a tight coupling with the TreeVisitor class. Each node has a
// corresponding method in that class. Each node type also has an Accept()
// method to help visitors visit the node. When you add a new node, or add a
// field to an existing node, you must ensure the Accept method works.
// A raw::File is produced by parsing a token stream. All of the
// Files in a library are then flattened out into a Library.
namespace fidl {
namespace raw {
// In order to be able to associate AST nodes with their original source, each
// node is a SourceElement, which contains information about the original
// source. The AST has a start token, whose previous_end field points to the
// end of the previous AST node, and an end token, which points to the end of
// this syntactic element.
//
// Note: The file may have a tail of whitespace / comment text not explicitly
// associated with any node. In order to reconstruct that text, raw::File
// contains an end token; the previous_end field of that token points to the end
// of the last interesting token.
class TreeVisitor;
class SourceElement {
public:
explicit SourceElement(SourceElement const& element)
: start_(element.start_), end_(element.end_) {}
explicit SourceElement(Token start, Token end) : start_(start), end_(end) {}
bool has_span() const {
return start_.span().valid() && end_.span().valid() &&
&start_.span().source_file() == &end_.span().source_file();
}
SourceSpan span() const {
if (!start_.span().valid() || !end_.span().valid()) {
return SourceSpan();
}
assert(has_span());
const char* start_pos = start_.span().data().data();
const char* end_pos = end_.span().data().data() + end_.span().data().length();
return SourceSpan(std::string_view(start_pos, end_pos - start_pos),
start_.span().source_file());
}
std::string copy_to_str() const {
const char* start_pos = start_.span().data().data();
const char* end_pos = end_.span().data().data() + end_.span().data().length();
return std::string(start_pos, end_pos);
}
void update_span(SourceElement const& element) {
start_ = element.start_;
end_ = element.end_;
}
virtual ~SourceElement() {}
Token start_;
Token end_;
};
class SourceElementMark {
public:
SourceElementMark(TreeVisitor* tv, const SourceElement& element);
~SourceElementMark();
private:
TreeVisitor* tv_;
const SourceElement& element_;
};
class Identifier final : public SourceElement {
public:
explicit Identifier(SourceElement const& element) : SourceElement(element) {}
void Accept(TreeVisitor* visitor) const;
};
class CompoundIdentifier final : public SourceElement {
public:
CompoundIdentifier(SourceElement const& element,
std::vector<std::unique_ptr<Identifier>> components)
: SourceElement(element), components(std::move(components)) {}
void Accept(TreeVisitor* visitor) const;
std::vector<std::unique_ptr<Identifier>> components;
};
class Literal : public SourceElement {
public:
enum struct Kind {
kString,
kNumeric,
// TODO(pascallouis): should have kBool instead.
kTrue,
kFalse,
};
explicit Literal(SourceElement const& element, Kind kind) : SourceElement(element), kind(kind) {}
virtual ~Literal() {}
const Kind kind;
};
class StringLiteral final : public Literal {
public:
explicit StringLiteral(SourceElement const& element) : Literal(element, Kind::kString) {}
void Accept(TreeVisitor* visitor) const;
};
class NumericLiteral final : public Literal {
public:
NumericLiteral(SourceElement const& element) : Literal(element, Kind::kNumeric) {}
void Accept(TreeVisitor* visitor) const;
};
class Ordinal64 final : public SourceElement {
public:
Ordinal64(SourceElement const& element, uint64_t value) : SourceElement(element), value(value) {}
void Accept(TreeVisitor* visitor) const;
const uint64_t value;
};
class TrueLiteral final : public Literal {
public:
TrueLiteral(SourceElement const& element) : Literal(element, Kind::kTrue) {}
void Accept(TreeVisitor* visitor) const;
};
class FalseLiteral final : public Literal {
public:
FalseLiteral(SourceElement const& element) : Literal(element, Kind::kFalse) {}
void Accept(TreeVisitor* visitor) const;
};
class Constant : public SourceElement {
public:
enum class Kind { kIdentifier, kLiteral, kBinaryOperator };
explicit Constant(Token token, Kind kind) : SourceElement(token, token), kind(kind) {}
explicit Constant(const SourceElement& element, Kind kind) : SourceElement(element), kind(kind) {}
virtual ~Constant() {}
const Kind kind;
};
class IdentifierConstant final : public Constant {
public:
explicit IdentifierConstant(std::unique_ptr<CompoundIdentifier> identifier)
: Constant(SourceElement(identifier->start_, identifier->end_), Kind::kIdentifier),
identifier(std::move(identifier)) {}
std::unique_ptr<CompoundIdentifier> identifier;
void Accept(TreeVisitor* visitor) const;
};
class LiteralConstant final : public Constant {
public:
explicit LiteralConstant(std::unique_ptr<Literal> literal)
: Constant(literal->start_, Kind::kLiteral), literal(std::move(literal)) {}
std::unique_ptr<Literal> literal;
void Accept(TreeVisitor* visitor) const;
};
class BinaryOperatorConstant final : public Constant {
public:
enum class Operator { kOr };
explicit BinaryOperatorConstant(std::unique_ptr<Constant> left_operand,
std::unique_ptr<Constant> right_operand, Operator op)
: Constant(SourceElement(left_operand->start_, right_operand->end_), Kind::kBinaryOperator),
left_operand(std::move(left_operand)),
right_operand(std::move(right_operand)),
op(op) {}
std::unique_ptr<Constant> left_operand;
std::unique_ptr<Constant> right_operand;
Operator op;
void Accept(TreeVisitor* visitor) const;
};
class Attribute final : public SourceElement {
public:
Attribute(SourceElement const& element, std::string name, std::string value)
: SourceElement(element), name(std::move(name)), value(std::move(value)) {}
void Accept(TreeVisitor* visitor) const;
const std::string name;
const std::string value;
};
class AttributeList final : public SourceElement {
public:
AttributeList(SourceElement const& element, std::vector<Attribute> attributes)
: SourceElement(element), attributes(std::move(attributes)) {}
bool HasAttribute(std::string name) const {
for (const auto& attribute : attributes) {
if (attribute.name == name)
return true;
}
return false;
}
void Accept(TreeVisitor* visitor) const;
std::vector<Attribute> attributes;
};
// TODO(fxbug.dev/70247): Remove the two type constructor versions and remove
// the New suffix.
class TypeConstructorOld;
class TypeConstructorNew;
using TypeConstructor =
std::variant<std::unique_ptr<TypeConstructorNew>, std::unique_ptr<TypeConstructorOld>>;
bool IsTypeConstructorDefined(const raw::TypeConstructor& maybe_type_ctor);
class TypeConstructorOld final : public SourceElement {
public:
TypeConstructorOld(SourceElement const& element, std::unique_ptr<CompoundIdentifier> identifier,
std::unique_ptr<TypeConstructorOld> maybe_arg_type_ctor,
std::unique_ptr<Identifier> handle_subtype_identifier,
std::unique_ptr<Constant> handle_rights, std::unique_ptr<Constant> maybe_size,
types::Nullability nullability)
: SourceElement(element),
identifier(std::move(identifier)),
maybe_arg_type_ctor(std::move(maybe_arg_type_ctor)),
handle_subtype_identifier(std::move(handle_subtype_identifier)),
handle_rights(std::move(handle_rights)),
maybe_size(std::move(maybe_size)),
nullability(nullability) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<CompoundIdentifier> identifier;
std::unique_ptr<TypeConstructorOld> maybe_arg_type_ctor;
std::unique_ptr<Identifier> handle_subtype_identifier;
std::unique_ptr<Constant> handle_rights;
std::unique_ptr<Constant> maybe_size;
types::Nullability nullability;
};
class LayoutReference;
class LayoutParameterList;
class TypeConstraints;
class TypeConstructorNew final : public SourceElement {
public:
TypeConstructorNew(SourceElement const& element, std::unique_ptr<LayoutReference> layout_ref,
std::unique_ptr<LayoutParameterList> parameters,
std::unique_ptr<TypeConstraints> constraints)
: SourceElement(element),
layout_ref(std::move(layout_ref)),
parameters(std::move(parameters)),
constraints(std::move(constraints)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<LayoutReference> layout_ref;
std::unique_ptr<LayoutParameterList> parameters;
std::unique_ptr<TypeConstraints> constraints;
};
class BitsMember final : public SourceElement {
public:
BitsMember(SourceElement const& element, std::unique_ptr<Identifier> identifier,
std::unique_ptr<Constant> value, std::unique_ptr<AttributeList> attributes)
: SourceElement(element),
identifier(std::move(identifier)),
value(std::move(value)),
attributes(std::move(attributes)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<Constant> value;
std::unique_ptr<AttributeList> attributes;
};
class BitsDeclaration final : public SourceElement {
public:
BitsDeclaration(SourceElement const& element, std::unique_ptr<Token> decl_start_token,
std::unique_ptr<AttributeList> attributes, std::unique_ptr<Identifier> identifier,
std::unique_ptr<TypeConstructorOld> maybe_type_ctor,
std::vector<std::unique_ptr<BitsMember>> members, types::Strictness strictness)
: SourceElement(element),
decl_start_token(std::move(decl_start_token)),
attributes(std::move(attributes)),
identifier(std::move(identifier)),
maybe_type_ctor(std::move(maybe_type_ctor)),
members(std::move(members)),
strictness(strictness) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Token> decl_start_token;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<TypeConstructorOld> maybe_type_ctor;
std::vector<std::unique_ptr<BitsMember>> members;
const types::Strictness strictness;
};
class AliasDeclaration final : public SourceElement {
public:
AliasDeclaration(SourceElement const& element, std::unique_ptr<AttributeList> attributes,
std::unique_ptr<Identifier> alias, TypeConstructor type_ctor)
: SourceElement(element),
attributes(std::move(attributes)),
alias(std::move(alias)),
type_ctor(std::move(type_ctor)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<Identifier> alias;
TypeConstructor type_ctor;
};
class Using final : public SourceElement {
public:
Using(SourceElement const& element, std::unique_ptr<Token> decl_start_token,
std::unique_ptr<AttributeList> attributes, std::unique_ptr<CompoundIdentifier> using_path,
std::unique_ptr<Identifier> maybe_alias,
std::unique_ptr<TypeConstructorOld> maybe_type_ctor)
: SourceElement(element),
decl_start_token(std::move(decl_start_token)),
attributes(std::move(attributes)),
using_path(std::move(using_path)),
maybe_alias(std::move(maybe_alias)),
maybe_type_ctor(std::move(maybe_type_ctor)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Token> decl_start_token;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<CompoundIdentifier> using_path;
std::unique_ptr<Identifier> maybe_alias;
// TODO(fxbug.dev/7807): Use a special purpose AST element, as is the case in the
// flat AST.
std::unique_ptr<TypeConstructorOld> maybe_type_ctor;
};
class ConstDeclaration final : public SourceElement {
public:
ConstDeclaration(SourceElement const& element, std::unique_ptr<AttributeList> attributes,
TypeConstructor type_ctor, std::unique_ptr<Identifier> identifier,
std::unique_ptr<Constant> constant)
: SourceElement(element),
attributes(std::move(attributes)),
type_ctor(std::move(type_ctor)),
identifier(std::move(identifier)),
constant(std::move(constant)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<AttributeList> attributes;
TypeConstructor type_ctor;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<Constant> constant;
};
class EnumMember final : public SourceElement {
public:
EnumMember(SourceElement const& element, std::unique_ptr<Identifier> identifier,
std::unique_ptr<Constant> value, std::unique_ptr<AttributeList> attributes)
: SourceElement(element),
identifier(std::move(identifier)),
value(std::move(value)),
attributes(std::move(attributes)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<Constant> value;
std::unique_ptr<AttributeList> attributes;
};
class EnumDeclaration final : public SourceElement {
public:
EnumDeclaration(SourceElement const& element, std::unique_ptr<Token> decl_start_token,
std::unique_ptr<AttributeList> attributes, std::unique_ptr<Identifier> identifier,
std::unique_ptr<TypeConstructorOld> maybe_type_ctor,
std::vector<std::unique_ptr<EnumMember>> members, types::Strictness strictness)
: SourceElement(element),
decl_start_token(std::move(decl_start_token)),
attributes(std::move(attributes)),
identifier(std::move(identifier)),
maybe_type_ctor(std::move(maybe_type_ctor)),
members(std::move(members)),
strictness(strictness) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Token> decl_start_token;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<TypeConstructorOld> maybe_type_ctor;
std::vector<std::unique_ptr<EnumMember>> members;
const types::Strictness strictness;
};
class Parameter final : public SourceElement {
public:
Parameter(SourceElement const& element, TypeConstructor type_ctor,
std::unique_ptr<Identifier> identifier, std::unique_ptr<AttributeList> attributes)
: SourceElement(element),
type_ctor(std::move(type_ctor)),
identifier(std::move(identifier)),
attributes(std::move(attributes)) {}
void Accept(TreeVisitor* visitor) const;
TypeConstructor type_ctor;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<AttributeList> attributes;
};
class ParameterList final : public SourceElement {
public:
ParameterList(SourceElement const& element,
std::vector<std::unique_ptr<Parameter>> parameter_list)
: SourceElement(element), parameter_list(std::move(parameter_list)) {}
void Accept(TreeVisitor* visitor) const;
std::vector<std::unique_ptr<Parameter>> parameter_list;
};
class ProtocolMethod : public SourceElement {
public:
ProtocolMethod(SourceElement const& element, std::unique_ptr<AttributeList> attributes,
std::unique_ptr<Identifier> identifier,
std::unique_ptr<ParameterList> maybe_request,
std::unique_ptr<ParameterList> maybe_response,
std::unique_ptr<TypeConstructorOld> maybe_error_ctor)
: SourceElement(element),
attributes(std::move(attributes)),
identifier(std::move(identifier)),
maybe_request(std::move(maybe_request)),
maybe_response(std::move(maybe_response)),
maybe_error_ctor(std::move(maybe_error_ctor)) {
// `maybe_response` must exist if `maybe_error_ctor` is exists.
if (maybe_error_ctor) {
assert(maybe_response);
}
}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<ParameterList> maybe_request;
std::unique_ptr<ParameterList> maybe_response;
std::unique_ptr<TypeConstructorOld> maybe_error_ctor;
};
class ComposeProtocol final : public SourceElement {
public:
ComposeProtocol(SourceElement const& element, std::unique_ptr<CompoundIdentifier> protocol_name)
: SourceElement(element), protocol_name(std::move(protocol_name)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<CompoundIdentifier> protocol_name;
};
class ProtocolDeclaration final : public SourceElement {
public:
ProtocolDeclaration(SourceElement const& element, std::unique_ptr<AttributeList> attributes,
std::unique_ptr<Identifier> identifier,
std::vector<std::unique_ptr<ComposeProtocol>> composed_protocols,
std::vector<std::unique_ptr<ProtocolMethod>> methods)
: SourceElement(element),
attributes(std::move(attributes)),
identifier(std::move(identifier)),
composed_protocols(std::move(composed_protocols)),
methods(std::move(methods)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<Identifier> identifier;
std::vector<std::unique_ptr<ComposeProtocol>> composed_protocols;
std::vector<std::unique_ptr<ProtocolMethod>> methods;
};
class ResourceProperty final : public SourceElement {
public:
ResourceProperty(SourceElement const& element, TypeConstructor type_ctor,
std::unique_ptr<Identifier> identifier,
std::unique_ptr<AttributeList> attributes)
: SourceElement(element),
type_ctor(std::move(type_ctor)),
identifier(std::move(identifier)),
attributes(std::move(attributes)) {}
void Accept(TreeVisitor* visitor) const;
TypeConstructor type_ctor;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<AttributeList> attributes;
};
class ResourceDeclaration final : public SourceElement {
public:
ResourceDeclaration(SourceElement const& element, std::unique_ptr<AttributeList> attributes,
std::unique_ptr<Identifier> identifier, TypeConstructor maybe_type_ctor,
std::vector<std::unique_ptr<ResourceProperty>> properties)
: SourceElement(element),
attributes(std::move(attributes)),
identifier(std::move(identifier)),
maybe_type_ctor(std::move(maybe_type_ctor)),
properties(std::move(properties)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<Identifier> identifier;
TypeConstructor maybe_type_ctor;
std::vector<std::unique_ptr<ResourceProperty>> properties;
};
class ServiceMember final : public SourceElement {
public:
ServiceMember(SourceElement const& element, TypeConstructor type_ctor,
std::unique_ptr<Identifier> identifier, std::unique_ptr<AttributeList> attributes)
: SourceElement(element),
type_ctor(std::move(type_ctor)),
identifier(std::move(identifier)),
attributes(std::move(attributes)) {}
void Accept(TreeVisitor* visitor) const;
TypeConstructor type_ctor;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<AttributeList> attributes;
};
class ServiceDeclaration final : public SourceElement {
public:
ServiceDeclaration(SourceElement const& element, std::unique_ptr<AttributeList> attributes,
std::unique_ptr<Identifier> identifier,
std::vector<std::unique_ptr<ServiceMember>> members)
: SourceElement(element),
attributes(std::move(attributes)),
identifier(std::move(identifier)),
members(std::move(members)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<Identifier> identifier;
std::vector<std::unique_ptr<ServiceMember>> members;
};
class StructMember final : public SourceElement {
public:
StructMember(SourceElement const& element, std::unique_ptr<TypeConstructorOld> type_ctor,
std::unique_ptr<Identifier> identifier,
std::unique_ptr<Constant> maybe_default_value,
std::unique_ptr<AttributeList> attributes)
: SourceElement(element),
type_ctor(std::move(type_ctor)),
identifier(std::move(identifier)),
maybe_default_value(std::move(maybe_default_value)),
attributes(std::move(attributes)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<TypeConstructorOld> type_ctor;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<Constant> maybe_default_value;
std::unique_ptr<AttributeList> attributes;
};
class StructDeclaration final : public SourceElement {
public:
// Note: A nullptr passed to attributes means an empty attribute list.
StructDeclaration(SourceElement const& element, std::unique_ptr<Token> decl_start_token,
std::unique_ptr<AttributeList> attributes,
std::unique_ptr<Identifier> identifier,
std::vector<std::unique_ptr<StructMember>> members,
types::Resourceness resourceness)
: SourceElement(element),
decl_start_token(std::move(decl_start_token)),
attributes(std::move(attributes)),
identifier(std::move(identifier)),
members(std::move(members)),
resourceness(resourceness) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Token> decl_start_token;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<Identifier> identifier;
std::vector<std::unique_ptr<StructMember>> members;
const types::Resourceness resourceness;
};
struct TableMember final : public SourceElement {
TableMember(SourceElement const& element, std::unique_ptr<Ordinal64> ordinal,
std::unique_ptr<TypeConstructorOld> type_ctor, std::unique_ptr<Identifier> identifier,
std::unique_ptr<Constant> maybe_default_value,
std::unique_ptr<AttributeList> attributes)
: SourceElement(element),
ordinal(std::move(ordinal)),
maybe_used(std::make_unique<Used>(std::move(type_ctor), std::move(identifier),
std::move(maybe_default_value), std::move(attributes))) {}
TableMember(SourceElement const& element, std::unique_ptr<Ordinal64> ordinal)
: SourceElement(element), ordinal(std::move(ordinal)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Ordinal64> ordinal;
// A used member is not 'reserved'
struct Used {
Used(std::unique_ptr<TypeConstructorOld> type_ctor, std::unique_ptr<Identifier> identifier,
std::unique_ptr<Constant> maybe_default_value, std::unique_ptr<AttributeList> attributes)
: type_ctor(std::move(type_ctor)),
identifier(std::move(identifier)),
maybe_default_value(std::move(maybe_default_value)),
attributes(std::move(attributes)) {}
std::unique_ptr<TypeConstructorOld> type_ctor;
std::unique_ptr<Identifier> identifier;
// We parse default values on union members so that we can give precise
// errors later in the compiler, but defaults are not supported
std::unique_ptr<Constant> maybe_default_value;
std::unique_ptr<AttributeList> attributes;
};
std::unique_ptr<Used> maybe_used;
};
struct TableDeclaration final : public SourceElement {
TableDeclaration(SourceElement const& element, std::unique_ptr<Token> decl_start_token,
std::unique_ptr<AttributeList> attributes,
std::unique_ptr<Identifier> identifier,
std::vector<std::unique_ptr<TableMember>> members, types::Strictness strictness,
types::Resourceness resourceness)
: SourceElement(element),
decl_start_token(std::move(decl_start_token)),
attributes(std::move(attributes)),
identifier(std::move(identifier)),
members(std::move(members)),
strictness(strictness),
resourceness(resourceness) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Token> decl_start_token;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<Identifier> identifier;
std::vector<std::unique_ptr<TableMember>> members;
const types::Strictness strictness;
const types::Resourceness resourceness;
};
class UnionMember final : public SourceElement {
public:
UnionMember(SourceElement const& element, std::unique_ptr<Ordinal64> ordinal,
std::unique_ptr<TypeConstructorOld> type_ctor, std::unique_ptr<Identifier> identifier,
std::unique_ptr<Constant> maybe_default_value,
std::unique_ptr<AttributeList> attributes)
: SourceElement(element),
ordinal(std::move(ordinal)),
maybe_used(std::make_unique<Used>(std::move(type_ctor), std::move(identifier),
std::move(maybe_default_value), std::move(attributes))) {}
UnionMember(SourceElement const& element, std::unique_ptr<Ordinal64> ordinal)
: SourceElement(element), ordinal(std::move(ordinal)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Ordinal64> ordinal;
// A used member is not 'reserved'
struct Used {
Used(std::unique_ptr<TypeConstructorOld> type_ctor, std::unique_ptr<Identifier> identifier,
std::unique_ptr<Constant> maybe_default_value, std::unique_ptr<AttributeList> attributes)
: type_ctor(std::move(type_ctor)),
identifier(std::move(identifier)),
maybe_default_value(std::move(maybe_default_value)),
attributes(std::move(attributes)) {}
std::unique_ptr<TypeConstructorOld> type_ctor;
std::unique_ptr<Identifier> identifier;
// We parse default values on union members so that we can give precise
// errors later in the compiler, but defaults are not supported
std::unique_ptr<Constant> maybe_default_value;
std::unique_ptr<AttributeList> attributes;
};
std::unique_ptr<Used> maybe_used;
};
class UnionDeclaration final : public SourceElement {
public:
UnionDeclaration(SourceElement const& element, std::unique_ptr<Token> decl_start_token,
std::unique_ptr<AttributeList> attributes,
std::unique_ptr<Identifier> identifier,
std::vector<std::unique_ptr<UnionMember>> members, types::Strictness strictness,
bool strictness_specified, types::Resourceness resourceness)
: SourceElement(element),
decl_start_token(std::move(decl_start_token)),
attributes(std::move(attributes)),
identifier(std::move(identifier)),
members(std::move(members)),
strictness(strictness),
strictness_specified(strictness_specified),
resourceness(resourceness) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Token> decl_start_token;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<Identifier> identifier;
std::vector<std::unique_ptr<UnionMember>> members;
const types::Strictness strictness;
const bool strictness_specified;
const types::Resourceness resourceness;
};
class LayoutMember : public SourceElement {
public:
enum Kind {
kOrdinaled,
kStruct,
kValue,
};
explicit LayoutMember(SourceElement const& element, Kind kind,
std::unique_ptr<Identifier> identifier)
: SourceElement(element), kind(kind), identifier(std::move(identifier)) {}
void Accept(TreeVisitor* visitor) const;
const Kind kind;
std::unique_ptr<Identifier> identifier;
};
class OrdinaledLayoutMember final : public LayoutMember {
public:
explicit OrdinaledLayoutMember(SourceElement const& element, std::unique_ptr<Ordinal64> ordinal,
std::unique_ptr<Identifier> identifier,
std::unique_ptr<TypeConstructorNew> type_ctor)
: LayoutMember(element, Kind::kOrdinaled, std::move(identifier)),
ordinal(std::move(ordinal)),
type_ctor(std::move(type_ctor)) {}
explicit OrdinaledLayoutMember(SourceElement const& element, std::unique_ptr<Ordinal64> ordinal)
: LayoutMember(element, Kind::kOrdinaled, nullptr),
ordinal(std::move(ordinal)),
type_ctor(nullptr),
reserved(true) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Ordinal64> ordinal;
std::unique_ptr<TypeConstructorNew> type_ctor;
const bool reserved = false;
};
class ValueLayoutMember final : public LayoutMember {
public:
explicit ValueLayoutMember(SourceElement const& element, std::unique_ptr<Identifier> identifier,
std::unique_ptr<Constant> value)
: LayoutMember(element, Kind::kValue, std::move(identifier)), value(std::move(value)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Constant> value;
};
class StructLayoutMember final : public LayoutMember {
public:
explicit StructLayoutMember(SourceElement const& element, std::unique_ptr<Identifier> identifier,
std::unique_ptr<TypeConstructorNew> type_ctor,
std::unique_ptr<Constant> default_value)
: LayoutMember(element, Kind::kStruct, std::move(identifier)),
type_ctor(std::move(type_ctor)),
default_value(std::move(default_value)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<TypeConstructorNew> type_ctor;
std::unique_ptr<Constant> default_value;
};
class Layout final : public SourceElement {
public:
enum Kind {
kBits,
kEnum,
kStruct,
kTable,
kUnion,
};
Layout(SourceElement const& element,
// TODO(fxbug.dev/65978): Support layout attributes.
Kind kind, std::vector<std::unique_ptr<LayoutMember>> members,
std::optional<types::Strictness> strictness, types::Resourceness resourceness,
std::unique_ptr<TypeConstructorNew> subtype_ctor)
: SourceElement(element),
kind(kind),
members(std::move(members)),
strictness(strictness),
resourceness(resourceness),
subtype_ctor(std::move(subtype_ctor)) {}
Kind kind;
std::vector<std::unique_ptr<raw::LayoutMember>> members;
std::optional<types::Strictness> strictness;
types::Resourceness resourceness;
// TODO(fxbug.dev/65978): Eventually we'll make [Struct/Ordinaled/Value]Layout
// classes to inherit from the now-abstract Layout class, similar to what can
// currently be seen on LayoutMember and its children. When that happens
// this field will only exist on ValueLayout.
std::unique_ptr<TypeConstructorNew> subtype_ctor;
};
class LayoutReference : public SourceElement {
public:
enum Kind {
kInline,
kNamed,
};
LayoutReference(SourceElement const& element, Kind kind) : SourceElement(element), kind(kind) {}
void Accept(TreeVisitor* visitor) const;
const Kind kind;
};
class InlineLayoutReference final : public LayoutReference {
public:
explicit InlineLayoutReference(SourceElement const& element, std::unique_ptr<Layout> layout)
: LayoutReference(element, Kind::kInline), layout(std::move(layout)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Layout> layout;
};
class NamedLayoutReference final : public LayoutReference {
public:
explicit NamedLayoutReference(SourceElement const& element,
std::unique_ptr<CompoundIdentifier> identifier)
: LayoutReference(element, Kind::kNamed), identifier(std::move(identifier)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<CompoundIdentifier> identifier;
};
class LayoutParameter : public SourceElement {
public:
enum Kind {
kAmbiguous,
kLiteral,
kType,
};
LayoutParameter(SourceElement const& element, Kind kind) : SourceElement(element), kind(kind) {}
void Accept(TreeVisitor* visitor) const;
const Kind kind;
};
class LiteralLayoutParameter final : public LayoutParameter {
public:
explicit LiteralLayoutParameter(SourceElement const& element,
std::unique_ptr<LiteralConstant> literal)
: LayoutParameter(element, Kind::kLiteral), literal(std::move(literal)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<LiteralConstant> literal;
};
class TypeLayoutParameter final : public LayoutParameter {
public:
explicit TypeLayoutParameter(SourceElement const& element,
std::unique_ptr<TypeConstructorNew> type_ctor)
: LayoutParameter(element, Kind::kType), type_ctor(std::move(type_ctor)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<TypeConstructorNew> type_ctor;
};
class AmbiguousLayoutParameter final : public LayoutParameter {
public:
explicit AmbiguousLayoutParameter(SourceElement const& element,
std::unique_ptr<CompoundIdentifier> identifier)
: LayoutParameter(element, Kind::kAmbiguous), identifier(std::move(identifier)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<CompoundIdentifier> identifier;
};
class LayoutParameterList final : public SourceElement {
public:
LayoutParameterList(SourceElement const& element,
std::vector<std::unique_ptr<raw::LayoutParameter>> items)
: SourceElement(element), items(std::move(items)) {}
void Accept(TreeVisitor* visitor) const;
std::vector<std::unique_ptr<raw::LayoutParameter>> items;
};
class TypeConstraints final : public SourceElement {
public:
TypeConstraints(SourceElement const& element, std::vector<std::unique_ptr<raw::Constant>> items)
: SourceElement(element), items(std::move(items)) {}
void Accept(TreeVisitor* visitor) const;
std::vector<std::unique_ptr<raw::Constant>> items;
};
class TypeDecl final : public SourceElement {
public:
TypeDecl(SourceElement const& element,
// TODO(fxbug.dev/65978): Support type decl attributes.
std::unique_ptr<Identifier> identifier,
// TODO(fxbug.dev/65978): We should also allow type decl over type
// constructors, i.e. FTP-052 type declaration.
std::unique_ptr<TypeConstructorNew> type_ctor)
: SourceElement(element),
identifier(std::move(identifier)),
type_ctor(std::move(type_ctor)) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<Identifier> identifier;
std::unique_ptr<TypeConstructorNew> type_ctor;
};
class File final : public SourceElement {
public:
File(SourceElement const& element, Token end, std::unique_ptr<AttributeList> attributes,
std::unique_ptr<CompoundIdentifier> library_name,
std::vector<std::unique_ptr<AliasDeclaration>> alias_list,
std::vector<std::unique_ptr<Using>> using_list,
std::vector<std::unique_ptr<BitsDeclaration>> bits_declaration_list,
std::vector<std::unique_ptr<ConstDeclaration>> const_declaration_list,
std::vector<std::unique_ptr<EnumDeclaration>> enum_declaration_list,
std::vector<std::unique_ptr<ProtocolDeclaration>> protocol_declaration_list,
std::vector<std::unique_ptr<ResourceDeclaration>> resource_declaration_list,
std::vector<std::unique_ptr<ServiceDeclaration>> service_declaration_list,
std::vector<std::unique_ptr<StructDeclaration>> struct_declaration_list,
std::vector<std::unique_ptr<TableDeclaration>> table_declaration_list,
std::vector<std::unique_ptr<UnionDeclaration>> union_declaration_list,
std::vector<std::unique_ptr<TypeDecl>> type_decls,
std::vector<std::unique_ptr<Token>> comment_tokens_list, fidl::utils::Syntax syntax)
: SourceElement(element),
attributes(std::move(attributes)),
library_name(std::move(library_name)),
alias_list(std::move(alias_list)),
using_list(std::move(using_list)),
bits_declaration_list(std::move(bits_declaration_list)),
const_declaration_list(std::move(const_declaration_list)),
enum_declaration_list(std::move(enum_declaration_list)),
protocol_declaration_list(std::move(protocol_declaration_list)),
resource_declaration_list(std::move(resource_declaration_list)),
service_declaration_list(std::move(service_declaration_list)),
struct_declaration_list(std::move(struct_declaration_list)),
table_declaration_list(std::move(table_declaration_list)),
union_declaration_list(std::move(union_declaration_list)),
type_decls(std::move(type_decls)),
comment_tokens_list(std::move(comment_tokens_list)),
end_(end),
syntax(syntax) {}
void Accept(TreeVisitor* visitor) const;
std::unique_ptr<AttributeList> attributes;
std::unique_ptr<CompoundIdentifier> library_name;
std::vector<std::unique_ptr<AliasDeclaration>> alias_list;
std::vector<std::unique_ptr<Using>> using_list;
std::vector<std::unique_ptr<BitsDeclaration>> bits_declaration_list;
std::vector<std::unique_ptr<ConstDeclaration>> const_declaration_list;
std::vector<std::unique_ptr<EnumDeclaration>> enum_declaration_list;
std::vector<std::unique_ptr<ProtocolDeclaration>> protocol_declaration_list;
std::vector<std::unique_ptr<ResourceDeclaration>> resource_declaration_list;
std::vector<std::unique_ptr<ServiceDeclaration>> service_declaration_list;
std::vector<std::unique_ptr<StructDeclaration>> struct_declaration_list;
std::vector<std::unique_ptr<TableDeclaration>> table_declaration_list;
std::vector<std::unique_ptr<UnionDeclaration>> union_declaration_list;
std::vector<std::unique_ptr<TypeDecl>> type_decls;
// TODO(fxbug.dev/70247): this member has been created solely for the benefit
// of fidlconv. Once the conversion using that tool has been completed and
// tool has been removed, this member should be removed as well.
std::vector<std::unique_ptr<Token>> comment_tokens_list;
Token end_;
fidl::utils::Syntax syntax;
};
} // namespace raw
} // namespace fidl
#endif // TOOLS_FIDL_FIDLC_INCLUDE_FIDL_RAW_AST_H_