我读了Regular Expression Matching: the Virtual Machine Approach,现在我尝试解析正则表达式并从中创建虚拟机。 标记器工作并创建其标记。在那一步之后,我从令牌流创建反向波兰表示法,所以最后我得到
a b c | |
来自正则表达式a|(b|c)
的。 那么,现在是我卡住的一步:我想要一个数组
0: split 1, 3
1: match 'a'
2: jump 7
3: split 4, 6
4: match 'b'
5: jump 7
6: match 'c'
7: noop
来自上面的流。我没有把它弄好......我使用输出数组和堆栈作为每个令牌的起始位置。首先,将3个值添加到输出中(并且它是堆栈的起始位置)。
output stack
------------------- ------
0: match 'a' 0: 0
1: match 'b' 1: 1
2: match 'c' 2: 2
使用|
,我会从堆叠中弹出最后2个位置,并在特定位置插入split
和jump
。根据当前堆栈长度和我添加的元素数量计算这些值。
最后,我将最后一个元素的新起始位置添加到堆栈中(在这种情况下保持不变)。
output stack
------------------- ------
0: match 'a' 0: 0
1: split 2, 4 1: 1
2: match 'b'
3: jump 5
4: match 'c'
这似乎没问题。现在,弹出下一个|
......
output stack
------------------- ------
0: split 1, 3 0: 0
1: match 'a'
2: jump 7
3: split 2, 4
4: match 'b'
5: jump 5
6: match 'c'
这就是问题所在。我必须更新之前计算的所有地址(第3行和第5行)。那不是我想要的。 我猜,相对地址有同样的问题(至少如果值为负)。
所以我的问题是,如何从正则表达式创建一个vm。 我是在正确的轨道上(使用rpn形式)还是有另一种(和/或更简单的)方式?
输出数组存储为整数数组。 split
- 命令实际上需要3个条目,jump
需要两个,......
答案 0 :(得分:0)
我认为在处理过程中不是设置地址,而是可以将引用存储到要跳转的命令,在输出数组中也可以存储引用(或指针)。完成所有处理后,您将继续生成的输出,并根据结果数组中引用命令的实际位置分配索引。
答案 1 :(得分:0)
RPN不是构建所需输出的最佳方式。如果您构建了一个AST,那么使用递归遍历生成代码会很容易。
假设您有一个OR节点,例如,有两个孩子“左”和“右”。每个节点实现一个方法generate(OutputBuffer)
,OR节点的实现如下所示:
void generate(OutputBuffer out)
{
int splitpos = out.length();
out.append(SPLIT);
out.append(splitpos+3); //L1
out.append(0); //reservation 1
//L1
left.generate(out);
int jumppos = out.length();
out.append("JUMP");
out.append(0); //reservation 2
//L2
out.set(splitpos+2, out.length()); //reservation 1 = L2
right.generate(out);
//L3
out.set(jumppos+1, out.length()); //reservation 2 = L3
}
答案 2 :(得分:0)
使用相对跳转和拆分会更容易。
a
-将match
推入堆栈
0: match 'a'
b
-将match
推入堆栈
0: match 'a'
--
0: match 'b'
c
-将match
推入堆栈
0: match 'a'
--
0: match 'b'
--
0: match 'c'
|
—从堆栈中弹出两帧,然后按split <frame1> jump <frame2>
0: match 'a'
--
0: split +1, +3
1: match 'b'
2: jump +2
3: match 'c'
|
—从堆栈中弹出两帧,然后按split <frame1> jump <frame2>
0: split +1, +3
1: match 'a'
2: jump +5
3: split +1, +3
4: match 'b'
5: jump +2
6: match 'c'
如果确实需要绝对跳跃,则可以轻松地迭代并调整所有偏移量。
答案 3 :(得分:0)
FWIW,Cox发布了他的方法here的实现。您可能会发现它对您有所帮助。