Ticket #2347: 2347.patch

File 2347.patch, 49.5 KB (added by mhansen, 14 years ago)
  • sage/calculus/calculus.py

    # HG changeset patch
    # User Mike Hansen <mhansen@gmail.com>
    # Date 1207940975 25200
    # Node ID a41794fe68e29280f5b342c6d8410e634335d9a3
    # Parent  8de168217630a3ed670be088572d0e8f0e73017b
    * * *
    Add symbolic expression parsing module. This is both safer and more flexible than eval.
    * * *
    Removed several unsafe calls to eval()
    * * *
    Parse lists and tuples
    * * *
    Move parser to misc
    * * *
    Remove use of sage_eval for symbolic expression parsing, allow construction via a string.
    * * *
    Cleanup all uses of sage_eval in calculus, all doctests pass.
    * * *
    a couple more tweaks
    
    diff -r 8de168217630 -r a41794fe68e2 sage/calculus/calculus.py
    a b import sage.numerical.optimize 
    266266# separate from the default system-wide version.
    267267maxima = Maxima(init_code = ['display2d:false; domain: complex; keepfloat: true'])
    268268
    269 from sage.misc.sage_eval import sage_eval
     269from sage.misc.parser import Parser
    270270
    271271from sage.calculus.equations import SymbolicEquation
    272272from sage.rings.real_mpfr import RealNumber
    class SymbolicExpressionRing_class(uniq, 
    439439            return x
    440440        elif hasattr(x, '_symbolic_'):
    441441            return x._symbolic_(self)
     442        elif isinstance(x, str):
     443            try:
     444                return symbolic_expression_from_string(x)
     445            except SyntaxError, err:
     446                msg, s, pos = err.args
     447                raise TypeError, "%s: %s !!! %s" % (msg, s[:pos], s[pos:])
    442448        return self._coerce_impl(x)
    443449
    444450    def _coerce_impl(self, x):
    class SymbolicExpression(RingElement): 
    33723378            try:
    33733379                f = self.polynomial(QQ)
    33743380                w = repr(f.factor())
    3375                 return sage_eval(w, _vars)
     3381                return symbolic_expression_from_string(w, _vars)
    33763382            except TypeError:
    33773383                pass
    33783384            return self.parent()(self._maxima_().factor())
    class SymbolicConstant(Symbolic_object): 
    41544160
    41554161        return SymbolicArithmetic([self, right], operator.div)       
    41564162
    4157 
     4163    def __neg__(self):
     4164        return SymbolicConstant(-self._obj)
    41584165
    41594166    def __pow__(self, right):
    41604167        """
    class SymbolicArithmetic(SymbolicOperati 
    48474854        for o in ops:
    48484855            try:
    48494856                obj = o._obj
    4850                 if isinstance(obj, Rational):
     4857                # negative numbers are not handled correctly because _is_atomic has no sense of precedence
     4858                if o is ops[0] and str(obj)[0] == '-':
     4859                    temp = SymbolicConstant(obj)
     4860                    temp._operator = operator.neg
     4861                    temp._binary = False
     4862                    temp._unary = True
     4863                    temp._precedence = 2000
     4864                    li.append(temp)
     4865                elif isinstance(obj, Rational):
    48514866                    temp = SymbolicConstant(obj)
    48524867                    if not temp._obj.is_integral():
    48534868                        temp._operator = operator.div
    def log(x, base=None): 
    73847399            return x.log(base)
    73857400        except AttributeError:
    73867401            return function_log(x) / function_log(base)
     7402           
     7403_syms['log'] = log
     7404_syms['ln'] = log
    73877405
    73887406#####################
    73897407# The polylogarithm
    def symbolic_expression_from_maxima_stri 
    81208138    #r = maxima._eval_line('listofvars(_tmp_);')[1:-1]
    81218139   
    81228140    s = maxima._eval_line('_tmp_;')
    8123 
     8141   
    81248142    formal_functions = maxima_tick.findall(s)
    81258143    if len(formal_functions) > 0:
    81268144        for X in formal_functions:
    def symbolic_expression_from_maxima_stri 
    81588176        # use a global flag so all expressions obtained via
    81598177        # evaluation of maxima code are assumed pre-simplified
    81608178        is_simplified = True
    8161         last_msg = ''
    8162         while True:
    8163             try:
    8164                 w = sage_eval(s, syms)
    8165             except NameError, msg:
    8166                 if msg == last_msg:
    8167                     raise NameError, msg
    8168                 msg = str(msg)
    8169                 last_msg = msg
    8170                 i = msg.find("'")
    8171                 j = msg.rfind("'")
    8172                 nm = msg[i+1:j]
    8173 
    8174                 res = re.match('.*' + nm + '\s*\(.*\)', s)
    8175                 if res:
    8176                     syms[nm] = function(nm)
    8177                 else:
    8178                     syms[nm] = var(nm)                   
    8179             else:
    8180                 break
    8181         if isinstance(w, (list, tuple)):
    8182             return w
    8183         else:
    8184             x = SR(w)
    8185         return x
     8179        return symbolic_expression_from_string(s, syms, accept_sequence=True)
    81868180    except SyntaxError:
    81878181        raise TypeError, "unable to make sense of Maxima expression '%s' in SAGE"%s
    81888182    finally:
    def maxima_options(**kwds): 
    82748268    return ','.join(['%s=%s'%(key,mapped_opts(val)) for key, val in kwds.iteritems()])
    82758269
    82768270
     8271# Parser for symbolic ring elements
     8272
     8273_augmented_syms = {}
     8274
     8275def _find_var(name):
     8276    try:
     8277        return (_augmented_syms or _syms)[name]
     8278    except KeyError:
     8279        pass
     8280    try:
     8281        return SR(sage.all.__dict__[name])
     8282    except (KeyError, TypeError):
     8283        return var(name)
     8284       
     8285def _find_func(name):
     8286    try:
     8287        func = (_augmented_syms or _syms)[name]
     8288        if not isinstance(func, (SymbolicConstant, SymbolicVariable)):
     8289            return func
     8290    except KeyError:
     8291        pass
     8292    try:
     8293        func = SR(sage.all.__dict__[name])
     8294        if not isinstance(func, (SymbolicConstant, SymbolicVariable)):
     8295            return func
     8296    except (KeyError, TypeError):
     8297        return function(name)
     8298
     8299SR_parser = Parser(make_int      = lambda x: SymbolicConstant(Integer(x)),
     8300                   make_float    = lambda x: SymbolicConstant(create_RealNumber(x)),
     8301                   make_var      = _find_var,
     8302                   make_function = _find_func)
     8303                   
     8304def symbolic_expression_from_string(s, syms=None, accept_sequence=False):
     8305    parse_func = SR_parser.parse_sequence if accept_sequence else SR_parser.parse_expression
     8306    if syms is None:
     8307        return parse_func(s)
     8308    else:
     8309        try:
     8310            global _augmented_syms
     8311            _augmented_syms = syms
     8312            return parse_func(s)
     8313        finally:
     8314            _augmented_syms = {}
  • sage/calculus/equations.py

    diff -r 8de168217630 -r a41794fe68e2 sage/calculus/equations.py
    a b _assumptions = [] 
    7676
    7777from sage.structure.sage_object import SageObject
    7878from sage.structure.sequence    import Sequence
    79 from sage.misc.sage_eval        import sage_eval
    8079
    8180from calculus                   import maxima
    8281
    class SymbolicEquation(SageObject): 
    994993            if len(X) == 0:
    995994                return X, []
    996995            else:
    997                 return X, sage_eval(P.get('multiplicities'))
     996                return X, [int(e) for e in str(P.get('multiplicities'))[1:-1].split(',')]
    998997        else:
    999998            return X
    1000999       
  • sage/coding/code_bounds.py

    diff -r 8de168217630 -r a41794fe68e2 sage/coding/code_bounds.py
    a b def codesize_upper_bound(n,d,q): 
    155155        sage: codesize_upper_bound(10,3,2)
    156156        85
    157157    """
    158     return eval(gap.eval("UpperBound(%s,%s,%s)"%( n, d, q )))
     158    return int(gap.eval("UpperBound(%s,%s,%s)"%( n, d, q )))
    159159
    160160def dimension_upper_bound(n,d,q):
    161161    r"""
  • sage/coding/guava.py

    diff -r 8de168217630 -r a41794fe68e2 sage/coding/guava.py
    a b def BinaryReedMullerCode(r,k): 
    7777    F = GF(2)
    7878    gap.eval("C:=ReedMullerCode("+str(r)+", "+str(k)+")")
    7979    gap.eval("G:=GeneratorMat(C)")
    80     k = eval(gap.eval("Length(G)"))
    81     n = eval(gap.eval("Length(G[1])"))
     80    k = int(gap.eval("Length(G)"))
     81    n = int(gap.eval("Length(G[1])"))
    8282    G = [[gfq_gap_to_sage(gap.eval("G["+str(i)+"]["+str(j)+"]"),F) for j in range(1,n+1)] for i in range(1,k+1)]
    8383    MS = MatrixSpace(F,k,n)
    8484    return LinearCode(MS(G))
    def QuasiQuadraticResidueCode(p): 
    115115    F = GF(2)
    116116    gap.eval("C:=QQRCode("+str(p)+")")
    117117    gap.eval("G:=GeneratorMat(C)")
    118     k = eval(gap.eval("Length(G)"))
    119     n = eval(gap.eval("Length(G[1])"))
    120     G = [[gfq_gap_to_sage(gap.eval("G["+str(i)+"]["+str(j)+"]"),F) for j in range(1,n+1)] for i in range(1,k+1)]
     118    k = int(gap.eval("Length(G)"))
     119    n = int(gap.eval("Length(G[1])"))
     120    G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i,j)),F) for j in range(1,n+1)] for i in range(1,k+1)]
    121121    MS = MatrixSpace(F,k,n)
    122122    return LinearCode(MS(G))
    123123
    def RandomLinearCodeGuava(n,k,F): 
    149149    q = F.order()
    150150    gap.eval("C:=RandomLinearCode("+str(n)+","+str(k)+", GF("+str(q)+"))")
    151151    gap.eval("G:=GeneratorMat(C)")
    152     k = eval(gap.eval("Length(G)"))
    153     n = eval(gap.eval("Length(G[1])"))
    154     G = [[gfq_gap_to_sage(gap.eval("G["+str(i)+"]["+str(j)+"]"),F) for j in range(1,n+1)] for i in range(1,k+1)]
     152    k = int(gap.eval("Length(G)"))
     153    n = int(gap.eval("Length(G[1])"))
     154    G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i,j)),F) for j in range(1,n+1)] for i in range(1,k+1)]
    155155    MS = MatrixSpace(F,k,n)
    156156    return LinearCode(MS(G))
    157157
  • sage/combinat/combinat.py

    diff -r 8de168217630 -r a41794fe68e2 sage/combinat/combinat.py
    a b def bell_number(n): 
    256256        TypeError: no coercion of this rational to integer
    257257    """
    258258    ans=gap.eval("Bell(%s)"%ZZ(n))
    259     return ZZ(eval(ans))
     259    return ZZ(ans)
    260260
    261261## def bernoulli_number(n):
    262262##     r"""
  • sage/combinat/dynkin_diagram.py

    diff -r 8de168217630 -r a41794fe68e2 sage/combinat/root_system/dynkin_diagram.py
    a b def dynkin_diagram(t): 
    270270    if len(t) == 3:
    271271        affine = "_affine"
    272272
    273     function = eval(f+letter+affine)
     273    function = globals()[f+letter+affine]
    274274    try:
    275275        return function(t)
    276     except RuntimeError:
     276    except KeyError:
    277277        raise TypeError, "Dynkin diagram data not yet hardcoded for type %s"%t
    278278
    279279   
  • sage/combinat/partition.py

    diff -r 8de168217630 -r a41794fe68e2 sage/combinat/partition.py
    a b def Partition(l=None, exp=None, core_and 
    7373    """
    7474    number_of_arguments = 0
    7575    for arg in ['l', 'exp', 'core_and_quotient']:
    76         if eval(arg) is not None:
     76        if locals()[arg] is not None:
    7777            number_of_arguments += 1
    7878
    7979    if number_of_arguments != 1:
  • sage/combinat/partition_algebra.py

    diff -r 8de168217630 -r a41794fe68e2 sage/combinat/partition_algebra.py
    a b def create_set_partitions_function(lette 
    3535        """
    3636        if isinstance(k, (int, Integer)):
    3737            if k > 0:
    38                 return eval('SetPartitions' + letter + 'k_k(k)')
     38                return globals()['SetPartitions' + letter + 'k_k'](k)
    3939        elif is_RealNumber(k):
    4040            if k - floor(k) == 0.5:
    41                 return eval('SetPartitions' + letter + 'khalf_k(floor(k))')
     41                return globals()['SetPartitions' + letter + 'khalf_k'](floor(k))
    4242
    4343        raise ValueError, "k must be an integer or an integer + 1/2"
    4444
  • sage/combinat/skew_partition.py

    diff -r 8de168217630 -r a41794fe68e2 sage/combinat/skew_partition.py
    a b def SkewPartitions(n=None, row_lengths=N 
    589589    """
    590590    number_of_arguments = 0
    591591    for arg in ['n', 'row_lengths']:
    592         if eval(arg) is not None:
     592        if locals()[arg] is not None:
    593593            number_of_arguments += 1
    594594
    595595    if number_of_arguments > 1:
  • sage/functions/transcendental.py

    diff -r 8de168217630 -r a41794fe68e2 sage/functions/transcendental.py
    a b def __prep_num(x): 
    3939
    4040CC = complex_field.ComplexField()
    4141I = CC.gen(0)
    42 def __eval(x):
    43     return eval(x)
    4442
    4543def exponential_integral_1(x, n=0):
    4644    r"""
  • new file sage/misc/parser.pyx

    diff -r 8de168217630 -r a41794fe68e2 sage/misc/parser.pyx
    - +  
     1"""
     2This module provides a parser for symbolic equations and expressions.
     3
     4It is both safer and more powerful than using Python's eval, as one has
     5complete control over what names are used (including dynamically creating
     6variables) and how integer and floating point literals are created.
     7
     8AUTHOR:
     9    -- Robert Bradshaw 2008-04 (initial version)
     10"""
     11
     12#*****************************************************************************
     13#     Copyright (C) 2008 Robert Bradshaw <robertwb@math.washington.edu>
     14#
     15#  Distributed under the terms of the GNU General Public License (GPL)
     16#
     17#    This code is distributed in the hope that it will be useful,
     18#    but WITHOUT ANY WARRANTY; without even the implied warranty of
     19#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20#    General Public License for more details.
     21#
     22#  The full text of the GPL is available at:
     23#
     24#                  http://www.gnu.org/licenses/
     25#*****************************************************************************
     26
     27cdef extern from "string.h":
     28    char *strchr(char *str, int ch)
     29   
     30cdef extern from "Python.h":
     31    object PyString_FromStringAndSize(char *v, Py_ssize_t len)
     32    int PyList_Append(object list, object item) except -1
     33
     34import math
     35
     36def foo(*args, **kwds):
     37    """
     38    This is a function for testing that simply returns the arguments and
     39    keywords passed into it.
     40   
     41    EXAMPLES:
     42        sage: from sage.misc.parser import foo
     43        sage: foo(1, 2, a=3)
     44        ((1, 2), {'a': 3})
     45    """
     46    return args, kwds
     47
     48fuction_map = {
     49  'foo': foo,
     50  'sqrt': math.sqrt,
     51  'sin': math.sin,
     52  'cos': math.cos,
     53  'tan': math.tan,
     54}
     55
     56cdef enum token_types:
     57    # leave room for ASCII character tokens such as '+'
     58    INT = 128
     59    FLOAT
     60    NAME
     61    EOS
     62    ERROR
     63   
     64    LESS_EQ
     65    GREATER_EQ
     66    NOT_EQ
     67
     68enum_map = {
     69  INT:        'INT',
     70  FLOAT:      'FLOAT',
     71  NAME:       'NAME',
     72  EOS:        'EOS',
     73  ERROR:      'ERROR',
     74  LESS_EQ:    'LESS_EQ',
     75  GREATER_EQ: 'GREATER_EQ',
     76  NOT_EQ:     'NOT_EQ',
     77}
     78
     79def token_to_str(int token):
     80    """
     81    For speed reasons, tokens are integers. This function returns a string
     82    representation of a given token.
     83   
     84    EXAMPLES:
     85        sage: from sage.misc.parser import Tokenizer, token_to_str
     86        sage: t = Tokenizer("+ 2")
     87        sage: token_to_str(t.next())
     88        '+'
     89        sage: token_to_str(t.next())
     90        'INT'
     91    """
     92    try:
     93        return enum_map[token]
     94    except KeyError:
     95        return chr(token)
     96
     97
     98cdef inline bint is_alphanumeric(char c):
     99    return 'a' <= c <= 'z' or 'A' <= c <= 'Z' or '0' <= c <= '9' or c == '_'
     100       
     101cdef inline bint is_whitespace(char c):
     102    return (c != 0) & (strchr(" \t\n\r", c) != NULL)
     103
     104
     105cdef class Tokenizer:
     106    cdef char *s
     107    cdef string_obj
     108    cdef int token
     109    cdef int pos
     110    cdef int last_pos
     111   
     112    def __init__(self, s):
     113        """
     114        This class takes a string and turns it into a list of tokens for use
     115        by the parser.
     116       
     117        The tokenizer wraps a string object, to tokenize a different string
     118        create a new tokenizer.
     119       
     120        EXAMPLES:
     121            sage: from sage.misc.parser import Tokenizer
     122            sage: Tokenizer("1.5+2*3^4-sin(x)").test()
     123            ['FLOAT(1.5)', '+', 'INT(2)', '*', 'INT(3)', '^', 'INT(4)', '-', 'NAME(sin)', '(', 'NAME(x)', ')']
     124           
     125        The single character tokens are given by:
     126            sage: Tokenizer("+-*/^(),=<>[]{}").test()
     127            ['+', '-', '*', '/', '^', '(', ')', ',', '=', '<', '>', '[', ']', '{', '}']
     128           
     129        Two-character comparisons accepted are:
     130            sage: Tokenizer("<= >= != == **").test()
     131            ['LESS_EQ', 'GREATER_EQ', 'NOT_EQ', '=', '^']
     132           
     133        Integers are strings of 0-9:
     134            sage: Tokenizer("1 123 9879834759873452908375013").test()
     135            ['INT(1)', 'INT(123)', 'INT(9879834759873452908375013)']
     136           
     137        Floating point numbers can contain a single decimal point and possibly exponential notation:
     138            sage: Tokenizer("1. .01 1e3 1.e-3").test()
     139            ['FLOAT(1.)', 'FLOAT(.01)', 'FLOAT(1e3)', 'FLOAT(1.e-3)']
     140           
     141        Note that negative signes are not attached to the token:
     142            sage: Tokenizer("-1 -1.2").test()
     143            ['-', 'INT(1)', '-', 'FLOAT(1.2)']
     144
     145        Names are alphanumeric sequences not starting with a digit:
     146            sage: Tokenizer("a a1 _a_24").test()
     147            ['NAME(a)', 'NAME(a1)', 'NAME(_a_24)']
     148       
     149        Anything else is an error:
     150            sage: Tokenizer("&@!~").test()
     151            ['ERROR', 'ERROR', 'ERROR', 'ERROR']
     152
     153        No attempt for correctness is made at this stage:
     154            sage: Tokenizer(") )( 5e5e5").test()
     155            [')', ')', '(', 'FLOAT(5e5)', 'NAME(e5)']
     156            sage: Tokenizer("?$%").test()
     157            ['ERROR', 'ERROR', 'ERROR']
     158        """
     159        self.pos = 0
     160        self.last_pos = 0
     161        self.s = s
     162        self.string_obj = s # so it doesn't get deallocated before self
     163       
     164    def test(self):
     165        """
     166        This is a utility function for easy testing of the tokenizer.
     167       
     168        Distructively read off the tokens in self, returning a list of string
     169        representations of the tokens.
     170
     171        EXAMPLES:
     172            sage: from sage.misc.parser import Tokenizer
     173            sage: t = Tokenizer("a b 3")
     174            sage: t.test()
     175            ['NAME(a)', 'NAME(b)', 'INT(3)']
     176            sage: t.test()
     177            []
     178        """
     179        all = []
     180        cdef int token = self.next()
     181        while token != EOS:
     182            if token in [INT, FLOAT, NAME]:
     183                all.append("%s(%s)" % (token_to_str(token), self.last_token_string()))
     184            else:
     185                all.append(token_to_str(token))
     186            token = self.next()
     187        return all
     188       
     189    cpdef reset(self, int pos = 0):
     190        """
     191        Reset the tokenizer to a given position.
     192       
     193        EXAMPLES:
     194            sage: from sage.misc.parser import Tokenizer
     195            sage: t = Tokenizer("a+b*c")
     196            sage: t.test()
     197            ['NAME(a)', '+', 'NAME(b)', '*', 'NAME(c)']
     198            sage: t.test()
     199            []
     200            sage: t.reset()
     201            sage: t.test()
     202            ['NAME(a)', '+', 'NAME(b)', '*', 'NAME(c)']
     203            sage: t.reset(3)
     204            sage: t.test()
     205            ['*', 'NAME(c)']
     206           
     207        No care is taken to make sure we don't jump in the middle of a token:
     208            sage: t = Tokenizer("12345+a")
     209            sage: t.test()
     210            ['INT(12345)', '+', 'NAME(a)']
     211            sage: t.reset(2)
     212            sage: t.test()
     213            ['INT(345)', '+', 'NAME(a)']
     214        """
     215        self.pos = self.last_pos = pos
     216       
     217    cdef int find(self) except -1:
     218        """
     219        This function actually does all the work, and extensively is tested above.
     220        """
     221        cdef bint seen_exp, seen_decimal
     222        cdef int type
     223        cdef char* s = self.s
     224        cdef int pos = self.pos
     225       
     226        # skip whitespace
     227        if is_whitespace(s[pos]):
     228            while is_whitespace(s[pos]):
     229                pos += 1
     230            self.pos = pos
     231
     232        # end of string
     233        if s[pos] == 0:
     234            return EOS
     235           
     236        # dipthongs
     237        if s[pos+1] == '=':
     238            if s[pos] == '<':
     239                self.pos += 2
     240                return LESS_EQ
     241            elif s[pos] == '>':
     242                self.pos += 2
     243                return GREATER_EQ
     244            elif s[pos] == '!':
     245                self.pos += 2
     246                return NOT_EQ
     247            elif s[pos] == '=':
     248                self.pos += 2
     249                return '='
     250               
     251        elif s[pos] == '*' and s[pos+1] == '*':
     252            self.pos += 2
     253            return '^'
     254           
     255        # simple tokens
     256        if strchr("+-*/^()=<>,[]{}", s[pos]):
     257            type = s[pos]
     258            self.pos += 1
     259            return type
     260                           
     261        # numeric literals
     262        if '0' <= s[pos] <= '9' or s[pos] == '.':
     263            type = INT
     264            seen_exp = False
     265            seen_decimal = False
     266            while True:
     267                if '0' <= s[pos] <= '9':
     268                    pass
     269                elif s[pos] == '.':
     270                    if seen_decimal or seen_exp:
     271                        self.pos = pos
     272                        return type
     273                    else:
     274                        type = FLOAT
     275                        seen_decimal = True
     276                elif s[pos] == 'e' or s[pos] == 'E':
     277                    if seen_exp:
     278                        self.pos = pos
     279                        return type
     280                    else:
     281                        type = FLOAT
     282                        seen_exp = True
     283                elif s[pos] == '+' or s[pos] == '-':
     284                    if not (seen_exp and (s[pos-1] == 'e' or s[pos-1] == 'E')):
     285                        self.pos = pos
     286                        return type
     287                else:
     288                    self.pos = pos
     289                    return type
     290                pos += 1
     291               
     292        # name literals
     293        if is_alphanumeric(s[pos]):
     294            while is_alphanumeric(s[pos]):
     295                pos += 1
     296            self.pos = pos
     297            return NAME
     298           
     299        pos += 1
     300        self.pos = pos
     301        return ERROR
     302       
     303    cpdef int next(self):
     304        """
     305        Returns the next token in the string.
     306       
     307        EXAMPLES:
     308            sage: from sage.misc.parser import Tokenizer, token_to_str
     309            sage: t = Tokenizer("a+3")
     310            sage: token_to_str(t.next())
     311            'NAME'
     312            sage: token_to_str(t.next())
     313            '+'
     314            sage: token_to_str(t.next())
     315            'INT'
     316            sage: token_to_str(t.next())
     317            'EOS'
     318        """
     319        while is_whitespace(self.s[self.pos]):
     320            self.pos += 1
     321        self.last_pos = self.pos
     322        self.token = self.find()
     323        return self.token
     324       
     325    cpdef int last(self):
     326        """
     327        Returns the last token seen.
     328       
     329        EXAMPLES:
     330            sage: from sage.misc.parser import Tokenizer, token_to_str
     331            sage: t = Tokenizer("3a")
     332            sage: token_to_str(t.next())
     333            'INT'
     334            sage: token_to_str(t.last())
     335            'INT'
     336            sage: token_to_str(t.next())
     337            'NAME'
     338            sage: token_to_str(t.last())
     339            'NAME'
     340        """
     341        return self.token
     342       
     343    cpdef int peek(self):
     344        """
     345        Returns the next token that will be encountered, without changing
     346        the state of self.
     347       
     348        EXAMPLES:
     349            sage: from sage.misc.parser import Tokenizer, token_to_str
     350            sage: t = Tokenizer("a+b")
     351            sage: token_to_str(t.peek())
     352            'NAME'
     353            sage: token_to_str(t.next())
     354            'NAME'
     355            sage: token_to_str(t.peek())
     356            '+'
     357            sage: token_to_str(t.peek())
     358            '+'
     359            sage: token_to_str(t.next())
     360            '+'
     361        """
     362        cdef int save_pos = self.pos
     363        cdef int token = self.find()
     364        self.pos = save_pos
     365        return token
     366       
     367    cpdef bint backtrack(self) except -2:
     368        """
     369        Put self in such a state that the subsequent call to next() will
     370        return the same as if next() had not been called.
     371       
     372        Currently, one can only backtrack once.
     373       
     374        EXAMPLES:
     375            sage: from sage.misc.parser import Tokenizer, token_to_str
     376            sage: t = Tokenizer("a+b")
     377            sage: token_to_str(t.next())
     378            'NAME'
     379            sage: token_to_str(t.next())
     380            '+'
     381            sage: t.backtrack()   # the return type is bint for performance reasons
     382            False
     383            sage: token_to_str(t.next())
     384            '+'
     385        """
     386        if self.pos == self.last_pos and self.token != EOS:
     387            raise NotImplementedError, "Can only backtrack once."
     388        else:
     389            self.pos = self.last_pos
     390            self.token = 0
     391       
     392    cpdef last_token_string(self):
     393        """
     394        Return the actual contents of the last token.
     395       
     396        EXAMPLES:
     397            sage: from sage.misc.parser import Tokenizer, token_to_str
     398            sage: t = Tokenizer("a - 1e5")
     399            sage: token_to_str(t.next())
     400            'NAME'
     401            sage: t.last_token_string()
     402            'a'
     403            sage: token_to_str(t.next())
     404            '-'
     405            sage: token_to_str(t.next())
     406            'FLOAT'
     407            sage: t.last_token_string()
     408            '1e5'
     409        """
     410        return PyString_FromStringAndSize(&self.s[self.last_pos], self.pos-self.last_pos)
     411
     412       
     413cdef class Parser:
     414
     415    cdef integer_constructor
     416    cdef float_constructor
     417    cdef variable_constructor
     418    cdef callable_constructor
     419    cdef bint implicit_multiplication
     420   
     421    def __init__(self, make_int=int, make_float=float, make_var=str, make_function={}, bint implicit_multiplication=True):
     422        """
     423        Create a symbolic expression parser.
     424       
     425        INPUT:
     426            make_int      -- callable object to construct integers from strings (default int)
     427            make_float    -- callable object to construct real numbers from strings (default float)
     428            make_var      -- callable object to construct variables from strings (default str)
     429                             this may also be a dictionary of variable names
     430            make_function -- callable object to construct callable functions from strings
     431                             this may also be a dictionary
     432            implicit_multiplication -- whether or not to accept implicit multiplication
     433           
     434        OUTPUT:
     435            The evaluated expression tree given by the string, where the above
     436            functions are used to create the leaves of this tree.
     437           
     438        EXAMPLES:
     439            sage: from sage.misc.parser import Parser
     440            sage: p = Parser()
     441            sage: p.parse("1+2")
     442            3
     443            sage: p.parse("1+2 == 3")
     444            True
     445
     446            sage: p = Parser(make_var=var)
     447            sage: p.parse("a*b^c - 3a")
     448            a*b^c - 3*a
     449           
     450            sage: R.<x> = QQ[]
     451            sage: p = Parser(make_var = {'x': x })
     452            sage: p.parse("(x+1)^5-x")
     453            x^5 + 5*x^4 + 10*x^3 + 10*x^2 + 4*x + 1
     454            sage: p.parse("(x+1)^5-x").parent() is R
     455            True
     456
     457            sage: p = Parser(make_float=RR, make_var=var, make_function={'foo': (lambda x: x*x+x)})
     458            sage: p.parse("1.5 + foo(b)")
     459            b^2 + b + 1.50000000000000
     460            sage: p.parse("1.9").parent()
     461            Real Field with 53 bits of precision
     462        """
     463        self.integer_constructor = make_int
     464        self.float_constructor = make_float
     465        if not callable(make_var):
     466            make_var = LookupNameMaker(make_var)
     467        if not callable(make_function):
     468            make_function = LookupNameMaker(make_function)
     469        self.variable_constructor = make_var
     470        self.callable_constructor = make_function
     471        self.implicit_multiplication = implicit_multiplication
     472       
     473    cpdef parse(self, s, bint accept_eqn=True):
     474        """
     475        Parse the given string.
     476       
     477        EXAMPLES:
     478            sage: from sage.misc.parser import Parser
     479            sage: p = Parser(make_var=var)
     480            sage: p.parse("E = m c^2")
     481            E == c^2*m
     482        """
     483        cdef Tokenizer tokens = Tokenizer(s)
     484        expr = self.p_eqn(tokens) if accept_eqn else self.p_expr(tokens)
     485        if tokens.next() != EOS:
     486            self.parse_error(tokens)
     487        return expr
     488       
     489    cpdef parse_expression(self, s):
     490        """
     491        Parse an expression.
     492       
     493        EXAMPLES:
     494            sage: from sage.misc.parser import Parser
     495            sage: p = Parser(make_var=var)
     496            sage: p.parse_expression('a-3b^2')
     497            a - 3*b^2
     498        """
     499        cdef Tokenizer tokens = Tokenizer(s)
     500        expr = self.p_expr(tokens)
     501        if tokens.next() != EOS:
     502            self.parse_error(tokens)
     503        return expr
     504       
     505    cpdef parse_sequence(self, s):
     506        """
     507        Parse a (possibly nested) set of lists and tuples.
     508       
     509        EXAMPLES:
     510            sage: from sage.misc.parser import Parser
     511            sage: p = Parser(make_var=var)
     512            sage: p.parse_sequence("1,2,3")
     513            [1, 2, 3]
     514            sage: p.parse_sequence("[1,2,(a,b,c+d)]")
     515            [1, 2, (a, b, d + c)]
     516            sage: p.parse_sequence("13")
     517            13
     518        """
     519        cdef Tokenizer tokens = Tokenizer(s)
     520        all = self.p_sequence(tokens)
     521        if tokens.next() != EOS:
     522            self.parse_error(tokens)
     523        if len(all) == 1 and type(all) is list:
     524            all = all[0]
     525        return all
     526       
     527       
     528    cpdef p_sequence(self, Tokenizer tokens):
     529        """
     530        Parse a (possibly nested) set of lists and tuples.
     531       
     532        EXAMPLES:
     533            sage: from sage.misc.parser import Parser, Tokenizer
     534            sage: p = Parser(make_var=var)
     535            sage: p.p_sequence(Tokenizer("[1+2,0]"))
     536            [[3, 0]]
     537            sage: p.p_sequence(Tokenizer("(1,2,3) , [1+a, 2+b, (3+c), (4+d,)]"))
     538            [(1, 2, 3), [a + 1, b + 2, c + 3, (d + 4,)]]
     539        """
     540        all = []
     541        cdef int token = ','
     542        while token == ',':
     543            token = tokens.peek()
     544            if token == INT:
     545                # we optimize for this rather than going all the way to atom
     546                tokens.next()
     547                if tokens.peek() == c',':
     548                    obj = self.integer_constructor(tokens.last_token_string())
     549                else:
     550                    tokens.backtrack()
     551                    obj = self.p_eqn(tokens)
     552            elif token == '[':
     553                obj = self.p_list(tokens)
     554            elif token == '(':
     555                obj = self.p_tuple(tokens)
     556            elif token == EOS:
     557                return all
     558            elif token == ']' or token == ')':
     559                tokens.token = ','
     560                return all
     561            else:
     562                obj = self.p_eqn(tokens)
     563            PyList_Append(all, obj)
     564            token = tokens.next()
     565           
     566        tokens.backtrack()
     567        return all
     568       
     569    cpdef p_list(self, Tokenizer tokens):
     570        """
     571        Parse a list of items.
     572       
     573        EXAMPLES:
     574            sage: from sage.misc.parser import Parser, Tokenizer
     575            sage: p = Parser(make_var=var)
     576            sage: p.p_list(Tokenizer("[1+2, 1e3]"))
     577            [3, 1000.0]
     578            sage: p.p_list(Tokenizer("[]"))
     579            []
     580        """
     581        cdef int token = tokens.next()
     582        if token != '[':
     583            self.parse_error(tokens, "Malformed list")
     584        all = self.p_sequence(tokens)
     585        token = tokens.next()
     586        if token != ']':
     587            self.parse_error(tokens, "Malformed list")
     588        return all
     589       
     590    cpdef p_tuple(self, Tokenizer tokens):
     591        """
     592        Parse a tuple of items.
     593       
     594        EXAMPLES:
     595            sage: from sage.misc.parser import Parser, Tokenizer
     596            sage: p = Parser(make_var=var)
     597            sage: p.p_tuple(Tokenizer("( (), (1), (1,), (1,2), (1,2,3), (1+2)^2, )"))
     598            ((), 1, (1,), (1, 2), (1, 2, 3), 9)
     599        """
     600        cdef int start = tokens.pos
     601        cdef int token = tokens.next()
     602        cdef bint real_tuple = True
     603        if token != '(':
     604            self.parse_error(tokens, "Malformed tuple")
     605        all = self.p_sequence(tokens)
     606        if len(all) == 1:
     607            if tokens.last() != c',':
     608                real_tuple = False
     609        token = tokens.next()
     610        if token != ')':
     611            self.parse_error(tokens, "Malformed tuple")
     612        if real_tuple:
     613            return tuple(all)
     614        else:
     615            token = tokens.peek()
     616            if token == ',' or token == EOS:
     617                return all[0]
     618            else:
     619                # we have to reparse the entire thing as an expression
     620                tokens.reset(start)
     621                return self.p_eqn(tokens)
     622       
     623# eqn ::= expr op expr | expr
     624    cpdef p_eqn(self, Tokenizer tokens):
     625        """
     626        Parse an equation or expression.
     627       
     628        This is the top-level node called by the \code{parse} function.
     629       
     630        EXAMPLES:
     631            sage: from sage.misc.parser import Parser, Tokenizer
     632            sage: p = Parser(make_var=var)
     633            sage: p.p_eqn(Tokenizer("1+a"))
     634            a + 1
     635           
     636            sage: p.p_eqn(Tokenizer("a == b"))
     637            a == b
     638            sage: p.p_eqn(Tokenizer("a < b"))
     639            a < b
     640            sage: p.p_eqn(Tokenizer("a > b"))
     641            a > b
     642            sage: p.p_eqn(Tokenizer("a <= b"))
     643            a <= b
     644            sage: p.p_eqn(Tokenizer("a >= b"))
     645            a >= b
     646            sage: p.p_eqn(Tokenizer("a != b"))
     647            a != b
     648        """
     649        lhs = self.p_expr(tokens)
     650        cdef int op = tokens.next()
     651        if op == '=':
     652            return lhs == self.p_expr(tokens)
     653        elif op == NOT_EQ:
     654            return lhs != self.p_expr(tokens)
     655        elif op == '<':
     656            return lhs < self.p_expr(tokens)
     657        elif op == LESS_EQ:
     658            return lhs <= self.p_expr(tokens)
     659        elif op == '>':
     660            return lhs > self.p_expr(tokens)
     661        elif op == GREATER_EQ:
     662            return lhs >= self.p_expr(tokens)
     663        else:
     664            tokens.backtrack()
     665            return lhs
     666       
     667# expr ::=  term | expr '+' term | expr '-' term
     668    cpdef p_expr(self, Tokenizer tokens):
     669        """
     670        Parse a list of one or more terms.
     671       
     672        EXAMPLES:
     673            sage: from sage.misc.parser import Parser, Tokenizer
     674            sage: p = Parser(make_var=var)
     675            sage: p.p_expr(Tokenizer("a+b"))
     676            b + a
     677            sage: p.p_expr(Tokenizer("a"))
     678            a
     679            sage: p.p_expr(Tokenizer("a - b + 4*c - d^2"))
     680            -d^2 + 4*c - b + a
     681            sage: p.p_expr(Tokenizer("a - -3"))
     682            a + 3
     683            sage: p.p_expr(Tokenizer("a + 1 == b"))
     684            a + 1
     685        """
     686        # Note: this is left-recursive, so we can't just recurse
     687        cdef int op
     688        operand1 = self.p_term(tokens)
     689        op = tokens.next()
     690        while op == '+' or op == '-':
     691            operand2 = self.p_term(tokens)
     692            if op == '+':
     693                operand1 = operand1 + operand2
     694            else:
     695                operand1 = operand1 - operand2
     696            op = tokens.next()
     697        tokens.backtrack()
     698        return operand1
     699           
     700# term ::=  factor | term '*' factor | term '/' factor
     701    cpdef p_term(self, Tokenizer tokens):
     702        """
     703        Parse a single term (consisting of one or more factors).
     704       
     705        EXAMPLES:
     706            sage: from sage.misc.parser import Parser, Tokenizer
     707            sage: p = Parser(make_var=var)
     708            sage: p.p_term(Tokenizer("a*b"))
     709            a*b
     710            sage: p.p_term(Tokenizer("a * b / c * d"))
     711            a*b*d/c
     712            sage: p.p_term(Tokenizer("-a * b + c"))
     713            -a*b
     714            sage: p.p_term(Tokenizer("a*(b-c)^2"))
     715            a*(b - c)^2
     716            sage: p.p_term(Tokenizer("-3a"))
     717            -3*a
     718        """
     719        # Note: this is left-recursive, so we can't just recurse
     720        cdef int op
     721        operand1 = self.p_factor(tokens)
     722        op = tokens.next()
     723        if op == NAME and self.implicit_multiplication:
     724            op = '*'
     725            tokens.backtrack()
     726        while op == '*' or op == '/':
     727            operand2 = self.p_factor(tokens)
     728            if op == '*':
     729                operand1 = operand1 * operand2
     730            else:
     731                operand1 = operand1 / operand2
     732            op = tokens.next()
     733            if op == NAME and self.implicit_multiplication:
     734                op = '*'
     735                tokens.backtrack()
     736        tokens.backtrack()
     737        return operand1
     738       
     739# factor ::=  '+' factor | '-' factor | power
     740    cpdef p_factor(self, Tokenizer tokens):
     741        """
     742        Parse a single factor, which consists of any number of unary +/-
     743        and a power.
     744       
     745        EXAMPLES:
     746            sage: from sage.misc.parser import Parser, Tokenizer
     747            sage: R.<t> = ZZ[['t']]
     748            sage: p = Parser(make_var={'t': t})
     749            sage: p.p_factor(Tokenizer("- -t"))
     750            t
     751            sage: p.p_factor(Tokenizer("- + - -t^2"))
     752            -t^2
     753            sage: p.p_factor(Tokenizer("t^11 * x"))
     754            t^11
     755        """
     756        cdef int token = tokens.next()
     757        if token == '+':
     758            return self.p_factor(tokens)
     759        elif token == '-':
     760            return -self.p_factor(tokens)
     761        else:
     762            tokens.backtrack()
     763            return self.p_power(tokens)
     764           
     765# power ::=  atom ^ factor | atom
     766    cpdef p_power(self, Tokenizer tokens):
     767        """
     768        Parses a power. Note that exponentiation groups right to left. 
     769       
     770        EXAMPLES:
     771            sage: from sage.misc.parser import Parser, Tokenizer
     772            sage: R.<t> = ZZ[['t']]
     773            sage: p = Parser(make_var={'t': t})
     774            sage: p.p_factor(Tokenizer("-(1+t)^-1"))
     775            -1 + t - t^2 + t^3 - t^4 + t^5 - t^6 + t^7 - t^8 + t^9 - t^10 + t^11 - t^12 + t^13 - t^14 + t^15 - t^16 + t^17 - t^18 + t^19 + O(t^20)
     776            sage: p.p_factor(Tokenizer("t**2"))
     777            t^2
     778            sage: p.p_power(Tokenizer("2^3^2")) == 2^9
     779            True
     780        """
     781        operand1 = self.p_atom(tokens)
     782        cdef int token = tokens.next()
     783        if token == '^':
     784            operand2 = self.p_factor(tokens)
     785            return operand1 ** operand2
     786        else:
     787            tokens.backtrack()
     788            return operand1
     789
     790# atom ::= int | float | name | '(' expr ')' | name '(' args ')'
     791    cpdef p_atom(self, Tokenizer tokens):
     792        """
     793        Parse an atom. This is either a parenthesized expression, a function call, or a literal name/int/float.
     794       
     795        EXAMPLES:
     796            sage: from sage.misc.parser import Parser, Tokenizer
     797            sage: p = Parser(make_var=var, make_function={'sin': sin})
     798            sage: p.p_atom(Tokenizer("1"))
     799            1
     800            sage: p.p_atom(Tokenizer("12"))
     801            12
     802            sage: p.p_atom(Tokenizer("12.5"))
     803            12.5
     804            sage: p.p_atom(Tokenizer("(1+a)"))
     805            a + 1
     806            sage: p.p_atom(Tokenizer("(1+a)^2"))
     807            a + 1
     808            sage: p.p_atom(Tokenizer("sin(1+a)"))
     809            sin(a + 1)
     810            sage: p = Parser(make_var=var, make_function={'foo': sage.misc.parser.foo})
     811            sage: p.p_atom(Tokenizer("foo(a, b, key=value)"))
     812            ((a, b), {'key': value})
     813            sage: p.p_atom(Tokenizer("foo()"))
     814            ((), {})
     815        """
     816        cdef int token = tokens.next()
     817        if token == INT:
     818            return self.integer_constructor(tokens.last_token_string())
     819        elif token == FLOAT:
     820            return self.float_constructor(tokens.last_token_string())
     821        elif token == NAME:
     822            name = tokens.last_token_string()
     823            token = tokens.next()
     824            if token == '(':
     825                func = self.callable_constructor(name)
     826                args, kwds = self.p_args(tokens)
     827                token = tokens.next()
     828                if token != ')':
     829                    self.parse_error(tokens, "Bad function call")
     830                return func(*args, **kwds)
     831            else:
     832                tokens.backtrack()
     833                return self.variable_constructor(name)
     834        elif token == '(':
     835            expr = self.p_expr(tokens)
     836            token = tokens.next()
     837            if token != ')':
     838                self.parse_error(tokens, "Mismatched parentheses")
     839            return expr
     840        else:
     841            self.parse_error(tokens)
     842       
     843# args = arg (',' arg)* | EMPTY
     844    cpdef p_args(self, Tokenizer tokens):
     845        """
     846        Returns a list, dict pair.
     847       
     848        EXAMPLES:
     849            sage: from sage.misc.parser import Parser, Tokenizer
     850            sage: p = Parser()
     851            sage: p.p_args(Tokenizer("1,2,a=3"))
     852            ([1, 2], {'a': 3})
     853            sage: p.p_args(Tokenizer("1, 2, a = 1+5^2"))
     854            ([1, 2], {'a': 26})
     855        """
     856        args = []
     857        kwds = {}
     858        if tokens.peek() == ')':
     859            return args, kwds
     860        cdef int token = ','
     861        while token == ',':
     862            arg = self.p_arg(tokens)
     863            if isinstance(arg, tuple):
     864                name, value = arg
     865                kwds[name] = value
     866            else:
     867                args.append(arg)
     868            token = tokens.next()
     869        tokens.backtrack()
     870        return args, kwds
     871
     872# arg = expr | name '=' expr
     873    cpdef p_arg(self, Tokenizer tokens):
     874        """
     875        Returns an expr, or a (name, expr) tuple corresponding to a single
     876        function call argument.
     877       
     878        EXAMPLES:
     879            sage: from sage.misc.parser import Parser, Tokenizer
     880            sage: p = Parser(make_var=var)
     881            sage: p.p_arg(Tokenizer("a+b"))
     882            b + a
     883            sage: p.p_arg(Tokenizer("val=a+b"))
     884            ('val', b + a)
     885        """
     886        cdef int token = tokens.next()
     887        if token == NAME and tokens.peek() == '=':
     888            name = tokens.last_token_string()
     889            tokens.next()
     890            return name, self.p_expr(tokens)
     891        else:
     892            tokens.backtrack()
     893            return self.p_expr(tokens)
     894           
     895    cdef parse_error(self, Tokenizer tokens, msg="Malformed expression"):
     896        raise SyntaxError, (msg, tokens.s, tokens.pos)
     897
     898
     899cdef class LookupNameMaker:
     900    cdef object names
     901    cdef object fallback
     902    def __init__(self, names, fallback=None):
     903        """
     904        This class wraps a dictionary as a callable for use in creating names.
     905        It takes a dictionary of names, and an (optional) callable to use
     906        when the given name is not found in the dictionary.
     907       
     908        EXAMPLES:
     909            sage: from sage.misc.parser import LookupNameMaker
     910            sage: maker = LookupNameMaker({'pi': pi}, var)
     911            sage: maker('pi')
     912            pi
     913            sage: maker('pi') is pi
     914            True
     915            sage: maker('a')
     916            a
     917        """
     918        self.names = names
     919        self.fallback = fallback
     920    def __call__(self, name):
     921        """
     922        TESTS:
     923            sage: from sage.misc.parser import LookupNameMaker
     924            sage: maker = LookupNameMaker({'a': x}, str)
     925            sage: maker('a')
     926            x
     927            sage: maker('a') is x
     928            True
     929            sage: maker('b')
     930            'b'
     931        """
     932        try:
     933            return self.names[name]
     934        except KeyError:
     935            if self.fallback is not None:
     936                return self.fallback(name)
     937            raise NameError, "Unknown variable: '%s'" % name
     938
     939
  • sage/rings/complex_double.pyx

    diff -r 8de168217630 -r a41794fe68e2 sage/rings/complex_double.pyx
    a b cdef extern from "math.h": 
    6464   
    6565cdef extern from "stdsage.h":
    6666    void set_gel(GEN x, long n, GEN z)
    67 
    68 from sage.misc.sage_eval import sage_eval
    6967
    7068cimport sage.rings.ring
    7169
    cdef class ComplexDoubleField_class(sage 
    271269            elif isinstance(x, tuple):
    272270                return ComplexDoubleElement(x[0], x[1])
    273271            elif isinstance(x, str):
    274                 t = eval(x.replace(' ',''), {"I":self.gen(),"i":self.gen(), 'RealNumber':float})
     272                t = cdf_parser.parse_expression(x)
    275273                if isinstance(t, float):
    276274                    return ComplexDoubleElement(t, 0)
    277275                else:
    def ComplexDoubleField(): 
    17611759    """
    17621760    return _CDF   
    17631761
     1762from sage.misc.parser import Parser
     1763cdef cdf_parser = Parser(float, float,  {"I" : _CDF.gen(), "i" : _CDF.gen()})
     1764
     1765
     1766
    17641767#####
    17651768#(fset 'wrap
    17661769#   [?\C-s ?F ?u ?n ?c ?\C-a ?\C-s ?g ?s ?l ?_ ?c ?o ?m ?p ?l ?e ?x ?_ ?\C-f ?\C-b ?\C-  ?\C-s ?  ?\C-b ?\M-w ?\C-a return ?\C-p ?  ?  ?  ?  ?d ?e ?f ?  ?\C-y ?( ?s ?e ?l ?f ?) ?: return ?r ?\" ?\" ?\" return ?\" ?\" ?\" return ?r ?e ?t ?u ?r ?n ?  ?n ?e ?w ?_ ?e ?l ?e ?m ?e ?n ?t ?( ?g backspace ?g ?s ?l ?_ ?c ?o ?m ?p ?l ?e ?x ?_ ?\C-y ?( ?s ?e ?l ?f ?. ?_ ?c ?o ?m ?p ?l ?e ?x ?) ?) ?\C-a ?\C-s ?F ?u ?n ?c ?\C-a ?\C-n ?\C-k ?\C-y ?\C-r ?r ?\" ?\" ?\C-f ?\C-f ?\C-f ?\C-f return ?\C-y return ?\C-p ?\M-q ?\C-n ?\C-n ?\C-a backspace ?\C-n ?\C-n ?\C-e return ?\C-n ?\C-n ?\C-n ?\C-n])
  • sage/rings/number_field/number_field.py

    diff -r 8de168217630 -r a41794fe68e2 sage/rings/number_field/number_field.py
    a b class NumberField_generic(number_field_b 
    27612761        except AttributeError:
    27622762            k = self.pari_bnf(proof)
    27632763            s = str(k.getattr('reg'))
    2764             self.__regulator = eval(s)
     2764            self.__regulator = float(s) # sage.rings.real_mpfr.create_RealNumber(s)
    27652765        return self.__regulator
    27662766
    27672767    def residue_field(self, prime, names = None, check = False):
  • sage/rings/polynomial/polynomial_ring.py

    diff -r 8de168217630 -r a41794fe68e2 sage/rings/polynomial/polynomial_ring.py
    a b class PolynomialRing_general(sage.algebr 
    222222                return x.sage_poly(self)
    223223            except:
    224224                raise TypeError, "Unable to coerce singular object"
    225         elif isinstance(x , str) and self._has_singular:
    226             self._singular_().set_ring()
     225        elif isinstance(x , str):
    227226            try:
    228                 return self._singular_().parent(x).sage_poly(self)
    229             except:
     227                from sage.misc.parser import Parser, LookupNameMaker
     228                R = self.base_ring()
     229                p = Parser(integer.Integer, R, LookupNameMaker({self.variable_name(): self.gen()}, R))
     230                return self(p.parse(x))
     231            except NameError:
    230232                raise TypeError,"Unable to coerce string"
    231233        elif isinstance(x, FractionFieldElement):
    232234            if x.denominator().is_unit():
  • sage/rings/rational.pyx

    diff -r 8de168217630 -r a41794fe68e2 sage/rings/rational.pyx
    a b cdef class Rational(sage.structure.eleme 
    10031003            sage: (2/3)^(x^n + y^n + z^n)
    10041004            3^(-z^n - y^n - x^n)*2^(z^n + y^n + x^n)
    10051005            sage: (-7/11)^(tan(x)+exp(x))
    1006             11^(-tan(x) - e^x)*-7^(tan(x) + e^x)
     1006            11^(-tan(x) - e^x)*(-7)^(tan(x) + e^x)
    10071007            sage: (2/3)^(3/4)
    10081008            2^(3/4)/3^(3/4)
    10091009            sage: (-1/3)^0
  • sage/rings/real_double.pyx

    diff -r 8de168217630 -r a41794fe68e2 sage/rings/real_double.pyx
    a b import math, operator 
    3232
    3333cimport sage.libs.pari.gen
    3434import sage.libs.pari.gen
    35 
    36 from sage.misc.sage_eval import sage_eval
    3735
    3836import sage.rings.complex_double
    3937import sage.rings.complex_field
    cdef class RealDoubleElement(FieldElemen 
    11721170        Symbolic examples:
    11731171            sage: x, y = var('x,y')
    11741172            sage: RDF('-2.3')^(x+y^3+sin(x))
    1175             -2.30000000000000^(y^3 + sin(x) + x)
     1173            (-2.30000000000000)^(y^3 + sin(x) + x)
    11761174            sage: RDF('-2.3')^x
    1177             -2.30000000000000^x
     1175            (-2.30000000000000)^x
    11781176        """
    11791177        cdef RealDoubleElement base, exp
    11801178        if PY_TYPE_CHECK(self, RealDoubleElement):
  • sage/schemes/elliptic_curves/cm.py

    diff -r 8de168217630 -r a41794fe68e2 sage/schemes/elliptic_curves/cm.py
    a b def hilbert_class_polynomial(D): 
    5858         raise ValueError, "D (=%s) must be a discriminant"%D
    5959    magma.eval("R<x> := PolynomialRing(IntegerRing())")
    6060    f = str(magma.eval("HilbertClassPolynomial(%s)"%D))
    61     x = PolynomialRing(IntegerRing(), name='x').gen()
    62     f = f.replace('^','**')
    63     return eval(f)
     61    return IntegerRing()['x'](f)
    6462
    6563def cm_j_invariants(K):
    6664    r"""
  • setup.py

    diff -r 8de168217630 -r a41794fe68e2 setup.py
    a b ext_modules = [ \ 
    682682
    683683    Extension('sage.misc.misc_c',
    684684              sources = ['sage/misc/misc_c.pyx']), \
     685
     686    Extension('sage.misc.parser',
     687              ['sage/misc/parser.pyx']), \
    685688
    686689    Extension('sage.misc.refcount',
    687690              sources = ['sage/misc/refcount.pyx']), \