1

我正在使用 proc-macros 和 syn 开发一种特定于域的小语言,我想在那里解析表单上的一系列运算符

 lhs + rsh => res
 lhs - rsh => res

或者

 lhs += rsh
 lhs -= rsh

等等。

我正在使用syn板条箱执行此操作,以实现Parser我需要的各种结构。我的想法是,我可以在前三个标记之后使用前瞻来解析这些,如下所示:

let lookahead = input.lookahead1();
            
let lhs = input.parse()?;
let op = input.parse()?;
let rhs = input.parse()?;

// now, conditionally parse the res part of an operator
let res = if lookahead.peek(syn::token::FatArrow) {
    input.parse::<syn::token::FatArrow>()?;
    Some(input.parse()?)
} else { None };

问题是,虽然syn::token::FatArrow是调用时的令牌,但=>调用parse时似乎不是peek

// This says false
println!("do we see =>? {}", lookahead.peek(syn::token::FatArrow));
// this also says false
println!("do we see =>? {}", lookahead.peek(Token![=>]));

解析工作正常,但如果我不能向前看,那么我无法区分这两种情况。(好吧,我可以通过分叉输入流并尝试两种规则,然后用有效的流替换流,但是当下一个令牌的峰值出现时,如果我知道如何解决问题,这似乎有点戏剧性)。

我在这里做错了什么?我是否需要peek使用其他参数调用以匹配令牌=>

4

1 回答 1

2

创建的时间有一个重要意义Lookahead1:它指向光标在调用lookahead1()的位置。Lookahead1意味着当你有一个可能的值列表时使用,并且你想在值无效时提供一个很好的错误消息,列出所有可能的值。如果您只想查看下一个令牌,请使用ParseBuffer::peek()

let res = if input.peek(syn::token::FatArrow) {
    input.parse::<syn::token::FatArrow>()?;
    Some(input.parse()?)
} else { None };
于 2022-02-13T13:56:04.597 回答