or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-to-source.mdfile-operations.mdindex.mdoperator-utilities.mdtree-manipulation.md

operator-utilities.mddocs/

0

# Operator Utilities

1

2

Utilities for working with Python operators, including symbol extraction and precedence handling for proper expression formatting. This module provides comprehensive support for AST operator nodes and ensures correct parenthesization in generated source code.

3

4

## Capabilities

5

6

### Operator Symbol Extraction

7

8

Extract string representations of Python operators from AST operator nodes.

9

10

```python { .api }

11

def get_op_symbol(obj, fmt='%s'):

12

"""

13

Return symbol string for an AST operator node.

14

15

Parameters:

16

- obj: AST operator node (BinOp, UnaryOp, BoolOp, Compare, etc.)

17

- fmt: str, format string for the symbol (default: '%s')

18

19

Returns:

20

str: String containing the operator symbol

21

22

Raises:

23

KeyError: If the operator type is not recognized

24

"""

25

```

26

27

**Usage Example:**

28

29

```python

30

import ast

31

import astor

32

33

# Parse expression with various operators

34

code = "a + b * c - d / e and f or g"

35

tree = ast.parse(code, mode='eval')

36

37

# Extract operator symbols

38

for node in ast.walk(tree):

39

if hasattr(node, 'op'):

40

symbol = astor.get_op_symbol(node.op)

41

print(f"{type(node.op).__name__}: {symbol}")

42

elif hasattr(node, 'ops'):

43

for op in node.ops:

44

symbol = astor.get_op_symbol(op)

45

print(f"{type(op).__name__}: {symbol}")

46

47

# Custom formatting

48

code = "x ** y"

49

tree = ast.parse(code, mode='eval')

50

binop_node = tree.body

51

52

symbol = astor.get_op_symbol(binop_node.op, fmt='[%s]')

53

print(f"Formatted symbol: {symbol}") # [**]

54

```

55

56

### Operator Precedence

57

58

Get precedence values for Python operators to ensure correct parenthesization in generated code.

59

60

```python { .api }

61

def get_op_precedence(obj):

62

"""

63

Return precedence value for an AST operator node.

64

65

Parameters:

66

- obj: AST operator node

67

68

Returns:

69

int: Integer precedence value (higher numbers = higher precedence)

70

71

Raises:

72

KeyError: If the operator type is not recognized

73

"""

74

```

75

76

**Usage Example:**

77

78

```python

79

import ast

80

import astor

81

82

# Parse complex expression

83

code = "a + b * c"

84

tree = ast.parse(code, mode='eval')

85

86

# Check precedence to understand grouping

87

binop = tree.body # BinOp for 'a + (b * c)'

88

add_prec = astor.get_op_precedence(binop.op) # Add

89

mult_prec = astor.get_op_precedence(binop.right.op) # Mult

90

91

print(f"Addition precedence: {add_prec}")

92

print(f"Multiplication precedence: {mult_prec}")

93

print(f"Multiplication has higher precedence: {mult_prec > add_prec}")

94

```

95

96

### Operator Symbol Data

97

98

Complete mapping from AST operator types to their string symbols.

99

100

```python { .api }

101

symbol_data: dict

102

```

103

104

This dictionary contains the complete mapping of all Python operators:

105

106

```python

107

import astor

108

109

# Explore all available operators

110

print("Binary operators:")

111

for op_type, symbol in astor.symbol_data.items():

112

if 'op' in op_type.__name__.lower():

113

print(f" {op_type.__name__}: {symbol}")

114

115

# Check specific operators

116

import ast

117

print(f"Add symbol: {astor.symbol_data[ast.Add]}") # +

118

print(f"Mult symbol: {astor.symbol_data[ast.Mult]}") # *

119

print(f"And symbol: {astor.symbol_data[ast.And]}") # and

120

print(f"Or symbol: {astor.symbol_data[ast.Or]}") # or

121

```

122

123

### Precedence Constants

124

125

Class containing precedence values for all Python operators.

126

127

```python { .api }

128

class Precedence:

129

"""

130

Container for operator precedence constants.

131

132

Contains precedence values for all Python operators following

133

Python's operator precedence rules.

134

"""

135

```

136

137

**Available Precedence Constants:**

138

139

```python

140

import astor

141

142

# Access precedence constants

143

print(f"Comma precedence: {astor.Precedence.Comma}") # Lowest

144

print(f"Or precedence: {astor.Precedence.Or}")

145

print(f"And precedence: {astor.Precedence.And}")

146

print(f"Not precedence: {astor.Precedence.Not}")

147

print(f"In precedence: {astor.Precedence.In}")

148

print(f"Compare precedence: {astor.Precedence.Comp}")

149

print(f"BitOr precedence: {astor.Precedence.BitOr}")

150

print(f"BitXor precedence: {astor.Precedence.BitXor}")

151

print(f"BitAnd precedence: {astor.Precedence.BitAnd}")

152

print(f"Shift precedence: {astor.Precedence.Shift}")

153

print(f"Add precedence: {astor.Precedence.Add}")

154

print(f"Mult precedence: {astor.Precedence.Mult}")

155

print(f"UAdd precedence: {astor.Precedence.UAdd}")

156

print(f"Power precedence: {astor.Precedence.Pow}") # Highest

157

```

158

159

## Advanced Operator Handling

160

161

### Expression Parenthesization

162

163

Using operator precedence to determine when parentheses are needed in generated expressions.

164

165

**Usage Example:**

166

167

```python

168

import ast

169

import astor

170

171

def needs_parens(parent_op, child_op, is_right=False):

172

"""Check if child operation needs parentheses."""

173

parent_prec = astor.get_op_precedence(parent_op)

174

child_prec = astor.get_op_precedence(child_op)

175

176

# Lower precedence needs parentheses

177

if child_prec < parent_prec:

178

return True

179

180

# Same precedence on right side of non-associative operators

181

if child_prec == parent_prec and is_right:

182

# Check for right-associative operators (like **)

183

return type(parent_op).__name__ not in ['Pow']

184

185

return False

186

187

# Example usage

188

code = "a - b + c" # Parsed as (a - b) + c

189

tree = ast.parse(code, mode='eval')

190

binop = tree.body

191

192

# Check if we need parentheses for sub-expressions

193

left_needs_parens = needs_parens(binop.op, binop.left.op, is_right=False)

194

print(f"Left side needs parentheses: {left_needs_parens}")

195

```

196

197

### Custom Operator Formatting

198

199

Using the formatting capabilities for specialized code generation.

200

201

**Usage Example:**

202

203

```python

204

import ast

205

import astor

206

207

def format_operator_with_spaces(op_node):

208

"""Format operator with surrounding spaces."""

209

symbol = astor.get_op_symbol(op_node, fmt=' %s ')

210

return symbol

211

212

# Parse and format expression

213

code = "a+b*c"

214

tree = ast.parse(code, mode='eval')

215

216

# Manually format with spacing

217

def add_spaces_to_binops(node):

218

if isinstance(node, ast.BinOp):

219

left = add_spaces_to_binops(node.left)

220

right = add_spaces_to_binops(node.right)

221

op_symbol = format_operator_with_spaces(node.op)

222

return f"{left}{op_symbol}{right}"

223

elif isinstance(node, ast.Name):

224

return node.id

225

elif isinstance(node, ast.Constant):

226

return str(node.value)

227

return str(node)

228

229

formatted = add_spaces_to_binops(tree.body)

230

print(formatted) # "a + b * c"

231

```

232

233

## Deprecated Operator Functions

234

235

For backward compatibility, astor provides deprecated aliases for operator functions:

236

237

```python { .api }

238

# Deprecated aliases (use get_op_symbol instead)

239

def get_boolop(obj): ... # → get_op_symbol

240

def get_binop(obj): ... # → get_op_symbol

241

def get_cmpop(obj): ... # → get_op_symbol

242

def get_unaryop(obj): ... # → get_op_symbol

243

def get_anyop(obj): ... # → get_op_symbol

244

245

# Deprecated alias (use symbol_data instead)

246

all_symbols: dict # → symbol_data

247

```

248

249

These functions are maintained for compatibility but should not be used in new code. Use `get_op_symbol()` and `symbol_data` instead.