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
每月下载 420 次
用于 2 个 crate(通过 web-rwkv)
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