-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsmoke.rs
138 lines (117 loc) · 5.12 KB
/
smoke.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use rhai_rowan::{
parser::{parsers::parse_expr, Operator, Parser},
syntax::SyntaxKind::*,
};
use test_case::test_case;
#[test_case("simple", include_str!("../../../testdata/valid/simple.rhai"))]
#[test_case("array", include_str!("../../../testdata/valid/array.rhai"))]
#[test_case("assignment", include_str!("../../../testdata/valid/assignment.rhai"))]
#[test_case("comments", include_str!("../../../testdata/valid/comments.rhai"))]
#[test_case("fibonacci", include_str!("../../../testdata/valid/fibonacci.rhai"))]
#[test_case("for1", include_str!("../../../testdata/valid/for1.rhai"))]
#[test_case("for2", include_str!("../../../testdata/valid/for2.rhai"))]
#[test_case("function_decl1", include_str!("../../../testdata/valid/function_decl1.rhai"))]
#[test_case("function_decl2", include_str!("../../../testdata/valid/function_decl2.rhai"))]
#[test_case("function_decl3", include_str!("../../../testdata/valid/function_decl3.rhai"))]
#[test_case("function_decl4", include_str!("../../../testdata/valid/function_decl4.rhai"))]
#[test_case("if1", include_str!("../../../testdata/valid/if1.rhai"))]
#[test_case("if2", include_str!("../../../testdata/valid/if2.rhai"))]
#[test_case("loop", include_str!("../../../testdata/valid/loop.rhai"))]
#[test_case("mat_mul", include_str!("../../../testdata/valid/mat_mul.rhai"))]
#[test_case("module", include_str!("../../../testdata/valid/module.rhai"))]
#[test_case("oop", include_str!("../../../testdata/valid/oop.rhai"))]
#[test_case("op1", include_str!("../../../testdata/valid/op1.rhai"))]
#[test_case("op2", include_str!("../../../testdata/valid/op2.rhai"))]
#[test_case("op3", include_str!("../../../testdata/valid/op3.rhai"))]
#[test_case("primes", include_str!("../../../testdata/valid/primes.rhai"))]
#[test_case("speed_test", include_str!("../../../testdata/valid/speed_test.rhai"))]
#[test_case("string", include_str!("../../../testdata/valid/string.rhai"))]
#[test_case("strings_map", include_str!("../../../testdata/valid/strings_map.rhai"))]
#[test_case("switch", include_str!("../../../testdata/valid/switch.rhai"))]
#[test_case("while", include_str!("../../../testdata/valid/while.rhai"))]
#[test_case("char", include_str!("../../../testdata/valid/char.rhai"))]
#[test_case("throw_try_catch", include_str!("../../../testdata/valid/throw_try_catch.rhai"))]
#[test_case("optional_ops", include_str!("../../../testdata/valid/optional_ops.rhai"))]
#[test_case("string_escape", include_str!("../../../testdata/valid/string_escape.rhai"))]
#[test_case("template", include_str!("../../../testdata/valid/template.rhai"))]
#[test_case("unary_ops", include_str!("../../../testdata/valid/unary_ops.rhai"))]
fn parse_valid(name: &str, src: &str) {
let parse = Parser::new(src)
// This operator does not actually exist among the scripts.
.with_operator("op", Operator::default())
.parse_script();
assert!(parse.errors.is_empty(), "{:#?}", parse.errors);
let mut engine = rhai::Engine::new();
engine.set_max_expr_depths(0, 0);
if src.starts_with("#!") {
engine
.compile(
src.lines()
.skip(1)
.map(ToString::to_string)
.collect::<Vec<String>>()
.join("\n"),
)
.unwrap();
} else {
engine.compile(src).unwrap();
}
insta::with_settings!(
{ snapshot_suffix => name },
{
insta::assert_snapshot!(format!("{:#?}", parse.into_syntax()));
}
);
}
#[test]
fn parse_custom_operator() {
let src = include_str!("../../../testdata/valid/operators.rhai");
let parse = Parser::new(src)
.with_operator("over", Operator::default())
.parse_script();
assert!(parse.errors.is_empty(), "{:#?}", parse.errors);
insta::assert_snapshot!(format!("{:#?}", parse.into_syntax()));
let parse = Parser::new(src).parse_script();
assert!(!parse.errors.is_empty());
}
#[test]
fn parse_ambiguous_ranges() {
Parser::new(r#"0..1"#).execute(|ctx| {
assert_eq!(ctx.token(), Some(LIT_INT));
ctx.eat();
assert_eq!(ctx.token(), Some(OP_RANGE));
ctx.eat();
assert_eq!(ctx.token(), Some(LIT_INT));
ctx.eat();
});
Parser::new(r#"0..=1"#).execute(|ctx| {
assert_eq!(ctx.token(), Some(LIT_INT));
ctx.eat();
assert_eq!(ctx.token(), Some(OP_RANGE_INCLUSIVE));
ctx.eat();
assert_eq!(ctx.token(), Some(LIT_INT));
ctx.eat();
});
Parser::new(r#"0. ..=1"#).execute(|ctx| {
assert_eq!(ctx.token(), Some(LIT_FLOAT));
ctx.eat();
assert_eq!(ctx.token(), Some(OP_RANGE_INCLUSIVE));
ctx.eat();
assert_eq!(ctx.token(), Some(LIT_INT));
ctx.eat();
});
}
#[test]
fn parse_ambiguous_integer_field_access() {
Parser::new(r#"0.foo"#).execute(|ctx| {
assert_eq!(ctx.token(), Some(LIT_INT));
ctx.eat();
assert_eq!(ctx.token(), Some(PUNCT_DOT));
ctx.eat();
assert_eq!(ctx.token(), Some(IDENT));
ctx.eat();
});
let mut parser = Parser::new(r#"0.foo()"#);
parser.execute(parse_expr);
assert!(parser.finish().errors.is_empty());
}