#可读性 #语言设计 # #语言 #元数据 #活塞 #解码

piston_meta

用于人类可读文本文档的领域特定语言(DSL)解析库

75个版本 (4个稳定版)

使用旧Rust 2015

2.0.1 2021年4月12日
1.0.1 2021年2月25日
1.0.0 2019年5月15日
0.30.0 2018年12月5日
0.10.6 2015年7月19日

#985解析器实现

Download history 132/week @ 2024-04-01 35/week @ 2024-04-08 48/week @ 2024-04-15 43/week @ 2024-04-22 51/week @ 2024-04-29 57/week @ 2024-05-06 50/week @ 2024-05-13 50/week @ 2024-05-20 48/week @ 2024-05-27 36/week @ 2024-06-03 38/week @ 2024-06-10 36/week @ 2024-06-17 40/week @ 2024-06-24 34/week @ 2024-07-08 86/week @ 2024-07-15

每月162次下载
用于 15crates (14直接)

MIT 许可证

205KB
5K SLoC

Piston-Meta

用于人类可读文本文档的领域特定语言(DSL)解析库

简介

Piston-Meta使编写人类可读文本文档的解析器变得容易。它可以用于语言设计、自定义格式和数据驱动开发。

元解析是一种可以追溯到第一台现代计算机的开发技术。其思想是将计算机程序的部分转换为可编程的管道,从而加速开发。在项目之间,一个重要且令人惊讶的可重用部分是从文本生成结构化数据的概念,因为文本易于修改和推理。

大多数处理文本的程序使用以下管道

f : text -> data

这种方法的缺点是 f 从项目到项目都会变化,将文本转换为数据结构的任务可能会变得非常复杂。例如,要创建编程语言语法的解析器,可能需要数千行代码。这会减慢开发速度并增加出错的机会。

元解析是一种将 f 分为两步的技术

f <=> f2 . f1
f1 : text -> meta data
f2 : meta data -> data

第一步 f1 将文本转换为元数据。使用领域特定语言(DSL)来描述这种转换是如何发生的。第二步 f2 将元数据转换为数据,这通常写成代码。

规则

元语言用于描述如何读取其他文档。首先定义一些可重复使用的字符串,然后是一些节点规则。最后一个节点用于读取整个文档。

20document= [.l(string:"string") .l(node:"node") .w?]

字符串以下划线开头,可以在规则之间重复使用

_opt: "可选"

节点以数字开头,该数字乘以1000后用作调试ID。如果您收到错误 #4003,则它是由以4开头的节点中的规则引起的。

规则 描述
.l(rule) 使用行分隔子规则。
.l+(rule) 使用行和缩进(空白敏感)分隔子规则。
.r?(rule) 重复子规则直到失败,允许零次重复。
.r!(规则) 重复子规则直到失败,至少需要一次重复。
...任意字符?:名称 读取字符串直到任意字符,允许零个字符。名称是可选的。
...任意字符!:名称 读取字符串直到任意字符,至少需要一个字符。名称是可选的。
..任意字符?:名称 读取字符串直到任意字符或空白字符,允许零个字符。名称是可选的。
..任意字符!:名称 读取字符串直到任意字符或空白字符,至少需要一个字符。名称是可选的。
.w? 读取空白字符。空白字符是可选的。
.w! 读取空白字符。空白字符是必需的。
?规则 使规则可选。
"标记":名称 期望一个标记,将名称设置为 true。名称是可选的。
"标记":!名称 期望一个标记,将名称设置为 false。名称是必需的。
!"标记":名称 如果读取标记则失败,如果未读取则将名称设置为 true。名称是可选的。
!"标记":!名称 如果读取标记则失败,如果未读取则将名称设置为 false。名称是必需的。
!规则 如果读取规则则失败。
.s?(通过规则规则) 通过另一个规则分隔规则,允许零次重复。
.s!(通过规则规则) 通过另一个规则分隔规则,至少需要一次重复。
.s?.(通过规则规则) 通过另一个规则分隔规则,允许尾部。
{规则} 选择一个规则。尝试第一个规则,然后第二个,等等。规则由空白字符分隔。
[规则] 一系列规则。规则由空白字符分隔。
node 使用没有名称的节点。读取的数据放在当前节点中。
节点:名称 使用具有名称的节点。读取的数据放在具有该名称的新节点中。
.t?:名称 读取具有名称的 JSON 字符串。字符串可以为空。名称是可选的。
.t!:名称 读取具有名称的 JSON 字符串。字符串不能为空。名称是可选的。
.$:名称 读取具有名称的数字。名称是可选的。
.$_:名称 读取具有下划线作为可见分隔符的数字,例如 10_000。名称是可选的。

"Hello world" 在 Piston-Meta 中

extern crate piston_meta;

use piston_meta::*;

fn main() {
    let text = r#"hi James!"#;
    let rules = r#"
        1 say_hi = ["hi" .w? {"James":"james" "Peter":"peter"} "!"]
        2 document = say_hi
    "#;
    // Parse rules with meta language and convert to rules for parsing text.
    let rules = match syntax_errstr(rules) {
        Err(err) => {
            println!("{}", err);
            return;
        }
        Ok(rules) => rules
    };
    let mut data = vec![];
    match parse_errstr(&rules, text, &mut data) {
        Err(err) => {
            println!("{}", err);
            return;
        }
        Ok(()) => {}
    };
    json::print(&data);
}

引导

当元语言发生变化时,使用引导将旧元语法提升到新元语法。以下是工作原理

  1. Piston-Meta 包含可组合的规则,可以解析许多可读文本格式。
  2. Piston-Meta 知道如何解析和转换为自身的规则,称为 "引导"。
  3. 因此,您可以使用元语言告诉 Piston-Meta 如何解析其他文本格式!
  4. 包括描述如何解析自身语法的文本格式,它生成与 Rust 中硬编码的规则等效的规则。
  5. 元语言的新版本可以通过略微更改自语法来描述旧版本,以保持向后兼容性,因此它可以读取旧版本的自身。

依赖项

~45KB