import textwrap from AttributeNodes import ATTRIBUTE_NODES from AvailabilityNodes import AVAILABILITY_NODES from CommonNodes import COMMON_NODES # noqa: I201 from DeclNodes import DECL_NODES # noqa: I201 from ExprNodes import EXPR_NODES # noqa: I201 from GenericNodes import GENERIC_NODES # noqa: I201 from PatternNodes import PATTERN_NODES # noqa: I201 from StmtNodes import STMT_NODES # noqa: I201 import Token from TypeNodes import TYPE_NODES # noqa: I201 # Re-export global constants SYNTAX_NODES = COMMON_NODES + EXPR_NODES + DECL_NODES + ATTRIBUTE_NODES + \ STMT_NODES + GENERIC_NODES + TYPE_NODES + PATTERN_NODES + \ AVAILABILITY_NODES SYNTAX_TOKENS = Token.SYNTAX_TOKENS SYNTAX_TOKEN_MAP = Token.SYNTAX_TOKEN_MAP def make_missing_child(child): """ Generates a C++ call to make the raw syntax for a given Child object. """ if child.is_token(): token = child.main_token() tok_kind = token.kind if token else "unknown" tok_text = token.text if token else "" return 'RawSyntax::missing(tok::%s, "%s")' % (tok_kind, tok_text) else: missing_kind = "Unknown" if child.syntax_kind == "Syntax" \ else child.syntax_kind if child.node_choices: return make_missing_child(child.node_choices[0]) return 'RawSyntax::missing(SyntaxKind::%s)' % missing_kind def check_child_condition_raw(child): """ Generates a C++ closure to check whether a given raw syntax node can satisfy the requirements of child. """ result = '[](const RC &Raw) {\n' result += ' // check %s\n' % child.name if child.token_choices: result += 'if (!Raw->isToken()) return false;\n' result += 'auto TokKind = Raw->getTokenKind();\n' tok_checks = [] for choice in child.token_choices: tok_checks.append("TokKind == tok::%s" % choice.kind) result += 'return %s;\n' % (' || '.join(tok_checks)) elif child.text_choices: result += 'if (!Raw->isToken()) return false;\n' result += 'auto Text = Raw->getTokenText();\n' tok_checks = [] for choice in child.text_choices: tok_checks.append('Text == "%s"' % choice) result += 'return %s;\n' % (' || '.join(tok_checks)) elif child.node_choices: node_checks = [] for choice in child.node_choices: node_checks.append(check_child_condition_raw(choice) + '(Raw)') result += 'return %s;\n' % ((' || ').join(node_checks)) else: result += 'return %s::kindof(Raw->getKind());' % child.type_name result += '}' return result def make_missing_swift_child(child): """ Generates a Swift call to make the raw syntax for a given Child object. """ if child.is_token(): token = child.main_token() tok_kind = token.swift_kind() if token else "unknown" if not token or not token.text: tok_kind += '("")' return 'RawSyntax.missingToken(.%s)' % tok_kind else: missing_kind = "unknown" if child.syntax_kind == "Syntax" \ else child.swift_syntax_kind return 'RawSyntax.missing(.%s)' % missing_kind def create_node_map(): """ Creates a lookup table to find nodes by their kind. """ return {node.syntax_kind: node for node in SYNTAX_NODES} def is_visitable(node): return not node.is_base() def dedented_lines(description): """ Each line of the provided string with leading whitespace stripped. """ if not description: return [] return textwrap.dedent(description).split('\n')