1pub mod ast;
6pub mod lexer;
7#[rustfmt::skip]
8mod parser;
9
10pub use crate::lexer::{LexError, Token};
11pub use lalrpop_util::ParseError;
12
13pub struct Parser {}
14
15impl Parser {
16 pub fn parse(input: &str) -> Result<ast::Expression, ParseError<usize, Token, LexError>> {
17 let lexer = lexer::Lexer::new(input);
18 Ok(*parser::ExpressionParser::new().parse(lexer)?)
19 }
20}
21
22#[cfg(test)]
23mod tests {
24 use super::*;
25 use crate::ast::{Expression, OpCode};
26
27 #[test]
28 fn literal() {
29 assert_eq!(Parser::parse("1"), Ok(Expression::Number(1.0)));
30 }
31
32 #[test]
33 fn binary_expression() {
34 assert_eq!(
35 Parser::parse("1+2"),
36 Ok(Expression::BinaryOperation {
37 operation: OpCode::Add,
38 left: Box::new(Expression::Number(1.0)),
39 right: Box::new(Expression::Number(2.0)),
40 }),
41 );
42 }
43
44 #[test]
45 fn binary_expression_whitespace() {
46 assert_eq!(Parser::parse("1 + 2 "), Parser::parse("1+2"),);
47 }
48
49 #[test]
50 fn transform_simple_no_args() {
51 let exp = "'T_T'|lower";
52 let parsed = Parser::parse(exp).unwrap();
53 assert_eq!(
54 parsed,
55 Expression::Transform {
56 name: "lower".to_string(),
57 subject: Box::new(Expression::String("T_T".to_string())),
58 args: None
59 }
60 );
61 }
62
63 #[test]
64 fn transform_multiple_args() {
65 let exp = "'John Doe'|split(' ')";
66 let parsed = Parser::parse(exp).unwrap();
67 assert_eq!(
68 parsed,
69 Expression::Transform {
70 name: "split".to_string(),
71 subject: Box::new(Expression::String("John Doe".to_string())),
72 args: Some(vec![Box::new(Expression::String(" ".to_string()))])
73 }
74 );
75 }
76
77 #[test]
78 fn trasform_way_too_many_args() {
79 let exp = "123456|math(12, 35, 100, 31, 90)";
80 let parsed = Parser::parse(exp).unwrap();
81 assert_eq!(
82 parsed,
83 Expression::Transform {
84 name: "math".to_string(),
85 subject: Box::new(Expression::Number(123_456f64)),
86 args: Some(vec![
87 Box::new(Expression::Number(12f64)),
88 Box::new(Expression::Number(35f64)),
89 Box::new(Expression::Number(100f64)),
90 Box::new(Expression::Number(31f64)),
91 Box::new(Expression::Number(90f64)),
92 ])
93 }
94 );
95 }
96
97 #[test]
98 fn test_index_op_ident() {
99 let exp = "foo[0]";
100 let parsed = Parser::parse(exp).unwrap();
101 assert_eq!(
102 parsed,
103 Expression::IndexOperation {
104 subject: Box::new(Expression::Identifier("foo".to_string())),
105 index: Box::new(Expression::Number(0f64))
106 }
107 );
108 }
109
110 #[test]
111 fn test_index_op_array_literal() {
112 let exp = "[1, 2, 3][0]";
113 let parsed = Parser::parse(exp).unwrap();
114 assert_eq!(
115 parsed,
116 Expression::IndexOperation {
117 subject: Box::new(Expression::Array(vec![
118 Box::new(Expression::Number(1f64)),
119 Box::new(Expression::Number(2f64)),
120 Box::new(Expression::Number(3f64)),
121 ])),
122 index: Box::new(Expression::Number(0f64))
123 }
124 );
125 }
126
127 #[test]
128 fn test_dot_op_ident() {
129 let exp = "foo.bar";
130 let parsed = Parser::parse(exp).unwrap();
131 assert_eq!(
132 parsed,
133 Expression::DotOperation {
134 subject: Box::new(Expression::Identifier("foo".to_string())),
135 ident: "bar".to_string()
136 }
137 );
138 }
139
140 #[test]
141 fn test_dot_op_equality_with_null() {
142 let exp = "foo.bar == null";
143 let parsed = Parser::parse(exp).unwrap();
144 assert_eq!(
145 parsed,
146 Expression::BinaryOperation {
147 operation: OpCode::Equal,
148 left: Box::new(Expression::DotOperation {
149 subject: Box::new(Expression::Identifier("foo".to_string())),
150 ident: "bar".to_string()
151 }),
152 right: Box::new(Expression::Null),
153 }
154 );
155 }
156
157 #[test]
158 fn test_dot_op_object_literal() {
159 let exp = "{'foo': 1}.foo";
160 let parsed = Parser::parse(exp).unwrap();
161 assert_eq!(
162 parsed,
163 Expression::DotOperation {
164 subject: Box::new(Expression::Object(vec![(
165 "foo".to_string(),
166 Box::new(Expression::Number(1f64))
167 )])),
168 ident: "foo".to_string()
169 }
170 );
171 }
172
173 #[test]
174 fn test_parsing_null() {
175 assert_eq!(Parser::parse("null"), Ok(Expression::Null));
176 }
177
178 #[test]
179 fn test_empty_object_literal() {
180 let exp = "{}";
181 let parsed = Parser::parse(exp).unwrap();
182 assert_eq!(parsed, Expression::Object(vec![]));
183 }
184}