我在Python中实现了一个基于生成器的扫描程序,它将字符串标记为表单的元组(标记类型,标记值):
for token in scan("a(b)"):
print token
Run Code Online (Sandbox Code Playgroud)
会打印
("literal", "a")
("l_paren", "(")
...
Run Code Online (Sandbox Code Playgroud)
下一个任务意味着解析令牌流,为此,我需要能够从当前的一个项目前面查看一个项目,而不必将指针向前移动.事实上,迭代器和生成器不能一次提供完整的项目序列,但是每个项目根据需要使得前瞻与列表相比有点棘手,因为除非__next__()
被调用,否则下一个项目是未知的.
什么可以直接实现基于生成器的前瞻看起来像?目前我正在使用一种解决方法,这意味着从生成器中生成一个列表:
token_list = [token for token in scan(string)]
Run Code Online (Sandbox Code Playgroud)
然后很容易通过以下方式实现前瞻:
try:
next_token = token_list[index + 1]
except: IndexError:
next_token = None
Run Code Online (Sandbox Code Playgroud)
当然这只是工作正常.但是考虑到这一点,我的第二个问题就出现了:首先是否真的需要制造scan()
发电机?
我写了一个小片段来计算给定节点的路径长度(例如它到根节点的距离):
def node_depth(node, depth=0, colored_nodes=set()):
"""
Return the length of the path in the parse tree from C{node}'s position
up to the root node. Effectively tests if C{node} is inside a circle
and, if so, returns -1.
"""
if node.mother is None:
return depth
mother = node.mother
if mother.id in colored_nodes:
return -1
colored_nodes.add(node.id)
return node_depth(mother, depth + 1, colored_nodes)
Run Code Online (Sandbox Code Playgroud)
现在这个函数发生了一件奇怪的事情(至少对我来说很奇怪):第一次调用node_depth会返回正确的值.但是,使用相同节点第二次调用它会返回-1.coloured_nodes集在第一次调用中为空,但包含第二次调用中已在第一次调用期间添加的所有节点ID:
print node_depth(node) # --> 9
# initially colored nodes --> set([])
print node_depth(node) # --> -1
# initially colored …
Run Code Online (Sandbox Code Playgroud) 我花了一些时间进行汇编编程(特别是Gas),最近我学习了align指令.我想我已经理解了它的基础知识,但我想更深入地了解它的性质以及何时使用对齐.
例如,我想知道一个简单的C++ switch语句的汇编代码.我知道在某些情况下,switch语句基于跳转表,如下面几行代码所示:
.section .rodata
.align 4
.align 4
.L8:
.long .L2
.long .L3
.long .L4
.long .L5
...
Run Code Online (Sandbox Code Playgroud)
.align 4在下一个4字节边界上对齐以下数据,以确保获取这些内存位置是有效的,对吗?我认为这样做是因为在switch语句之前可能会发生导致错位的事情.但为什么实际上有两次调用.align?在调用.align时是否有任何经验法则,或者只要在新的数据块存储在内存中并且之前的某些内容可能导致错位,它是否应该完成?
对于数组,一旦数组占用至少32个字节,似乎就在32字节边界上进行对齐.以这种方式执行它是否更有效还是32字节边界的另一个原因是什么?
我很欣赏任何有关文学的解释或暗示.
我正在尝试在C++中实现方法链接,如果类的构造函数调用是一个单独的语句,结果很容易,例如:
Foo foo;
foo.bar().baz();
Run Code Online (Sandbox Code Playgroud)
但是一旦构造函数调用成为方法链的一部分,编译器就会抱怨期望";" 代替"." 在构造函数调用后立即:
Foo foo().bar().baz();
Run Code Online (Sandbox Code Playgroud)
我现在想知道这在C++中是否真的可行.这是我的测试类:
class Foo
{
public:
Foo()
{
}
Foo& bar()
{
return *this;
}
Foo& baz()
{
return *this;
}
};
Run Code Online (Sandbox Code Playgroud)
我还在C++(http://en.wikipedia.org/wiki/Fluent_interface#C.2B.2B)中找到了一个"流畅的接口"的例子,这似乎正是我正在寻找的.但是,我得到该代码的相同编译器错误.
我写了一个小的汇编代码段(Gas,32位),它接受一个命令行参数,计算它的字符并打印字符串,如果它有一定的长度(仅用于调试目的).我对汇编比较陌生,所以我很确定这里有一些我想念的东西,因为当我将字符串存储在eax中时,我会得到不同的行为,例如ecx,edx或esi.
这是片段.当用eax替换esi时,无论字符串有多长,循环都只输入两次,因此计数器(ebx)始终为1.使用esi或其他寄存器,一切似乎都能正常工作.
.section .text
.globl _start
_start:
movl %esp, %ebp
movl 0(%ebp), %eax # get argc
cmpl $2, %eax # ensure argc == 2
jne _exit
movl 8(%ebp), %eax # get argv[1]
movl $0, %ebx # set counter to 0
_begin_loop:
movb (%eax), %al # load a character into %al
cmpb $0, %al # see if \0 is reached
je _end_loop # exit loop if at end of string
incl %ebc # increment counter
incl %eax # advance string
jmp …
Run Code Online (Sandbox Code Playgroud)