forked from MarkTraceur/redlandside
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lol.py
157 lines (143 loc) · 4.27 KB
/
lol.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#! /usr/bin/python
#
"""LOLCODE to Python translator
A quick hack to translate LOLCODE to Python. OH NOES!
"""
__author__ = "David Basden "
__copyright__ = "GNU Public Licence v2.0"
__version__ = "0.2"
import re
import sys
class State(object):
def __init__(self): self.level = 0
def indent(self): return "\t"*self.level
class Keyword(object):
format = ""
match = None
indent = True
subparse = ()
def __init__(self, match):
self.match = match
self.args = list( match.groups() )
def on_match_start(self, state): pass
def on_match_end(self, state): pass
def on_recurse_start(self, state): pass
def on_recurse_end(self, state): pass
def render(self, state):
if self.indent: out = state.indent()
else: out = ""
out += self.format % tuple(self.args)
return out
def __str__(self): return str(type(self))+str(self.args)
class Hai(Keyword):
matchon = "HAI"
format = "for __HAI in ('l0l',):\n"
def on_match_end(self, state): state.level += 1
class KThxBye(Keyword):
matchon = "KTHXBYE"
format = "break\n"
class CanHas(Keyword): # TODO: make this ! noop
matchon = "CAN HAS (.+)\?"
format = "# import %s\n"
class Visible(Keyword):
matchon = "VISIBLE (.+)$"
subparse = (0,)
format = "print %s\n"
class Gimmeh(Keyword):
matchon = "GIMMEH (.+)"
format = "%s = raw_input()\n"
class IHasA(Keyword):
matchon = "I HAS A (.+)"
format = "%s = 0\n"
class ImInUrLoop(Keyword):
matchon = "IM IN YR LOOP"
format = "while True:\n"
def on_match_end(self, state): state.level += 1
class ImOuttaUrLoop(Keyword):
matchon = "IM OUTTA YR LOOP"
format = "pass\n"
def on_match_end(self, state): state.level -= 1
class BiggerThan(Keyword):
matchon = """IZ (.+) BIGGER THAN (.+)\?(.+)$"""
format = "if %s > %s:\n%s"
subparse = (2,)
def on_recurse_start(self, state): state.level += 1
def on_recurse_end(self, state): state.level -= 1
class Up(Keyword):
matchon = "UP (.+)!!(\d+)"
format = "%s += %s\n"
class NN(Keyword):
matchon = """^(.+?)\ N\ (.+)$"""
subparse = (0,1)
indent = False
format = "%s + %s"
# This also defines precedence in descending order
keywords = (Hai,KThxBye,CanHas,Visible,Gimmeh,IHasA,ImInUrLoop,ImOuttaUrLoop,BiggerThan,Up,NN)
class LolLex(object):
def __init__(self, keywords):
self.keywords = keywords
self.patternmap = [(re.compile(c.matchon,re.MULTILINE & re.DOTALL),c) for c in keywords]
def getkw(self,cs):
for pattern,c in self.patternmap:
m = pattern.match(cs.strip())
if m != None: return c(m)
return None
def parse(self,cs):
kw = self.getkw(cs)
if kw == None: return kw
for sp in kw.subparse:
# Iff recursed keyword is empty, we should leave the input in place
# because it probably contains a variable name -- Base case
recursekw = self.parse(kw.args[sp])
if recursekw != None: kw.args[sp]= recursekw
return kw
class Lol2Py(object):
def get_code_str(self, kws, s=None):
out = ""
if s == None: s = State()
for kw in kws:
if not isinstance(kw,Keyword): ## Leave non-keywords in-place
out = out + str(kw)
continue
kw.on_match_start(s)
for sp in kw.subparse: # recursive render - tres evil
kw.on_recurse_start(s)
token = self.get_code_str((kw.args[sp],), s=s)
kw.args[sp] = token
kw.on_recurse_end(s)
out = out + kw.render(s)
kw.on_match_end(s)
return out
def usage():
print >> sys.stderr, "%s < [-h|--help] | [-c|--show-code] | [-r|--run-code] > [filename]" % (sys.argv[0],)
sys.exit()
if __name__ == "__main__":
filename,runcode,showcode = None,False,False
for arg in sys.argv[1:]:
if arg == '-r' or arg == '--run': runcode = True
elif arg == '-c' or arg == '--show-code': showcode = True
elif filename != None or arg == '-h' or arg == '--help': usage()
else: filename = arg
if not (runcode or showcode): showcode = True
if filename == None: codefile = sys.stdin
else: codefile = open(filename,'r')
ll = LolLex(keywords)
kws,buf = [], ""
while True:
line = codefile.readline()
if line == "": break
buf = buf+" "+line.strip()
kw = ll.parse(buf)
if kw != None:
kws.append(kw)
buf = buf[kw.match.end()+1:]
else:
print "### DO NOT WANT!!! : [%s]" % (buf,)
buf = ""
l2p = Lol2Py()
codez = l2p.get_code_str(kws)
if showcode:
if runcode: print "# Start lolpy code output"
print codez
if runcode: print "# End lolpy code output\n\n# RUNZ0RZ!"
if runcode: exec codez in {}