6 个版本 (破坏性更新)
0.6.0 | 2024 年 5 月 3 日 |
---|---|
0.5.1 | 2024 年 4 月 8 日 |
0.4.0 | 2024 年 4 月 2 日 |
0.3.0 | 2024 年 3 月 27 日 |
0.1.0 | 2024 年 2 月 18 日 |
#464 in 解析器实现
每月 35 次下载
42KB
795 行
RustDOT 主要基于 Graphviz DOT 语言,并轻微地 Rust 化。它可以嵌入为宏或从字符串或文件中解析。目的是提取结构。布局提示目前不在此范围内。
let g1 = rust_dot! {
graph {
A -- B -- C; /* semicolon is optional */
"B" -- D // quotes not needed here
}
};
println!("{} {} \"{}\" {:?} {:?}", g1.strict, g1.directed, g1.name, g1.nodes, g1.edges);
// false false "" ["A", "B", "C", "D"] [(0, 1), (1, 2), (1, 3)]
let g2 = parse_string("digraph Didi { -1 -> 2 -> .3 2 -> 4.2 }");
println!("{} {} \"{}\" {:?} {:?}", g2.strict, g2.directed, g2.name, g2.nodes, g2.edges);
// false true "Didi" ["-1", "2", ".3", "4.2"] [(0, 1), (1, 2), (1, 3)]
返回值可以传递给 petgraph
let mut petgraph = petgraph::graph::Graph::new();
let nodes: Vec<_> = rust_dot_graph.nodes
.iter()
.map(|node| petgraph
.add_node(node))
.collect();
for edge in rust_dot_graph.edges {
petgraph
.add_edge(nodes[edge.0], nodes[edge.1], ());
};
或 graph/
graph_builder
use graph::prelude::*;
let graph: DirectedCsrGraph<usize> = GraphBuilder::new()
.csr_layout(CsrLayout::Sorted)
.edges(rust_dot_graph.edges)
.build();
这是一个正在进行中的工作。没有什么是稳定的!
待办事项
-
实现
strict
,目前被忽略/跳过 -
在错误输入上返回 Err 而不是恐慌
-
在词素上放置 Span,基于它们的输入,可能使用 crate 宏
-
分离返回类型(目前为
Parser
,应该是内部的) -
实现节点属性,目前被忽略/跳过
-
实现节点默认值
-
实现边属性,目前被忽略/跳过
-
实现边默认值
-
处理图属性,有和没有关键词
graph
-
将
rust_dot
重新实现为 proc-macro,在编译时将其输入转换为 const -
作为 DOT 的扩展,允许标签或权重来自 Rust 表达式
-
作为 DOT 的扩展,允许标签或权重来自调用闭包
限制
Rust 宏由 Rust 词汇分析器分析,这与 Graphviz 微妙不同。为了保持一致性(和易于实现),parse_*
函数使用相同的词汇分析器。这些是后果
- 宏必须是 UTF-8,而
parse_*
函数的输入可以是 UTF-16 或 Latin-1。你必须自己处理其他编码。 - 双引号、括号、花括号和方括号必须平衡,并且某些字符是不允许的。作为一个变通方法,你可以首先将以下第一行更改为第二行。注释引号被 Rust 看到但被忽略作为 HTML(一旦实现)
<<I>"</I> <B> )}] [{( </B> \\> <<I>"<!--"--></I> <B><!--"--> )}] [{( <!--"--></B> <!--"-->\\<!--"-->>
- HTML是一种部分考虑空格的语言,而Rust则不是。所以在宏层面,正确处理空格是不可能的,在运行时输入处理也会相当费力。因此,这里采用了一种对所有元素之间空格的启发式处理方法,除了在标签和实体内部以及以下代码(不适用于某些语言):
- 当我们接收到字符串时,字符串尚未进行转义,但Rust词法分析器会对其进行验证。函数
parse_*
通过这种方法绕过了这个问题,但在rust_dot!
中,如果字符串包含非Rust转义序列,则必须使用原始字符串,例如: - 注释与Rust注释完全相同。它们与DOT的不同之处在于,块注释可以嵌套。
- 虽然不是官方注释,但同一行上位于
#
之后的所有内容也会被丢弃。与真实注释不同,这些由RustDOT在词法分析之后处理。这意味着该行的其余部分,例如上面的第一个点,必须是平衡的。它将仅在结束分隔符之后结束,因此您应该将其放在同一行上!在rust_dot!
中,必须使用//
代替!(只有夜间编译器才能在宏中访问行号。) - Rust应该接受有效的标识符。尽管(仅在
rust_dot!
中)混淆字母,如西里尔字母“о”或罕见脚本,如如尼文,会发出警告。 - Rust应该接受有效的数字。并且浮点数不需要在十进制点之前有前导零。
- RustDOT返回一个图,因此它希望输入一个图。语法没有明确说明每个文件可以包含多个图,但它们是可接受的。然而,它们会导致一个文件中无效地连接了2个svg,或者一个只显示第一个的png。同样,它也接受空文档——这不是RustDOT所希望的。
依赖关系
~80KB