parsing - 用 nom 解析多行注释
问题描述
我正在尝试编写一个识别多行注释的名词解析器......
/*
yo!
*/
...并消耗/丢弃(同样的事情,对吗?)结果:
use nom::{
bytes::complete::{tag, take_until},
error::{ErrorKind, ParseError},
sequence::preceded,
IResult,
};
fn multiline_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
preceded(tag("/*"), take_until("*/"))(i)
}
这几乎可以工作。我知道 take_until 在 之前停止*/
,但我不知道该怎么做才能让它包含它。
#[test]
fn should_consume_multiline_comments() {
assert_eq!(
multiline_comment::<(&str, ErrorKind)>("/*abc\n\ndef*/"),
Ok(("", "/*abc\n\ndef*/"))
);
}
给出结果
thread 'should_consume_multiline_comments' panicked at 'assertion failed: `(left == right)`
left: `Ok(("*/", "abc\n\ndef"))`,
right: `Ok(("", "/*abc\n\ndef*/"))`'
所以我的问题是,我如何获得完整的评论,包括结尾*/
谢谢!
解决方案
我假设您并不真的希望返回的字符串在前面/*
和结束时都*/
完好无损 - 因为preceded
总是丢弃第一个解析器的匹配项,所以您永远不会使用preceded
. 我认为您主要关心的是确保*/
实际消耗关闭。
为此,您可以使用delimited
而不是preceded
:
fn multiline_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
delimited(tag("/*"), is_not("*/"), tag("*/"))(i)
}
这通过了这个测试:
assert_eq!(
multiline_comment1::<(&str, ErrorKind)>("/*abc\n\ndef*/"),
Ok(("", "abc\n\ndef"))
);
所以你可以确定关闭*/
已经消耗。
推荐阅读
- c# - EF Core - 当我指定自己的外键时会自动添加不需要的外键
- firebase - 如何将 Firebase 中的集合转换为字符串列表并使用它创建一些条件
- kubectl - kubectl 返回“无法连接到服务器:x509:证书对...有效”
- azure - 如何在 Azure 门户上限制用户
- python - SyntaxError:比较运算符的无效字符
- node.js - CDK Stack 404 重定向笑话测试
- windows - 如何用另一个 bat 文件或程序关闭 cmd 窗口打开的 bat 文件
- powerbi - 将 Azure Blob 容器连接到 Power BI 服务
- java - 请帮助我了解静态对象
- reactjs - 在 Gatsby / React 中将文件作为字符串(或源资产)导入