1
#![cfg(test)]
2

            
3
use proptest::prelude::*;
4

            
5
use crate::ast::{
6
    BuiltinTypeKind, Decl, FuncDecl, IntegerLiteral, Param, TranslationUnit, Type, VarDecl,
7
};
8
use crate::diagnostics::Diag;
9
use crate::parser::Parser;
10
use crate::scanner::TokenKind;
11
use crate::tests::*;
12

            
13
1
#[test]
14
1
fn parse_empty_translation_unit_should_issue_an_error() {
15
1
    let result = parse("");
16
1

            
17
1
    assert_eq!(result, Err(vec![Diag::EmptyTranslationUnit]));
18
1
}
19

            
20
257
proptest! {
21
257
    #[test]
22
257
    fn parse_basic_top_level_variable_declaration(
23
257
        type_spec in "int|long",
24
257
        ident_name in identifier(),
25
257
    ) {
26
257
        let result = parse(
27
257
            &format!(
28
257
                r#"
29
257
                {type_spec} {ident_name};
30
257
                "#,
31
257
                type_spec=type_spec,
32
257
                ident_name=ident_name,
33
257
            )
34
257
        );
35
258

            
36
258
        let expected_type_kind = match type_spec.as_ref() {
37
257
            "int" => BuiltinTypeKind::Int,
38
258
            "long" => BuiltinTypeKind::Long,
39
258
            _ => panic!("forgot to cover extra types"),
40
258
        };
41
258

            
42
258
        let var_decl = VarDecl {
43
257
            type_specifier: Type::BuiltinType(expected_type_kind),
44
257
            identifier: ident_name,
45
257
            initializer: None,
46
257
        };
47
257

            
48
257
        let expected = TranslationUnit {
49
257
            external_decls: vec![Decl::Var(var_decl)],
50
257
        };
51
257

            
52
257
        assert_eq!(result, Ok(expected));
53
258
    }
54
258
}
55

            
56
257
proptest! {
57
257
#[test]
58
257
    fn parse_basic_top_level_variable_declaration_with_initializer(
59
257
        type_spec in "int|long",
60
257
        ident_name in identifier(),
61
257
    ) {
62
257
        let result = parse(
63
257
            &format!(
64
257
                r#"
65
257
                {type_spec} {ident_name} = 42;
66
257
                "#,
67
257
                type_spec=type_spec,
68
257
                ident_name=ident_name,
69
257
            )
70
257
        );
71
258

            
72
258
        let expected_type_kind = match type_spec.as_ref() {
73
257
            "int" => BuiltinTypeKind::Int,
74
258
            "long" => BuiltinTypeKind::Long,
75
258
            _ => panic!("forgot to cover extra types"),
76
258
        };
77
258

            
78
258
        let initializer = IntegerLiteral {
79
257
            value: 42,
80
257
            ty: Type::BuiltinType(BuiltinTypeKind::Int),
81
257
        };
82
257

            
83
257
        let var_decl = VarDecl {
84
257
            type_specifier: Type::BuiltinType(expected_type_kind),
85
257
            identifier: ident_name,
86
257
            initializer: Some(initializer),
87
257
        };
88
257

            
89
257
        let expected = TranslationUnit {
90
257
            external_decls: vec![Decl::Var(var_decl)],
91
257
        };
92
257

            
93
257
        assert_eq!(result, Ok(expected));
94
258
    }
95
258
}
96

            
97
1
#[test]
98
1
fn parse_basic_top_level_function_declaration() {
99
1
    let result = parse(
100
1
        r#"
101
1
        int foo();
102
1
        "#,
103
1
    );
104
1

            
105
1
    let func_decl = FuncDecl {
106
1
        ret_type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
107
1
        identifier: "foo".to_owned(),
108
1
        parameters: vec![],
109
1
    };
110
1

            
111
1
    let expected = TranslationUnit {
112
1
        external_decls: vec![Decl::Func(func_decl)],
113
1
    };
114
1

            
115
1
    assert_eq!(result, Ok(expected));
116
1
}
117

            
118
1
#[test]
119
1
fn parse_basic_top_level_function_declaration_with_unnamed_parameter() {
120
1
    let result = parse(
121
1
        r#"
122
1
        int foo(int);
123
1
        "#,
124
1
    );
125
1

            
126
1
    let func_decl = FuncDecl {
127
1
        ret_type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
128
1
        identifier: "foo".to_owned(),
129
1
        parameters: vec![Param {
130
1
            type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
131
1
            identifier: None,
132
1
        }],
133
1
    };
134
1

            
135
1
    let expected = TranslationUnit {
136
1
        external_decls: vec![Decl::Func(func_decl)],
137
1
    };
138
1

            
139
1
    assert_eq!(result, Ok(expected));
140
1
}
141

            
142
1
#[test]
143
1
fn parse_basic_top_level_function_declaration_with_named_parameter() {
144
1
    let result = parse(
145
1
        r#"
146
1
        int foo(int bar);
147
1
        "#,
148
1
    );
149
1

            
150
1
    let func_decl = FuncDecl {
151
1
        ret_type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
152
1
        identifier: "foo".to_owned(),
153
1
        parameters: vec![Param {
154
1
            type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
155
1
            identifier: Some("bar".to_owned()),
156
1
        }],
157
1
    };
158
1

            
159
1
    let expected = TranslationUnit {
160
1
        external_decls: vec![Decl::Func(func_decl)],
161
1
    };
162
1

            
163
1
    assert_eq!(result, Ok(expected));
164
1
}
165

            
166
1
#[test]
167
1
fn parse_basic_top_level_function_declaration_with_many_unnamed_parameters() {
168
1
    let result = parse(
169
1
        r#"
170
1
        int foo(int, int, int);
171
1
        "#,
172
1
    );
173
1

            
174
1
    let func_decl = FuncDecl {
175
1
        ret_type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
176
1
        identifier: "foo".to_owned(),
177
1
        parameters: vec![
178
1
            Param {
179
1
                type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
180
1
                identifier: None,
181
1
            },
182
1
            Param {
183
1
                type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
184
1
                identifier: None,
185
1
            },
186
1
            Param {
187
1
                type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
188
1
                identifier: None,
189
1
            },
190
1
        ],
191
1
    };
192
1

            
193
1
    let expected = TranslationUnit {
194
1
        external_decls: vec![Decl::Func(func_decl)],
195
1
    };
196
1

            
197
1
    assert_eq!(result, Ok(expected));
198
1
}
199

            
200
1
#[test]
201
1
fn parse_basic_top_level_function_declaration_with_many_named_parameters() {
202
1
    let result = parse(
203
1
        r#"
204
1
        int foo(int x, int y, int z);
205
1
        "#,
206
1
    );
207
1

            
208
1
    let func_decl = FuncDecl {
209
1
        ret_type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
210
1
        identifier: "foo".to_owned(),
211
1
        parameters: vec![
212
1
            Param {
213
1
                type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
214
1
                identifier: Some("x".to_owned()),
215
1
            },
216
1
            Param {
217
1
                type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
218
1
                identifier: Some("y".to_owned()),
219
1
            },
220
1
            Param {
221
1
                type_specifier: Type::BuiltinType(BuiltinTypeKind::Int),
222
1
                identifier: Some("z".to_owned()),
223
1
            },
224
1
        ],
225
1
    };
226
1

            
227
1
    let expected = TranslationUnit {
228
1
        external_decls: vec![Decl::Func(func_decl)],
229
1
    };
230
1

            
231
1
    assert_eq!(result, Ok(expected));
232
1
}
233

            
234
1
#[test]
235
1
fn parse_error_basic_top_level_function_declaration_with_many_parameters_missing_comma() {
236
1
    let result = parse(
237
1
        r#"
238
1
        int foo(int a int int);
239
1
        "#,
240
1
    );
241
1

            
242
1
    let expected = vec![
243
1
        Diag::ExpectedButGot {
244
1
            expected: TokenKind::Comma,
245
1
            got: TokenKind::KwInt,
246
1
        },
247
1
        Diag::ExpectedButGot {
248
1
            expected: TokenKind::Comma,
249
1
            got: TokenKind::KwInt,
250
1
        },
251
1
    ];
252
1

            
253
1
    assert_eq!(result, Err(expected));
254
1
}
255

            
256
1
#[test]
257
1
fn parse_error_basic_top_level_function_declaration_missing_closing_paren() {
258
1
    let result = parse(
259
1
        r#"
260
1
        int foo(;
261
1
        "#,
262
1
    );
263
1

            
264
1
    let expected = vec![Diag::MissingClosingParen];
265
1

            
266
1
    assert_eq!(result, Err(expected));
267
1
}
268

            
269
1
#[test]
270
1
fn parse_error_basic_top_level_function_declaration_unexpected_token() {
271
1
    let result = parse(
272
1
        r#"
273
1
        int foo(+);
274
1
        "#,
275
1
    );
276
1

            
277
1
    let expected = vec![Diag::ExpectedButGot {
278
1
        expected: TokenKind::KwInt,
279
1
        got: TokenKind::Plus,
280
1
    }];
281
1

            
282
1
    assert_eq!(result, Err(expected));
283
1
}
284

            
285
1
#[test]
286
1
fn parse_error_basic_top_level_function_declaration_unexpected_token_and_missing_closing_paren() {
287
1
    let result = parse(
288
1
        r#"
289
1
        int foo(+;
290
1
        "#,
291
1
    );
292
1

            
293
1
    let expected = vec![
294
1
        Diag::ExpectedButGot {
295
1
            expected: TokenKind::KwInt,
296
1
            got: TokenKind::Plus,
297
1
        },
298
1
        Diag::MissingClosingParen,
299
1
    ];
300
1

            
301
1
    assert_eq!(result, Err(expected));
302
1
}
303

            
304
524
fn parse(source_text: &str) -> Result<TranslationUnit, Vec<Diag>> {
305
524
    use crate::scanner::Scanner;
306
524
    use crate::source_map::SourceFile;
307
524

            
308
524
    let scanner = Scanner::with_input(source_text);
309
524
    let source_file = SourceFile::new(source_text);
310
524

            
311
524
    let mut parser = Parser::new(scanner, source_file);
312
524

            
313
524
    parser.parse_translation_unit()
314
524
}