Changeset 7954:f08d04cd966e


Ignore:
Timestamp:
01/04/08 04:54:56 (5 years ago)
Author:
Robert Bradshaw <robertwb@…>
Branch:
default
Message:

implicit multiplication function for preparsing

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sage/misc/preparser.py

    r7836 r7938  
    139139    return s.isalpha() or s.isdigit() or s=="_" 
    140140 
     141keywords = """ 
     142and       del       from      not       while     
     143as        elif      global    or        with      
     144assert    else      if        pass      yield     
     145break     except    import    print               
     146class     exec      in        raise               
     147continue  finally   is        return              
     148def       for       lambda    try 
     149""".split() 
    141150 
    142151in_single_quote = False 
     
    163172        sage: print s % literals 
    164173        ['a', "b", 'c', "d\""] 
     174        sage: print strip_string_literals(r'-"\\\""-"\\"-')[0] 
     175        -%(L1)s-%(L2)s- 
    165176         
    166177    Triple-quotes are handled as well. 
     
    170181        sage: print s % literals 
    171182        [a, '''b''', c, ''] 
     183 
     184    Comments are subsituted too: 
     185        sage: s, literals = strip_string_literals("code '#' # ccc 't'"); s 
     186        'code %(L1)s #%(L2)s' 
     187        sage: s % literals 
     188        "code '#' # ccc 't'" 
    172189    """ 
    173190    new_code = [] 
     
    180197        sig_q = code.find("'", q) 
    181198        dbl_q = code.find('"', q) 
     199        hash_q = code.find('#', q) 
    182200        q = min(sig_q, dbl_q) 
    183201        if q == -1: q = max(sig_q, dbl_q) 
    184         if q == -1: 
     202        if not in_quote and hash_q != -1 and (q == -1 or hash_q < q): 
     203            # it's a comment 
     204            newline = code.find('\n', hash_q) 
     205            if newline == -1: newline = len(code) 
     206            counter += 1 
     207            label = "L%s" % counter 
     208            literals[label] = code[hash_q+1:newline] 
     209            new_code.append(code[start:hash_q].replace('%','%%')) 
     210            new_code.append("#%%(%s)s" % label) 
     211            start = q = newline 
     212        elif q == -1: 
    185213            new_code.append(code[start:].replace('%','%%')) 
    186             return "".join(new_code), literals 
    187         if in_quote: 
     214            break 
     215        elif in_quote: 
    188216            if not raw and code[q-1] == '\\': 
    189                 q += 1 
     217                k = 2 
     218                while code[q-k] == '\\': 
     219                    k += 1 
     220                if k % 2 == 0: 
     221                    q += 1 
    190222            if code[q:q+len(in_quote)] == in_quote: 
    191223                counter += 1 
     
    207239            start = q 
    208240            q += len(in_quote) 
     241             
     242    return "".join(new_code), literals 
    209243 
    210244 
     
    847881    return '\n'.join(F) 
    848882 
     883def implicit_mul(code, level=5): 
     884    """ 
     885    Insert explicit *'s for implicit multiplication.  
     886 
     887    INPUT:  
     888        code  -- the code with missing *'s 
     889        level -- how agressive to be in placing *'s 
     890                   0) Do nothing 
     891                   1) numeric followed by alphanumeric 
     892                   2) closing parentheses followed by alphanumeric 
     893                   3) Spaces between alphanumeric 
     894                  10) Adjacent parentheses (may mangle call statements) 
     895                    
     896    EXAMPLES:  
     897        sage: from sage.misc.preparser import implicit_mul 
     898        sage: implicit_mul('(2x^2-4x+3)a0') 
     899        '(2*x^2-4*x+3)*a0' 
     900        sage: implicit_mul('a b c in L') 
     901        'a*b*c in L' 
     902        sage: implicit_mul('1r + 1e3 + 5exp(2)') 
     903        '1r + 1e3 + 5*exp(2)' 
     904        sage: implicit_mul('f(a)(b)', level=10) 
     905        'f(a)*(b)' 
     906    """ 
     907    def re_no_keyword(pattern, code): 
     908        for _ in range(2): # do it twice in because matches don't overlap 
     909            for m in reversed(list(re.finditer(pattern, code))): 
     910                left, right = m.groups() 
     911                if left not in keywords and right not in keywords: 
     912                    code = "%s%s*%s%s" % (code[:m.start()], 
     913                                          left, 
     914                                          right, 
     915                                          code[m.end():]) 
     916        return code 
     917         
     918    code, literals = strip_string_literals(code) 
     919    if level >= 1: 
     920        no_mul_token = " '''_no_mult_token_''' " 
     921        code = re.sub(r'\b(\d+\.?\d*)((r\b)|(e[-\d]))', r'\1%s\2' % no_mul_token, code)  # exclude such things as 1e5 and 10r 
     922        code = re_no_keyword(r'\b(\d+\.?\d*) *([a-zA-Z_(]\w*)\b', code) 
     923    if level >= 2: 
     924        code = re.sub(r'(\%\(L\d+\))s', r'\1%ss%s' % (no_mul_token, no_mul_token), code) # literal strings 
     925        code = re_no_keyword(r'(\)) *(\w+)', code) 
     926    if level >= 3: 
     927        code = re_no_keyword(r'(\w+) +(\w+)', code) 
     928    if level >= 10: 
     929        code = re.sub(r'\) *\(', ')*(', code) 
     930    code = code.replace(no_mul_token, '') 
     931    return code % literals 
Note: See TracChangeset for help on using the changeset viewer.