Skip to content

Commit c57afa8

Browse files
committed
reapply changes after updated master
1 parent 9c334e7 commit c57afa8

12 files changed

+1530
-1546
lines changed

src/parser/tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use crate::ast::{SourceRange, Statement};
33
// Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
44
mod control_parser_tests;
55
mod expressions_parser_tests;
6+
mod misc_parser_tests;
67
mod parse_errors;
7-
mod parser_tests;
88

99
pub fn lex(source: &str) -> crate::lexer::ParseSession {
1010
crate::lexer::lex(source)

src/parser/tests/misc_parser_tests.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
2+
use crate::{
3+
ast::*,
4+
parser::{parse, tests::lex},
5+
};
6+
use pretty_assertions::*;
7+
8+
#[test]
9+
fn empty_returns_empty_compilation_unit() {
10+
let (result, ..) = parse(lex("")).unwrap();
11+
assert_eq!(result.units.len(), 0);
12+
}
13+
14+
#[test]
15+
fn programs_can_be_external() {
16+
let lexer = lex("@EXTERNAL PROGRAM foo END_PROGRAM");
17+
let parse_result = parse(lexer).unwrap().0;
18+
let implementation = &parse_result.implementations[0];
19+
assert_eq!(LinkageType::External, implementation.linkage);
20+
}

src/parser/tests/parse_errors.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
mod parse_error_containers_tests;
2+
mod parse_error_function_tests;
3+
mod parse_error_initializer_tests;
24
mod parse_error_literals_tests;
5+
mod parse_error_messages_test;
6+
mod parse_error_program_tests;
37
mod parse_error_statements_tests;
8+
mod parse_error_type_tests;
9+
mod parse_error_variable_tests;

src/parser/tests/parse_errors/parse_error_containers_tests.rs

+135
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,138 @@ fn test_unexpected_type_declaration_error_message() {
279279
diagnostics
280280
);
281281
}
282+
283+
#[test]
284+
fn action_container_parsed() {
285+
let lexer = lex("ACTIONS foo ACTION bar END_ACTION END_ACTIONS");
286+
let result = parse(lexer).unwrap().0;
287+
288+
let prg = &result.implementations[0];
289+
assert_eq!(prg.name, "foo.bar");
290+
assert_eq!(prg.type_name, "foo");
291+
}
292+
293+
#[test]
294+
fn two_action_containers_parsed() {
295+
let lexer = lex("ACTIONS foo ACTION bar END_ACTION ACTION buz END_ACTION END_ACTIONS");
296+
let result = parse(lexer).unwrap().0;
297+
298+
let prg = &result.implementations[0];
299+
assert_eq!(prg.name, "foo.bar");
300+
assert_eq!(prg.type_name, "foo");
301+
302+
let prg2 = &result.implementations[1];
303+
assert_eq!(prg2.name, "foo.buz");
304+
assert_eq!(prg2.type_name, "foo");
305+
}
306+
307+
#[test]
308+
fn mixed_action_types_parsed() {
309+
let lexer = lex("PROGRAM foo END_PROGRAM ACTIONS foo ACTION bar END_ACTION END_ACTIONS ACTION foo.buz END_ACTION");
310+
let result = parse(lexer).unwrap().0;
311+
312+
let prg = &result.implementations[1];
313+
assert_eq!(prg.name, "foo.bar");
314+
assert_eq!(prg.type_name, "foo");
315+
316+
let prg2 = &result.implementations[2];
317+
assert_eq!(prg2.name, "foo.buz");
318+
assert_eq!(prg2.type_name, "foo");
319+
}
320+
321+
#[test]
322+
fn actions_with_no_container_error() {
323+
let lexer = lex("ACTIONS ACTION bar END_ACTION ACTION buz END_ACTION END_ACTIONS");
324+
let err = parse(lexer).expect_err("Expecting parser failure");
325+
assert_eq!(
326+
err,
327+
Diagnostic::unexpected_token_found("Identifier".into(), "ACTION".into(), (8..14).into())
328+
);
329+
}
330+
331+
#[test]
332+
fn two_programs_can_be_parsed() {
333+
let lexer = lex("PROGRAM foo END_PROGRAM PROGRAM bar END_PROGRAM");
334+
let result = parse(lexer).unwrap().0;
335+
336+
let prg = &result.units[0];
337+
assert_eq!(prg.name, "foo");
338+
let prg2 = &result.units[1];
339+
assert_eq!(prg2.name, "bar");
340+
}
341+
342+
#[test]
343+
fn simple_program_with_varblock_can_be_parsed() {
344+
let lexer = lex("PROGRAM buz VAR END_VAR END_PROGRAM");
345+
let result = parse(lexer).unwrap().0;
346+
347+
let prg = &result.units[0];
348+
349+
assert_eq!(prg.variable_blocks.len(), 1);
350+
}
351+
352+
#[test]
353+
fn simple_program_with_two_varblocks_can_be_parsed() {
354+
let lexer = lex("PROGRAM buz VAR END_VAR VAR END_VAR END_PROGRAM");
355+
let result = parse(lexer).unwrap().0;
356+
357+
let prg = &result.units[0];
358+
359+
assert_eq!(prg.variable_blocks.len(), 2);
360+
}
361+
362+
#[test]
363+
fn a_program_needs_to_end_with_end_program() {
364+
let lexer = lex("PROGRAM buz ");
365+
let (_, diagnostics) = parse(lexer).unwrap();
366+
assert_eq!(
367+
diagnostics,
368+
vec![Diagnostic::unexpected_token_found(
369+
"KeywordEndProgram".into(),
370+
"''".into(),
371+
(12..12).into()
372+
),]
373+
);
374+
}
375+
376+
#[test]
377+
fn a_variable_declaration_block_needs_to_end_with_endvar() {
378+
let lexer = lex("PROGRAM buz VAR END_PROGRAM ");
379+
let (_, diagnostics) = parse(lexer).unwrap();
380+
381+
assert_eq!(
382+
diagnostics,
383+
vec![
384+
Diagnostic::missing_token("[KeywordEndVar]".into(), (16..27).into()),
385+
Diagnostic::unexpected_token_found(
386+
"KeywordEndVar".into(),
387+
"'END_PROGRAM'".into(),
388+
(16..27).into()
389+
),
390+
]
391+
);
392+
}
393+
394+
#[test]
395+
fn single_action_parsed() {
396+
let lexer = lex("ACTION foo.bar END_ACTION");
397+
let result = parse(lexer).unwrap().0;
398+
399+
let prg = &result.implementations[0];
400+
assert_eq!(prg.name, "foo.bar");
401+
assert_eq!(prg.type_name, "foo");
402+
}
403+
404+
#[test]
405+
fn two_actions_parsed() {
406+
let lexer = lex("ACTION foo.bar END_ACTION ACTION fuz.bar END_ACTION");
407+
let result = parse(lexer).unwrap().0;
408+
409+
let prg = &result.implementations[0];
410+
assert_eq!(prg.name, "foo.bar");
411+
assert_eq!(prg.type_name, "foo");
412+
413+
let prg2 = &result.implementations[1];
414+
assert_eq!(prg2.name, "fuz.bar");
415+
assert_eq!(prg2.type_name, "fuz");
416+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use crate::{
2+
ast::*,
3+
parser::{parse, tests::lex},
4+
Diagnostic,
5+
};
6+
use pretty_assertions::*;
7+
8+
#[test]
9+
fn simple_foo_function_can_be_parsed() {
10+
let lexer = lex("FUNCTION foo : INT END_FUNCTION");
11+
let result = parse(lexer).unwrap().0;
12+
13+
let prg = &result.units[0];
14+
assert_eq!(prg.pou_type, PouType::Function);
15+
assert_eq!(prg.name, "foo");
16+
assert_eq!(
17+
prg.return_type.as_ref().unwrap(),
18+
&DataTypeDeclaration::DataTypeReference {
19+
referenced_type: "INT".to_string()
20+
}
21+
);
22+
}
23+
24+
#[test]
25+
fn simple_foo_function_block_can_be_parsed() {
26+
let lexer = lex("FUNCTION_BLOCK foo END_FUNCTION_BLOCK");
27+
let result = parse(lexer).unwrap().0;
28+
29+
let prg = &result.units[0];
30+
assert_eq!(prg.pou_type, PouType::FunctionBlock);
31+
assert_eq!(prg.name, "foo");
32+
assert!(prg.return_type.is_none());
33+
}
34+
35+
#[test]
36+
fn a_function_with_varargs_can_be_parsed() {
37+
let lexer = lex("FUNCTION foo : INT VAR_INPUT x : INT; y : ...; END_VAR END_FUNCTION");
38+
let result = parse(lexer).unwrap().0;
39+
40+
let prg = &result.units[0];
41+
let variable_block = &prg.variable_blocks[0];
42+
let ast_string = format!("{:#?}", variable_block);
43+
let expected_ast = r#"VariableBlock {
44+
variables: [
45+
Variable {
46+
name: "x",
47+
data_type: DataTypeReference {
48+
referenced_type: "INT",
49+
},
50+
},
51+
Variable {
52+
name: "y",
53+
data_type: DataTypeDefinition {
54+
data_type: VarArgs {
55+
referenced_type: None,
56+
},
57+
},
58+
},
59+
],
60+
variable_block_type: Input,
61+
}"#;
62+
assert_eq!(ast_string, expected_ast);
63+
}
64+
65+
#[test]
66+
fn a_function_with_typed_varargs_can_be_parsed() {
67+
let lexer = lex("FUNCTION foo : INT VAR_INPUT x : INT; y : INT...; END_VAR END_FUNCTION");
68+
let result = parse(lexer).unwrap().0;
69+
70+
let prg = &result.units[0];
71+
let variable_block = &prg.variable_blocks[0];
72+
let ast_string = format!("{:#?}", variable_block);
73+
let expected_ast = r#"VariableBlock {
74+
variables: [
75+
Variable {
76+
name: "x",
77+
data_type: DataTypeReference {
78+
referenced_type: "INT",
79+
},
80+
},
81+
Variable {
82+
name: "y",
83+
data_type: DataTypeDefinition {
84+
data_type: VarArgs {
85+
referenced_type: Some(
86+
DataTypeReference {
87+
referenced_type: "INT",
88+
},
89+
),
90+
},
91+
},
92+
},
93+
],
94+
variable_block_type: Input,
95+
}"#;
96+
assert_eq!(ast_string, expected_ast);
97+
}
98+
99+
#[test]
100+
fn varargs_parameters_can_be_parsed() {
101+
let lexer = lex("
102+
FUNCTION foo : DINT
103+
VAR_INPUT
104+
args1 : ...;
105+
args2 : INT...;
106+
END_VAR
107+
END_FUNCTION
108+
");
109+
let (parse_result, diagnostics) = parse(lexer).unwrap();
110+
111+
assert_eq!(
112+
format!("{:#?}", diagnostics),
113+
format!("{:#?}", Vec::<Diagnostic>::new()).as_str()
114+
);
115+
116+
let x = &parse_result.units[0];
117+
let expected = Pou {
118+
name: "foo".into(),
119+
pou_type: PouType::Function,
120+
return_type: Some(DataTypeDeclaration::DataTypeReference {
121+
referenced_type: "DINT".into(),
122+
}),
123+
variable_blocks: vec![VariableBlock {
124+
variable_block_type: VariableBlockType::Input,
125+
variables: vec![
126+
Variable {
127+
name: "args1".into(),
128+
data_type: DataTypeDeclaration::DataTypeDefinition {
129+
data_type: DataType::VarArgs {
130+
referenced_type: None,
131+
},
132+
},
133+
initializer: None,
134+
location: SourceRange::undefined(),
135+
},
136+
Variable {
137+
name: "args2".into(),
138+
data_type: DataTypeDeclaration::DataTypeDefinition {
139+
data_type: DataType::VarArgs {
140+
referenced_type: Some(Box::new(
141+
DataTypeDeclaration::DataTypeReference {
142+
referenced_type: "INT".into(),
143+
},
144+
)),
145+
},
146+
},
147+
initializer: None,
148+
location: SourceRange::undefined(),
149+
},
150+
],
151+
}],
152+
location: SourceRange::undefined(),
153+
};
154+
assert_eq!(format!("{:#?}", expected), format!("{:#?}", x).as_str());
155+
}

0 commit comments

Comments
 (0)