def left_assign(token_stream: TokenStream, rbp: int, left: Node) -> Node: """ Normal binary operator like 1+2 or 2*3, etc. """ # x += 1, or a[i] += 1 before = next(token_stream) if left.token.type not in ("name", "get"): raise ParseError("Can't assign to %r (%s)" % (left, left.token)) return Node(before, [left, p.parse(rule_map, token_stream, rbp)])
def left_ternary(token_stream: TokenStream, rbp: int, left: Node) -> Node: """ e.g. a > 1 ? x : y """ # 0 binding power since any operators allowed until ':'. See: # # http://en.cppreference.com/w/c/language/operator_precedence#cite_note-2 # # "The expression in the middle of the conditional operator (between ? and # :) is parsed as if parenthesized: its precedence relative to ?: is # ignored." before = next(token_stream) true_expr = p.parse(rule_map, token_stream, 0) p.eat(token_stream, ":") false_expr = p.parse(rule_map, token_stream, rbp) children = [left, true_expr, false_expr] return Node(before, children)
def null_inc_dec(token_stream: TokenStream, bp: int) -> Node: """ ++x or ++x[1] """ before = next(token_stream) right = p.parse(rule_map, token_stream, bp) if right.token.type not in ("name", "get"): raise ParseError("Can't assign to %r (%s)" % (right, right.token)) return Node(before, [right])
def left_index(token_stream: TokenStream, rbp: int, left: Node) -> Node: """ index f[x+1] """ # f[x] or f[x][y] before = next(token_stream) if left.token.type not in ("name", "get"): raise ParseError("%s can't be indexed" % left) index = p.parse(rule_map, token_stream, 0) p.eat(token_stream, "]") before.type = "get" return Node(before, [left, index])
def null_prefix_op(token_stream: TokenStream, bp: int) -> Node: """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) """ before = next(token_stream) r = p.parse(rule_map, token_stream, bp) return Node(before, [r])
def left_comma(token_stream: TokenStream, rbp: int, left: Node) -> Node: """foo, bar, baz Could be sequencing operator, or tuple without parens """ before = next(token_stream) r = p.parse(rule_map, token_stream, rbp) if left.token.type == ",": # Keep adding more children left.children.append(r) return left children = [left, r] return Node(before, children)
def left_func_call(token_stream: TokenStream, rbp: int, left: Node) -> Node: """ Function call f(a, b). """ before = next(token_stream) children = [left] # f(x) or f[i](x) if left.token.type not in ("name", "get"): raise ParseError("%s can't be called" % left) while True: if token_stream.current.type == ")": break # We don't want to grab the comma, e.g. it is NOT a sequence operator. So # set the precedence to 5. children.append(p.parse(rule_map, token_stream, COMMA_PREC)) if token_stream.current.type == ",": p.eat(token_stream, ",") p.eat(token_stream, ")") before.type = "call" return Node(before, children)
def null_paren(token_stream: TokenStream, bp: int) -> Node: """ Arithmetic grouping """ next(token_stream) r = p.parse(rule_map, token_stream, bp) p.eat(token_stream, ")") return r
def left_binary_op(token_stream: TokenStream, rbp: int, left: Node) -> Node: """ Normal binary operator like 1+2 or 2*3, etc. """ before = next(token_stream) return Node(before, [left, p.parse(rule_map, token_stream, rbp)])