blob: 7cb5160f769929c6c9b9f6a7257c00cfae6ee43c [file] [log] [blame]
# flake8: noqa I201
from Classification import classification_by_name
from Token import SYNTAX_TOKEN_MAP
from kinds import SYNTAX_BASE_KINDS, kind_to_type, lowercase_first_word
class Child(object):
"""
A child of a node, that may be declared optional or a token with a
restricted subset of acceptable kinds or texts.
"""
def __init__(self, name, kind, description=None, is_optional=False,
token_choices=None, text_choices=None, node_choices=None,
classification=None, force_classification=False):
"""
If a classification is passed, it specifies the color identifiers in
that subtree should inherit for syntax coloring. Must be a member of
SyntaxClassification in SyntaxClassifier.h.gyb
If force_classification is also set to true, all child nodes (not only
identifiers) inherit the syntax classification.
"""
self.name = name
self.swift_name = lowercase_first_word(name)
self.syntax_kind = kind
self.description = description
self.swift_syntax_kind = lowercase_first_word(self.syntax_kind)
self.type_name = kind_to_type(self.syntax_kind)
self.classification = classification_by_name(classification)
self.force_classification = force_classification
# If the child has "token" anywhere in the kind, it's considered
# a token node. Grab the existing reference to that token from the
# global list.
self.token_kind = \
self.syntax_kind if "Token" in self.syntax_kind else None
self.token = SYNTAX_TOKEN_MAP.get(self.token_kind)
self.is_optional = is_optional
# A restricted set of token kinds that will be accepted for this
# child.
self.token_choices = []
if self.token:
self.token_choices.append(self.token)
for choice in token_choices or []:
token = SYNTAX_TOKEN_MAP[choice]
self.token_choices.append(token)
# A list of valid text for tokens, if specified.
# This will force validation logic to check the text passed into the
# token against the choices.
self.text_choices = text_choices or []
# A list of valid choices for a child
self.node_choices = node_choices or []
# Check the choices are either empty or multiple
assert len(self.node_choices) != 1
# Check node choices are well-formed
for choice in self.node_choices:
assert not choice.is_optional, \
"node choice %s cannot be optional" % choice.name
assert not choice.node_choices, \
"node choice %s cannot have further choices" % choice.name
def is_token(self):
"""
Returns true if this child has a token kind.
"""
return self.token_kind is not None
def main_token(self):
"""
Returns the first choice from the token_choices if there are any,
otherwise returns None.
"""
if self.token_choices:
return self.token_choices[0]
return None