我试图为an LL(1) parser制作一个确定性的无上下文语法。我希望能够使用的一件事,因为它可以使更多更简单,更少贪婪和更易于维护的文字记录(如数字,字符串,注释和引用)的解析是 k 前瞻标记,而不仅仅是 1 前瞻标记。
目前,我的解决方案(有效,但我感觉不是最理想)就像(但不是)以下内容:
for idx, tok in enumerate(toklist):
if tok == "blah":
do(stuff)
elif tok == "notblah":
try:
toklist[idx + 1]
except:
whatever()
else:
something(else)
(您可以在上面的链接中看到我实际的,更大的实现。)
有时候,就像解析器找到字符串或块注释的开头一样,跳过"跳转"迭代器的当前计数器,这样迭代器中的许多索引都会被跳过。
理论上可以用(例如)idx += idx - toklist[idx+1:].index(COMMENT)
完成,但实际上,每次循环重复时,idx
和obj
都是使用toklist.next()
重新初始化,覆盖对变量的任何更改。
显而易见的解决方案是while True:
或while i < len(toklist): ... i += 1
,但这些问题存在一些明显的问题:
在迭代器上使用while
就像列表一样真的是C样的,而且不是 Pythonic,除了它的事实之外与迭代器上的enumerate
相比,可怕的不可读和不清楚。 (另外,对于有时可能需要的while True:
,您必须处理list index out of range
。)
对于while
的每个周期,有两种获取当前令牌的方法:
toklist[i]
(丑陋,当你可以迭代时)toklist[i]
分配给更短,更易读,更少错字的名称。这样做的缺点就是会占用内存,而且速度慢,效率低。也许可以说while
循环是我应该使用的东西,但我认为while
循环用于处理直到条件不再成立,和for
循环用于在迭代或上进行有限迭代和循环,而(n迭代LL)解析器应该清楚地实现后者。
是否有一种干净,Pythonic,有效的方法来控制和任意改变迭代器的当前索引?
这不是this的欺骗,因为所有这些答案都使用复杂的,不可读的while
循环,这是我 想要的。
答案 0 :(得分:4)
是否有一种干净,Pythonic,有效的方法来控制和任意改变迭代器的当前索引?
不,没有。您可以实现自己的迭代器类型;它不会以相同的速度运行(在Python中实现),但它是可行的。例如:
# Created outside for loop so you have name to call seek on
myseqiter = SequenceIterator(myseq)
for x in myseqiter:
if test(x):
# do stuff with x
else:
# Seek somehow, e.g.
myseqiter.seek(1) # Skips the next value
要使用它,您可以执行以下操作:
heightForHeaderInSection
添加诸如提供索引和值之类的行为作为练习。