Reads a python expression from the text and returns the expression and remaining text. expr -> simple_expr | paren_expr simple_expr -> id extended_expr extended_expr -> attr_access | paren_expr extended_expr | '' attr_access -> dot id extended_expr paren_expr
(self, text, escape=True)
| 247 | return StatementNode(line.strip() + "\n"), text |
| 248 | |
| 249 | def read_expr(self, text, escape=True): # noqa: C901, PLR0915 |
| 250 | """Reads a python expression from the text and returns the expression and remaining text. |
| 251 | |
| 252 | expr -> simple_expr | paren_expr |
| 253 | simple_expr -> id extended_expr |
| 254 | extended_expr -> attr_access | paren_expr extended_expr | '' |
| 255 | attr_access -> dot id extended_expr |
| 256 | paren_expr -> [ tokens ] | ( tokens ) | { tokens } |
| 257 | |
| 258 | >>> read_expr = Parser().read_expr |
| 259 | >>> read_expr("name") |
| 260 | ($name, '') |
| 261 | >>> read_expr("a.b and c") |
| 262 | ($a.b, ' and c') |
| 263 | >>> read_expr("a. b") |
| 264 | ($a, '. b') |
| 265 | >>> read_expr("name</h1>") |
| 266 | ($name, '</h1>') |
| 267 | >>> read_expr("(limit)ing") |
| 268 | ($(limit), 'ing') |
| 269 | >>> read_expr('a[1, 2][:3].f(1+2, "weird string[).", 3 + 4) done.') |
| 270 | ($a[1, 2][:3].f(1+2, "weird string[).", 3 + 4), ' done.') |
| 271 | """ |
| 272 | |
| 273 | def simple_expr(): |
| 274 | identifier() |
| 275 | extended_expr() |
| 276 | |
| 277 | def identifier(): |
| 278 | return next(tokens) |
| 279 | |
| 280 | def extended_expr(): |
| 281 | lookahead = tokens.peek() |
| 282 | if lookahead is None: |
| 283 | return |
| 284 | elif lookahead.value == ".": |
| 285 | attr_access() |
| 286 | elif lookahead.value in parens: |
| 287 | paren_expr() |
| 288 | extended_expr() |
| 289 | else: |
| 290 | return |
| 291 | |
| 292 | def attr_access(): |
| 293 | from token import NAME # python token constants |
| 294 | |
| 295 | if tokens[1].type == NAME: |
| 296 | next(tokens) # consume dot |
| 297 | identifier() |
| 298 | extended_expr() |
| 299 | |
| 300 | def paren_expr(): |
| 301 | begin = next(tokens).value |
| 302 | end = parens[begin] |
| 303 | while True: |
| 304 | if tokens.peek().value in parens: |
| 305 | paren_expr() |
| 306 | else: |