Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os,re,sys,string,random
- _synerr = 'error: invalid syntax'
- _generr = lambda x,y,z: '%s: %s (in line: \'%s\')'%(type(x).__name__, y, z)
- _alterr = lambda x,y: 'error: %s (in line: \'%s\')'%(x,y)
- _plnerr = lambda x: 'error: %s'%x
- reserved = list(string.printable[26+26+10:-7])
- nums = list(range(10))
- var = {}
- def mexp(s,eval_s=None): # Take string, return bool
- if type(s) != str: return False
- s = s.strip(' ')
- l = []
- for x in list(s.replace(' ','')):
- if (x in (list(str(y) for y in range(9)))) or (x in ['+','-','*','/','(',')']):
- l.append(x)
- if ''.join(l) == s.replace(' ','') and (l[0].isdigit() if len(l) != 0 else False): a = True
- else: a = False
- return a
- def issym(s):
- if type(s) != str: return False
- c = 0
- for x in list(str(s)):
- if x in reserved: c = c+1
- if c == len(s): return True
- return False
- def isint(s):
- if not type(s) in [int,str]: return False
- try: int(s)
- except: return False
- return True
- isqstr = lambda x: ((True if x.startswith('"') and x.endswith('"') else False) if isinstance(x, str) else False)
- issstr = lambda x: ((True if x.startswith("'") and x.endswith("'") else False) if isinstance(x, str) else False)
- isproc = lambda x: ((True if x.startswith('(') and x.endswith(')') else False) if isinstance(x, str) else False)
- write = lambda x: sys.stderr.write('%s\n'%str(x))
- def symbol():
- global _s,_dqs,_i,_p,_sym,_mxp,_bool,_none,_stack,commands,procs,o_types,\
- o_s,o_dqs,o_i,o_p,o_sym,o_mxp,o_bool,o_stack,o_none
- _s = 'string'; o_s = "optional %s"%_s
- _dqs = 'double-quoted string'; o_dqs = "optional %s"%_dqs
- _i = 'int'; o_i = "optional %s"%_i
- _sym = 'symbol'; o_sym = "optional %s"%_sym
- _bool = 'bool'; o_bool = "optional %s"%_bool
- _stack = 'stack'; o_stack = "optional %s"%_stack
- _none = 'none'; o_none = "optional %s"%_none
- types = [_s,_dqs,_i,_sym,_bool,_stack,_none]
- o_types = [o_s,o_dqs,o_i,o_sym,o_bool,o_stack,o_none]
- commands = {'if':[
- [_dqs,_i,_bool], # first comparison
- [_sym],
- [_dqs,_i,_bool], # second comparison
- [_sym]
- ], # end of the "if" parsing tree
- 'print':[
- [o_dqs,o_i,o_bool,o_none,_dqs,_i,_bool,_none]
- ], # end of "print" parsing tree
- 'def':[
- [_s],
- [_dqs,_i,_bool,o_dqs,o_i,o_bool]
- ], # end of def parsing tree
- 'input':[
- [_s],
- [o_dqs,_dqs]
- ],
- 'push':[
- [_s],
- [_dqs,_i,_bool,_stack]
- ] # end of push parsing tree
- }
- procs = { # define global procedure calls for use by
- 'eval':lambda x: _eval(tokenize(x)),\
- 'null?':lambda x: x==None or x==[] or x=='' or x=='Null',\
- 'var?':lambda x: (True if x in var.keys() else False),\
- 'proc?': lambda x: (True if x in procs.keys() else False),\
- 'bool?': lambda x: (True if (x == True or 'True') or (x == False or 'False') else False),\
- 'return': lambda x: (x if not mexp(x) else eval(x)),\
- 'equ': lambda x: compact_if('==',x),\
- 'neq': lambda x: compact_if('!=',x),\
- 'geq': lambda x: compact_if('>=',x),\
- 'leq': lambda x: compact_if('<=',x),\
- 'aneq': lambda x: compact_if('<>',x),\
- 'type': lambda x: gettype(x),\
- 'random':lambda x: abs(random.randrange(int(x.split()[0]),int(x.split()[1]))),\
- 'math':lambda x: (eval(x) if mexp(x) else x),\
- 'convert': lambda x: converttype(x),\
- 'valueof': lambda x: getvar(x),\
- }
- symbol()
- def gettype(arg):
- if arg in var.keys(): return
- def getvar(arg):
- if arg in var.keys(): return var[arg]
- else:
- write(_plnerr('unknown variable name "%s" given to valueof'%arg))
- return ''
- def converttype(args):
- args = tokenizer(args.replace(';;',' '))
- transferables = {_i:[_dqs,_i,_bool],_dqs:[_dqs,_i,_bool],_bool:[_i,_dqs,_bool]}
- if args[1] == _i and isint(args[0]): return [_i,args[0]]
- elif args[1] == _dqs and isqstr(args[0]): return [_dqs,args[0]]
- elif args[1] == _bool and args[0] in ['true','false']: return [_bool,{'true':True,'false':False}[args[0]]]
- elif args[1] == _stack:
- write(_plnerr('can\'t change from stack type using convert, use join instead'))
- return ''
- else:
- write(_plnerr('can\'t change type of value %s from %s to %s'%(args[0],atomizer(args[0])[0],args[1])))
- return ''
- def compact_if(comp,args):
- orig = args
- args = args.split(';;')
- if len(args) != 2:
- print 'error: invalid amount of arguments provided'
- return False
- try:
- exps = {
- '==':(True if args[0].rstrip().lstrip()==args[1].rstrip().lstrip() else False),
- '!=':(True if args[0].rstrip().lstrip()!=args[1].rstrip().lstrip() else False),
- '<>':(True if args[0].rstrip().lstrip()!=args[1].rstrip().lstrip() else False),
- '>=':(True if args[0].rstrip().lstrip()>=args[1].rstrip().lstrip() else False),
- '<=':(True if args[0].rstrip().lstrip()<=args[1].rstrip().lstrip() else False)}
- return exps[comp]
- except Exception as e: write(_generr(type(e).__name__, e, orig)); return False
- def getprocs(s): # Takes string, tokenizes it and yea
- if not isproc(s): return _alterr('process isn\'t correctly defined', s)
- s = s[1:-1] #del s[0];del s[-1]
- l = tokenizer(s)
- n = []
- for x in l:
- if isproc(x):
- n.append(getprocs(x))
- elif mexp(x):
- n.append(eval(x))
- else: n.append(x)
- l = n
- if l[0] in procs.keys(): return procs[s.split()[0]](' '.join(s.split()[1:]))
- else: print _alterr('unknown process name', ' '.join(l))
- return '#no-op'
- def tokenizer(s): # Take string, return tokenized list
- if isinstance(s, list): s = ' '.join(s)
- t = []
- tokenizer_ = r'''\s*(,@|\((?:[\\].|[^\\"])*?\)|[('`,)]|"(?:[\\].|[^\\"])*"|;.*|[^\s('"`,)]*)(.*)'''
- inline = lambda x: list(re.match(tokenizer_, x).groups())
- a = inline(s)
- b = [a[0]]
- for _ in range(len(s.split())):
- a = inline(a[1])
- b.append(a[0])
- while '' or ' ' in b:
- b = b.remove('')
- try: b = b.remove(' ')
- except: pass
- return b
- def atomizer(l): # Return atomized list
- n = []
- if isinstance(l, str): l = [l]
- for x in l:
- if isint(x): n.append([_i, int(x)])
- elif isqstr(x): n.append([_dqs, x.replace('"','')])
- elif issstr(x): n.append([_sqs, x.replace("'",'')])
- elif isproc(x): n.append(atomizer([getprocs(x)])[0])
- elif x in var.keys():
- n.append(var[x])
- elif issym(x): n.append([_sym, x])
- elif mexp(x): n.append([_i, eval(x)])
- elif x == 'true' or x == True: n.append([_bool, True])
- elif x == 'false' or x == False: n.append([_bool, False])
- elif x == 'nul': n.append([_none, ""])
- else: n.append([_s, x])
- return n
- def r_sub(arg, lst): # internal module: arg = str, lst = list
- # so i made the mistake of not commenting what this does... i'll just leave it here...
- for x in lst:
- if x == arg[0]: return True
- return False
- def mkl_printable(l):
- n = []
- for x in l: n.append(str(x))
- return n
- def requires(l,mode='loud'): # Return boolean if l matches command definition
- order,tokens = [],[]
- _l = l
- c = -1
- returner = [l[0][1]]
- for x in l:
- order.append(x[0])
- tokens.append(x[1])
- if not order[0] == _s:
- if not mode == 'silent': write(_plnerr('unknown command token: %s (typeof %s)'%(tokens[0],order[0])))
- return False
- elif tokens[0] not in commands.keys():
- if not mode == 'silent': write(_plnerr('unknown command: %s'%tokens[0]))
- return False
- retain = tokens[:]
- keyword = tokens[0]; del tokens[0]; del order[0]
- for _ in commands[keyword]:
- c = c+1
- try:
- if order[c] in _: pass
- else:
- if not mode == 'silent':
- print 1
- write(_plnerr('unknown token in line: "%s"'%' '.join(mkl_printable(retain))))
- write('token: %s (position in string: %d)'%(tokens[c],c+1))
- write('type : %s (expected %s)'%(order[c],' or '.join(_)))
- return False
- except IndexError:
- if _ in o_types:
- _l.append([_none, ""])
- tokens.append("blank")
- else:
- if not mode == 'silent':
- print 2
- write(_plnerr('missing token in line: "%s"'%' '.join(mkl_printable(retain))))
- return True if _l == l else [True, _l]
- def cleanup(l):
- n = []
- for x in l:
- if x != [_sym, '']: n.append(x)
- return n
- def preproc(l): # take list, pre-process concat's and stuff
- c = -1
- skip = False
- n = list()
- _n = list()
- multiline = False
- _l = l # retain l, just in case
- if (l[0] == '#' or l[0] == '//' if len(l) != 0 else False): return '#no-op'
- for token in l:
- c = c+1
- if skip != True:
- if token == '+':
- if (not l[c+1] == '+' and c != 0):
- del n[c-1]
- use = l[c-1]+l[c+1]
- del l[c+1]
- else:
- write(_plnerr('unexpected concat token at position %d'%c))
- return '#no-op'
- n.append(use) # append the two tokens either side (+1 & -1) of '+' token to the list while deleting previous list element in n and deleting next element in l
- # if in the future a retained version of l is needed, see variable _l
- elif token == '#': skip = True
- ## elif token == '\\':
- ## try:
- ## multiline = True
- ## n = [[n]]
- ## if preproc(l[c+1:])[0] == True:
- ## n.append([preproc(l[c+1:])))
- ## else:
- ## n.append(l[c+1:])
- ## except RuntimeError: throw(_plnerr('maximum single-line command length exceeded'))
- else:
- n.append(token)
- return n
- def _detyper(l):
- n = {}
- c = -1
- for token in l:
- c = c+1
- n[c] = token
- return n
- def detyper(l,i):
- n = []
- for token in l: n.append(token[i] if i < len(token) and i > 0 else token[-1])
- return n
- def to_string(l):
- converter = {
- _dqs:lambda x: '"%s"'%x,
- _i:lambda x: x,
- _sym:lambda x: x,
- _bool:lambda x: repr(x).lower(),
- }
- return converter[l[0]](l[1])
- def throw(error):
- write(error)
- exit()
- def _eval(l):
- if isinstance(requires(l,'silent'), list):
- l = requires(l)[1]
- elif requires(l) != True: return ''
- global var
- _l = l
- l = detyper(_l,1)
- if l[0] == 'print': return l[1]
- elif l[0] == 'if':
- # if a == b: thiiiiiings
- # 0 1 2 34 5
- c,op,c2,blank = l[1:5]
- exps = {
- '==':(True if c==c2 else False),
- '!=':(True if c!=c2 else False),
- '<>':(True if c!=c2 else False),
- '>=':(True if c>=c2 else False),
- '<=':(True if c<=c2 else False)}
- if exps[op] == True:
- if requires(_l[5:]):
- return _eval(_l[5:])
- elif l[0] == 'def': var[l[1]] = _l[2]
- elif l[0] == 'input': var[l[1]] = [_dqs, '%s'%raw_input(l[2])]
- elif l[0] == 'push':
- if l[1] in var.keys() and isinstance(var[l[1]], list): var[l[1]] = var[l[1]].append(_l[2])
- elif l[1] not in var.keys(): var[l[1]] = [_l[2]]
- return
- elif l[0] == 'get':
- if l[1] in var.keys():
- try: return var[l[1]][l[2]]
- except IndexError: throw(_plnerr('stack id of %s isn\'t in stack "%s"'%(l[2],l[1])))
- else: throw(_plnerr('unknown stack name "%s"'%l[1]))
- def handle(s): # take string, do all messy stuff and pass data to _eval()
- s = tokenizer(s) # tokenize! str == list
- s = preproc(s) # preprocess, no comments and concat'ed strs/ints are concat'd
- ## if isinstance(s, list):
- ## if s[0] == True:
- ## l = None
- ## for command in s[1:]:
- ## l.append
- if s == '#no-op' or s == False: return '' # if s == comment, return nothing, print nothing :)
- s = atomizer(s) # make the tokenized list Wyvern-readable, helps with converting to python readable types as well
- s = _eval(cleanup(s))
- return (s if not s == '#no-op' else '')
- def repl(input_='none',prompt='==> '):
- global repl_line,mode; repl_line = 0; mode = 'repl'
- while input_ != 'end':
- repl_line = repl_line+1
- input_ = raw_input('@%d%s'%(repl_line,prompt))
- write(handle(input_))
- def fepl(_file):
- global line_buffer, line_id, mode; line_buffer = []; line_id = -1; mode = 'fepl'
- with open(_file, 'r').readlines() as lines:
- for line in lines: line_buffer.append(preproc(line))
- for line in line_buffer:
- line_id = line_id + 1
- write(handle(line))
- repl()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement