Exemplo n.º 1
0
    def _ParseTerm(self, must=False):
        """Parses a [-]<key> <operator> <operand> term.

    Args:
      must: Raises ExpressionSyntaxError if must is True and there is no
        expression.

    Raises:
      ExpressionSyntaxError: The expression has a syntax error.

    Returns:
      The new backend expression tree.
    """
        here = self._lex.GetPosition()
        if not self._lex.SkipSpace():
            if must:
                raise resource_exceptions.ExpressionSyntaxError(
                    'Term expected [{0}].'.format(self._lex.Annotate(here)))
            return None

        # Check for end of (...) term.
        if self._lex.IsCharacter(')', peek=True):
            # The caller will determine if this ends (...) or is a syntax error.
            return None

        # Check for start of (...) term.
        if self._lex.IsCharacter('('):
            self._parenthesize.append(set())
            tree = self._ParseExpr()
            # Either the next char is ')' or we hit an end of expression syntax error.
            self._lex.IsCharacter(')')
            self._parenthesize.pop()
            return tree

        # Check for term inversion.
        invert = self._lex.IsCharacter('-')

        # Parse the key.
        key, transform = self._ParseKey()

        # Parse the operator.
        here = self._lex.GetPosition()
        operator = self._ParseOperator()
        if not operator:
            if transform and not key:
                # A global restriction function.
                tree = self._backend.ExprGlobal(transform)
            elif not transform and len(key) == 1:
                # A global restriction on key[0].
                func_name = 'global'
                func = self._defaults.symbols.get(func_name, None)
                if not func:
                    raise resource_exceptions.ExpressionSyntaxError(
                        'Global restriction not supported [{0}].'.format(
                            self._lex.Annotate(here)))
                transform = resource_lex.MakeTransform(func_name,
                                                       func,
                                                       args=key,
                                                       restriction=True)
                tree = self._backend.ExprGlobal(transform)
            else:
                raise resource_exceptions.ExpressionSyntaxError(
                    'Operator expected [{0}].'.format(
                        self._lex.Annotate(here)))
            if invert:
                tree = self._backend.ExprNOT(tree)
            return tree

        # Parse the operand.
        self._lex.SkipSpace(token='Operand')
        here = self._lex.GetPosition()
        if any([self._lex.IsString(x) for x in self._LOGICAL]):
            raise resource_exceptions.ExpressionSyntaxError(
                'Logical operator not expected [{0}].'.format(
                    self._lex.Annotate(here)))
        # The '=' and ':' operators accept '('...')' list operands.
        if (operator in (self._backend.ExprEQ, self._backend.ExprHAS)
                and self._lex.IsCharacter('(')):
            # List valued operand.
            operand = self._lex.Args(separators=' \t\n,')
        else:
            operand = self._lex.Token('()')
        if operand is None:
            raise resource_exceptions.ExpressionSyntaxError(
                'Term operand expected [{0}].'.format(
                    self._lex.Annotate(here)))

        # Make an Expr node for the term.
        tree = operator(key=key,
                        operand=self._backend.ExprOperand(operand),
                        transform=transform)
        if invert:
            tree = self._backend.ExprNOT(tree)
        return tree
Exemplo n.º 2
0
  def _ParseTerm(self, must=False):
    """Parses a [-]<key> <operator> <operand> term.

    Args:
      must: Raises ExpressionSyntaxError if must is True and there is no
        expression.

    Raises:
      ExpressionSyntaxError: The expression has a syntax error.

    Returns:
      The new backend expression tree.
    """
    here = self._lex.GetPosition()
    if not self._lex.SkipSpace():
      if must:
        raise resource_exceptions.ExpressionSyntaxError(
            'Term expected [{0}].'.format(self._lex.Annotate(here)))
      return None

    # Check for end of (...) term.
    if self._lex.IsCharacter(')', peek=True):
      # The caller will determine if this ends (...) or is a syntax error.
      return None

    # Check for start of (...) term.
    if self._lex.IsCharacter('('):
      self._parenthesize.append(set())
      tree = self._ParseExpr()
      # Either the next char is ')' or we hit an end of expression syntax error.
      self._lex.IsCharacter(')')
      self._parenthesize.pop()
      return tree

    # Check for term inversion.
    invert = self._lex.IsCharacter('-')

    # Parse the key.
    here = self._lex.GetPosition()
    syntax_error = None
    try:
      key, transform = self._ParseKey()
      restriction = None
    except resource_exceptions.ExpressionSyntaxError as syntax_error:
      # An invalid key could be a global restriction.
      self._lex.SetPosition(here)
      restriction = self._lex.Token(resource_lex.OPERATOR_CHARS, space=False)
      transform = None
      key = None

    # Parse the operator.
    here = self._lex.GetPosition()
    operator = self._ParseOperator()
    if not operator:
      if transform and not key:
        # A global restriction function.
        tree = self._backend.ExprGlobal(transform)
      elif transform:
        # key.transform() must be followed by an operator.
        raise resource_exceptions.ExpressionSyntaxError(
            'Operator expected [{0}].'.format(self._lex.Annotate(here)))
      elif restriction in ['AND', 'OR']:
        raise resource_exceptions.ExpressionSyntaxError(
            'Term expected [{0}].'.format(self._lex.Annotate()))
      else:
        # A global restriction on key.
        if not restriction:
          restriction = resource_lex.GetKeyName(key, quote=False)
        pattern = re.compile(re.escape(restriction), re.IGNORECASE)
        name = resource_projection_spec.GLOBAL_RESTRICTION_NAME
        tree = self._backend.ExprGlobal(
            resource_lex.MakeTransform(
                name,
                self._defaults.symbols.get(
                    name,
                    resource_property.EvaluateGlobalRestriction),
                args=[restriction, pattern]))
      if invert:
        tree = self._backend.ExprNOT(tree)
      return tree
    elif syntax_error:
      raise syntax_error  # pylint: disable=raising-bad-type

    # Parse the operand.
    self._lex.SkipSpace(token='Operand')
    here = self._lex.GetPosition()
    if any([self._lex.IsString(x) for x in self._LOGICAL]):
      raise resource_exceptions.ExpressionSyntaxError(
          'Logical operator not expected [{0}].'.format(
              self._lex.Annotate(here)))
    # The '=' and ':' operators accept '('...')' list operands.
    if (operator in (self._backend.ExprEQ, self._backend.ExprHAS) and
        self._lex.IsCharacter('(')):
      # List valued operand.
      operand = [arg for arg in self._lex.Args(separators=' \t\n,')
                 if arg not in self._LOGICAL]
    else:
      operand = self._lex.Token('()')
    if operand is None:
      raise resource_exceptions.ExpressionSyntaxError(
          'Term operand expected [{0}].'.format(self._lex.Annotate(here)))

    # Make an Expr node for the term.
    tree = operator(key=key, operand=self._backend.ExprOperand(operand),
                    transform=transform)
    if invert:
      tree = self._backend.ExprNOT(tree)
    return tree