All pastes #21011 Raw Edit

sc.py

public text v1 · immutable
#21011 ·published 2005-08-24 18:53 UTC
rendered paste body
import string,math

delin_debug = 0
exec_debug = 0


def sc(command):
    return execute(parse(tokenize(string.strip(command), symbols)))

class scalar:
    pass

class vector:
    def __str__(self):
        return '(' + ','.join(map(str, self.data)) + ')'
    def make(self, l):
        self.length = len(l)
        self.data = []
        [self.data.append(component) for component in l]
    def set(self, i,s):
        self.data[i-1]=s
    def get(self, i):
        self.data[i-1]
        
class matrix:
    pass


symbols = ['(',')','[',']','<','>','degrees','sin','cos','tan','log','ln','factor','^','*','/','+','-',',','=','_']

# bugs: some whitespace gets through
def tokenize(s, symbols):
    parts = [s]
    for symbol in symbols:
        newparts = []
        for part in parts:
            for newpart in string.split(part, symbol):
                newparts.append(newpart)
                newparts.append(symbol)
            newparts = newparts[:-1]
            newparts = [newpart for newpart in newparts if newpart != '']
        parts = newparts
    return parts

def parse(tokens):
    return numericize(tokens)

def numericize_anon(part):
    if part in symbols:
        return part
    if '.' in part:
        return float(part)
    return int(part)
def numericize(parts):
    return map(numericize_anon, parts)

delin_tokens = {'(': ')',
                '[': ']',
                '<': '>'}
def delinearizer(tokens, start, matching):
    if delin_debug:
        print 'delinearizer(%r, %r)'%(tokens, start)
    i=start
    while i<len(tokens):
        if tokens[i] in delin_tokens:
            if delin_debug:
                print '%r detected- start=%r, i=%r'%(tokens[i], start, i)
            (tokens, i) = delinearizer(tokens, i+1, delin_tokens[tokens[i]])
        if tokens[i] == matching:
            if delin_debug:
                print '%r detected- start=%r, i=%r'%(tokens[i], start, i)
            tokens[start:i+1] = [tokens[start:i+1]]
            if delin_debug:
                print 'returning tokens=%r, i=%r'%(tokens, start)
            return tokens, start
        else:
            if delin_debug:
                print 'tokens[%r] is not a ( or a ) but a %r'%(i, tokens[i])
        i=i+1
    return tokens, i
def delinearize(tokens):
    tokens = delinearizer(tokens, 0, None)[0]
    if delin_debug:
        print 'delinearlizer: i think that tokens should be %s'%tokens
    return tokens

def noop(tokens, index):
    return tokens, index
def add(x,y):
    return x+y
def sub(x,y):
    return x-y
def mul(x,y):
    return x*y
def div(x,y):
    return x/y
def pow(x,y):
    return x**y
def binop(op, tokens, index):
    tokens[index-1:index+2] = [op(tokens[index-1],tokens[index+1])]
    return (tokens, index-1)
#def parens(tokens, index):
#    tokens[index:index+2] = [execute(tokens[index+1])]
#    return tokens, index
def parens(tokens, index):
    execute(tokens, index+1)
    return (tokens, index)
def prevleftparen(tokens, index):
    while tokens[index] != '(':
        index=index-1
    return index
def endparens(tokens, index):
    tokens[prevleftparen(tokens, index):index+1] = [execute(tokens[prevleftparen(tokens, index)+1:index])]
    return tokens, index
def leftunop(op, tokens, index):
    tokens[index:index+2] = [op(tokens[index+1])]
    return tokens, index 
def degrees(tokens, index):
    tokens[index-1:index+1] = [tokens[index-1]*math.pi/180]
    return tokens, index
def logger(tokens, index):
    if tokens[index+1] == '_':
        tokens[index:index+4] = [math.log(tokens[index+3], tokens[index+2])]
    else:
        tokens[index:index+2] = [math.log(tokens[index+1])]
    return tokens, index
def vectorcollect(tokens, index):
    v = vector()
    v.make([tokens[index-1],tokens[index+1]])
    tokens[index-1:index+2] = [v]
    return tokens, index

symbolfunctions = {'+': lambda x,y: binop(add, x, y),
                   '-': lambda x,y: binop(sub, x, y),
                   '*': lambda x,y: binop(mul, x, y),
                   '/': lambda x,y: binop(div, x, y),
                   '^': lambda x,y: binop(pow, x, y),
                   '(': parens,
                   ')': endparens,
                   ',': vectorcollect,
                   'sin': lambda x,y: leftunop(math.sin, x, y),
                   'cos': lambda x,y: leftunop(math.cos, x, y),
                   'tan': lambda x,y: leftunop(math.tan, x, y),
                   'degrees': degrees,
                   'log': logger,
                   'ln': lambda x,y: leftunop(math.log, x, y)}

def execute(tokens, start=0):
    for symbol in symbols:
        index = start
        while(index < len(tokens)):
            if tokens[index] == symbol:
                (tokens, index) = symbolfunctions[symbol](tokens, index)
            index = index+1
    return tokens[0]