duskphantom_frontend/parse/
expr.rs

1// Copyright 2024 Duskphantom Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// SPDX-License-Identifier: Apache-2.0
16
17use crate::gen_lrec_binary;
18
19use super::*;
20
21/// Parse a vector of Expr.
22pub fn vec_expr(input: &mut &str) -> PResult<Vec<Expr>> {
23    separated(0.., expr, token(",")).parse_next(input)
24}
25
26/// Parse a box of Expr.
27/// Like an `expr`, but returns the boxed version.
28pub fn box_expr(input: &mut &str) -> PResult<Box<Expr>> {
29    expr.map(Box::new).parse_next(input)
30}
31
32/// Parse prefix expressions like `!x->y.z`.
33pub fn prefix(input: &mut &str) -> PResult<Expr> {
34    let disp = dispatch! { peek(any);
35        '{' => curly(separated(0.., expr, token(","))).map(Expr::Array),
36        '.' | '0'..='9' => pad(constant_number),
37        '"' => pad(string_lit).map(Expr::String),
38        '(' => paren(expr),
39        _ => fail,
40    };
41    let atom = alt((disp, pad(ident).map(Expr::Var)));
42
43    // Postfix: `head[a].b(c)->d`.
44    // Tail parsers return mutation on `head`.
45    // Closures should be wrapped in `BoxF` for equal sizes.
46    // Wrapping all closures with `BoxF` can also fix type inference problems,
47    // because all closures have unique types, making `alt` report errors.
48    let postfix_tail = dispatch! { peek(any);
49        '[' => bracket(box_expr).map(|x| BoxF::new(|acc| Expr::Index(acc, x))),
50        '(' => paren(vec_expr).map(|x| BoxF::new(|acc| Expr::Call(acc, x))),
51        _ => fail,
52    };
53    let postfix = lrec(atom, repeat(0.., postfix_tail));
54
55    // Prefix unary operator.
56    let prefix_init = unary_op.map(|op| BoxF::new(|acc| Expr::Unary(op, acc)));
57    rrec(repeat(0.., prefix_init), postfix).parse_next(input)
58}
59
60// Generate parser for each level of expressions,
61// featuring binary operators.
62gen_lrec_binary!(binary_lv0, binary_op_lv0, prefix);
63gen_lrec_binary!(binary_lv1, binary_op_lv1, binary_lv0);
64gen_lrec_binary!(binary_lv2, binary_op_lv2, binary_lv1);
65gen_lrec_binary!(binary_lv3, binary_op_lv3, binary_lv2);
66gen_lrec_binary!(binary_lv4, binary_op_lv4, binary_lv3);
67gen_lrec_binary!(binary_lv5, binary_op_lv5, binary_lv4);
68gen_lrec_binary!(binary_lv6, binary_op_lv6, binary_lv5);
69gen_lrec_binary!(binary_lv7, binary_op_lv7, binary_lv6);
70gen_lrec_binary!(binary_lv8, binary_op_lv8, binary_lv7);
71gen_lrec_binary!(binary_lv9, binary_op_lv9, binary_lv8);
72
73/// Parse a conditional expression.
74pub fn expr(input: &mut &str) -> PResult<Expr> {
75    binary_lv9.parse_next(input)
76}