Add tags

Add tags to the following comment

せっかくなので++++が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

Add tags

The input will be splited to tags with space.

Index

Feed

Other

Link

Pathtraq

loading...