You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart/Flutter用petitparser解析字符串遇大写字母预期错误求助

问题:Petitparser解析含字母的中间段失败及修改验证

问题场景

原本的Flutter/Dart代码使用Petitparser解析包含数字中间段的表达式完全正常,但将中间的数字替换为单词(如把5改成test)后,解析器抛出错误:uppercase letter expected at 1:1。尝试将digit().plus()改为word().plus()后解析恢复正常,需确认该修改是否正确。

原始可运行代码

testString = '((S|71|L || S|70|L || S|69|L || S|72|L) && (F|54|L || F|52|L || H|5|L))';
final builder = ExpressionBuilder();
final primitive = (uppercase() & char('|') & digit().plus() & char('|') & uppercase()).flatten().trim();
builder.group().primitive(primitive);
builder.group()
    .wrapper(char('(').trim(), char(')').trim(), (l, v, r) => v);
builder.group()
  ..left(string('&&').trim(), (a, op, b) => ['&&', a, b])
  ..left(string('||').trim(), (a, op, b) => ['||', a, b]);
final parser = builder.build().end();
final result = parser.parse(testString);

修改后的测试字符串

testString = '((S|71|L || S|70|L || S|69|L || S|72|L) && (F|54|L || F|52|L || H|test|L))';

解答

把digit().plus()改为word().plus()是正确的修改方式,原因如下:

  • 原始的digit().plus()仅能匹配连续数字,当中间段变为字母组成的test时,这部分解析直接失败,导致整个primitive规则匹配失败。Petitparser的错误提示有时会指向表达式起始位置,因此出现了看似偏离实际问题位置的1:1错误。
  • word()在Petitparser中匹配字母、数字和下划线(等价于letter() | digit() | char('_')),刚好覆盖你需要的「数字」和「单词」两种中间段场景。
  • 若需要更精确的匹配(比如仅允许字母数字、排除下划线),可以自定义规则:(letter() | digit()).plus(),更贴合表达式的结构需求。

另外,你之前尝试any().plus()仍报错,是因为any()会匹配任意字符(包括后续的|),导致primitive规则中后续的char('|') & uppercase()无法匹配,最终触发错误。而word().plus()会在遇到非单词字符(如|)时停止匹配,完全符合表达式中|分隔的结构逻辑。

内容的提问来源于stack exchange,提问作者Coltuxumab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:00:42