• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TyRoXx / NonlocalityOS / 15517294876

08 Jun 2025 10:01AM UTC coverage: 74.495% (+0.3%) from 74.179%
15517294876

push

github

TyRoXx
GH-280: clippy

2 of 2 new or added lines in 1 file covered. (100.0%)

26 existing lines in 5 files now uncovered.

3765 of 5054 relevant lines covered (74.5%)

2083.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.0
/lambda_compiler/src/parsing.rs
1
use crate::{
2
    ast::{self, LambdaParameter},
3
    compilation::{CompilerError, SourceLocation},
4
    tokenization::{Token, TokenContent},
5
};
6
use lambda::name::{Name, NamespaceId};
7

8
#[derive(Debug)]
9
pub struct ParserError {
10
    pub message: String,
11
    pub location: SourceLocation,
12
}
13

14
impl ParserError {
15
    pub fn new(message: String, location: SourceLocation) -> Self {
5✔
16
        Self { message, location }
17
    }
18
}
19

20
impl std::fmt::Display for ParserError {
21
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5✔
22
        write!(f, "{}", &self.message)
5✔
23
    }
24
}
25

26
pub type ParserResult<T> = std::result::Result<T, ParserError>;
27

28
pub fn pop_next_non_whitespace_token<'t>(
433✔
29
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
30
) -> Option<&'t Token> {
31
    let token = peek_next_non_whitespace_token(tokens);
433✔
32
    if token.is_some() {
866✔
33
        tokens.next();
433✔
34
    }
35

36
    token
433✔
37
}
38

39
pub fn peek_next_non_whitespace_token<'t>(
1,207✔
40
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
41
) -> Option<&'t Token> {
42
    loop {
×
43
        let next = tokens.peek();
1,472✔
44
        match next {
1,472✔
45
            Some(token) => match token.content {
1,472✔
46
                TokenContent::Whitespace | TokenContent::Comment(_) => {
×
47
                    tokens.next();
265✔
48
                    continue;
265✔
49
                }
50

51
                TokenContent::Identifier(_)
×
52
                | TokenContent::Assign
×
53
                | TokenContent::LeftParenthesis
×
54
                | TokenContent::RightParenthesis
×
55
                | TokenContent::LeftBracket
×
56
                | TokenContent::RightBracket
×
57
                | TokenContent::LeftBrace
×
58
                | TokenContent::RightBrace
×
59
                | TokenContent::Dot
×
60
                | TokenContent::Colon
×
61
                | TokenContent::Quotes(_)
×
62
                | TokenContent::FatArrow
×
63
                | TokenContent::Comma
×
64
                | TokenContent::EndOfFile => return Some(token),
1,207✔
65
            },
66
            None => return None,
×
67
        }
68
    }
69
}
70

71
fn expect_right_brace(
11✔
72
    tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>,
73
) -> ParserResult<()> {
74
    match peek_next_non_whitespace_token(tokens) {
11✔
75
        Some(non_whitespace) => match &non_whitespace.content {
11✔
76
            TokenContent::Comment(_) => unreachable!(),
77
            TokenContent::Whitespace => unreachable!(),
78
            TokenContent::Identifier(_) => todo!(),
79
            TokenContent::Assign => todo!(),
80
            TokenContent::LeftParenthesis => todo!(),
81
            TokenContent::RightParenthesis => todo!(),
82
            TokenContent::LeftBracket => todo!(),
83
            TokenContent::RightBracket => todo!(),
84
            TokenContent::LeftBrace => todo!(),
85
            TokenContent::RightBrace => {
86
                pop_next_non_whitespace_token(tokens);
11✔
87
                Ok(())
11✔
88
            }
89
            TokenContent::Dot => todo!(),
90
            TokenContent::Colon => todo!(),
91
            TokenContent::Quotes(_) => todo!(),
92
            TokenContent::FatArrow => todo!(),
93
            TokenContent::Comma => todo!(),
94
            TokenContent::EndOfFile => todo!(),
95
        },
96
        None => todo!(),
97
    }
98
}
99

100
fn try_skip_right_parenthesis(
69✔
101
    tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>,
102
) -> bool {
103
    match peek_next_non_whitespace_token(tokens) {
69✔
104
        Some(non_whitespace) => match &non_whitespace.content {
69✔
105
            TokenContent::Comment(_) => unreachable!(),
106
            TokenContent::Whitespace => unreachable!(),
107
            TokenContent::Identifier(_) => false,
8✔
108
            TokenContent::Assign => todo!(),
109
            TokenContent::LeftParenthesis => todo!(),
110
            TokenContent::RightParenthesis => {
111
                pop_next_non_whitespace_token(tokens);
48✔
112
                true
48✔
113
            }
114
            TokenContent::LeftBracket => false,
×
115
            TokenContent::RightBracket => todo!(),
116
            TokenContent::LeftBrace => false,
×
117
            TokenContent::RightBrace => todo!(),
118
            TokenContent::Dot => todo!(),
119
            TokenContent::Colon => todo!(),
120
            TokenContent::Quotes(_) => false,
8✔
121
            TokenContent::FatArrow => todo!(),
122
            TokenContent::Comma => false,
5✔
123
            TokenContent::EndOfFile => todo!(),
124
        },
125
        None => todo!(),
126
    }
127
}
128

129
fn try_skip_assign(tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>) -> bool {
8✔
130
    match peek_next_non_whitespace_token(tokens) {
8✔
131
        Some(non_whitespace) => match &non_whitespace.content {
8✔
132
            TokenContent::Comment(_) => unreachable!(),
133
            TokenContent::Whitespace => unreachable!(),
134
            TokenContent::Identifier(_) => false,
×
135
            TokenContent::Assign => {
136
                pop_next_non_whitespace_token(tokens);
8✔
137
                true
8✔
138
            }
139
            TokenContent::LeftParenthesis => todo!(),
140
            TokenContent::RightParenthesis => todo!(),
141
            TokenContent::LeftBracket => todo!(),
142
            TokenContent::RightBracket => todo!(),
143
            TokenContent::LeftBrace => false,
×
144
            TokenContent::RightBrace => todo!(),
145
            TokenContent::Dot => todo!(),
146
            TokenContent::Colon => todo!(),
147
            TokenContent::Quotes(_) => false,
×
148
            TokenContent::FatArrow => todo!(),
149
            TokenContent::Comma => false,
×
150
            TokenContent::EndOfFile => todo!(),
151
        },
152
        None => todo!(),
153
    }
154
}
155

156
fn expect_fat_arrow(tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>) {
40✔
157
    match pop_next_non_whitespace_token(tokens) {
40✔
158
        Some(non_whitespace) => match &non_whitespace.content {
40✔
159
            TokenContent::Comment(_) => unreachable!(),
160
            TokenContent::Whitespace => unreachable!(),
161
            TokenContent::Identifier(_identifier) => todo!(),
162
            TokenContent::Assign => todo!(),
163
            TokenContent::LeftParenthesis => todo!(),
164
            TokenContent::RightParenthesis => todo!(),
165
            TokenContent::LeftBracket => todo!(),
166
            TokenContent::RightBracket => todo!(),
167
            TokenContent::LeftBrace => todo!(),
168
            TokenContent::RightBrace => todo!(),
169
            TokenContent::Dot => todo!(),
170
            TokenContent::Colon => todo!(),
171
            TokenContent::Quotes(_) => todo!(),
172
            TokenContent::FatArrow => {}
40✔
173
            TokenContent::Comma => todo!(),
174
            TokenContent::EndOfFile => todo!(),
175
        },
176
        None => todo!(),
177
    }
178
}
179

180
fn expect_comma(tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>) {
35✔
181
    match pop_next_non_whitespace_token(tokens) {
35✔
182
        Some(non_whitespace) => match &non_whitespace.content {
35✔
183
            TokenContent::Comment(_) => unreachable!(),
184
            TokenContent::Whitespace => unreachable!(),
185
            TokenContent::Identifier(_) => todo!(),
186
            TokenContent::Assign => todo!(),
187
            TokenContent::LeftParenthesis => todo!(),
188
            TokenContent::RightParenthesis => todo!(),
189
            TokenContent::LeftBracket => todo!(),
190
            TokenContent::RightBracket => todo!(),
191
            TokenContent::LeftBrace => todo!(),
192
            TokenContent::RightBrace => todo!(),
193
            TokenContent::Dot => todo!(),
194
            TokenContent::Colon => todo!(),
195
            TokenContent::Quotes(_) => todo!(),
196
            TokenContent::FatArrow => todo!(),
197
            TokenContent::Comma => {}
35✔
198
            TokenContent::EndOfFile => todo!(),
199
        },
200
        None => todo!(),
201
    }
202
}
203

204
fn skip_right_bracket(tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>) -> bool {
142✔
205
    let maybe_right_bracket = peek_next_non_whitespace_token(tokens);
142✔
206
    match maybe_right_bracket {
142✔
207
        Some(token) => match &token.content {
142✔
208
            TokenContent::Comment(_) => unreachable!(),
209
            TokenContent::Whitespace => unreachable!(),
210
            TokenContent::Identifier(_) => false,
64✔
211
            TokenContent::Assign => false,
×
212
            TokenContent::LeftParenthesis => false,
×
213
            TokenContent::RightParenthesis => false,
×
214
            TokenContent::LeftBracket => false,
2✔
215
            TokenContent::RightBracket => {
216
                tokens.next();
35✔
217
                true
35✔
218
            }
219
            TokenContent::LeftBrace => todo!(),
220
            TokenContent::RightBrace => todo!(),
221
            TokenContent::Dot => false,
×
222
            TokenContent::Colon => todo!(),
223
            TokenContent::Quotes(_) => false,
9✔
224
            TokenContent::FatArrow => false,
×
225
            TokenContent::Comma => false,
32✔
226
            TokenContent::EndOfFile => todo!(),
227
        },
228
        None => false,
×
229
    }
230
}
231

232
fn parse_tree_construction(
35✔
233
    tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>,
234
    local_namespace: &NamespaceId,
235
) -> ParserResult<ast::Expression> {
236
    let mut elements = Vec::new();
35✔
237
    loop {
238
        if skip_right_bracket(tokens) {
83✔
239
            break;
24✔
240
        }
241
        if !elements.is_empty() {
91✔
242
            expect_comma(tokens);
32✔
243
        }
244
        if skip_right_bracket(tokens) {
245
            break;
11✔
246
        }
247
        let element = parse_expression(tokens, local_namespace)?;
48✔
248
        elements.push(element);
249
    }
250
    Ok(ast::Expression::ConstructTree(elements))
35✔
251
}
252

253
fn parse_braces(
11✔
254
    tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>,
255
    local_namespace: &NamespaceId,
256
) -> ParserResult<ast::Expression> {
257
    let content = parse_expression(tokens, local_namespace)?;
22✔
258
    expect_right_brace(tokens)?;
×
259
    Ok(ast::Expression::Braces(Box::new(content)))
11✔
260
}
261

262
fn parse_let(
8✔
263
    tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>,
264
    local_namespace: &NamespaceId,
265
    let_location: &SourceLocation,
266
) -> ParserResult<ast::Expression> {
267
    let (name, location) = match try_pop_identifier(tokens) {
16✔
268
        Some((name, location)) => (name, location),
8✔
269
        None => {
270
            return Err(ParserError::new(
×
271
                "Expected identifier after 'let' keyword.".to_string(),
×
272
                *let_location,
×
273
            ))
274
        }
275
    };
276
    if !try_skip_assign(tokens) {
8✔
277
        return Err(ParserError::new(
×
278
            "Expected '=' after 'let' identifier.".to_string(),
×
279
            *let_location,
×
280
        ));
281
    }
282
    let value = parse_expression(tokens, local_namespace)?;
16✔
283
    let body = parse_expression(tokens, local_namespace)?;
8✔
284
    Ok(ast::Expression::Let {
285
        name: Name::new(*local_namespace, name),
286
        location,
287
        value: Box::new(value),
288
        body: Box::new(body),
289
    })
290
}
291

292
fn parse_expression_start<'t>(
207✔
293
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
294
    local_namespace: &NamespaceId,
295
) -> ParserResult<ast::Expression> {
296
    match peek_next_non_whitespace_token(tokens) {
207✔
297
        Some(non_whitespace) => match &non_whitespace.content {
207✔
298
            TokenContent::Comment(_) => unreachable!(),
299
            TokenContent::Whitespace => unreachable!(),
300
            TokenContent::Identifier(identifier) => {
102✔
301
                pop_next_non_whitespace_token(tokens);
102✔
302
                if identifier.as_str() == "let" {
102✔
303
                    parse_let(tokens, local_namespace, &non_whitespace.location)
8✔
304
                } else {
305
                    Ok(ast::Expression::Identifier(
94✔
306
                        Name::new(*local_namespace, identifier.clone()),
94✔
307
                        non_whitespace.location,
94✔
308
                    ))
309
                }
310
            }
311
            TokenContent::Assign => todo!(),
312
            TokenContent::LeftParenthesis => {
×
313
                pop_next_non_whitespace_token(tokens);
42✔
314
                parse_lambda(tokens, local_namespace)
42✔
315
            }
316
            TokenContent::RightParenthesis => Err(ParserError::new(
1✔
317
                "Expected expression, found right parenthesis.".to_string(),
1✔
318
                non_whitespace.location,
1✔
319
            )),
320
            TokenContent::LeftBracket => {
×
321
                pop_next_non_whitespace_token(tokens);
35✔
322
                parse_tree_construction(tokens, local_namespace)
35✔
323
            }
324
            TokenContent::RightBracket => Err(ParserError::new(
×
325
                "Expected expression, found right bracket.".to_string(),
×
326
                non_whitespace.location,
×
327
            )),
328
            TokenContent::LeftBrace => {
×
329
                pop_next_non_whitespace_token(tokens);
11✔
330
                parse_braces(tokens, local_namespace)
11✔
331
            }
332
            TokenContent::RightBrace => todo!(),
333
            TokenContent::Dot => todo!(),
334
            TokenContent::Colon => todo!(),
335
            TokenContent::Quotes(content) => {
13✔
336
                pop_next_non_whitespace_token(tokens);
13✔
337
                Ok(ast::Expression::StringLiteral(
13✔
338
                    content.clone(),
13✔
339
                    non_whitespace.location,
13✔
340
                ))
341
            }
342
            TokenContent::FatArrow => Err(ParserError::new(
1✔
343
                "Expected expression, found fat arrow.".to_string(),
1✔
344
                non_whitespace.location,
1✔
345
            )),
346
            TokenContent::Comma => Err(ParserError::new(
1✔
347
                "Expected expression, found comma.".to_string(),
1✔
348
                non_whitespace.location,
1✔
349
            )),
350
            TokenContent::EndOfFile => Err(ParserError::new(
1✔
351
                "Expected expression, got end of file.".to_string(),
1✔
352
                non_whitespace.location,
1✔
353
            )),
354
        },
355
        None => todo!(),
356
    }
357
}
358

359
fn parse_apply(
9✔
360
    callee: ast::Expression,
361
    tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>,
362
    local_namespace: &NamespaceId,
363
) -> ParserResult<ast::Expression> {
364
    let mut arguments = Vec::new();
9✔
365
    loop {
366
        if try_skip_right_parenthesis(tokens) {
18✔
367
            break;
8✔
368
        }
369
        if !arguments.is_empty() {
13✔
370
            expect_comma(tokens);
3✔
371
        }
372
        if try_skip_right_parenthesis(tokens) {
UNCOV
373
            break;
×
374
        }
375
        let argument = parse_expression(tokens, local_namespace)?;
10✔
376
        arguments.push(argument);
377
    }
378
    Ok(ast::Expression::Apply {
8✔
379
        callee: Box::new(callee),
8✔
380
        arguments,
8✔
381
    })
382
}
383

384
pub fn parse_expression<'t>(
207✔
385
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
386
    local_namespace: &NamespaceId,
387
) -> ParserResult<ast::Expression> {
388
    let start = parse_expression_start(tokens, local_namespace)?;
414✔
UNCOV
389
    match peek_next_non_whitespace_token(tokens) {
×
390
        Some(more) => match &more.content {
199✔
391
            TokenContent::Comment(_) => unreachable!(),
392
            TokenContent::Whitespace => unreachable!(),
393
            TokenContent::Identifier(_) => Ok(start),
7✔
UNCOV
394
            TokenContent::Assign => Ok(start),
×
UNCOV
395
            TokenContent::LeftParenthesis => {
×
396
                tokens.next();
9✔
397
                parse_apply(start, tokens, local_namespace)
9✔
398
            }
399
            TokenContent::RightParenthesis => Ok(start),
13✔
400
            TokenContent::LeftBracket => Ok(start),
1✔
401
            TokenContent::RightBracket => Ok(start),
16✔
402
            TokenContent::LeftBrace => todo!(),
403
            TokenContent::RightBrace => Ok(start),
19✔
404
            TokenContent::Dot => todo!(),
405
            TokenContent::Colon => todo!(),
406
            TokenContent::Quotes(_) => todo!(),
407
            TokenContent::FatArrow => todo!(),
408
            TokenContent::Comma => Ok(start),
40✔
409
            TokenContent::EndOfFile => Ok(start),
94✔
410
        },
411
        None => todo!(),
412
    }
413
}
414

415
fn try_pop_identifier(
64✔
416
    tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>,
417
) -> Option<(String, SourceLocation)> {
418
    match peek_next_non_whitespace_token(tokens) {
64✔
419
        Some(non_whitespace) => match &non_whitespace.content {
64✔
420
            TokenContent::Comment(_) => unreachable!(),
421
            TokenContent::Whitespace => unreachable!(),
422
            TokenContent::Identifier(identifier) => {
45✔
423
                pop_next_non_whitespace_token(tokens);
45✔
424
                Some((identifier.clone(), non_whitespace.location))
45✔
425
            }
426
            TokenContent::Assign => todo!(),
427
            TokenContent::LeftParenthesis => todo!(),
428
            TokenContent::RightParenthesis => None,
19✔
429
            TokenContent::LeftBracket => todo!(),
430
            TokenContent::RightBracket => todo!(),
431
            TokenContent::LeftBrace => todo!(),
432
            TokenContent::RightBrace => todo!(),
433
            TokenContent::Dot => todo!(),
434
            TokenContent::Colon => todo!(),
435
            TokenContent::Quotes(_) => todo!(),
436
            TokenContent::FatArrow => todo!(),
437
            TokenContent::Comma => None,
×
UNCOV
438
            TokenContent::EndOfFile => None,
×
439
        },
UNCOV
440
        None => None,
×
441
    }
442
}
443

444
fn try_skip_comma(tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>) -> bool {
36✔
445
    match peek_next_non_whitespace_token(tokens) {
36✔
446
        Some(non_whitespace) => match &non_whitespace.content {
36✔
447
            TokenContent::Comment(_) => unreachable!(),
448
            TokenContent::Whitespace => unreachable!(),
449
            TokenContent::Identifier(_identifier) => false,
1✔
450
            TokenContent::Assign => todo!(),
451
            TokenContent::LeftParenthesis => todo!(),
452
            TokenContent::RightParenthesis => false,
21✔
453
            TokenContent::LeftBracket => todo!(),
454
            TokenContent::RightBracket => todo!(),
455
            TokenContent::LeftBrace => todo!(),
456
            TokenContent::RightBrace => todo!(),
457
            TokenContent::Dot => todo!(),
458
            TokenContent::Colon => todo!(),
459
            TokenContent::Quotes(_) => todo!(),
460
            TokenContent::FatArrow => todo!(),
461
            TokenContent::Comma => {
462
                pop_next_non_whitespace_token(tokens);
14✔
463
                true
14✔
464
            }
UNCOV
465
            TokenContent::EndOfFile => false,
×
466
        },
UNCOV
467
        None => false,
×
468
    }
469
}
470

471
fn try_skip_colon(tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>) -> bool {
37✔
472
    match peek_next_non_whitespace_token(tokens) {
37✔
473
        Some(non_whitespace) => match &non_whitespace.content {
37✔
474
            TokenContent::Comment(_) => unreachable!(),
475
            TokenContent::Whitespace => unreachable!(),
476
            TokenContent::Identifier(_identifier) => false,
1✔
477
            TokenContent::Assign => todo!(),
478
            TokenContent::LeftParenthesis => todo!(),
479
            TokenContent::RightParenthesis => false,
16✔
480
            TokenContent::LeftBracket => todo!(),
481
            TokenContent::RightBracket => todo!(),
482
            TokenContent::LeftBrace => todo!(),
483
            TokenContent::RightBrace => todo!(),
484
            TokenContent::Dot => todo!(),
485
            TokenContent::Colon => {
486
                pop_next_non_whitespace_token(tokens);
11✔
487
                true
11✔
488
            }
489
            TokenContent::Quotes(_) => todo!(),
490
            TokenContent::FatArrow => todo!(),
491
            TokenContent::Comma => false,
9✔
UNCOV
492
            TokenContent::EndOfFile => false,
×
493
        },
UNCOV
494
        None => false,
×
495
    }
496
}
497

498
fn parse_lambda<'t>(
42✔
499
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
500
    local_namespace: &NamespaceId,
501
) -> ParserResult<ast::Expression> {
502
    let mut parameters = Vec::new();
42✔
503
    while let Some((parameter_name, parameter_location)) = try_pop_identifier(tokens) {
93✔
UNCOV
504
        let namespaced_name = Name::new(*local_namespace, parameter_name);
×
UNCOV
505
        let mut type_annotation = None;
×
UNCOV
506
        if try_skip_colon(tokens) {
×
507
            type_annotation = Some(parse_expression(tokens, local_namespace)?);
22✔
508
        }
509
        parameters.push(LambdaParameter::new(
36✔
510
            namespaced_name,
36✔
511
            parameter_location,
36✔
512
            type_annotation,
36✔
513
        ));
514
        if !try_skip_comma(tokens) {
36✔
515
            break;
22✔
516
        }
517
    }
518
    if !try_skip_right_parenthesis(tokens) {
41✔
519
        let next_token = peek_next_non_whitespace_token(tokens).unwrap();
1✔
520
        return Err(ParserError::new(
1✔
521
            "Expected comma or right parenthesis in lambda parameter list.".to_string(),
1✔
522
            next_token.location,
1✔
523
        ));
524
    }
525
    expect_fat_arrow(tokens);
40✔
526
    let body = parse_expression(tokens, local_namespace)?;
80✔
UNCOV
527
    Ok(ast::Expression::Lambda {
×
UNCOV
528
        parameters,
×
UNCOV
529
        body: Box::new(body),
×
530
    })
531
}
532

533
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
534
pub struct ParserOutput {
535
    pub entry_point: Option<ast::Expression>,
536
    pub errors: Vec<CompilerError>,
537
}
538

539
impl ParserOutput {
540
    pub fn new(entry_point: Option<ast::Expression>, errors: Vec<CompilerError>) -> ParserOutput {
26✔
541
        ParserOutput {
542
            entry_point,
543
            errors,
544
        }
545
    }
546
}
547

548
pub fn parse_expression_tolerantly<'t>(
22✔
549
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
550
    local_namespace: &NamespaceId,
551
) -> ParserOutput {
552
    let mut errors = Vec::new();
22✔
553
    let entry_point_result = parse_expression(tokens, local_namespace);
22✔
554
    match entry_point_result {
22✔
555
        Ok(entry_point) => ParserOutput::new(Some(entry_point), errors),
17✔
556
        Err(error) => {
5✔
557
            errors.push(CompilerError::new(
5✔
558
                format!("Parser error: {}", &error),
5✔
559
                error.location,
5✔
560
            ));
561
            ParserOutput::new(None, errors)
5✔
562
        }
563
    }
564
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc