Skip to main content

parser/
expr.rs

1use crate::Stmt;
2use anyhow::{Result, anyhow};
3use dynamic::Dynamic;
4use smol_str::SmolStr;
5
6use super::{Parser, ParserErr, Span, Type, try_parse};
7use num_enum::{FromPrimitive, IntoPrimitive};
8
9#[repr(i32)]
10#[derive(Debug, Clone, PartialEq, IntoPrimitive, FromPrimitive)]
11pub enum UnaryOp {
12    Neg = 0,
13    Not,
14    #[num_enum(default)]
15    Unknow = 255,
16}
17
18#[repr(i32)]
19#[derive(Debug, Clone, PartialEq, IntoPrimitive, FromPrimitive)]
20pub enum BinaryOp {
21    Add = 10,
22    Sub,
23    Mul,
24    Div,
25    Mod,
26    Shr,
27    Shl,
28    BitAnd,
29    BitOr,
30    BitXor,
31    AddAssign,
32    SubAssign,
33    MulAssign,
34    DivAssign,
35    ModAssign,
36    ShrAssign,
37    ShlAssign,
38    BitAndAssign,
39    BitOrAssign,
40    BitXorAssign,
41    Assign,
42    Eq,
43    Ne,
44    Lt,
45    Gt,
46    Le,
47    Ge,
48    And,
49    Or,
50    Idx,
51    RangeOpen,
52    RangeClose,
53    #[num_enum(default)]
54    Unknow = 255,
55}
56
57impl BinaryOp {
58    pub fn is_logic(&self) -> bool {
59        matches!(self, Self::And | Self::Or | Self::Eq | Self::Ne | Self::Lt | Self::Gt | Self::Le | Self::Ge)
60    }
61
62    pub fn is_add(&self) -> bool {
63        matches!(self, Self::Add | Self::AddAssign)
64    }
65
66    pub fn is_arith(&self) -> bool {
67        matches!(
68            self,
69            Self::Sub
70                | Self::Mul
71                | Self::Div
72                | Self::Mod
73                | Self::Shr
74                | Self::Shl
75                | Self::BitAnd
76                | Self::BitOr
77                | Self::BitXor
78                | Self::SubAssign
79                | Self::MulAssign
80                | Self::DivAssign
81                | Self::ModAssign
82                | Self::ShrAssign
83                | Self::ShlAssign
84                | Self::BitAndAssign
85                | Self::BitOrAssign
86                | Self::BitXorAssign
87        )
88    }
89
90    pub fn symbol(&self) -> &'static str {
91        match self {
92            Self::Add => "+",
93            Self::Sub => "-",
94            Self::Mul => "*",
95            Self::Div => "/",
96            Self::Mod => "%",
97            Self::Shl => "<<",
98            Self::Shr => ">>",
99            Self::BitAnd => "&",
100            Self::BitOr => "|",
101            Self::BitXor => "^",
102            Self::AddAssign => "+=",
103            Self::SubAssign => "-=",
104            Self::MulAssign => "*=",
105            Self::DivAssign => "/=",
106            Self::ModAssign => "%=",
107            Self::ShlAssign => "<<=",
108            Self::ShrAssign => ">>=",
109            Self::BitAndAssign => "&=",
110            Self::BitOrAssign => "|=",
111            Self::BitXorAssign => "^=",
112            Self::Assign => "=",
113            Self::Eq => "==",
114            Self::Ne => "!=",
115            Self::Lt => "<",
116            Self::Gt => ">",
117            Self::Le => "<=",
118            Self::Ge => ">=",
119            Self::And => "&&",
120            Self::Or => "||",
121            Self::Idx => "[]",
122            Self::RangeOpen => "..",
123            Self::RangeClose => "..=",
124            Self::Unknow => "?",
125        }
126    }
127
128    pub fn is_assign(&self) -> bool {
129        matches!(
130            self,
131            Self::AddAssign | Self::Assign | Self::DivAssign | Self::ModAssign | Self::MulAssign | Self::SubAssign | Self::BitAndAssign | Self::BitOrAssign | Self::BitXorAssign | Self::ShlAssign | Self::ShrAssign
132        )
133    }
134
135    pub fn weight(&self) -> usize {
136        match self {
137            Self::Idx => 30,
138            Self::Mul | Self::Div | Self::Mod => 20,
139            Self::Add | Self::Sub => 19,
140            Self::Shl | Self::Shr => 18,
141            Self::BitAnd => 17,
142            Self::BitXor => 16,
143            Self::BitOr => 15,
144            Self::Eq | Self::Ne | Self::Lt | Self::Gt | Self::Le | Self::Ge => 10,
145            Self::And | Self::Or => 9,
146            Self::RangeOpen | Self::RangeClose => 5,
147            _ => usize::MIN,
148        }
149    }
150}
151
152#[derive(Debug, Clone)]
153pub struct Expr {
154    pub kind: ExprKind,
155    pub span: Span,
156}
157
158#[derive(Debug, Clone, Default)]
159pub enum ExprKind {
160    #[default]
161    Null,
162    Value(Dynamic),
163    Const(usize),
164    Typed {
165        value: Box<Expr>,
166        ty: Type,
167    },
168    Unary {
169        op: UnaryOp,
170        value: Box<Expr>,
171    },
172    Binary {
173        left: Box<Expr>,
174        op: BinaryOp,
175        right: Box<Expr>,
176    },
177    Ident(SmolStr),
178    Var(u32),
179    Capture(u32),
180    Id(u32, Option<Box<Expr>>),
181    Generic {
182        obj: Box<Expr>,
183        params: Vec<Type>,
184    },
185    Assoc {
186        ty: Type,
187        name: SmolStr,
188    },
189    TypedMethod {
190        obj: Box<Expr>,
191        ty: Type,
192        name: SmolStr,
193    },
194    AssocId {
195        id: u32,
196        params: Vec<Type>,
197    },
198    Tuple(Vec<Expr>),
199    List(Vec<Expr>),
200    Repeat {
201        value: Box<Expr>,
202        len: Type,
203    },
204    Dict(Vec<(SmolStr, Expr)>),
205    Range {
206        start: Box<Expr>,
207        stop: Box<Expr>,
208        inclusive: bool,
209    },
210    Call {
211        obj: Box<Expr>,
212        params: Vec<Expr>,
213    },
214    Stmt(Box<Stmt>),
215    Closure {
216        args: Vec<(SmolStr, Type)>,
217        body: Box<Stmt>,
218    },
219}
220
221#[derive(Debug, thiserror::Error)]
222pub enum ExprErr {
223    #[error("{0} 不是标识符")]
224    NotIdent(SmolStr),
225    #[error("{0} 非原生类型")]
226    NotNative(SmolStr),
227    #[error("期望表达式")]
228    ExpectExpr,
229}
230
231impl Default for Expr {
232    fn default() -> Self {
233        Self::new(ExprKind::Null, Span::default())
234    }
235}
236
237impl From<Dynamic> for Expr {
238    fn from(value: Dynamic) -> Self {
239        Self::new(ExprKind::Value(value), Span::default())
240    }
241}
242
243impl Expr {
244    pub fn new(kind: ExprKind, span: Span) -> Self {
245        Self { kind, span }
246    }
247
248    pub fn with_span(mut self, span: Span) -> Self {
249        self.span = span;
250        self
251    }
252
253    pub fn is_range(&self) -> bool {
254        matches!(self.kind, ExprKind::Range { .. })
255    }
256
257    pub fn is_typed(&self) -> bool {
258        matches!(self.kind, ExprKind::Typed { .. })
259    }
260
261    pub fn get_type(&self) -> Type {
262        match &self.kind {
263            ExprKind::Typed { ty, .. } => ty.clone(),
264            ExprKind::Value(v) => v.get_type(),
265            ExprKind::Unary { value, .. } => value.get_type(),
266            ExprKind::Tuple(list) => Type::Tuple(list.iter().map(|l| l.get_type()).collect()),
267            ExprKind::List(list) => {
268                if list.is_empty() {
269                    return Type::list_any();
270                }
271                let mut elem_ty = Type::Any;
272                for item in list {
273                    let item_ty = item.get_type();
274                    elem_ty = if elem_ty.is_any() { item_ty } else { elem_ty + item_ty };
275                }
276                Type::Array(std::rc::Rc::new(elem_ty), list.len() as u32)
277            }
278            ExprKind::Repeat { value, len } => {
279                if let Type::ConstInt(len) = len {
280                    Type::Array(std::rc::Rc::new(value.get_type()), *len as u32)
281                } else {
282                    Type::ArrayParam(std::rc::Rc::new(value.get_type()), std::rc::Rc::new(len.clone()))
283                }
284            }
285            ExprKind::Range { start, .. } => start.get_type(),
286            ExprKind::Stmt(stmt) => stmt.get_type().unwrap_or(Type::Any),
287            _ => Type::Any,
288        }
289    }
290
291    pub fn id(&self) -> Option<u32> {
292        if let ExprKind::Id(id, _) = &self.kind { Some(*id) } else { None }
293    }
294
295    pub fn var(&self) -> Option<u32> {
296        if let ExprKind::Var(idx) = &self.kind { Some(*idx) } else { None }
297    }
298
299    pub fn ident(&self) -> Result<&str> {
300        if let ExprKind::Ident(ident) = &self.kind { Ok(ident.as_str()) } else { Err(ExprErr::NotIdent(SmolStr::from(format!("{:?}", self))).into()) }
301    }
302
303    pub fn binary_op(&self) -> Option<BinaryOp> {
304        if let ExprKind::Binary { op, .. } = &self.kind { Some(op.clone()) } else { None }
305    }
306
307    pub fn is_idx(&self) -> bool {
308        matches!(&self.kind, ExprKind::Binary { op, .. } if *op == BinaryOp::Idx)
309    }
310
311    pub fn is_value(&self) -> bool {
312        match &self.kind {
313            ExprKind::Value(_) => true,
314            ExprKind::Typed { value, ty } => ty.is_native() && value.is_value(),
315            _ => false,
316        }
317    }
318
319    pub fn is_const(&self) -> bool {
320        matches!(self.kind, ExprKind::Const(_))
321    }
322
323    pub fn value(self) -> Result<Dynamic> {
324        match self.kind {
325            ExprKind::Value(v) => Ok(v),
326            ExprKind::Typed { value, ty } => {
327                if ty.is_native() {
328                    Ok(ty.force(value.value()?)?)
329                } else {
330                    Err(anyhow!("不是 Value"))
331                }
332            }
333            _ => Err(anyhow!("不是 Value")),
334        }
335    }
336
337    pub fn binary(self) -> Option<(Expr, BinaryOp, Expr)> {
338        match self.kind {
339            ExprKind::Binary { left, op, right } => Some((*left, op, *right)),
340            _ => None,
341        }
342    }
343
344    pub fn compact(&self) -> Option<Dynamic> {
345        match &self.kind {
346            ExprKind::Value(v) => Some(v.clone()),
347            ExprKind::Unary { op, value } => {
348                if value.is_value() {
349                    let v = value.clone().value().unwrap();
350                    match op {
351                        UnaryOp::Neg => Some(-v),
352                        UnaryOp::Not => Some(!v),
353                        _ => None,
354                    }
355                } else {
356                    None
357                }
358            }
359            ExprKind::Binary { left, op, right } => {
360                if left.is_value() && right.is_value() {
361                    let left = left.clone().value().unwrap();
362                    let right = right.clone().value().unwrap();
363                    let r = match op {
364                        BinaryOp::Add | BinaryOp::AddAssign => left + right,
365                        BinaryOp::Sub | BinaryOp::SubAssign => left - right,
366                        BinaryOp::Mul | BinaryOp::MulAssign => left * right,
367                        BinaryOp::Div | BinaryOp::DivAssign => left / right,
368                        BinaryOp::Mod | BinaryOp::ModAssign => left % right,
369                        BinaryOp::And => Dynamic::Bool(left.is_true() && right.is_true()),
370                        BinaryOp::Or => Dynamic::Bool(left.is_true() || right.is_true()),
371                        BinaryOp::Eq => Dynamic::Bool(left == right),
372                        BinaryOp::Ne => Dynamic::Bool(left != right),
373                        BinaryOp::Le => Dynamic::Bool(left <= right),
374                        BinaryOp::Lt => Dynamic::Bool(left < right),
375                        BinaryOp::Ge => Dynamic::Bool(left >= right),
376                        BinaryOp::Gt => Dynamic::Bool(left > right),
377                        BinaryOp::Shl | BinaryOp::ShlAssign => left << right,
378                        BinaryOp::Shr | BinaryOp::ShrAssign => left >> right,
379                        BinaryOp::Assign => right,
380                        BinaryOp::BitAnd | BinaryOp::BitAndAssign => left & right,
381                        BinaryOp::BitXor | BinaryOp::BitXorAssign => left ^ right,
382                        BinaryOp::BitOr | BinaryOp::BitOrAssign => left | right,
383                        BinaryOp::Idx => {
384                            if let Some(idx) = right.as_int() {
385                                return left.get_idx(idx as usize);
386                            } else if let Ok(key) = SmolStr::try_from(right) {
387                                return left.get_dynamic(&key);
388                            } else {
389                                return None;
390                            }
391                        }
392                        _ => Dynamic::Null,
393                    };
394                    Some(r)
395                } else {
396                    None
397                }
398            }
399            _ => None,
400        }
401    }
402}
403
404impl Parser {
405    fn is_dict_item_boundary(ch: u8) -> bool {
406        matches!(ch, b',' | b'}')
407    }
408
409    fn is_shorthand_field_name(name: &str) -> bool {
410        name.as_bytes().first().is_some_and(|ch| ch.is_ascii_alphabetic() || *ch == b'_')
411    }
412
413    pub(crate) fn looks_like_dict(&mut self) -> bool {
414        let save_pos = self.pos;
415        let result = (|| -> Result<bool> {
416            self.whitespace()?;
417            if self.take(b'{').is_err() {
418                return Ok(false);
419            }
420            self.whitespace()?;
421            if self.take(b'}').is_ok() {
422                return Ok(true);
423            }
424            if self.ident().is_err() && self.string().is_err() {
425                return Ok(false);
426            }
427            self.whitespace()?;
428            Ok(matches!(self.get(), Ok(b':' | b',' | b'}')))
429        })()
430        .unwrap_or(false);
431        self.pos = save_pos;
432        result
433    }
434
435    pub(crate) fn looks_like_empty_dict(&mut self) -> bool {
436        let save_pos = self.pos;
437        let result = (|| -> Result<bool> {
438            self.whitespace()?;
439            self.take(b'{')?;
440            self.whitespace()?;
441            Ok(self.take(b'}').is_ok())
442        })()
443        .unwrap_or(false);
444        self.pos = save_pos;
445        result
446    }
447
448    fn postfix_expr(&mut self, start: usize, mut expr: Expr) -> Result<Expr> {
449        while !self.is_eof() && [b'.', b'[', b'(', b':'].contains(&self.get()?) {
450            if self.ahead()? == b'.' && self.get()? == b'.' {
451                break;
452            }
453            if self.just("::<").is_ok() {
454                let params = crate::parse_list!(self, Vec::new(), b'>', b',', self.get_type_param()?);
455                self.whitespace()?;
456                if self.just("::").is_ok() {
457                    if params.len() != 1 {
458                        return Err(anyhow!("类型提示只能包含一个类型参数"));
459                    }
460                    let name = self.ident()?;
461                    expr = Expr::new(ExprKind::TypedMethod { obj: Box::new(expr), ty: params[0].clone(), name }, Span::new(start, self.current_pos()));
462                } else {
463                    expr = Expr::new(ExprKind::Generic { obj: Box::new(expr), params }, Span::new(start, self.current_pos()));
464                }
465            } else if self.take(b'.').is_ok() {
466                let key_start = self.current_pos();
467                let key = self.ident()?;
468                let right = Expr::new(ExprKind::Value(Dynamic::String(key)), self.span_from(key_start));
469                let span = expr.span.merge(right.span);
470                expr = Expr::new(ExprKind::Binary { left: Box::new(expr), op: BinaryOp::Idx, right: Box::new(right) }, span);
471            } else if self.take(b'[').is_ok() {
472                let key = self.expr(None, None)?.0;
473                self.until(b']')?;
474                let span = Span::new(start, self.current_pos());
475                expr = Expr::new(ExprKind::Binary { left: Box::new(expr), op: BinaryOp::Idx, right: Box::new(key) }, span);
476            } else if self.take(b'(').is_ok() {
477                let params = crate::parse_list!(self, Vec::new(), b')', b',', self.expr(None, None)?.0);
478                expr = Expr::new(ExprKind::Call { obj: Box::new(expr), params }, Span::new(start, self.current_pos()));
479            } else {
480                break;
481            }
482        }
483        // `as` 紧绑定到刚解析出的原子(优先级高于所有二元运算符),因此
484        // `a + b as i64` 解析为 `a + (b as i64)` 而非 `(a + b) as i64`。
485        // 用 save/restore 包裹,避免在没有 `as` 时吞掉后续空白。
486        loop {
487            let save = self.pos;
488            self.whitespace()?;
489            if self.keyword("as").is_ok() {
490                let ty = self.get_type()?;
491                expr = Expr::new(ExprKind::Typed { value: Box::new(expr), ty }, Span::new(start, self.current_pos()));
492            } else {
493                self.pos = save;
494                break;
495            }
496        }
497        Ok(expr.with_span(Span::new(start, self.current_pos())))
498    }
499
500    fn binary_op(&mut self) -> Option<BinaryOp> {
501        if self.just("<<=").is_ok() {
502            Some(BinaryOp::ShlAssign)
503        } else if self.just(">>=").is_ok() {
504            Some(BinaryOp::ShrAssign)
505        } else if self.just("<<").is_ok() {
506            Some(BinaryOp::Shl)
507        } else if self.just(">>").is_ok() {
508            Some(BinaryOp::Shr)
509        } else if self.just(">=").is_ok() {
510            Some(BinaryOp::Ge)
511        } else if self.just("==").is_ok() {
512            Some(BinaryOp::Eq)
513        } else if self.just("!=").is_ok() {
514            Some(BinaryOp::Ne)
515        } else if self.just("<=").is_ok() {
516            Some(BinaryOp::Le)
517        } else if self.just("&&").is_ok() {
518            Some(BinaryOp::And)
519        } else if self.just("||").is_ok() {
520            Some(BinaryOp::Or)
521        } else if self.just("+=").is_ok() {
522            Some(BinaryOp::AddAssign)
523        } else if self.just("-=").is_ok() {
524            Some(BinaryOp::SubAssign)
525        } else if self.just("*=").is_ok() {
526            Some(BinaryOp::MulAssign)
527        } else if self.just("/=").is_ok() {
528            Some(BinaryOp::DivAssign)
529        } else if self.just("%=").is_ok() {
530            Some(BinaryOp::ModAssign)
531        } else if self.just("&=").is_ok() {
532            Some(BinaryOp::BitAndAssign)
533        } else if self.just("|=").is_ok() {
534            Some(BinaryOp::BitOrAssign)
535        } else if self.just("^=").is_ok() {
536            Some(BinaryOp::BitXorAssign)
537        } else if self.just("..=").is_ok() {
538            Some(BinaryOp::RangeClose)
539        } else if self.just("..").is_ok() {
540            Some(BinaryOp::RangeOpen)
541        } else {
542            match self.get() {
543                Ok(b'+') => {
544                    self.pos += 1;
545                    Some(BinaryOp::Add)
546                }
547                Ok(b'-') => {
548                    self.pos += 1;
549                    Some(BinaryOp::Sub)
550                }
551                Ok(b'*') => {
552                    self.pos += 1;
553                    Some(BinaryOp::Mul)
554                }
555                Ok(b'/') => {
556                    self.pos += 1;
557                    Some(BinaryOp::Div)
558                }
559                Ok(b'%') => {
560                    self.pos += 1;
561                    Some(BinaryOp::Mod)
562                }
563                Ok(b'<') => {
564                    self.pos += 1;
565                    Some(BinaryOp::Lt)
566                }
567                Ok(b'>') => {
568                    self.pos += 1;
569                    Some(BinaryOp::Gt)
570                }
571                Ok(b'=') => {
572                    self.pos += 1;
573                    Some(BinaryOp::Assign)
574                }
575                Ok(b'&') => {
576                    self.pos += 1;
577                    Some(BinaryOp::BitAnd)
578                }
579                Ok(b'|') => {
580                    self.pos += 1;
581                    Some(BinaryOp::BitOr)
582                }
583                Ok(b'^') => {
584                    self.pos += 1;
585                    Some(BinaryOp::BitXor)
586                }
587                _ => None,
588            }
589        }
590    }
591
592    pub fn kv(&mut self) -> Result<(SmolStr, Expr)> {
593        let start = self.current_pos();
594        if let Ok(key) = self.ident() {
595            self.whitespace()?;
596            if self.take(b':').is_ok() {
597                let value = self.expr(None, None)?.0;
598                Ok((SmolStr::from(key), value))
599            } else if Self::is_shorthand_field_name(&key) && self.get().map(Self::is_dict_item_boundary).unwrap_or(false) {
600                let span = Span::new(start, start + key.len());
601                Ok((key.clone(), Expr::new(ExprKind::Ident(key), span)))
602            } else {
603                Err(anyhow!("expect ':' after field name"))
604            }
605        } else if let Ok(key) = self.string() {
606            self.until(b':')?;
607            let value = self.expr(None, None)?.0;
608            Ok((SmolStr::from(key), value))
609        } else {
610            Err(anyhow!("expect string as key"))
611        }
612    }
613
614    pub fn base_expr(&mut self, allow_struct_literal: bool) -> Result<Expr> {
615        self.check_fatal()?;
616        let start = self.current_pos();
617        if let Ok(s) = self.text() {
618            let expr = Expr::new(ExprKind::Value(Dynamic::String(s)), self.span_from(start));
619            self.postfix_expr(start, expr)
620        } else if self.get().map(|c| c.is_ascii_digit()).unwrap_or(false) {
621            // 数字开头一定是数字字面量:解析失败(如越界)直接上抛,
622            // 不要回落到其它产生式而把"超出范围"错误吞成笼统的"期望表达式"。
623            let n = self.number()?;
624            let expr = if let Ok(ty) = self.get_type() {
625                if ty.is_native() {
626                    Expr::new(ExprKind::Typed { value: Box::new(Expr::new(ExprKind::Value(n), self.span_from(start))), ty }, self.span_from(start))
627                } else {
628                    return Err(ExprErr::NotNative(SmolStr::from(format!("{:?}", ty))).into());
629                }
630            } else {
631                Expr::new(ExprKind::Value(n), self.span_from(start))
632            };
633            self.postfix_expr(start, expr)
634        } else if self.keyword("true").is_ok() {
635            let expr = Expr::new(ExprKind::Value(Dynamic::Bool(true)), self.span_from(start));
636            self.postfix_expr(start, expr)
637        } else if self.keyword("false").is_ok() {
638            let expr = Expr::new(ExprKind::Value(Dynamic::Bool(false)), self.span_from(start));
639            self.postfix_expr(start, expr)
640        } else if self.keyword("null").is_ok() {
641            let expr = Expr::new(ExprKind::Value(Dynamic::Null), self.span_from(start));
642            self.postfix_expr(start, expr)
643        } else if let Ok(ident) = self.ident() {
644            self.whitespace()?;
645            let save_pos = self.pos;
646            if self.take(b'<').is_ok() {
647                let typed_literal = (|| -> Result<Expr> {
648                    let type_params = crate::parse_list!(self, Vec::new(), b'>', b',', self.get_type_param()?);
649                    self.whitespace()?;
650                    if self.just("::").is_ok() {
651                        let name = self.ident()?;
652                        let expr = Expr::new(ExprKind::Assoc { ty: Type::Ident { name: ident.clone(), params: type_params }, name }, self.span_from(start));
653                        return self.postfix_expr(start, expr);
654                    }
655                    if allow_struct_literal
656                        && self.looks_like_dict()
657                        && let Ok(b'{') = self.get()
658                        && let Ok(dict) = try_parse!(self, self.dict())
659                    {
660                        return Ok(Expr::new(ExprKind::Typed { value: Box::new(dict), ty: Type::Ident { name: ident.clone(), params: type_params } }, self.span_from(start)));
661                    }
662                    Err(ExprErr::ExpectExpr.into())
663                })();
664                if let Ok(expr) = typed_literal {
665                    return Ok(expr);
666                }
667                self.pos = save_pos;
668            }
669            if allow_struct_literal
670                && self.looks_like_dict()
671                && let Ok(b'{') = self.get()
672                && let Ok(dict) = try_parse!(self, self.dict())
673            {
674                return Ok(Expr::new(ExprKind::Typed { value: Box::new(dict), ty: Type::Ident { name: ident, params: Vec::new() } }, self.span_from(start)));
675            }
676            self.postfix_expr(start, Expr::new(ExprKind::Ident(ident), self.span_from(start)))
677        } else {
678            Err(ExprErr::ExpectExpr.into())
679        }
680    }
681
682    pub(crate) fn dict(&mut self) -> Result<Expr> {
683        let start = self.current_pos();
684        self.pos += 1;
685        Ok(Expr::new(ExprKind::Dict(crate::parse_list!(self, Vec::new(), b'}', b',', self.kv()?)), self.span_from(start)))
686    }
687
688    fn static_dynamic_literal_expr(&mut self) -> Result<Expr> {
689        let start = self.current_pos();
690        let value = self.static_dynamic_value()?;
691        Ok(Expr::new(ExprKind::Value(value), self.span_from(start)))
692    }
693
694    fn static_dynamic_value(&mut self) -> Result<Dynamic> {
695        self.whitespace()?;
696        if self.get()? == b'[' {
697            return self.static_dynamic_list();
698        }
699        if self.get()? == b'{' {
700            return self.static_dynamic_map();
701        }
702        if self.take(b'-').is_ok() {
703            return Ok(-self.number()?);
704        }
705        if let Ok(text) = self.text() {
706            return Ok(Dynamic::String(text));
707        }
708        if let Ok(number) = self.number() {
709            return Ok(number);
710        }
711        if self.keyword("true").is_ok() {
712            return Ok(Dynamic::Bool(true));
713        }
714        if self.keyword("false").is_ok() {
715            return Ok(Dynamic::Bool(false));
716        }
717        if self.keyword("null").is_ok() {
718            return Ok(Dynamic::Null);
719        }
720        Err(ExprErr::ExpectExpr.into())
721    }
722
723    fn static_dynamic_list(&mut self) -> Result<Dynamic> {
724        self.take(b'[')?;
725        let mut values = Vec::new();
726        loop {
727            self.whitespace()?;
728            if self.take(b']').is_ok() {
729                break;
730            }
731            values.push(self.static_dynamic_value()?);
732            self.whitespace()?;
733            if self.take(b',').is_ok() {
734                continue;
735            }
736            self.until(b']')?;
737            break;
738        }
739        Ok(Dynamic::list(values))
740    }
741
742    fn static_dynamic_map(&mut self) -> Result<Dynamic> {
743        self.take(b'{')?;
744        let mut values = std::collections::BTreeMap::new();
745        loop {
746            self.whitespace()?;
747            if self.take(b'}').is_ok() {
748                break;
749            }
750            let key = if let Ok(key) = self.ident() { key } else { self.string()? };
751            self.until(b':')?;
752            let value = self.static_dynamic_value()?;
753            values.insert(key, value);
754            self.whitespace()?;
755            if self.take(b',').is_ok() {
756                continue;
757            }
758            self.until(b'}')?;
759            break;
760        }
761        Ok(Dynamic::map(values))
762    }
763
764    pub fn get_expr(&mut self) -> Result<Expr> {
765        self.expr(None, None).map(|(e, _)| e)
766    }
767
768    pub fn get_expr_without_struct_literal(&mut self) -> Result<Expr> {
769        self.expr_with_min_weight(None, None, 0, false).map(|(e, _)| e)
770    }
771
772    /// 类似 `get_expr_without_struct_literal`,但额外排除赋值类运算符
773    /// (`=`, `+=`, `-=` …)以便在 `match` arm body / guard 中 `=>` 不被吞成 `Assign`。
774    pub fn get_expr_no_assign(&mut self) -> Result<Expr> {
775        self.expr_with_min_weight(None, None, 1, false).map(|(e, _)| e)
776    }
777
778    pub fn expr(&mut self, left: Option<(Expr, bool)>, left_op: Option<BinaryOp>) -> Result<(Expr, bool)> {
779        self.expr_with_min_weight(left, left_op, 0, true)
780    }
781
782    fn expr_with_min_weight(&mut self, left: Option<(Expr, bool)>, left_op: Option<BinaryOp>, min_weight: usize, allow_struct_literal: bool) -> Result<(Expr, bool)> {
783        self.check_fatal()?;
784        self.enter_depth()?;
785        let result = self.expr_with_min_weight_inner(left, left_op, min_weight, allow_struct_literal);
786        self.exit_depth();
787        result
788    }
789
790    fn expr_with_min_weight_inner(&mut self, left: Option<(Expr, bool)>, left_op: Option<BinaryOp>, min_weight: usize, allow_struct_literal: bool) -> Result<(Expr, bool)> {
791        self.whitespace()?;
792        if self.is_eof() {
793            return left.ok_or_else(|| ParserErr::at("左操作数缺失", self.current_pos()).into());
794        }
795        let start = self.current_pos();
796        let ch = self.get()?;
797        let mut expr = if ch == b'(' {
798            let start = self.current_pos();
799            self.pos += 1;
800            self.whitespace()?;
801            if self.take(b')').is_ok() {
802                let expr = Expr::new(ExprKind::Tuple(Vec::new()), Span::new(start, self.current_pos()));
803                return Ok((self.postfix_expr(start, expr)?, true));
804            }
805            let (e, _closed) = self.expr_with_min_weight(None, None, 0, true)?;
806            self.whitespace()?;
807            if self.get()? == b',' {
808                self.pos += 1;
809                let list = crate::parse_list!(self, vec![e], b')', b',', self.expr_with_min_weight(None, None, 0, true)?.0);
810                let expr = Expr::new(ExprKind::Tuple(list), Span::new(start, self.current_pos()));
811                Ok((self.postfix_expr(start, expr)?, true))
812            } else {
813                self.until(b')')?;
814                let expr = e.with_span(Span::new(start, self.current_pos()));
815                Ok((self.postfix_expr(start, expr)?, true))
816            }
817        } else if ch == b'!' && self.ahead().map(|a| a != b'=').unwrap_or(true) {
818            let start = self.current_pos();
819            self.pos += 1;
820            let value = self.expr_with_min_weight(None, None, BinaryOp::Mul.weight() + 1, allow_struct_literal)?.0;
821            Ok((Expr::new(ExprKind::Unary { op: UnaryOp::Not, value: Box::new(value) }, Span::new(start, self.current_pos())), false))
822        } else if ch == b'-' && self.ahead().map(|a| a != b'=').unwrap_or(true) && (left.is_none() || (left.is_some() && left_op.is_some())) {
823            let start = self.current_pos();
824            self.pos += 1;
825            let value = self.expr_with_min_weight(None, None, BinaryOp::Mul.weight() + 1, allow_struct_literal)?.0;
826            Ok((Expr::new(ExprKind::Unary { op: UnaryOp::Neg, value: Box::new(value) }, Span::new(start, self.current_pos())), false))
827        } else if ch == b'[' {
828            if let Ok(expr) = try_parse!(self, self.static_dynamic_literal_expr()) {
829                Ok((self.postfix_expr(start, expr)?, false))
830            } else {
831                let start = self.current_pos();
832                self.pos += 1;
833                self.whitespace()?;
834                if self.take(b']').is_ok() {
835                    let expr = Expr::new(ExprKind::List(Vec::new()), Span::new(start, self.current_pos()));
836                    Ok((self.postfix_expr(start, expr)?, false))
837                } else {
838                    let first = self.expr_with_min_weight(None, None, 0, true)?.0;
839                    self.whitespace()?;
840                    if self.take(b';').is_ok() {
841                        let len = self.get_type_param()?;
842                        self.until(b']')?;
843                        let expr = Expr::new(ExprKind::Repeat { value: Box::new(first), len }, Span::new(start, self.current_pos()));
844                        Ok((self.postfix_expr(start, expr)?, false))
845                    } else {
846                        let mut items = vec![first];
847                        let mut closed = false;
848                        while self.take(b',').is_ok() {
849                            self.whitespace()?;
850                            if self.take(b']').is_ok() {
851                                closed = true;
852                                break;
853                            }
854                            items.push(self.expr_with_min_weight(None, None, 0, true)?.0);
855                            self.whitespace()?;
856                        }
857                        if !closed {
858                            self.until(b']')?;
859                        }
860                        let expr = Expr::new(ExprKind::List(items), Span::new(start, self.current_pos()));
861                        Ok((self.postfix_expr(start, expr)?, false))
862                    }
863                }
864            }
865        } else if ch == b'{'
866            && (left.is_none() || left_op.is_some())
867            && let Ok(expr) = try_parse!(self, self.static_dynamic_literal_expr())
868        {
869            Ok((self.postfix_expr(start, expr)?, false))
870        } else if ch == b'{'
871            && (left.is_none() || left_op.is_some())
872            && let Ok(dict) = try_parse!(self, self.dict())
873        {
874            Ok((self.postfix_expr(start, dict)?, false))
875        } else if (left.is_none() || left_op.is_some()) && self.keyword("if").is_ok() {
876            let stmt = self.if_block()?;
877            Ok((Expr::new(ExprKind::Stmt(Box::new(stmt)), Span::new(start, self.current_pos())), true))
878        } else if (left.is_none() || left_op.is_some()) && self.keyword("match").is_ok() {
879            let stmt = self.match_block(start)?;
880            Ok((Expr::new(ExprKind::Stmt(Box::new(stmt)), Span::new(start, self.current_pos())), true))
881        } else if ch == b'|' && left.is_none() {
882            let start = self.current_pos();
883            self.pos += 1;
884            let args = crate::parse_list!(self, Vec::new(), b'|', b',', self.ident_typed()?);
885            let body = Box::new(self.function_body(&args)?);
886            let expr = Expr::new(ExprKind::Closure { args, body }, Span::new(start, self.current_pos()));
887            Ok((self.postfix_expr(start, expr)?, true))
888        } else if let Some(this_op) = self.binary_op() {
889            let (left, close) = left.ok_or(anyhow!("{:?} need left value", this_op))?;
890            if this_op == BinaryOp::RangeOpen {
891                self.whitespace()?;
892                if self.get()? == b']' {
893                    let span = Span::new(left.span.start, self.current_pos());
894                    let stop = Expr::new(ExprKind::Value(Dynamic::Null), Span::empty(self.current_pos()));
895                    return Ok((Expr::new(ExprKind::Range { start: Box::new(left), stop: Box::new(stop), inclusive: false }, span), false));
896                }
897            }
898            if this_op.weight() < min_weight {
899                self.pos = start;
900                return Ok((left, close));
901            }
902            // range 的上界要按完整子表达式解析(优先级降到 range 之上),
903            // 否则 `0 .. n * 2` 只会把 `n` 当上界,`* 2` 反而套在整个 range 外面。
904            if matches!(this_op, BinaryOp::RangeOpen | BinaryOp::RangeClose) {
905                let stop = self.expr_with_min_weight(None, None, this_op.weight() + 1, allow_struct_literal)?.0;
906                let span = left.span.merge(stop.span);
907                let inclusive = this_op == BinaryOp::RangeClose;
908                let range = Expr::new(ExprKind::Range { start: Box::new(left), stop: Box::new(stop), inclusive }, span);
909                return self.expr_with_min_weight(Some((range, false)), None, min_weight, allow_struct_literal);
910            }
911            // 赋值右结合:右侧按完整表达式解析,min_weight 取赋值自身权重(0),
912            // 使得 `a = b = c` 解析为 `a = (b = c)`、`a = b + c` 为 `a = (b + c)`。
913            if this_op.is_assign() {
914                let rhs = self.expr_with_min_weight(None, None, this_op.weight(), allow_struct_literal)?.0;
915                let span = left.span.merge(rhs.span);
916                let expr = Expr::new(ExprKind::Binary { left: Box::new(left), op: this_op, right: Box::new(rhs) }, span);
917                return self.expr_with_min_weight(Some((expr, false)), None, min_weight, allow_struct_literal);
918            }
919            if left_op.is_some() {
920                return Err(anyhow!("unexpected binary op {:?}", this_op));
921            }
922            return if !close && left.binary_op().map(|op| op.weight() < this_op.weight()).unwrap_or(false) {
923                let (binary_left, op, right) = left.binary().unwrap();
924                let this_weight = this_op.weight();
925                let new_right = self.expr_with_min_weight(Some((right, false)), Some(this_op), this_weight, allow_struct_literal)?.0;
926                let span = binary_left.span.merge(new_right.span);
927                let expr = Expr::new(ExprKind::Binary { left: Box::new(binary_left), op, right: Box::new(new_right) }, span);
928                self.expr_with_min_weight(Some((expr, false)), None, min_weight, allow_struct_literal)
929            } else {
930                self.expr_with_min_weight(Some((left, false)), Some(this_op), min_weight, allow_struct_literal)
931            };
932        } else {
933            // 注:`as` 现在由 postfix_expr 紧绑定到原子处理,不再在二元位置兜底。
934            self.base_expr(allow_struct_literal).map(|e| (e, false))
935        };
936
937        if left.is_some() {
938            if let Some(op) = left_op {
939                let left = left.unwrap().0;
940                let right = expr?.0;
941                let span = left.span.merge(right.span);
942                expr = Ok((
943                    match op {
944                        BinaryOp::RangeOpen => Expr::new(ExprKind::Range { start: Box::new(left), stop: Box::new(right), inclusive: false }, span),
945                        BinaryOp::RangeClose => Expr::new(ExprKind::Range { start: Box::new(left), stop: Box::new(right), inclusive: true }, span),
946                        _ => Expr::new(ExprKind::Binary { left: Box::new(left), op, right: Box::new(right) }, span),
947                    },
948                    false,
949                ));
950            } else if expr.is_ok() {
951                return Err(anyhow!("unexpected {:?}", expr));
952            } else {
953                return Ok((left.unwrap().0, false));
954            }
955        }
956        let result = self.expr_with_min_weight(Some(expr?), None, min_weight, allow_struct_literal)?;
957        Ok(result)
958    }
959}