Пример #1
0
Файл: tdop.py Проект: silky/oil
    def ParseUntil(self, rbp):
        """
    Parse to the right, eating tokens until we encounter a token with binding
    power LESS THAN OR EQUAL TO rbp.
    """
        # TODO: use Kind.Eof
        if self.op_id in (Id.Eof_Real, Id.Eof_RParen, Id.Eof_Backtick):
            raise TdopParseError('Unexpected end of input')

        t = self.cur_word
        self.Next()  # skip over the token, e.g. ! ~ + -

        null_info = self.spec.LookupNud(word.ArithId(t))
        node = null_info.nud(self, t, null_info.bp)

        while True:
            t = self.cur_word
            try:
                left_info = self._Led(word.ArithId(t))
            except KeyError:
                raise TdopParseError('Invalid token %s' % t)

            # Examples:
            # If we see 1*2+  , rbp = 27 and lbp = 25, so stop.
            # If we see 1+2+  , rbp = 25 and lbp = 25, so stop.
            # If we see 1**2**, rbp = 26 and lbp = 27, so keep going.
            if rbp >= left_info.lbp:
                break
            self.Next()  # skip over the token, e.g. / *

            node = left_info.led(self, t, node, left_info.rbp)

        return node
Пример #2
0
def LeftIncDec(p, w, left, rbp):
    """ For i++ and i--
  """
    if word.ArithId(w) == Id.Arith_DPlus:
        op_id = Id.Node_PostDPlus
    elif word.ArithId(w) == Id.Arith_DMinus:
        op_id = Id.Node_PostDMinus
    else:
        raise AssertionError

    child = tdop.ToLValue(left)
    return ast.UnaryAssign(op_id, child)
Пример #3
0
def LeftIncDec(p, w, left, rbp):
    """ For i++ and i--
  """
    if not tdop.IsLValue(left):
        raise tdop.ParseError("Can't assign to %r (%s)" % (left, left.token))
    if word.ArithId(w) == Id.Arith_DPlus:
        op_id = Id.Node_PostDPlus
    elif word.ArithId(w) == Id.Arith_DMinus:
        op_id = Id.Node_PostDMinus
    else:
        raise AssertionError
    return ast.ArithUnary(op_id, left)
Пример #4
0
def LeftIndex(p, w, left, unused_bp):
    """Array indexing, in both LValue and RValue context.

  LValue: f[0] = 1  f[x+1] = 2
  RValue: a = f[0]  b = f[x+1]

  On RHS, you can have:
  1. a = f[0]
  2. a = f(x, y)[0]
  3. a = f[0][0]  # in theory, if we want character indexing?
     NOTE: a = f[0].charAt() is probably better

  On LHS, you can only have:
  1. a[0] = 1

  Nothing else is valid:
  2. function calls return COPIES.  They need a name, at least in osh.
  3. strings don't have mutable characters.
  """
    if not tdop.IsIndexable(left):
        p_die("%s can't be indexed", left, word=w)
    index = p.ParseUntil(0)
    p.Eat(Id.Arith_RBracket)

    return ast.ArithBinary(word.ArithId(w), left, index)
Пример #5
0
def LeftAssign(p, w, left, rbp):
    """ Normal binary operator like 1+2 or 2*3, etc. """
    # x += 1, or a[i] += 1
    lhs = ToLValue(left)
    if lhs is None:
        p_die("Can't assign to %r", lhs, word=w)
    return ast.BinaryAssign(word.ArithId(w), lhs, p.ParseUntil(rbp))
Пример #6
0
def NullIncDec(p, w, bp):
    """ ++x or ++x[1] """
    right = p.ParseUntil(bp)
    child = tdop.ToLValue(right)
    if child is None:
        p_die("This value can't be assigned to", word=w)
    return ast.UnaryAssign(word.ArithId(w), child)
Пример #7
0
 def Next(self):
     """Preferred over Eat()? """
     self.cur_word = self.w_parser.ReadWord(lex_mode_e.ARITH)
     if self.cur_word is None:
         error_stack = self.w_parser.Error()
         self.error_stack.extend(error_stack)
         p_die('Error reading arith word in ArithParser')
     self.op_id = word.ArithId(self.cur_word)
     return True
Пример #8
0
def LeftIndex(p, w, left, unused_bp):
    """ index f[x+1] """
    # f[x] or f[x][y]
    if not tdop.IsIndexable(left):
        raise tdop.ParseError("%s can't be indexed" % left)
    index = p.ParseUntil(0)
    p.Eat(Id.Arith_RBracket)

    return ast.ArithBinary(word.ArithId(w), left, index)
Пример #9
0
Файл: tdop.py Проект: silky/oil
def NullPrefixOp(p, w, bp):
    """Prefix operator.

  Low precedence:  return, raise, etc.
    return x+y is return (x+y), not (return x) + y

  High precedence: logical negation, bitwise complement, etc.
    !x && y is (!x) && y, not !(x && y)
  """
    right = p.ParseUntil(bp)
    return ast.ArithUnary(word.ArithId(w), right)
Пример #10
0
Файл: tdop.py Проект: silky/oil
 def Next(self):
     """Preferred over Eat()? """
     self.cur_word = self.w_parser.ReadWord(LexMode.ARITH)
     if self.cur_word is None:
         error_stack = self.w_parser.Error()
         self.error_stack.extend(error_stack)
         self.AddErrorContext('Error reading arith word in ArithParser',
                              word=self.cur_word)
         #return False
         raise TdopParseError()  # use exceptions for now
     self.op_id = word.ArithId(self.cur_word)
     return True
Пример #11
0
Файл: tdop.py Проект: silky/oil
def LeftAssign(p, w, left, rbp):
    """ Normal binary operator like 1+2 or 2*3, etc. """
    # x += 1, or a[i] += 1

    if not IsLValue(left):
        raise TdopParseError("Can't assign to %r (%s)" %
                             (left, IdName(left.id)))

    # HACK: NullConstant makes this of type RightVar?  Change that to something
    # generic?
    if left.tag == arith_expr_e.RightVar:
        lhs = ast.LeftVar(left.name)
    elif left.tag == arith_expr_e.ArithBinary:
        assert left.op_id == Id.Arith_LBracket
        # change a[i] to LeftIndex(a, i)
        lhs = ast.LeftIndex(left.left, left.right)
    else:
        raise AssertionError

    return ast.ArithAssign(word.ArithId(w), lhs, p.ParseUntil(rbp))
Пример #12
0
def LeftBinaryOp(p, w, left, rbp):
    """ Normal binary operator like 1+2 or 2*3, etc. """
    # TODO: w shoudl be a TokenWord, and we should extract the token from it.
    return ast.ArithBinary(word.ArithId(w), left, p.ParseUntil(rbp))
Пример #13
0
def LeftAssign(p, w, left, rbp):
    """ Normal binary operator like 1+2 or 2*3, etc. """
    # x += 1, or a[i] += 1
    lhs = ToLValue(left)
    return ast.BinaryAssign(word.ArithId(w), lhs, p.ParseUntil(rbp))
Пример #14
0
def NullIncDec(p, w, bp):
    """ ++x or ++x[1] """
    right = p.ParseUntil(bp)
    if not tdop.IsLValue(right):
        raise tdop.ParseError("Can't assign to %r (%s)" % (right, right.token))
    return ast.ArithUnary(word.ArithId(w), right)
Пример #15
0
Файл: tdop.py Проект: silky/oil
def LeftBinaryOp(p, w, left, rbp):
    """ Normal binary operator like 1+2 or 2*3, etc. """
    return ast.ArithBinary(word.ArithId(w), left, p.ParseUntil(rbp))
Пример #16
0
def NullIncDec(p, w, bp):
    """ ++x or ++x[1] """
    right = p.ParseUntil(bp)
    child = tdop.ToLValue(right)
    return ast.UnaryAssign(word.ArithId(w), child)
Пример #17
0
 def Next(self):
     """Preferred over Eat()? """
     self.cur_word = self.w_parser.ReadWord(lex_mode_e.ARITH)
     assert self.cur_word is not None
     self.op_id = word.ArithId(self.cur_word)
     return True