mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
237 lines
8.1 KiB
Swift
237 lines
8.1 KiB
Swift
%{
|
|
# -*- mode: Swift -*-
|
|
from gyb_syntax_support import *
|
|
from gyb_syntax_support.Traits import TRAITS
|
|
NODE_MAP = create_node_map()
|
|
# Ignore the following admonition it applies to the resulting .swift file only
|
|
}%
|
|
//// Automatically Generated From SyntaxNodes.swift.gyb.
|
|
//// Do Not Edit Directly!
|
|
//===------------ SyntaxNodes.swift - Syntax Node definitions -------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
%{
|
|
"""
|
|
Each Syntax node implements the protocol of a more generic node. For example,
|
|
StructDeclSyntax implements DeclSyntax and can be used in contexts
|
|
where DeclSyntax is expected.
|
|
|
|
Each node will have:
|
|
- An accessor for each child that will lazily instantiate it.
|
|
- A `withX(_ x: XSyntax)` method for each child that will return a new Syntax
|
|
node with the existing X child replaced with the passed-in version. This is a
|
|
way to incrementally transform nodes in the tree.
|
|
- An `addX(_ x: XSyntax)` method for children that are collections. This will
|
|
append the provided node to the collection and return a new node with that
|
|
collection replaced.
|
|
- (in DEBUG mode) a `validate()` method that's called in the initializer. This
|
|
only validates that all the children are the right kind/token, and does not
|
|
raise an error if, say, a non-optional child is missing.
|
|
"""
|
|
}%
|
|
|
|
/// A wrapper around a raw Syntax layout.
|
|
public struct UnknownSyntax: _SyntaxBase {
|
|
let _root: SyntaxData
|
|
unowned let _data: SyntaxData
|
|
|
|
/// Creates an `UnknownSyntax` node from the provided root and data.
|
|
internal init(root: SyntaxData, data: SyntaxData) {
|
|
self._root = root
|
|
self._data = data
|
|
#if DEBUG
|
|
validate()
|
|
#endif
|
|
}
|
|
}
|
|
|
|
% for node in SYNTAX_NODES:
|
|
% base_type = node.base_type
|
|
% if node.is_base():
|
|
% for line in dedented_lines(node.description):
|
|
/// ${line}
|
|
% end
|
|
public protocol ${node.name}: Syntax {}
|
|
|
|
% elif node.collection_element:
|
|
% pass
|
|
% else:
|
|
|
|
% for line in dedented_lines(node.description):
|
|
/// ${line}
|
|
% end
|
|
public struct ${node.name}: ${base_type}, _SyntaxBase, Hashable {
|
|
% if node.children:
|
|
enum Cursor: Int {
|
|
% for child in node.children:
|
|
case ${child.swift_name}
|
|
% end
|
|
}
|
|
% end
|
|
|
|
let _root: SyntaxData
|
|
unowned let _data: SyntaxData
|
|
|
|
/// Creates a `${node.name}` node from the provided root and data.
|
|
internal init(root: SyntaxData, data: SyntaxData) {
|
|
self._root = root
|
|
self._data = data
|
|
#if DEBUG
|
|
validate()
|
|
#endif
|
|
}
|
|
|
|
% if node.requires_validation():
|
|
#if DEBUG
|
|
func validate() {
|
|
if isMissing { return }
|
|
precondition(raw.layout.count == ${len(node.children)})
|
|
% for child in node.children:
|
|
% child_var = '_' + child.swift_name
|
|
let ${child_var} = raw[Cursor.${child.swift_syntax_kind}]
|
|
% if child.token_choices:
|
|
% choices = ["." + choice.swift_kind() for choice in child.token_choices]
|
|
% choice_array = "[%s]" % ', '.join(choices)
|
|
guard let ${child_var}TokenKind = ${child_var}.tokenKind else {
|
|
fatalError("expected token child, got \(${child_var}.kind)")
|
|
}
|
|
precondition(${choice_array}.contains(${child_var}TokenKind),
|
|
"expected one of ${choice_array} for '${child.swift_name}' " +
|
|
"in node of kind ${node.swift_syntax_kind}")
|
|
% elif child.text_choices:
|
|
% choices = ", ".join("\"%s\"" % choice
|
|
% for choice in child.text_choices)
|
|
guard let ${child_var}TokenKind = ${child_var}.tokenKind else {
|
|
fatalError("expected token child, got \(${child_var}.kind)")
|
|
}
|
|
precondition([${choices}].contains(${child_var}TokenKind.text),
|
|
"expected one of '[${', '.join(child.text_choices)}]', got " +
|
|
"'\(${child_var}TokenKind.text)'")
|
|
% else:
|
|
precondition(${child_var}.kind == .${child.swift_syntax_kind},
|
|
"expected child of kind .${child.swift_syntax_kind}, " +
|
|
"got \(${child_var}.kind)")
|
|
% end
|
|
% end
|
|
}
|
|
#endif
|
|
% end
|
|
% for child in node.children:
|
|
% ret_type = child.type_name
|
|
% cast_symbol = 'as!'
|
|
% if child.is_optional:
|
|
% ret_type += '?'
|
|
% cast_symbol = 'as?'
|
|
% end
|
|
% cast = '' if child.type_name == 'Syntax' \
|
|
% else '%s %s' % (cast_symbol, child.type_name)
|
|
% for line in dedented_lines(child.description):
|
|
/// ${line}
|
|
% end
|
|
public var ${child.swift_name}: ${ret_type} {
|
|
let child = data.cachedChild(at: Cursor.${child.swift_name})
|
|
% if child.is_optional:
|
|
if child == nil { return nil }
|
|
% end
|
|
return makeSyntax(root: _root, data: child!) ${cast}
|
|
}
|
|
% child_node = NODE_MAP.get(child.syntax_kind)
|
|
% if child_node and child_node.is_syntax_collection():
|
|
% child_elt = child_node.collection_element_name
|
|
% child_elt_type = child_node.collection_element_type
|
|
|
|
/// Adds the provided `${child_elt}` to the node's `${child.swift_name}`
|
|
/// collection.
|
|
/// - param element: The new `${child_elt}` to add to the node's
|
|
/// `${child.swift_name}` collection.
|
|
/// - returns: A copy of the receiver with the provided `${child_elt}`
|
|
/// appended to its `${child.swift_name}` collection.
|
|
public func add${child_elt}(_ element: ${child_elt_type}) -> ${node.name} {
|
|
var collection: RawSyntax
|
|
if let col = raw[Cursor.${child.swift_name}] {
|
|
collection = col.appending(element.raw)
|
|
} else {
|
|
collection = RawSyntax.node(SyntaxKind.${child_node.swift_syntax_kind},
|
|
[element.raw], .present)
|
|
}
|
|
let (root, newData) = data.replacingChild(collection,
|
|
at: Cursor.${child.swift_name})
|
|
return ${node.name}(root: root, data: newData)
|
|
}
|
|
% end
|
|
|
|
/// Returns a copy of the receiver with its `${child.swift_name}` replaced.
|
|
/// - param newChild: The new `${child.swift_name}` to replace the node's
|
|
/// current `${child.swift_name}`, if present.
|
|
public func with${child.name}(
|
|
_ newChild: ${child.type_name}?) -> ${node.name} {
|
|
let raw = newChild?.raw ?? ${make_missing_swift_child(child)}
|
|
let (root, newData) = data.replacingChild(raw,
|
|
at: Cursor.${child.swift_name})
|
|
return ${node.name}(root: root, data: newData)
|
|
}
|
|
% end
|
|
|
|
/// Determines if two `${node.name}` nodes are equal to each other.
|
|
public static func ==(lhs: ${node.name}, rhs: ${node.name}) -> Bool {
|
|
return lhs._data === rhs._data
|
|
}
|
|
|
|
/// A unique hash value for this node.
|
|
public var hashValue: Int {
|
|
return ObjectIdentifier(_data).hashValue
|
|
}
|
|
}
|
|
|
|
% end
|
|
% end
|
|
|
|
% for trait in TRAITS:
|
|
public protocol ${trait.trait_name}Syntax: Syntax {
|
|
% for child in trait.children:
|
|
% ret_type = child.type_name
|
|
% if child.is_optional:
|
|
% ret_type += '?'
|
|
% end
|
|
var ${child.swift_name}: ${ret_type} { get }
|
|
func with${child.name}(_ newChild: ${child.type_name}?) -> Self
|
|
% end
|
|
}
|
|
% end
|
|
|
|
% for node in SYNTAX_NODES:
|
|
% base_type = node.base_type
|
|
% if node.is_base():
|
|
% pass
|
|
% elif node.collection_element:
|
|
% pass
|
|
% elif node.traits:
|
|
% traits_list = ", ".join(trait + 'Syntax' for trait in node.traits)
|
|
extension ${node.name}: ${traits_list} {}
|
|
% end
|
|
% end
|
|
|
|
/// MARK: Convenience methods
|
|
|
|
extension StructDeclSyntax {
|
|
/// Creates a new StructDeclSyntax with the provided name as its identifier.
|
|
/// - param name: The new struct's name.
|
|
/// - returns: A new StructDeclSyntax with the same fields as the receiver,
|
|
/// but with the provided identifier.
|
|
func withIdentifier(_ name: String) -> StructDeclSyntax {
|
|
let newToken = SyntaxFactory.makeIdentifier(name,
|
|
leadingTrivia: identifier.leadingTrivia,
|
|
trailingTrivia: identifier.trailingTrivia)
|
|
return withIdentifier(newToken)
|
|
}
|
|
}
|