Esempio n. 1
0
    def parse(cls, ctx, tokens, npargs, kwargs, flags, breakstack):
        """
    Standard parser for the commands in the form of::

        command_name(parg1 parg2 parg3...
                    KEYWORD1 kwarg1 kwarg2...
                    KEYWORD2 kwarg3 kwarg4...
                    FLAG1 FLAG2 FLAG3)

    The parser starts off as a positional parser. If a keyword or flag is
    encountered the positional parser is popped off the parse stack. If it was
    a keyword then the keyword parser is pushed on the parse stack. If it was
    a flag than a new flag parser is pushed onto the stack.
    """
        if isinstance(npargs, IMPLICIT_PARG_TYPES):
            pargspecs = [PositionalSpec(npargs, flags=flags, legacy=True)]
        else:
            assert isinstance(npargs, (list, tuple)), (
                "Invalid positional group specification of type {}".format(
                    type(npargs).__name__))
            assert flags is None, (
                "Invalid usage of old-style 'flags' parameter with new style"
                " positional group specifications")
            pargspecs = npargs

        return cls.parse2(ctx, tokens, CommandSpec("<none>", pargspecs),
                          kwargs, breakstack)
Esempio n. 2
0
def parse_pspec(pargs, flags):
    """
  Parse a positional argument specification.
  """
    out = []

    # Default pargs is "*"
    if pargs is None:
        pargs = ZERO_OR_MORE

    # If we only have one scalar specification, return a legacy specification
    if isinstance(pargs, STRING_TYPES + (int, )):
        return [PositionalSpec(pargs, flags=flags, legacy=True)]

    if flags:
        raise UserError(
            "Illegal use of top-level 'flags' keyword with new-style positional"
            " argument declaration")

    # If we only have one dictionary specification, then put it in a dictionary
    # so that we can do the rest consistently
    if isinstance(pargs, dict):
        pargs = [pargs]

    for pargdecl in pargs:
        if isinstance(pargdecl, STRING_TYPES + (int, )):
            # A scalar declaration is interpreted as npargs
            out.append(PositionalSpec(pargdecl))
            continue

        if isinstance(pargdecl, dict):
            # A dictionary is interpreted as init kwargs
            if "npargs" not in pargdecl:
                pargdecl = dict(pargdecl)
                pargdecl["nargs"] = ZERO_OR_MORE
            out.append(PositionalSpec(**pargdecl))
            continue

        if isinstance(pargdecl, (list, tuple)):
            # A list or tuple is interpreted as (*args, [kwargs])
            args = list(pargdecl)
            kwargs = {}
            if isinstance(args[-1], dict):
                kwargs = args.pop(-1)
            out.append(PositionalSpec(*args, **kwargs))

    return out
Esempio n. 3
0
  def __init__(self, pspec=None, kwargs=None, doc=None):
    if pspec is None:
      pspec = PositionalSpec("*")
    if kwargs is None:
      kwargs = {}

    self.pspec = pspec
    self.kwargs = kwargs
    self.doc = doc
Esempio n. 4
0
  def parse(cls, ctx, tokens, npargs, flags, breakstack, sortable=False,
            tags=None):
    """
    Parse a continuous sequence of `npargs` positional arguments. If npargs is
    an integer we will consume exactly that many arguments. If it is not an
    integer then it is a string meaning:

    * "?": zero or one
    * "*": zero or more
    * "+": one or more
    """

    spec = PositionalSpec(npargs, sortable, tags, flags)
    return cls.parse2(ctx, tokens, spec, breakstack)
Esempio n. 5
0
    get_tag,
    npargs_is_exact,
    pargs_are_full,
    IMPLICIT_PARG_TYPES,
    CommandSpec,
    PositionalSpec,
    WHITESPACE_TOKENS,
    should_break,
)
from cmake_format.parse.common import (NodeType, ParenBreaker, KwargBreaker,
                                       TreeNode)
from cmake_format.parse.simple_nodes import CommentNode, OnOffNode

logger = logging.getLogger(__name__)

DEFAULT_PSPEC = PositionalSpec("*")


class ArgGroupNode(TreeNode):
    """A group-of-groups. Top-level for the argument subtree of a statement, as
     well as the argument subtree of a keyword."""
    def __init__(self):
        super(ArgGroupNode, self).__init__(NodeType.ARGGROUP)


class StandardArgTree(ArgGroupNode):
    """Argument tree for most cmake-statement commands. Generically arguments
     are composed of a positional argument list, followed by one or more
     keyword arguments, followed by one or more flags::

      command_name(parg1 parg2 parg3...
Esempio n. 6
0
def parse_add_library_standard(ctx, tokens, breakstack, sortable):
    """
  ::

    add_library(<name> [STATIC | SHARED | MODULE]
               [EXCLUDE_FROM_ALL]
               source1 [source2 ...])

  :see: https://cmake.org/cmake/help/v3.0/command/add_library.html
  """
    # pylint: disable=too-many-statements

    parsing_name = 1
    parsing_type = 2
    parsing_flag = 3
    parsing_sources = 4

    tree = TreeNode(NodeType.ARGGROUP)

    # If it is a whitespace token then put it directly in the parse tree at
    # the current depth
    while tokens and tokens[0].type in WHITESPACE_TOKENS:
        tree.children.append(tokens.pop(0))
        continue

    state_ = parsing_name
    parg_group = None
    src_group = None
    active_depth = tree

    flags = ("STATIC", "SHARED", "MODULE", "OBJECT")

    while tokens:
        # This parse function breakson the first right paren, since parenthetical
        # groups are not allowed. A parenthesis might exist in a filename, but
        # if so that filename should be quoted so it wont show up as a RIGHT_PAREN
        # token.
        if tokens[0].type is TokenType.RIGHT_PAREN:
            break

        # If it is a whitespace token then put it directly in the parse tree at
        # the current depth
        if tokens[0].type in WHITESPACE_TOKENS:
            active_depth.children.append(tokens.pop(0))
            continue

        # If it's a comment token not associated with an argument, then put it
        # directly into the parse tree at the current depth
        if tokens[0].type in (TokenType.COMMENT, TokenType.BRACKET_COMMENT):
            if state_ > parsing_name:
                if get_tag(tokens[0]) in ("unsort", "unsortable"):
                    sortable = False
                elif get_tag(tokens[0]) in ("sort", "sortable"):
                    sortable = True
            child = TreeNode(NodeType.COMMENT)
            active_depth.children.append(child)
            child.children.append(tokens.pop(0))
            continue

        if state_ is parsing_name:
            token = tokens.pop(0)
            parg_group = PositionalGroupNode()
            parg_group.spec = PositionalSpec("+")
            active_depth = parg_group
            tree.children.append(parg_group)
            child = TreeNode(NodeType.ARGUMENT)
            child.children.append(token)
            CommentNode.consume_trailing(ctx, tokens, child)
            parg_group.children.append(child)
            state_ += 1
        elif state_ is parsing_type:
            if get_normalized_kwarg(tokens[0]) in flags:
                token = tokens.pop(0)
                child = TreeNode(NodeType.FLAG)
                child.children.append(token)
                CommentNode.consume_trailing(ctx, tokens, child)
                parg_group.children.append(child)
            state_ += 1
        elif state_ is parsing_flag:
            if get_normalized_kwarg(tokens[0]) == "EXCLUDE_FROM_ALL":
                token = tokens.pop(0)
                child = TreeNode(NodeType.FLAG)
                child.children.append(token)
                CommentNode.consume_trailing(ctx, tokens, child)
                parg_group.children.append(child)
            state_ += 1
            src_group = PositionalGroupNode(sortable=sortable,
                                            tags=["file-list"])
            src_group.spec = PositionalSpec("+")
            active_depth = src_group
            tree.children.append(src_group)
        elif state_ is parsing_sources:
            token = tokens.pop(0)
            child = TreeNode(NodeType.ARGUMENT)
            child.children.append(token)
            CommentNode.consume_trailing(ctx, tokens, child)
            src_group.children.append(child)

            if only_comments_and_whitespace_remain(tokens, breakstack):
                active_depth = tree

    return tree