#command #generic #preprocessor #macro #exec #define #input

bin+lib gpp

一个针对 Rust 的通用 C 风格预处理器

14 个版本

0.6.2 2021年9月22日
0.6.1 2021年9月22日
0.6.0 2020年8月31日
0.5.0 2019年12月17日
0.1.0 2019年11月1日

Rust 模式 中排名 #2099

Download history 161/week @ 2024-03-11 175/week @ 2024-03-18 78/week @ 2024-03-25 111/week @ 2024-04-01 87/week @ 2024-04-08 180/week @ 2024-04-15 134/week @ 2024-04-22 214/week @ 2024-04-29 120/week @ 2024-05-06 117/week @ 2024-05-13 172/week @ 2024-05-20 125/week @ 2024-05-27 73/week @ 2024-06-03 155/week @ 2024-06-10 114/week @ 2024-06-17 73/week @ 2024-06-24

每月下载 420
用于 2 个 crate(通过 web-rwkv

MIT/Apache

28KB
605

gpp

这是一个简单的针对 Rust 的通用 C 风格预处理器。请参阅文档(cargo doc --open)以获取详细信息。


lib.rs:

gpp 是用 Rust 编写的通用预处理器。

它支持

  • 简单的宏,没有函数宏
  • #include
  • #define 和 #undef
  • #ifdef, #ifndef, #elifdef, #elifndef, #else 和 #endif
  • #exec 用于运行命令
  • #in 和 #endin 用于向命令提供输入

与 C 不同,#includes 不需要(也不与)引号或尖括号,因此 #include file.txt 是正确的语法。它不支持 #if 或 #elif,递归宏将导致库卡住。

关于

任何命令中的哈希值后面可以跟可选的空白字符,例如 是有效的,但 # undef Macro 是无效的。

#define 和 #undef

#define 的工作方式类似于 C:#define [name] [value],和 #undef 也一样:#undef [name]。但是请注意,与 C 不同,宏展开是递归的:如果你 #define A A 然后使用 A,gpp 将无限运行。如果没有提供 #define 的值,它将默认为空字符串。

#include

与 C 不同,包含不需要引号或尖括号,因此这个:#include "file.txt" 或这个:#include <file.txt> 将不会工作;你必须写 #include file.txt

此外,与C不同,当你使用 #include 时目录不会改变;否则,gpp 会改变当前目录并且不会是线程安全的。这意味着如果你使用 #include dir/file.txt,并且在 dir/file.txt 中它说 #include other_file.txt,那么这将引用 other_file.txt,而不是 dir/other_file.txt

如果

#ifdef, #ifndef, #elifdef, #elifndef, #else 和 #endif 命令的工作方式与您预期的一样。我没有在 gpp 中添加通用的 #if 命令,因为它会使它变得更加复杂,并且需要大量的解析,而且大多数时候您需要的只是这些。

#exec, #in 和 #endin

exec 命令使用 cmd /C 在 Windows 上执行给定的命令,对于其他所有系统使用 sh -c,并捕获命令的标准输出。例如,#exec echo Hi! 将输出 Hi!。它不会捕获命令的标准错误,并且如果命令以非零状态退出,解析将停止。

由于启用 #exec 存在安全风险,默认情况下禁用 exec,但是您可以通过更改您的上下文中的 allow_exec 标志来启用它。如果输入尝试在禁用 exec 时执行 #exec,将导致错误。

in 命令与 exec 类似,但是所有直到 endin 命令的文本都传递到程序的标准输入。例如,

#in sed 's/tree/three/g'
One, two, tree.
#endin

将输出 One, two, three.。注意,您不应该这样做,仅使用 #define tree three 会更快并且更少依赖于平台。您也可以在 in 块中放置更多命令,包括其他 in 块。以下是一个有用的示例

<style>
#in sassc -s
# include styles.scss
#endin
</style>

这会将您的 scss 文件编译成 css,使用 Sassc,并在您每次使用 gpp 生成网页时包含在 HTML 中。

字面量井号

为了在行首插入字面量井号符号,只需使用两个井号。 ##some text 将转换为 #some text,而 #some text 将抛出错误,因为 some 不是一个命令。

示例

// Create a context for preprocessing
let mut context = gpp::Context::new();

// Add a macro to that context manually (context.macros is a HashMap)
context.macros.insert("my_macro".to_owned(), "my_value".to_owned());

// Process some text using that
assert_eq!(gpp::process_str("My macro is my_macro\n", &mut context).unwrap(), "My macro is my_value\n");

// Process some multi-line text, changing the context
assert_eq!(gpp::process_str("
#define Line Row
Line One
Line Two
The Third Line", &mut context).unwrap(), "
Row One
Row Two
The Third Row
");

// The context persists
assert_eq!(context.macros.get("Line").unwrap(), "Row");

// Try some more advanced commands
assert_eq!(gpp::process_str("
Line Four
#ifdef Line
#undef Line
#endif
Line Five", &mut context).unwrap(), "
Row Four
Line Five
");

依赖关系

~120KB