Example #1
0
  def testVarOps(self):
    ev = InitEvaluator()  # initializes x=xxx and y=yyy
    unset_sub = braced_var_sub(Tok(Id.VSub_Name, 'unset'))
    part_vals = []
    ev._EvalWordPart(unset_sub, part_vals)
    print(part_vals)

    set_sub = braced_var_sub(Tok(Id.VSub_Name, 'x'))
    part_vals = []
    ev._EvalWordPart(set_sub, part_vals)
    print(part_vals)

    # Now add some ops
    part = Tok(Id.Lit_Chars, 'default')
    arg_word = compound_word([part])
    test_op = suffix_op.Unary(Id.VTest_ColonHyphen, arg_word)
    unset_sub.suffix_op = test_op
    set_sub.suffix_op = test_op

    part_vals = []
    ev._EvalWordPart(unset_sub, part_vals)
    print(part_vals)

    part_vals = []
    ev._EvalWordPart(set_sub, part_vals)
    print(part_vals)
Example #2
0
  def _ParseVarExpr(self, arg_lex_mode, allow_query=False):
    # type: (lex_mode_t, bool) -> braced_var_sub
    """
    Start parsing at the op -- we already skipped past the name.
    """
    part = self._ParseVarOf()

    self._Peek()
    if self.token_type == Id.Right_DollarBrace:
      return part  # no ops

    op_kind = self.token_kind

    if op_kind == Kind.VTest:
      op_id = self.token_type
      arg_word = self._ReadVarOpArg(arg_lex_mode)
      if self.token_type != Id.Right_DollarBrace:
        p_die('Expected } to close ${', token=self.cur_token)

      part.suffix_op = suffix_op.Unary(op_id, arg_word)

    elif op_kind == Kind.VOp0:
      part.suffix_op = self.cur_token  # Nullary
      self._Next(lex_mode_e.VSub_2)  # Expecting }
      self._Peek()

    elif op_kind == Kind.VOp1:  # % %% # ## etc.
      op_id = self.token_type
      # Weird exception that all shells have: these operators take a glob
      # pattern, so they're lexed as VSub_ArgUnquoted, not VSub_ArgDQ
      arg_word = self._ReadVarOpArg(lex_mode_e.VSub_ArgUnquoted)
      if self.token_type != Id.Right_DollarBrace:
        p_die('Expected } to close ${', token=self.cur_token)

      part.suffix_op = suffix_op.Unary(op_id, arg_word)

    elif op_kind == Kind.VOp2:  # / : [ ]
      if self.token_type == Id.VOp2_Slash:
        op_spid = self.cur_token.span_id  # for attributing error to /
        patsub_op = self._ReadPatSubVarOp()
        patsub_op.spids.append(op_spid)

        # awkwardness for mycpp; could fix
        temp = cast(suffix_op_t, patsub_op)
        part.suffix_op = temp

        # Checked by the method above
        assert self.token_type == Id.Right_DollarBrace, self.cur_token

      elif self.token_type == Id.VOp2_Colon:
        part.suffix_op = self._ReadSliceVarOp()
        # NOTE: } in arithmetic mode.
        if self.token_type != Id.Arith_RBrace:
          # Token seems off; doesn't point to X in # ${a:1:2 X
          p_die('Expected } to close ${', token=self.cur_token)

      else:
        # TODO: Does this ever happen?
        p_die('Unexpected token in ${} (%s)', 'VOp2', token=self.cur_token)

    elif op_kind == Kind.VOp3:  # ${prefix@} etc.
      if allow_query:
        part.suffix_op = self.cur_token  # Nullary
        self._Next(lex_mode_e.VSub_2)  # Expecting }
        self._Peek()
      else:
        p_die("Unexpected token in ${} (%s)", 'VOp3', token=self.cur_token)

    # NOTE: Arith_RBrace is for slicing, because it reads } in arithmetic
    # mode.  It's redundantly checked above.
    if self.token_type not in (Id.Right_DollarBrace, Id.Arith_RBrace):
      # ${a.} or ${!a.}
      p_die('Expected } to close ${', token=self.cur_token)

    # Now look for ops
    return part
Example #3
0
  def _ParseVarExpr(self, arg_lex_mode):
    # type: (lex_mode_t) -> braced_var_sub
    """
    Start parsing at the op -- we already skipped past the name.
    """
    part = self._ParseVarOf()

    self._Peek()
    if self.token_type == Id.Right_DollarBrace:
      return part  # no ops

    op_kind = self.token_kind

    if op_kind == Kind.VTest:
      op_id = self.token_type
      arg_word = self._ReadVarOpArg(arg_lex_mode)
      if self.token_type != Id.Right_DollarBrace:
        p_die('Unexpected token (after VTest): %r', self.cur_token.val,
              token=self.cur_token)

      part.suffix_op = suffix_op.Unary(op_id, arg_word)

    elif op_kind == Kind.VOp0:
      op_id = self.token_type
      part.suffix_op = suffix_op.Nullary(op_id)
      self._Next(lex_mode_e.VSub_2)  # Expecting }
      self._Peek()

    elif op_kind == Kind.VOp1:
      op_id = self.token_type
      arg_word = self._ReadVarOpArg(arg_lex_mode)
      if self.token_type != Id.Right_DollarBrace:
        p_die('Unexpected token (after VOp1): %r', self.cur_token.val,
              token=self.cur_token)

      part.suffix_op = suffix_op.Unary(op_id, arg_word)

    elif op_kind == Kind.VOp2:
      if self.token_type == Id.VOp2_Slash:
        op_spid = self.cur_token.span_id  # for attributing error to /

        # TODO: op_temp is only necessary for MyPy.  It can be removed when
        # 'spids' are put on the base class suffix_op_t.
        op_temp = self._ReadPatSubVarOp(arg_lex_mode)
        op_temp.spids.append(op_spid)

        op = cast(suffix_op_t, op_temp)  # for MyPy

        # Checked by the method above
        assert self.token_type == Id.Right_DollarBrace, self.cur_token

      elif self.token_type == Id.VOp2_Colon:
        op = self._ReadSliceVarOp()
        # NOTE: } in arithmetic mode.
        if self.token_type != Id.Arith_RBrace:
          # Token seems off; doesn't point to X in # ${a:1:2 X
          p_die('Unexpected token after slice: %r', self.cur_token.val,
                token=self.cur_token)

      else:
        p_die('Unexpected token %r', self.cur_token.val, token=self.cur_token)

      part.suffix_op = op

    # NOTE: Arith_RBrace is for slicing, because it reads } in arithmetic
    # mode.  It's redundantly checked above.
    if self.token_type not in (Id.Right_DollarBrace, Id.Arith_RBrace):
      # ${a.} or ${!a.}
      p_die('Expected } after var sub, got %r', self.cur_token.val,
            token=self.cur_token)

    # Now look for ops
    return part