1use rustc_span::BytePos;
4
5use crate::{ParseCtxt, ParseError, ParseResult, lexer::Token, surface::BinOp};
6
7pub(crate) trait Peek: Copy {
11 fn matches(self, tok: Token) -> bool;
13
14 fn display(self) -> impl Iterator<Item = &'static str>;
17}
18
19impl Peek for Token {
20 fn matches(self, tok: Token) -> bool {
21 self == tok
22 }
23
24 fn display(self) -> impl Iterator<Item = &'static str> {
25 [self.descr()].into_iter()
26 }
27}
28
29#[derive(Clone, Copy)]
31pub(crate) struct AnyIdent;
32impl Peek for AnyIdent {
33 fn matches(self, tok: Token) -> bool {
34 matches!(tok, Token::Ident(_))
35 }
36
37 fn display(self) -> impl Iterator<Item = &'static str> {
38 ["identifier"].into_iter()
39 }
40}
41
42#[derive(Clone, Copy)]
44pub(crate) struct AnyLit;
45impl Peek for AnyLit {
46 fn matches(self, tok: Token) -> bool {
47 matches!(tok, Token::Literal(_))
48 }
49
50 fn display(self) -> impl Iterator<Item = &'static str> {
51 ["literal"].into_iter()
52 }
53}
54
55#[derive(Clone, Copy)]
60pub(crate) struct LAngle;
61impl Peek for LAngle {
62 fn matches(self, tok: Token) -> bool {
63 matches!(tok, Token::LtFollowedByLt | Token::Lt)
64 }
65
66 fn display(self) -> impl Iterator<Item = &'static str> {
67 ["<"].into_iter()
68 }
69}
70
71#[derive(Clone, Copy)]
78pub(crate) struct RAngle;
79impl Peek for RAngle {
80 fn matches(self, tok: Token) -> bool {
81 matches!(tok, Token::GtFollowedByGt | Token::Gt)
82 }
83
84 fn display(self) -> impl Iterator<Item = &'static str> {
85 [">"].into_iter()
86 }
87}
88
89impl Peek for &'static str {
91 fn matches(self, tok: Token) -> bool {
92 matches!(tok, Token::Ident(sym) if sym.as_str() == self)
93 }
94
95 fn display(self) -> impl Iterator<Item = &'static str> {
96 [self].into_iter()
97 }
98}
99
100impl<T: Peek, const N: usize> Peek for [T; N] {
102 fn matches(self, tok: Token) -> bool {
103 self.into_iter().any(|t| t.matches(tok))
104 }
105
106 fn display(self) -> impl Iterator<Item = &'static str> {
107 self.into_iter().flat_map(Peek::display)
108 }
109}
110
111pub(crate) struct Lookahead1<'a, 'cx> {
119 expected: Vec<&'static str>,
121 cx: &'a mut ParseCtxt<'cx>,
122}
123
124impl<'a, 'cx> Lookahead1<'a, 'cx> {
125 fn new(cx: &'a mut ParseCtxt<'cx>) -> Self {
126 Lookahead1 { expected: Vec::new(), cx }
127 }
128
129 pub(crate) fn peek<T: Peek>(&mut self, t: T) -> bool {
133 self.expected.extend(t.display());
134 self.cx.peek(t)
135 }
136
137 pub(crate) fn advance_if<T: Peek>(&mut self, t: T) -> bool {
141 self.expected.extend(t.display());
142 self.cx.advance_if(t)
143 }
144
145 pub(crate) fn into_error(self) -> ParseError {
148 self.cx.unexpected_token(self.expected)
149 }
150}
151
152impl<'cx> ParseCtxt<'cx> {
153 pub(crate) fn at(&mut self, n: usize) -> (BytePos, Token, BytePos) {
155 self.tokens.at(n)
156 }
157
158 pub(crate) fn peek<T: Peek>(&mut self, t: T) -> bool {
161 t.matches(self.at(0).1)
162 }
163
164 pub(crate) fn peek2<T1: Peek, T2: Peek>(&mut self, t1: T1, t2: T2) -> bool {
166 t1.matches(self.at(0).1) && t2.matches(self.at(1).1)
167 }
168
169 pub(crate) fn peek3<T1: Peek, T2: Peek, T3: Peek>(&mut self, t1: T1, t2: T2, t3: T3) -> bool {
171 t1.matches(self.at(0).1) && t2.matches(self.at(1).1) && t3.matches(self.at(2).1)
172 }
173
174 pub(crate) fn peek_binop(&mut self) -> Option<(BinOp, usize)> {
178 let op = match self.at(0).1 {
179 Token::Iff => (BinOp::Iff, 1),
180 Token::FatArrow => (BinOp::Imp, 1),
181 Token::OrOr => (BinOp::Or, 1),
182 Token::AndAnd => (BinOp::And, 1),
183 Token::EqEq => (BinOp::Eq, 1),
184 Token::Ne => (BinOp::Ne, 1),
185 Token::Lt => (BinOp::Lt, 1),
186 Token::Gt => (BinOp::Gt, 1),
187 Token::Le => (BinOp::Le, 1),
188 Token::Ge => (BinOp::Ge, 1),
189 Token::Caret => (BinOp::BitOr, 1),
190 Token::And => (BinOp::BitAnd, 1),
191 Token::LtFollowedByLt => (BinOp::BitShl, 2),
192 Token::GtFollowedByGt => (BinOp::BitShr, 2),
193 Token::Plus => (BinOp::Add, 1),
194 Token::Minus => (BinOp::Sub, 1),
195 Token::Star => (BinOp::Mul, 1),
196 Token::Slash => (BinOp::Div, 1),
197 Token::Percent => (BinOp::Mod, 1),
198 _ => return None,
199 };
200 Some(op)
201 }
202
203 pub(crate) fn advance(&mut self) {
205 self.tokens.advance();
206 }
207
208 pub(crate) fn advance_by(&mut self, n: usize) {
210 self.tokens.advance_by(n);
211 }
212
213 pub(crate) fn advance_if<T: Peek>(&mut self, t: T) -> bool {
216 if self.peek(t) {
217 self.advance();
218 true
219 } else {
220 false
221 }
222 }
223
224 pub(crate) fn advance_if2<T1: Peek, T2: Peek>(&mut self, t1: T1, t2: T2) -> bool {
226 if self.peek2(t1, t2) {
227 self.advance_by(2);
228 true
229 } else {
230 false
231 }
232 }
233
234 pub(crate) fn expect<T: Peek>(&mut self, t: T) -> ParseResult {
237 if self.advance_if(t) { Ok(()) } else { Err(self.unexpected_token(t.display().collect())) }
238 }
239
240 pub(crate) fn lookahead1(&mut self) -> Lookahead1<'_, 'cx> {
242 Lookahead1::new(self)
243 }
244}