2个版本

0.1.11 2021年1月2日
0.1.0 2021年1月1日

#991进程宏

GPL-3.0-only

39KB
825

想法

Rust宏,用于生成PEG解析器。

功能

  • 文字
    • strs "Hello"
    • chars 'c'
    • 字符范围 '0'..='9'
    • 任何字符 any
  • Span $e
  • 原子 @e
  • 命名 name: e
  • 前瞻
    • 正向前瞻 &e
    • 负向前瞻 !e
  • 序列 e e
  • 选择 e | e
  • 数字
    • 多个0(零个或多个) e*
    • 多个1(一个或多个) e+
    • 可选(零个或一个) e?

预定义规则

any = // Matches any single character
digit = '0'..='9'
alpha = insensitive['a'..='z']
alnum = alpha | digit
comment = !any
space = (whitespace | comment)*

语法

rule = name '=' alt
alt = cat ('|' cat)* action?
cat = (named | unary)+
named = name ':' unary
unary = prefix | postfix | atom
prefix_op
  = '$' // Span
  | '@' // Atomic
  | '!' // Negative lookahead
  | '&' // Positive lookahead
postfix_op
  = '*' // Many0
  | '+' // Many1
  | '?' // Optional
prefix = prefix_op atom
postfix = postfix_op atom
atom = name | literal | parenthesized
parenthesized = '(' alt ')'

左递归

检测

运行时

尝试规则,从1..开始递归,直到解析失败。现在最新的缓存结果是答案。

编译

  • 解析语法
  • 将所有规则名称替换为索引
  • 检测内置规则的覆盖
  • 标记左递归规则
  • 报告可反驳的绑定

分隔符

对于分隔符,我们可能想要选择

  • 0个或多个出现 []
  • 1个或多个出现 [1]
  • 1个或多个出现,但只有当有尾随逗号时 [1,]
  • x 的返回类型为 Xy 的返回类型为 Y 时,x ^ y 应该有返回类型 (Vec<X>, Vec<Y>)
  • 元组可以按以下方式创建
tuple = '(' item: item ',' items: item ^ ',' ')' {
    let mut items = items.0;
    items.insert(0, item);
    items
}

或者(目前还不行)

tuple = '(' items: item ^ ',' ')' {?
  // At least one comma
  match items.1.len() {
    0 => None
    _ => Some(items.0)
  }
}

待办事项

依赖项

~1.5MB
~35K SLoC