为任何已知长度的数据优化 Ragel 语义条件
Optimize Ragel semantic conditions for any data of known length
Ragel manual 6.5 语义条件中有一个示例,演示了如何使用 when 子句为可变大小结构编写语法。
action rec_num { i = 0; n = getnumber(); }
action test_len { i++ < n }
data_fields = (
’d’
[0-9]+ %rec_num
’:’
( [a-z] when test_len )*
)**;
它适用于小型结构,但对于较大的结构它会变慢,因为解析器会尝试评估每个字符的条件。
我想要做的是跳过扫描,只是将数据复制到缓冲区中,对于这样的语法(注意 any*):
action rec_num { i = 0; n = getnumber(); }
action test_len { i++ < n }
data_fields = (
’d’
[0-9]+ %rec_num
’:’
( any* when test_len )*
)**;
所以我想直接复制长度为 n 的缓冲区而不用迭代。如何在不离开解析器上下文的情况下执行此操作?
您可能需要自己处理事情。 ragel 用户指南提到您可以在机器内更改 fpc
/p
变量,因此这应该足够安全。这假设您正在处理一个块中的所有数据(即,数据字段不会被分解)
machine foo;
action rec_num { i = 0; n = getnumber(); }
action test_len { i++ < n }
action buffer_data_field {
/* p is still pointing to ':' at this point. */
if (p + 1 + n >= pe) { fgoto *foo_error; }
buffer(p + 1, n);
p += n;
}
action buffer_data_field_eof {
/* check for eof while data was expected */
/* p is pointing past the ':' at this point */
if (n) { fgoto *foo_error; }
}
data_fields = (
'd'
[0-9]+ %rec_num
':'
$buffer_data_field
$eof(buffer_data_field_eof)
)**;
如果数据被分块,您可以拆分缓冲:
buffer_data :=
any+
$eof{ fnext *foo_error; }
${
size_t avail = pe - p;
if (avail >= n) {
buffer(p, n);
p += n - 1;
fnext data_fields;
} else {
buffer_partial(p, avail);
n -= avail;
p += avail - 1;
}
}
;
data_fields = (
'd'
[0-9]+ %rec_num
':' ${ if (n) fnext buffer_data; }
)**;
Ragel manual 6.5 语义条件中有一个示例,演示了如何使用 when 子句为可变大小结构编写语法。
action rec_num { i = 0; n = getnumber(); }
action test_len { i++ < n }
data_fields = (
’d’
[0-9]+ %rec_num
’:’
( [a-z] when test_len )*
)**;
它适用于小型结构,但对于较大的结构它会变慢,因为解析器会尝试评估每个字符的条件。
我想要做的是跳过扫描,只是将数据复制到缓冲区中,对于这样的语法(注意 any*):
action rec_num { i = 0; n = getnumber(); }
action test_len { i++ < n }
data_fields = (
’d’
[0-9]+ %rec_num
’:’
( any* when test_len )*
)**;
所以我想直接复制长度为 n 的缓冲区而不用迭代。如何在不离开解析器上下文的情况下执行此操作?
您可能需要自己处理事情。 ragel 用户指南提到您可以在机器内更改 fpc
/p
变量,因此这应该足够安全。这假设您正在处理一个块中的所有数据(即,数据字段不会被分解)
machine foo;
action rec_num { i = 0; n = getnumber(); }
action test_len { i++ < n }
action buffer_data_field {
/* p is still pointing to ':' at this point. */
if (p + 1 + n >= pe) { fgoto *foo_error; }
buffer(p + 1, n);
p += n;
}
action buffer_data_field_eof {
/* check for eof while data was expected */
/* p is pointing past the ':' at this point */
if (n) { fgoto *foo_error; }
}
data_fields = (
'd'
[0-9]+ %rec_num
':'
$buffer_data_field
$eof(buffer_data_field_eof)
)**;
如果数据被分块,您可以拆分缓冲:
buffer_data :=
any+
$eof{ fnext *foo_error; }
${
size_t avail = pe - p;
if (avail >= n) {
buffer(p, n);
p += n - 1;
fnext data_fields;
} else {
buffer_partial(p, avail);
n -= avail;
p += avail - 1;
}
}
;
data_fields = (
'd'
[0-9]+ %rec_num
':' ${ if (n) fnext buffer_data; }
)**;