にしお #3988(2007/11/14 04:32 GMT) [ Python ] Rating1/1=1.00
せっかくなので++++がbf.inc(4)に置き換わるような設計にしてみました。
この程度の規模なら正規表現でも十分いけるんじゃないかと思いつつ勉強がてらにlexとyaccを使いました。
PLY (Python Lex-Yacc)
あとインデントうんぬんを考慮しないといけないのはそもそも直接while文を使うからなので式で表現しました。
,+[-.,+]を入力するとbf.get()or bf.inc(1)or bf.loop(lambda: bf.inc(-1)or bf.put()or bf.get()or bf.inc (1))と出力されます。
下のFizzBuzzコードを食わせると2638バイトの出力で、処理時間はあっという間でした。 http://d.hatena.ne.jp/n_shuyo/20070516/fizzbuzz
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
from ply import lex, yacc import sys # lex tokens = "PLUS MINUS LEFT RIGHT WHILE WEND PUT GET COMMENT".split() t_WHILE = "\[" t_WEND = "]" t_PUT = "\." t_GET = "," def t_PLUS(t): "\++" t.value = len(t.value) return t def t_MINUS(t): "-+" t.value = len(t.value) return t def t_LEFT(t): "<+" t.value = len(t.value) return t def t_RIGHT(t): ">+" t.value = len(t.value) return t def t_COMMENT(t): '[^[\]><+-,.]' # return nothing def t_error(t): pass # yacc """*** grammar definition sequence : sequence command | command command : PLUS | MINUS | LEFT | RIGHT | PUT | GET | loop loop : WHILE sequence WEND """ def p_sequence(p): "sequence : sequence command" p[0] = p[1] + "or " + p[2] def p_sequence_command(p): "sequence : command" p[0] = p[1] def p_command_PLUS(p): "command : PLUS" p[0] = "bf.inc(%s)" % p[1] def p_command_MINUS(p): "command : MINUS" p[0] = "bf.inc(%s)" % -p[1] def p_command_LEFT(p): "command : LEFT" p[0] = "bf.mov(%s)" % -p[1] def p_command_RIGHT(p): "command : RIGHT" p[0] = "bf.mov(%s)" % p[1] def p_command_PUT(p): "command : PUT" p[0] = "bf.put()" def p_command_GET(p): "command : GET" p[0] = "bf.get()" def p_command_loop(p): "command : loop" p[0] = p[1] def p_loop(p): "loop : WHILE sequence WEND" p[0] = "bf.loop(lambda: %s)" % p[2] def p_error(p): pass # input and parse data = sys.stdin.read() lex.lex() yacc.yacc() result = yacc.parse(data) # output print """ from collections import defaultdict import sys class BF(object): mem = defaultdict(int) cur = 0 def inc(self, n): self.mem[self.cur] += n self.mem[self.cur] %= 256 def mov(self, n): self.cur += n def put(self): c = chr(self.mem[self.cur]) sys.stdout.write(c) def get(self): c = sys.stdin.read(1) self.mem[self.cur] = ord(c) def loop(self, seq): while self.mem[self.cur]: seq() bf = BF() """ print result
Rating1/1=1.00-0+
1 reply [ reply ]
にしお
#3988()
[
Python
]
Rating1/1=1.00
せっかくなので++++がbf.inc(4)に置き換わるような設計にしてみました。
この程度の規模なら正規表現でも十分いけるんじゃないかと思いつつ勉強がてらにlexとyaccを使いました。
PLY (Python Lex-Yacc)
あとインデントうんぬんを考慮しないといけないのはそもそも直接while文を使うからなので式で表現しました。
,+[-.,+]を入力するとbf.get()or bf.inc(1)or bf.loop(lambda: bf.inc(-1)or bf.put()or bf.get()or bf.inc (1))と出力されます。
下のFizzBuzzコードを食わせると2638バイトの出力で、処理時間はあっという間でした。 http://d.hatena.ne.jp/n_shuyo/20070516/fizzbuzz
Rating1/1=1.00-0+