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

TyRoXx / NonlocalityOS / 14777764055

01 May 2025 03:08PM UTC coverage: 76.437% (-1.2%) from 77.611%
14777764055

Pull #225

github

web-flow
Merge 783ce7edc into 824c46b00
Pull Request #225: Update GitHub Actions runner to Ubuntu 24.04

3977 of 5203 relevant lines covered (76.44%)

1814.93 hits per line

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

65.71
/lambda_compiler/src/parsing.rs
1
use crate::{
2
    compilation::{CompilerError, CompilerOutput, SourceLocation},
3
    tokenization::{Token, TokenContent},
4
};
5
use astraea::tree::{HashedValue, Value};
6
use lambda::expressions::{DeepExpression, Expression};
7
use lambda::name::{Name, NamespaceId};
8
use std::sync::Arc;
9

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

15
impl ParserError {
16
    pub fn new(message: String) -> Self {
2✔
17
        Self { message }
18
    }
19
}
20

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

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

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

37
    return token;
60✔
38
}
39

40
pub fn peek_next_non_whitespace_token<'t>(
81✔
41
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
42
) -> Option<&'t Token> {
43
    loop {
×
44
        let next = tokens.peek();
99✔
45
        match next {
99✔
46
            Some(token) => match token.content {
84✔
47
                TokenContent::Whitespace => {
×
48
                    tokens.next();
18✔
49
                    continue;
18✔
50
                }
51
                TokenContent::Identifier(_)
×
52
                | TokenContent::Assign
×
53
                | TokenContent::LeftParenthesis
×
54
                | TokenContent::RightParenthesis
×
55
                | TokenContent::Dot
×
56
                | TokenContent::Quotes(_)
×
57
                | TokenContent::FatArrow => return Some(token),
66✔
58
            },
59
            None => return None,
15✔
60
        }
61
    }
62
}
63

64
fn expect_right_parenthesis(tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>) {
13✔
65
    match pop_next_non_whitespace_token(tokens) {
13✔
66
        Some(non_whitespace) => match &non_whitespace.content {
13✔
67
            TokenContent::Whitespace => todo!(),
68
            TokenContent::Identifier(_) => todo!(),
69
            TokenContent::Assign => todo!(),
70
            TokenContent::LeftParenthesis => todo!(),
71
            TokenContent::RightParenthesis => {}
13✔
72
            TokenContent::Dot => todo!(),
73
            TokenContent::Quotes(_) => todo!(),
74
            TokenContent::FatArrow => todo!(),
75
        },
76
        None => todo!(),
77
    }
78
}
79

80
fn expect_fat_arrow(tokens: &mut std::iter::Peekable<std::slice::Iter<'_, Token>>) {
9✔
81
    match pop_next_non_whitespace_token(tokens) {
9✔
82
        Some(non_whitespace) => match &non_whitespace.content {
9✔
83
            TokenContent::Whitespace => todo!(),
84
            TokenContent::Identifier(_) => todo!(),
85
            TokenContent::Assign => todo!(),
86
            TokenContent::LeftParenthesis => todo!(),
87
            TokenContent::RightParenthesis => todo!(),
88
            TokenContent::Dot => todo!(),
89
            TokenContent::Quotes(_) => todo!(),
90
            TokenContent::FatArrow => {}
9✔
91
        },
92
        None => todo!(),
93
    }
94
}
95

96
async fn parse_expression_start<'t>(
24✔
97
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
98
    local_namespace: &NamespaceId,
99
) -> ParserResult<DeepExpression> {
100
    match pop_next_non_whitespace_token(tokens) {
24✔
101
        Some(non_whitespace) => match &non_whitespace.content {
23✔
102
            TokenContent::Whitespace => todo!(),
103
            TokenContent::Identifier(identifier) => Ok(DeepExpression(Expression::ReadVariable(
12✔
104
                Name::new(*local_namespace, identifier.clone()),
12✔
105
            ))),
106
            TokenContent::Assign => todo!(),
107
            TokenContent::LeftParenthesis => Box::pin(parse_lambda(tokens, local_namespace)).await,
9✔
108
            TokenContent::RightParenthesis => Err(ParserError::new(
1✔
109
                "Expected expression, found right parenthesis.".to_string(),
1✔
110
            )),
111
            TokenContent::Dot => todo!(),
112
            TokenContent::Quotes(content) => Ok(DeepExpression(Expression::Literal(
1✔
113
                HashedValue::from(Arc::new(
1✔
114
                    Value::from_string(&content).expect("It's too long. That's what she said."),
1✔
115
                ))
116
                .digest()
1✔
117
                .clone(),
1✔
118
            ))),
119
            TokenContent::FatArrow => todo!(),
120
        },
121
        None => Err(ParserError::new(
1✔
122
            "Expected expression, got EOF.".to_string(),
1✔
123
        )),
124
    }
125
}
126

127
pub async fn parse_expression<'t>(
24✔
128
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
129
    local_namespace: &NamespaceId,
130
) -> ParserResult<DeepExpression> {
131
    let start = parse_expression_start(tokens, local_namespace).await?;
48✔
132
    match peek_next_non_whitespace_token(tokens) {
×
133
        Some(more) => match &more.content {
11✔
134
            TokenContent::Whitespace => unreachable!(),
135
            TokenContent::Identifier(_) => Ok(start),
×
136
            TokenContent::Assign => Ok(start),
×
137
            TokenContent::LeftParenthesis => {
×
138
                tokens.next();
5✔
139
                let argument = Box::pin(parse_expression(tokens, local_namespace)).await?;
10✔
140
                expect_right_parenthesis(tokens);
×
141
                Ok(DeepExpression(Expression::make_apply(
×
142
                    Arc::new(start),
×
143
                    Arc::new(argument),
×
144
                )))
145
            }
146
            TokenContent::RightParenthesis => Ok(start),
6✔
147
            TokenContent::Dot => todo!(),
148
            TokenContent::Quotes(_) => todo!(),
149
            TokenContent::FatArrow => todo!(),
150
        },
151
        None => Ok(start),
10✔
152
    }
153
}
154

155
async fn parse_lambda<'t>(
9✔
156
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
157
    local_namespace: &NamespaceId,
158
) -> ParserResult<DeepExpression> {
159
    let parameter_name: Name = Name::new(
160
        *local_namespace,
9✔
161
        match pop_next_non_whitespace_token(tokens) {
9✔
162
            Some(non_whitespace) => match &non_whitespace.content {
9✔
163
                TokenContent::Whitespace => todo!(),
×
164
                TokenContent::Identifier(identifier) => identifier.clone(),
9✔
165
                TokenContent::Assign => todo!(),
×
166
                TokenContent::LeftParenthesis => todo!(),
×
167
                TokenContent::RightParenthesis => todo!(),
×
168
                TokenContent::Dot => todo!(),
×
169
                TokenContent::Quotes(_) => todo!(),
×
170
                TokenContent::FatArrow => todo!(),
×
171
            },
172
            None => todo!(),
×
173
        },
174
    );
175
    expect_right_parenthesis(tokens);
9✔
176
    expect_fat_arrow(tokens);
9✔
177
    let body = parse_expression(tokens, local_namespace).await?;
18✔
178
    Ok(DeepExpression(Expression::make_lambda(
×
179
        parameter_name,
×
180
        Arc::new(body),
×
181
    )))
182
}
183

184
pub async fn parse_entry_point_lambda<'t>(
7✔
185
    tokens: &mut std::iter::Peekable<std::slice::Iter<'t, Token>>,
186
    local_namespace: &NamespaceId,
187
) -> CompilerOutput {
188
    let mut errors = Vec::new();
7✔
189
    let entry_point_result = parse_expression(tokens, local_namespace).await;
14✔
190
    match entry_point_result {
7✔
191
        Ok(entry_point) => match &entry_point.0 {
5✔
192
            Expression::Literal(_)
×
193
            | Expression::Apply {
×
194
                callee: _,
×
195
                argument: _,
×
196
            }
197
            | Expression::ReadVariable(_) => {
×
198
                errors.push(CompilerError::new(
1✔
199
                    "The entry point is expected to be a lambda expression.".to_string(),
1✔
200
                    SourceLocation::new(0, 0),
1✔
201
                ));
202
                CompilerOutput::new(None, errors)
1✔
203
            }
204
            Expression::Lambda {
×
205
                parameter_name: _,
×
206
                body: _,
×
207
            } => CompilerOutput::new(Some(entry_point), errors),
4✔
208
            Expression::Construct(_arguments) => {
×
209
                todo!()
210
            }
211
        },
212
        Err(error) => {
2✔
213
            errors.push(CompilerError::new(
2✔
214
                format!("Parser error: {}", &error),
2✔
215
                SourceLocation::new(0, 0),
2✔
216
            ));
217
            CompilerOutput::new(None, errors)
2✔
218
        }
219
    }
220
}
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