

from ..semantics import mpq
from .common import OPERATORS, ADD_OP, MULTIPLY_OP


def try_to_number(s):
    try:
        return mpq(s)
    except (ValueError, TypeError):
        return s


def _parse_r(s):
    s = s.strip()
    bracket_level = 0
    operator_pos = -1
    for i, v in enumerate(s):
        if v == '(':
            bracket_level += 1
        if v == ')':
            bracket_level -= 1
        if bracket_level == 1 and v in OPERATORS:
            operator_pos = i
            break
    if operator_pos == -1:
        return s
    a1 = _parse_r(s[1:operator_pos].strip())
    a2 = _parse_r(s[operator_pos + 1:-1].strip())
    return Expr(s[operator_pos], a1, a2)



import ast

from ..semantics import mpq
from .common import OPERATORS, ADD_OP, MULTIPLY_OP


def try_to_number(s):
    try:
        return mpq(s)
    except (ValueError, TypeError):
        return s


OPERATOR_MAP = {
    ast.Add: ADD_OP,
    ast.Mult: MULTIPLY_OP,
}


def parse(s):
    from .biop import Expr
    def _parse_r(t):
        try:
            return t.n
        except AttributeError:
            pass
        try:
            return t.id
        except AttributeError:
            op = OPERATOR_MAP[t.op.__class__]
            a1 = _parse_r(t.left)
            a2 = _parse_r(t.right)
            return Expr(op, a1, a2)
    return _parse_r(ast.parse(s, mode='eval').body)

Replace parsing with Python's ast
Replace parsing with Python's ast

Allows greater flexibility and syntax checks

  
+ 
+ import ast
  
  from ..semantics import mpq
  from .common import OPERATORS, ADD_OP, MULTIPLY_OP
  
  
  def try_to_number(s):
      try:
          return mpq(s)
      except (ValueError, TypeError):
          return s
  
  
+ OPERATOR_MAP = {
+     ast.Add: ADD_OP,
+     ast.Mult: MULTIPLY_OP,
+ }
- def _parse_r(s):
-     s = s.strip()
-     bracket_level = 0
-     operator_pos = -1
-     for i, v in enumerate(s):
-         if v == '(':
-             bracket_level += 1
-         if v == ')':
-             bracket_level -= 1
-         if bracket_level == 1 and v in OPERATORS:
-             operator_pos = i
-             break
-     if operator_pos == -1:
-         return s
-     a1 = _parse_r(s[1:operator_pos].strip())
-     a2 = _parse_r(s[operator_pos + 1:-1].strip())
-     return Expr(s[operator_pos], a1, a2)
  
+ 
+ def parse(s):
+     from .biop import Expr
+     def _parse_r(t):
+         try:
+             return t.n
+         except AttributeError:
+             pass
+         try:
+             return t.id
+         except AttributeError:
+             op = OPERATOR_MAP[t.op.__class__]
+             a1 = _parse_r(t.left)
+             a2 = _parse_r(t.right)
+             return Expr(op, a1, a2)
+     return _parse_r(ast.parse(s, mode='eval').body)
+ 
Replace parsing with Python's ast
## Code Before:


from ..semantics import mpq
from .common import OPERATORS, ADD_OP, MULTIPLY_OP


def try_to_number(s):
    try:
        return mpq(s)
    except (ValueError, TypeError):
        return s


def _parse_r(s):
    s = s.strip()
    bracket_level = 0
    operator_pos = -1
    for i, v in enumerate(s):
        if v == '(':
            bracket_level += 1
        if v == ')':
            bracket_level -= 1
        if bracket_level == 1 and v in OPERATORS:
            operator_pos = i
            break
    if operator_pos == -1:
        return s
    a1 = _parse_r(s[1:operator_pos].strip())
    a2 = _parse_r(s[operator_pos + 1:-1].strip())
    return Expr(s[operator_pos], a1, a2)

## Instruction:
Replace parsing with Python's ast
## Code After:


import ast

from ..semantics import mpq
from .common import OPERATORS, ADD_OP, MULTIPLY_OP


def try_to_number(s):
    try:
        return mpq(s)
    except (ValueError, TypeError):
        return s


OPERATOR_MAP = {
    ast.Add: ADD_OP,
    ast.Mult: MULTIPLY_OP,
}


def parse(s):
    from .biop import Expr
    def _parse_r(t):
        try:
            return t.n
        except AttributeError:
            pass
        try:
            return t.id
        except AttributeError:
            op = OPERATOR_MAP[t.op.__class__]
            a1 = _parse_r(t.left)
            a2 = _parse_r(t.right)
            return Expr(op, a1, a2)
    return _parse_r(ast.parse(s, mode='eval').body)
