#tokenizer #lexer #byte-offset #text #fuzz-testing

pretok

适用于 C 类语法的字符串预处理器

1 个不稳定版本

0.1.0 2020 年 9 月 12 日

#1310 in 文本处理

MIT 许可证

31KB
563

pretok

Pretok 是适用于 C 类语法的预处理器。Pretok 通过处理行和块注释、空白和字符串来简化后续的标记器。Pretok 在 UTF-8 代码点输入字符串上作为一个迭代器运行。

给定一个输入字符串,pretok 执行以下操作。

  • 实现了迭代器特性,其中 next() 返回一系列 Option<Pretoken> 结构。
  • 从输入字符串中过滤 // 行注释
  • 从输入字符串中过滤 /* 块注释 */
  • 将带转义字符的引号字符串作为单个 Pretoken 返回。
  • 跳过空白字符。
  • 在上述过滤器之后,返回通常由空白分隔的 Pretokens
  • 返回每个 pretoken 的行号和字节偏移量

示例

空白通常分隔 pretoken,并且在引号字符串之外被移除。

let mut pretok = PreTokenizer::new("Hello World!");
assert!(pretok.next() == Some(Pretoken{s:"Hello", line:1, offset:0}));
assert!(pretok.next() == Some(Pretoken{s:"World!", line:1, offset:6}));
assert!(pretok.next() == None);

注释被移除,也可能分隔 pretoken。

let mut pretok = PreTokenizer::new("x/*y*/z");
assert!(pretok.next() == Some(Pretoken{s:"x", line:1, offset:0}));
assert!(pretok.next() == Some(Pretoken{s:"z", line:1, offset:6}));
assert!(pretok.next() == None);

let mut pretok = PreTokenizer::new("x\ny//z");
assert!(pretok.next() == Some(Pretoken{s:"x", line:1, offset:0}));
assert!(pretok.next() == Some(Pretoken{s:"y", line:2, offset:2}));
assert!(pretok.next() == None);

引号字符串是一个单独的 pretoken。

let mut pretok = PreTokenizer::new("Hello \"W o r l d!\"");
assert!(pretok.next() == Some(Pretoken{s:"Hello", line:1, offset:0}));
assert!(pretok.next() == Some(Pretoken{s:"\"W o r l d!\"", line:1, offset:6}));
assert!(pretok.next() == None);

引号字符串创建一个单独的 pretoken,与周围的 pretoken(s) 分开。

let mut pretok = PreTokenizer::new("x+\"h e l l o\"+z");
assert!(pretok.next() == Some(Pretoken{s:"x+", line:1, offset:0}));
assert!(pretok.next() == Some(Pretoken{s:"\"h e l l o\"", line:1, offset:2}));
assert!(pretok.next() == Some(Pretoken{s:"+z", line:1, offset:13}));
assert!(pretok.next() == None);

单元测试

Pretok 支持单元测试。

cargo test

模糊测试

Pretok 支持模糊测试。模糊测试从随机输入的语料库开始,然后进一步随机化这些输入以尝试造成崩溃和挂起。在写作时(Rust 1.46.0),模糊测试 需要夜间构建

运行模糊测试

cargo +nightly fuzz run fuzz_target_1

模糊测试将在 Ctrl-C 中止之前运行。根据我的经验,模糊测试几乎会立即发现一个问题或根本不会发现问题。

Cargo fuzz 在内部使用 LLVM 的 libFuzzer,它提供了大量的运行时选项。要使用夜间编译器构建查看选项

cargo +nightly fuzz run fuzz_target_1 -- -help=1

例如,为挂起设置较短的 5 秒超时

cargo +nightly fuzz run fuzz_target_1 -- -timeout=5

依赖关系

~695KB
~10K SLoC