您需要的是一个简单的解析器。您的输入可以用以下扩展的BNF表示法显示:input := NUM ':' edge_defn*
edge_defn := '(' NUM ',' NUM ';' NUM )
NUM := [0-9]+
然后,您可以编写自顶向下的解析器,或者使用解析器生成器(例如ANTLR或yacc/bison)。在
让我们开始编写自己的解析器。首先需要在输入中标识标记。到目前为止,只有标记是:):,;和数字。我们可以简单地使用Python的split()方法,如Peter Norvig的Python Lisp:
^{pr2}$
我知道,这看起来也很难看,但这是我们唯一使用这种黑客的地方。我们所做的只是在符号周围加上空格,然后使用split方法得到所有标记的列表。在
接下来,我们需要一个get_token函数,由于edge_defn,我们需要为最后一个情况再考虑一个令牌。这就是为什么全局前瞻变量在哪里。在look_ahead = None
def next_token(t):
global look_ahead
if look_ahead:
temp = look_ahead
try:
look_ahead = t.next()
except StopIteration:
look_ahead = None
return temp
然后从BNF符号开始,我们将为定义的左侧编写函数。在def match(t, tok):
if next_token(t) != tok:
print "Syntax error! Expecting: ", tok
exit()
def read_num(t):
return int(next_token(t))
def edge_defn(t):
match(t, '(')
a = read_num(t)
match(t, ',')
b = read_num(t)
match(t, ';')
c = read_num(t)
print "%d,%d = %d" % (a,b,c) # ..do whatever here..
match(t, ')')
def input(t):
global grid_size
grid_size = read_num(t)
match(t, ':')
while True:
edge_defn(t)
if look_ahead:
match(t, ',')
else:
return
t = tokenizer()
look_ahead = t.next()
input(t)
在调用第一个规则(input)之后,将解析输入,并在执行操作的过程中执行。虽然这本身是一个很好的练习,但是最好使用解析器生成器,但是我不确定它是否会被接受。(取决于任务的目的。)