welly_parser/expr/
mod.rs

1//! Welly's expressions.
2
3use super::{lexer, word, bracket, Tree, Location, Loc, Stream, Context, Parse};
4use lexer::{Comment, CharacterLiteral, StringLiteral};
5use word::{Whitespace, Alphanumeric};
6use bracket::{Round, Brace};
7
8mod op;
9pub use op::{Precedence, Op};
10
11mod atom;
12pub use atom::{Operator};
13
14mod precedence;
15use precedence::{Stack};
16
17pub const MISSING_FIELD: &'static str = "Missing field name";
18pub const MISSING_ARGS: &'static str = "Missing function arguments";
19pub const MISSING_RETURN_TYPE: &'static str = "Missing function return type";
20
21// ----------------------------------------------------------------------------
22
23/// A keyword that can appear in an [`Expr`].
24// TODO: `def`, `obj`, `type`, type constructors.
25#[derive(Debug, Copy, Clone, PartialEq)]
26pub enum Keyword { Fn, Dot }
27
28impl Tree for Keyword {
29    fn declare_keywords(mut declare: impl FnMut(&'static str, Self)) {
30        declare("fn", Self::Fn);
31        declare(".", Self::Dot);
32    }
33}
34
35// ----------------------------------------------------------------------------
36
37/// Represents a possibly missing [`Expr`].
38pub type MaybeExpr = Option<Box<Expr>>;
39
40/// Represents a Welly expression.
41///
42/// Examples:
43/// - `3`
44/// - `"hello"`
45/// - `p.x ** 2 + p.y ** 2`
46/// - `object.method(arg1, arg2)`
47///
48/// In Welly's grammar it is impossible for two `Expr`s to be adjacent.
49/// Therefore, we can make all `Expr`s optional without ambiguity.
50/// We do this in the hope of reporting more helpful errors.
51// TODO: Add `Location`s to sub-`Tree`s that need them, including literals,
52// identifiers and `Op`.
53#[derive(Debug)]
54pub enum Expr {
55    /// A literal character value.
56    Char(Loc<char>),
57
58    /// A literal string value.
59    String(Loc<String>),
60
61    /// An identifier or literal number value.
62    Name(Loc<String>),
63
64    /// Comma-separated [`Expr`]s in round brackets.
65    Round(Round),
66
67    /// A function or function type literal.
68    Function(Option<Loc<String>>, Loc<Round>, MaybeExpr, Option<Brace>),
69
70    /// A keyword operator applied to zero, one or two operands.
71    Op(MaybeExpr, Loc<Op>, MaybeExpr),
72
73    /// Field access.
74    Field(MaybeExpr, Loc<String>),
75
76    /// Function or macro call.
77    Call(MaybeExpr, Loc<Round>),
78}
79
80impl Tree for Expr {}
81
82// ----------------------------------------------------------------------------
83
84/// Read and discard [`Whitespace`]s and [`Comment]`s, if possible.
85fn skip(input: &mut Context<impl Stream>) -> Result<(), String> {
86    while input.read::<Whitespace>()?.is_some() || input.read::<Comment>()?.is_some() {
87        input.pop();
88    }
89    Ok(())
90}
91
92/// A [`Parse`] implementation that recognises [`Expr`]s.
93///
94/// The input [`Stream`] can contain [`char`]s, [`CharacterLiteral`]s,
95/// [`StringLiteral`]s, [`Alphanumeric`]s, [`Round`]s, [`Brace`]s,
96/// [`Operator`]s and [`Keyword`]s. In addition, [`Comment`]s and
97/// [`Whitespace`]s are discarded.
98#[derive(Default, Debug)]
99pub struct Parser;
100
101impl Parser {
102    /// Parse a field access, starting after the `.`.
103    fn parse_field(
104        &self,
105        input: &mut Context<impl Stream>,
106    ) -> Result<Box<Alphanumeric>, String> {
107        input.read::<Alphanumeric>()?.ok_or_else(|| MISSING_FIELD.into())
108    }
109
110    /// Parse a function or function type literal, starting after the `fn`.
111    fn parse_function(
112        &self,
113        input: &mut Context<impl Stream>,
114    ) -> Result<Expr, String> {
115        skip(input)?;
116        let name = input.read::<Alphanumeric>()?;
117        let name = name.map(|name| input.locate(name.0));
118        let args = input.read::<Round>()?.ok_or_else(|| MISSING_ARGS)?;
119        let args = input.locate(*args);
120        skip(input)?;
121        let return_type = if let Some(c) = input.read::<char>()? {
122            if *c == ':' {
123                skip(input)?;
124                if let Some(type_name) = input.read::<Alphanumeric>()? {
125                    Some(Box::new(Expr::Name(input.locate(type_name.0))))
126                } else if let Some(round) = input.read::<Round>()? {
127                    Some(Box::new(Expr::Round(*round)))
128                } else {
129                    Err(MISSING_RETURN_TYPE)?
130                }
131            } else {
132                input.unread(c);
133                None
134            }
135        } else {
136            None
137        };
138        skip(input)?;
139        let body = input.read::<Brace>()?.map(|body| *body);
140        Ok(Expr::Function(name, args, return_type, body))
141    }
142}
143
144impl Parse for Parser {
145    fn parse(
146        &self,
147        input: &mut Context<impl Stream>,
148    ) -> Result<Box<dyn Tree>, String> {
149        let mut stack = Stack::default();
150        loop {
151            skip(input)?;
152            if let Some(tree) = input.read::<Alphanumeric>()? {
153                stack.nonfix(Expr::Name(input.locate(tree.0)), input.last());
154            } else if let Some(tree) = input.read::<Round>()? {
155                if stack.has_expr() {
156                    let tree = input.locate(*tree);
157                    stack.postfix(Precedence::MAX, |expr| Expr::Call(expr, tree));
158                } else {
159                    stack.nonfix(Expr::Round(*tree), input.last());
160                }
161            } else if let Some(tree) = input.read::<Operator>()? {
162                stack.op(input.locate(
163                    if stack.has_expr() { tree.with_left } else { tree.without_left }
164                ));
165            } else if let Some(keyword) = input.read::<Keyword>()? {
166                match *keyword {
167                    Keyword::Fn => {
168                        let loc = input.last();
169                        stack.nonfix(self.parse_function(input)?, loc);
170                    },
171                    Keyword::Dot => {
172                        let field = self.parse_field(input)?;
173                        let field = input.locate(field.0);
174                        stack.postfix(Precedence::MAX, |expr| Expr::Field(expr, field));
175                    },
176                }
177            } else if let Some(tree) = input.read::<CharacterLiteral>()? {
178                stack.nonfix(Expr::Char(input.locate(tree.0)), input.last());
179            } else if let Some(tree) = input.read::<StringLiteral>()? {
180                stack.nonfix(Expr::String(input.locate(tree.0)), input.last());
181            } else {
182                break;
183            }
184        }
185        Ok(if let Some(expr) = stack.flush() { expr } else { input.read_any()? })
186    }
187}
188
189// ----------------------------------------------------------------------------
190
191#[cfg(test)]
192mod tests {
193    use super::*;
194    use crate::{parsers, EndOfFile, Characters};
195    use parsers::{Brackets};
196
197    /// Parse a [`Stream`] containing [`Round`]s and [`Brace`]s into [`Expr`]s.
198    fn expr(input: impl Stream) -> impl Stream {
199        Parser.parse_stream(input)
200    }
201
202    /// Parse a [`Stream`] containing [`Brace`]s into [`Round`]s and [`Expr`]s.
203    fn round(input: impl Stream) -> impl Stream {
204        expr(Brackets::new('(', ')', |contents| {
205            let contents = expr(contents.into_iter()).read_all();
206            Round::new(contents)
207        }, input))
208    }
209
210    /// Parse a [`Stream`] into [`Brace`]s, [`Round`]s and [`Expr`]s.
211    fn brace(input: impl Stream) -> impl Stream {
212        round(Brackets::new('{', '}', |contents| {
213            let contents = round(contents.into_iter()).read_all();
214            Brace::new(contents)
215        }, input))
216    }
217
218    /// Parse `source` into a [`Stream`] containing [`Expr`]s.
219    fn parse(source: &'static str) -> impl Stream {
220        let stream = Characters::new(source, true);
221        let stream = parsers::LEXER.parse_stream(stream);
222        let mut word_parser = parsers::Word::default();
223        word_parser.add_keywords::<Operator>();
224        word_parser.add_keywords::<Keyword>();
225        let stream = word_parser.parse_stream(stream);
226        brace(stream)
227    }
228
229    /// Parse `source` into a single [`Expr`].
230    fn parse_one(source: &'static str) -> Box<Expr> {
231        let mut stream = parse(source);
232        let result = match stream.read().result() {
233            Ok(tree) => match tree.downcast::<Expr>() {
234                Ok(tree) => tree,
235                Err(tree) => panic!("Got a non-Expr: {:?}", tree),
236            },
237            Err(e) => panic!("Got error: {:?}", e),
238        };
239        assert_eq!(stream.read(), EndOfFile);
240        result
241    }
242
243    /// Check that `e` is of the form `Some(Expr::Op(left, expected, right))`
244    /// and return `(left, right)`.
245    fn check_op(e: impl Into<MaybeExpr>, expected: Op) -> (MaybeExpr, MaybeExpr) {
246        match *e.into().expect("Missing Expr::Op") {
247            Expr::Op(left, observed, right) => {
248                assert_eq!(observed, expected);
249                (left, right)
250            },
251            e => panic!("Expected an Expr::Op but got {:?}", e),
252        }
253    }
254
255    /// Check that `e` is of the form `Some(Expr::Name(expected))`.
256    fn check_name(e: impl Into<MaybeExpr>, expected: &'static str) {
257        match *e.into().expect("Missing Expr::Name") {
258            Expr::Name(observed) => assert_eq!(observed, expected),
259            e => panic!("Expected an Expr::Name but got {:?}", e),
260        }
261    }
262
263    /// Check that `e` is of the form `Some(Expr::Field(object, expected))`
264    /// and return `object`.
265    fn check_field(e: impl Into<MaybeExpr>, expected: &'static str) -> MaybeExpr {
266        match *e.into().expect("Missing Expr::Field") {
267            Expr::Field(object, observed) => {
268                assert_eq!(observed, expected);
269                object
270            },
271            e => panic!("Expected an Expr::Name but got {:?}", e),
272        }
273    }
274
275    #[test]
276    fn missing() {
277        let tree = parse_one("a b");
278        let (a, b) = check_op(tree, Op::Missing);
279        check_name(a, "a");
280        check_name(b, "b");
281    }
282
283    #[test]
284    fn ergonomics1() {
285        let tree = parse_one("item in low .. high and condition");
286        let (tree, condition) = check_op(tree, Op::BoolAnd);
287        check_name(condition, "condition");
288        let (item, tree) = check_op(tree, Op::In);
289        check_name(item, "item");
290        let (low, high) = check_op(tree, Op::Exclusive);
291        check_name(low, "low");
292        check_name(high, "high");
293    }
294
295    #[test]
296    fn ergonomics2() {
297        let tree = parse_one("0 == x & 1 << 4");
298        let (zero, tree) = check_op(tree, Op::EQ);
299        check_name(zero, "0");
300        let (x, tree) = check_op(tree, Op::BitAnd);
301        check_name(x, "x");
302        let (one, four) = check_op(tree, Op::SL);
303        check_name(one, "1");
304        check_name(four, "4");
305    }
306
307    #[test]
308    fn ergonomics3() {
309        let tree = parse_one("-x ** 2");
310        let (none, tree) = check_op(tree, Op::Minus);
311        assert!(none.is_none());
312        let (x, two) = check_op(tree, Op::Pow);
313        check_name(x, "x");
314        check_name(two, "2");
315    }
316
317    #[test]
318    fn ergonomics4() {
319        let tree = parse_one("x == 1 + y.z");
320        let (x, tree) = check_op(tree, Op::EQ);
321        check_name(x, "x");
322        let (one, tree) = check_op(tree, Op::Add);
323        check_name(one, "1");
324        let y = check_field(tree, "z");
325        check_name(y, "y");
326    }
327
328    #[test]
329    fn ergonomics5() {
330        let tree = parse_one("1 + 2 * 3");
331        let (one, tree) = check_op(tree, Op::Add);
332        check_name(one, "1");
333        let (two, three) = check_op(tree, Op::Mul);
334        check_name(two, "2");
335        check_name(three, "3");
336    }
337
338    #[test]
339    fn ergonomics6() {
340        let tree = parse_one("x + 1 << 4 * y");
341        let (left, right) = check_op(tree, Op::SL);
342        let (x, one) = check_op(left, Op::Add);
343        check_name(x, "x");
344        check_name(one, "1");
345        let (four, y) = check_op(right, Op::Mul);
346        check_name(four, "4");
347        check_name(y, "y");
348    }
349
350    #[test]
351    fn ergonomics7() {
352        let tree = parse_one("low ... high : type");
353        let (low, tree) = check_op(tree, Op::Inclusive);
354        check_name(low, "low");
355        let (high, type_) = check_op(tree, Op::Cast);
356        check_name(high, "high");
357        check_name(type_, "type");
358    }
359
360    #[test]
361    fn ergonomics8() {
362        let tree = parse_one("x: type >= 0");
363        let (tree, zero) = check_op(tree, Op::GE);
364        check_name(zero, "0");
365        let (x, type_) = check_op(tree, Op::Cast);
366        check_name(x, "x");
367        check_name(type_, "type");
368    }
369}