blob: 2da0c1452b86079151878505f4ac7a12394df54d [file] [log] [blame]
//===- - TableGen metamodel for syntax::Node hierarchy ----------===//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// The tree representation of the is C++ syntax is quite regular.
// There are 4 archetypes of nodes in the syntax tree:
// - Leaves, owning exactly one token. (syntax::Leaf)
// - Sequences, with a fixed list of children that should appear in order.
// The concrete node defines a Role sequence which identifies the children.
// The type of child in each role is also constrained.
// - Lists, with children in alternating Element/Delimiter roles. (syntax::List)
// The concrete node defines the element type, delimiters are always leaves.
// - Alternatives, where several different node types are allowed.
// These are modeled as abstract types with inheritance (e.g. Declaration).
// This file defines TableGen classes modelling these archetypes.
// The concrete nodes are defined in terms of these classes in
// 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.
// Syntax is any constraint on constructs that can appear somewhere.
class Syntax;
class Optional<Syntax inner_> : Syntax { Syntax inner = inner_; }
class AnyToken<list<string> kinds_> : Syntax { list<string> kinds = kinds_; }
class Token<string kind_> : AnyToken<[kind_]>;
class Keyword<string kw> : Token<!strconcat("kw_", kw)>;
// Defs derived from NodeType correspond to syntax tree node types.
// NodeType is also a syntax constraint: one node of this type.
class NodeType : Syntax {
// The NodeType that this node is derived from in the Node class hierarchy.
NodeType base = ?;
// Documentation for this Node subclass.
string documentation;
// A node type which is defined in Nodes.h rather than by generated code.
// We merely specify the inheritance hierarchy here.
class External<NodeType base_> : NodeType { let base = base_; }
// Special nodes defined here.
def Node : External<?> {}
def Leaf : External<Node> {}
def Tree : External<Node> {}
// An abstract node type which merely serves as a base for more specific types.
// This corresponds to an alternative rule in the grammar, such as:
// Statement = IfStatement | ForStatement | ...
// Statement is modeled using Alternatives, and IfStatement.base is Statement.
class Alternatives<NodeType base_ = Tree> : NodeType { let base = base_; }
// A node type which may contain anything and has no specific accessors.
// These are generally placeholders for a more precise implementation.
class Unconstrained<NodeType base_ = Tree> : NodeType { let base = base_; }
class Role<string role_, Syntax syntax_> {
string role = role_;
Syntax syntax = syntax_;
// A node which contains a fixed sequence of children in a particular order.
// Each child is characterized by a role (unique within the sequence), and
// has an allowed base type for the node.
// The role sequence and role/type match are enforced invariants of the class.
// We also record whether the child is required to be present, and which tokens
// are permitted (for Leaf nodes). These invariants are not enforced.
class Sequence<NodeType base_ = Tree> : NodeType {
let base = base_;
// Children must be Role or have a default role derived from the NodeType.
list<Role> children;
// FIXME: add list archetype.