| 1300 | |
| 1301 | |
| 1302 | class _FromStringWorker: |
| 1303 | |
| 1304 | def __init__(self, language=Language.C): |
| 1305 | self.original = None |
| 1306 | self.quotes_map = None |
| 1307 | self.language = language |
| 1308 | |
| 1309 | def finalize_string(self, s): |
| 1310 | return insert_quotes(s, self.quotes_map) |
| 1311 | |
| 1312 | def parse(self, inp): |
| 1313 | self.original = inp |
| 1314 | unquoted, self.quotes_map = eliminate_quotes(inp) |
| 1315 | return self.process(unquoted) |
| 1316 | |
| 1317 | def process(self, s, context='expr'): |
| 1318 | """Parse string within the given context. |
| 1319 | |
| 1320 | The context may define the result in case of ambiguous |
| 1321 | expressions. For instance, consider expressions `f(x, y)` and |
| 1322 | `(x, y) + (a, b)` where `f` is a function and pair `(x, y)` |
| 1323 | denotes complex number. Specifying context as "args" or |
| 1324 | "expr", the subexpression `(x, y)` will be parse to an |
| 1325 | argument list or to a complex number, respectively. |
| 1326 | """ |
| 1327 | if isinstance(s, (list, tuple)): |
| 1328 | return type(s)(self.process(s_, context) for s_ in s) |
| 1329 | |
| 1330 | assert isinstance(s, str), (type(s), s) |
| 1331 | |
| 1332 | # replace subexpressions in parenthesis with f2py @-names |
| 1333 | r, raw_symbols_map = replace_parenthesis(s) |
| 1334 | r = r.strip() |
| 1335 | |
| 1336 | def restore(r): |
| 1337 | # restores subexpressions marked with f2py @-names |
| 1338 | if isinstance(r, (list, tuple)): |
| 1339 | return type(r)(map(restore, r)) |
| 1340 | return unreplace_parenthesis(r, raw_symbols_map) |
| 1341 | |
| 1342 | # comma-separated tuple |
| 1343 | if ',' in r: |
| 1344 | operands = restore(r.split(',')) |
| 1345 | if context == 'args': |
| 1346 | return tuple(self.process(operands)) |
| 1347 | if context == 'expr': |
| 1348 | if len(operands) == 2: |
| 1349 | # complex number literal |
| 1350 | return as_complex(*self.process(operands)) |
| 1351 | raise NotImplementedError( |
| 1352 | f'parsing comma-separated list (context={context}): {r}') |
| 1353 | |
| 1354 | # ternary operation |
| 1355 | m = re.match(r'\A([^?]+)[?]([^:]+)[:](.+)\Z', r) |
| 1356 | if m: |
| 1357 | assert context == 'expr', context |
| 1358 | oper, expr1, expr2 = restore(m.groups()) |
| 1359 | oper = self.process(oper) |