#语法树 #语言 #解析器 #辅助 #编译 #API

spdl

编译和使用 SPDL(一种用于将代码解析为语法树的辅助语言)的 API

1 个不稳定版本

0.0.1 2020年9月25日

#23 in #辅助

MIT 许可证

42KB
787

此包包含用于编译和使用 SPDL 编程语言的 API。SPDL(发音为 spiddle)代表结构化解析描述语言,用于使编译器中的解析更加容易。此包包含一个将 SPDL 编译成解析器的函数,该解析器可用于将代码转换为语法树。

在编译器术语中,一个语法实例是指在某个特定点描述的语法结构。此生成的 SPDL 解析器包含整个文件的根语法实例,以及一组变量语法实例。每个语法实例都有一个在输入代码中的特定点进行解析的函数。

SPDLParser 结构围绕一个在代码开始处进行解析的根语法实例,并预期覆盖整个文件。它还包装了根语法实例中的所有变量的数组。SPDLParser 结构包含一个 get_syntax_tree 函数,该函数根据根语法实例的描述获取输入代码的语法树,并返回一个结果,该结果可能包含错误或输出语法树。

每个语法实例都有一定的语法实例类型,并在输入代码的某个点给出解析结果。目前 SPDL 中有许多类型的语法实例可供使用。

  1. 集合(&[语法实例])

"集合" 语法实例类型包含一组按顺序解析的语法实例。

  1. 零或更多(&语法实例)

"零或更多" 语法实例类型要求解析器尽可能多地解析语法实例,然后放弃。

  1. 一或更多(&语法实例)

类似于“零或更多”,只不过它要求至少成功解析一次才能成功。

  1. 或者(&[语法实例])

这允许集合中的任何一个语法实例在某个点成功解析。如果集合中没有任何一个成功,则失败。

  1. (&语法实例)

"非" 语法实例类型禁止在某个点成功解析特定的语法实例。

  1. 正则(&str)

"正则" 语法实例类型在当前点以该语法实例类型描述的字符串开头时解析成功。

  1. 搜索(&str)

"搜索" 语法实例类型在运行时搜索具有特定名称的语法实例。此中的任何无效变量名将在编译时检测到。当两个或更多变量相互依赖时,需要此功能,因此可用于递归。

  1. 正则表达式(正则表达式)

"正则表达式" 语法实例类型在输入的当前点与该正则表达式匹配时解析成功。

  1. 疑问(&str, &语法实例)

这捕获了解析语法实例的结果(如第二字段所示),并使用另一个语法实例(该名称在第一字段中)对其进行解析。

以下是一个示例,说明如何使用此crate,在某些计算机上解析30万个打印语句只需不到一秒钟。

fn main() {
let code = r#"
print "Hello, world!";
"#.repeat(300_000);

let spdl_code = r##"
freeform true
string = /"[^"]*"/
printStmt = print #string#;
seterror printStmt Invalid print statement!
parse printStmt
"##;
let parser = spdl::process_spdl(spdl_code);
if parser.is_err() {
let errors = parser.unwrap_err();
for err in errors {
println!("{}", err);
}
panic!("Failed test!");
}
let parser = parser.unwrap();

let time = std::time::Instant::now();
parser.get_syntax_tree(Box::leak(Box::new(code.into_boxed_str())), false).unwrap();
println!("{:?}", time.elapsed());
}

有效的SPDL代码的实际语法包括注释、变量声明、自由配置、自定义错误处理配置以及单个解析配置。SPDL不是一种自由格式语言,除了行中断。SPDL代码中的每一行在处理之前都会在两端进行修剪。SPDL中的每一条注释都是修剪后以井号开始的行。SPDL中的每一行必须正好开始和完成以下描述之一,或者修剪后完全为空。

修剪后以井号开始的每一行都是注释,会被忽略。修剪后的每一行空行也会被忽略。

每个变量声明都有这种严格的语法

varName=sequence

声明中的序列可以是空的,也可以是以下语法描述之一

*sequenceGoesHere*(这描述了零个或多个语句,用于具有ZeroOrMore类型的语法实例)

+sequenceGoesHere+(这描述了一个或多个语句,用于具有OneOrMore类型的语法实例)

|sequenceGoesHere$maybeAnotherHere|(这描述了具有Either类型的语法实例的“或者”语句)

/regexGoesHere/(这描述了具有Regex类型的语法实例的正则表达式语句)

^sequenceGoesHere^(这描述了具有Not类型的语法实例的“非”语句)

&variableName&(这描述了具有Search类型的语法实例的搜索语句)

?parseAs:sequenceGoesHere?(这描述了具有Questioned类型的语法实例的解析语句)

#variableName#(这包括在变量声明中包含之前声明的变量的语法)

\punctuationGoesHere(这描述了转义。没有转义是无效的,但如果反斜杠后面不是标点符号或反斜杠,则它被解释为普通反斜杠后面跟着普通字符)

regularSyntacticalInstance(这描述了具有Regular类型的语法实例,由一个或多个转义字符或非标点字符的连续集合组成)

如上所述的标点可以是以下字符中的任何一种,用逗号分隔:*, +, |, /, ^, &, #, ? 标点用于指定在变量声明中语法实例序列中不同类型的语法实例的开始。转义提供了去除其含义的方法。

SPDL中的每个自定义错误处理配置,在解析变量失败时设置自定义错误抛出,具有以下语法

seterror varName message

描述SPDL解析器的SPDL代码的解析配置告诉应该解析哪个变量,直到解析器输入的末尾。这种语法的语法如下

parse varName

SPDL中的每个自由配置由“freeform”关键字组成,后面跟一个空格,然后是true或false。这是为了配置在某一行之后是否启用自由格式。默认情况下,自由格式是禁用的,但它具有围绕变量声明中每个常规语法实例的正则表达式捕获可选空格的效果。

依赖关系

~2–3MB
~53K SLoC