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        // 修复:支持 Unicode 首字符。原先只看首字节是否是 ASCII 字母或下划线,
411        // 中文等合法 Unicode ident 不能用作 dict 简写 (`{ 中文key }` 被当成 block)。
412        // ident 的合法性由 `Parser::ident()` 整体保证,这里只要保证"非空且首字符
413        // 是合法的 ident 首字符"即可。用 `chars().next()` 取第一个字符,而不是
414        // 直接看首字节。
415        name.chars().next().is_some_and(|ch| ch == '_' || ch.is_alphabetic())
416    }
417
418    pub(crate) fn looks_like_dict(&mut self) -> bool {
419        let save_pos = self.pos;
420        let result = (|| -> Result<bool> {
421            self.whitespace()?;
422            if self.take(b'{').is_err() {
423                return Ok(false);
424            }
425            self.whitespace()?;
426            if self.take(b'}').is_ok() {
427                return Ok(true);
428            }
429            if self.ident().is_err() && self.string().is_err() {
430                return Ok(false);
431            }
432            self.whitespace()?;
433            Ok(matches!(self.get(), Ok(b':' | b',' | b'}')))
434        })()
435        .unwrap_or(false);
436        self.pos = save_pos;
437        result
438    }
439
440    pub(crate) fn looks_like_empty_dict(&mut self) -> bool {
441        let save_pos = self.pos;
442        let result = (|| -> Result<bool> {
443            self.whitespace()?;
444            self.take(b'{')?;
445            self.whitespace()?;
446            Ok(self.take(b'}').is_ok())
447        })()
448        .unwrap_or(false);
449        self.pos = save_pos;
450        result
451    }
452
453    fn postfix_expr(&mut self, start: usize, mut expr: Expr) -> Result<Expr> {
454        while !self.is_eof() && [b'.', b'[', b'(', b':'].contains(&self.get()?) {
455            if self.ahead()? == b'.' && self.get()? == b'.' {
456                break;
457            }
458            if self.just("::<").is_ok() {
459                let params = crate::parse_list!(self, Vec::new(), b'>', b',', self.get_type_param()?);
460                self.whitespace()?;
461                if self.just("::").is_ok() {
462                    if params.len() != 1 {
463                        return Err(anyhow!("类型提示只能包含一个类型参数"));
464                    }
465                    let name = self.ident()?;
466                    expr = Expr::new(ExprKind::TypedMethod { obj: Box::new(expr), ty: params[0].clone(), name }, Span::new(start, self.current_pos()));
467                } else {
468                    expr = Expr::new(ExprKind::Generic { obj: Box::new(expr), params }, Span::new(start, self.current_pos()));
469                }
470            } else if self.take(b'.').is_ok() {
471                let key_start = self.current_pos();
472                let key = self.ident()?;
473                let right = Expr::new(ExprKind::Value(Dynamic::String(key)), self.span_from(key_start));
474                let span = expr.span.merge(right.span);
475                expr = Expr::new(ExprKind::Binary { left: Box::new(expr), op: BinaryOp::Idx, right: Box::new(right) }, span);
476            } else if self.take(b'[').is_ok() {
477                let key = self.expr(None, None)?.0;
478                self.until(b']')?;
479                let span = Span::new(start, self.current_pos());
480                expr = Expr::new(ExprKind::Binary { left: Box::new(expr), op: BinaryOp::Idx, right: Box::new(key) }, span);
481            } else if self.take(b'(').is_ok() {
482                let params = crate::parse_list!(self, Vec::new(), b')', b',', self.expr(None, None)?.0);
483                expr = Expr::new(ExprKind::Call { obj: Box::new(expr), params }, Span::new(start, self.current_pos()));
484            } else {
485                break;
486            }
487        }
488        // `as` 紧绑定到刚解析出的原子(优先级高于所有二元运算符),因此
489        // `a + b as i64` 解析为 `a + (b as i64)` 而非 `(a + b) as i64`。
490        // 用 save/restore 包裹,避免在没有 `as` 时吞掉后续空白。
491        loop {
492            let save = self.pos;
493            self.whitespace()?;
494            if self.keyword("as").is_ok() {
495                let ty = self.get_type()?;
496                expr = Expr::new(ExprKind::Typed { value: Box::new(expr), ty }, Span::new(start, self.current_pos()));
497            } else {
498                self.pos = save;
499                break;
500            }
501        }
502        Ok(expr.with_span(Span::new(start, self.current_pos())))
503    }
504
505    fn binary_op(&mut self) -> Option<BinaryOp> {
506        if self.just("<<=").is_ok() {
507            Some(BinaryOp::ShlAssign)
508        } else if self.just(">>=").is_ok() {
509            Some(BinaryOp::ShrAssign)
510        } else if self.just("<<").is_ok() {
511            Some(BinaryOp::Shl)
512        } else if self.just(">>").is_ok() {
513            Some(BinaryOp::Shr)
514        } else if self.just(">=").is_ok() {
515            Some(BinaryOp::Ge)
516        } else if self.just("==").is_ok() {
517            Some(BinaryOp::Eq)
518        } else if self.just("!=").is_ok() {
519            Some(BinaryOp::Ne)
520        } else if self.just("<=").is_ok() {
521            Some(BinaryOp::Le)
522        } else if self.just("&&").is_ok() {
523            Some(BinaryOp::And)
524        } else if self.just("||").is_ok() {
525            Some(BinaryOp::Or)
526        } else if self.just("+=").is_ok() {
527            Some(BinaryOp::AddAssign)
528        } else if self.just("-=").is_ok() {
529            Some(BinaryOp::SubAssign)
530        } else if self.just("*=").is_ok() {
531            Some(BinaryOp::MulAssign)
532        } else if self.just("/=").is_ok() {
533            Some(BinaryOp::DivAssign)
534        } else if self.just("%=").is_ok() {
535            Some(BinaryOp::ModAssign)
536        } else if self.just("&=").is_ok() {
537            Some(BinaryOp::BitAndAssign)
538        } else if self.just("|=").is_ok() {
539            Some(BinaryOp::BitOrAssign)
540        } else if self.just("^=").is_ok() {
541            Some(BinaryOp::BitXorAssign)
542        } else if self.just("..=").is_ok() {
543            Some(BinaryOp::RangeClose)
544        } else if self.just("..").is_ok() {
545            Some(BinaryOp::RangeOpen)
546        } else {
547            match self.get() {
548                Ok(b'+') => {
549                    self.pos += 1;
550                    Some(BinaryOp::Add)
551                }
552                Ok(b'-') => {
553                    self.pos += 1;
554                    Some(BinaryOp::Sub)
555                }
556                Ok(b'*') => {
557                    self.pos += 1;
558                    Some(BinaryOp::Mul)
559                }
560                Ok(b'/') => {
561                    self.pos += 1;
562                    Some(BinaryOp::Div)
563                }
564                Ok(b'%') => {
565                    self.pos += 1;
566                    Some(BinaryOp::Mod)
567                }
568                Ok(b'<') => {
569                    self.pos += 1;
570                    Some(BinaryOp::Lt)
571                }
572                Ok(b'>') => {
573                    self.pos += 1;
574                    Some(BinaryOp::Gt)
575                }
576                Ok(b'=') => {
577                    self.pos += 1;
578                    Some(BinaryOp::Assign)
579                }
580                Ok(b'&') => {
581                    self.pos += 1;
582                    Some(BinaryOp::BitAnd)
583                }
584                Ok(b'|') => {
585                    self.pos += 1;
586                    Some(BinaryOp::BitOr)
587                }
588                Ok(b'^') => {
589                    self.pos += 1;
590                    Some(BinaryOp::BitXor)
591                }
592                _ => None,
593            }
594        }
595    }
596
597    pub fn kv(&mut self) -> Result<(SmolStr, Expr)> {
598        let start = self.current_pos();
599        if let Ok(key) = self.ident() {
600            self.whitespace()?;
601            if self.take(b':').is_ok() {
602                let value = self.expr(None, None)?.0;
603                Ok((SmolStr::from(key), value))
604            } else if Self::is_shorthand_field_name(&key) && self.get().map(Self::is_dict_item_boundary).unwrap_or(false) {
605                let span = Span::new(start, start + key.len());
606                Ok((key.clone(), Expr::new(ExprKind::Ident(key), span)))
607            } else {
608                Err(anyhow!("expect ':' after field name"))
609            }
610        } else if let Ok(key) = self.string() {
611            self.until(b':')?;
612            let value = self.expr(None, None)?.0;
613            Ok((SmolStr::from(key), value))
614        } else {
615            Err(anyhow!("expect string as key"))
616        }
617    }
618
619    pub fn base_expr(&mut self, allow_struct_literal: bool) -> Result<Expr> {
620        self.check_fatal()?;
621        let start = self.current_pos();
622        if let Ok(s) = self.text() {
623            let expr = Expr::new(ExprKind::Value(Dynamic::String(s)), self.span_from(start));
624            self.postfix_expr(start, expr)
625        } else if self.get().map(|c| c.is_ascii_digit()).unwrap_or(false) {
626            // 数字开头一定是数字字面量:解析失败(如越界)直接上抛,
627            // 不要回落到其它产生式而把"超出范围"错误吞成笼统的"期望表达式"。
628            let n = self.number()?;
629            let expr = if let Ok(ty) = self.get_type() {
630                if ty.is_native() {
631                    Expr::new(ExprKind::Typed { value: Box::new(Expr::new(ExprKind::Value(n), self.span_from(start))), ty }, self.span_from(start))
632                } else {
633                    return Err(ExprErr::NotNative(SmolStr::from(format!("{:?}", ty))).into());
634                }
635            } else {
636                Expr::new(ExprKind::Value(n), self.span_from(start))
637            };
638            self.postfix_expr(start, expr)
639        } else if self.keyword("true").is_ok() {
640            let expr = Expr::new(ExprKind::Value(Dynamic::Bool(true)), self.span_from(start));
641            self.postfix_expr(start, expr)
642        } else if self.keyword("false").is_ok() {
643            let expr = Expr::new(ExprKind::Value(Dynamic::Bool(false)), self.span_from(start));
644            self.postfix_expr(start, expr)
645        } else if self.keyword("null").is_ok() {
646            let expr = Expr::new(ExprKind::Value(Dynamic::Null), self.span_from(start));
647            self.postfix_expr(start, expr)
648        } else if let Ok(ident) = self.ident() {
649            self.whitespace()?;
650            let save_pos = self.pos;
651            if self.take(b'<').is_ok() {
652                let typed_literal = (|| -> Result<Expr> {
653                    let type_params = crate::parse_list!(self, Vec::new(), b'>', b',', self.get_type_param()?);
654                    self.whitespace()?;
655                    if self.just("::").is_ok() {
656                        let name = self.ident()?;
657                        let expr = Expr::new(ExprKind::Assoc { ty: Type::Ident { name: ident.clone(), params: type_params }, name }, self.span_from(start));
658                        return self.postfix_expr(start, expr);
659                    }
660                    if allow_struct_literal
661                        && self.looks_like_dict()
662                        && let Ok(b'{') = self.get()
663                        && let Ok(dict) = try_parse!(self, self.dict())
664                    {
665                        return Ok(Expr::new(ExprKind::Typed { value: Box::new(dict), ty: Type::Ident { name: ident.clone(), params: type_params } }, self.span_from(start)));
666                    }
667                    Err(ExprErr::ExpectExpr.into())
668                })();
669                if let Ok(expr) = typed_literal {
670                    return Ok(expr);
671                }
672                self.pos = save_pos;
673            }
674            if allow_struct_literal
675                && self.looks_like_dict()
676                && let Ok(b'{') = self.get()
677                && let Ok(dict) = try_parse!(self, self.dict())
678            {
679                return Ok(Expr::new(ExprKind::Typed { value: Box::new(dict), ty: Type::Ident { name: ident, params: Vec::new() } }, self.span_from(start)));
680            }
681            self.postfix_expr(start, Expr::new(ExprKind::Ident(ident), self.span_from(start)))
682        } else {
683            Err(ExprErr::ExpectExpr.into())
684        }
685    }
686
687    pub(crate) fn dict(&mut self) -> Result<Expr> {
688        let start = self.current_pos();
689        self.pos += 1;
690        Ok(Expr::new(ExprKind::Dict(crate::parse_list!(self, Vec::new(), b'}', b',', self.kv()?)), self.span_from(start)))
691    }
692
693    fn static_dynamic_literal_expr(&mut self) -> Result<Expr> {
694        let start = self.current_pos();
695        let value = self.static_dynamic_value()?;
696        Ok(Expr::new(ExprKind::Value(value), self.span_from(start)))
697    }
698
699    fn static_dynamic_value(&mut self) -> Result<Dynamic> {
700        self.whitespace()?;
701        if self.get()? == b'[' {
702            return self.static_dynamic_list();
703        }
704        if self.get()? == b'{' {
705            return self.static_dynamic_map();
706        }
707        if self.take(b'-').is_ok() {
708            return Ok(-self.number()?);
709        }
710        if let Ok(text) = self.text() {
711            return Ok(Dynamic::String(text));
712        }
713        if let Ok(number) = self.number() {
714            return Ok(number);
715        }
716        if self.keyword("true").is_ok() {
717            return Ok(Dynamic::Bool(true));
718        }
719        if self.keyword("false").is_ok() {
720            return Ok(Dynamic::Bool(false));
721        }
722        if self.keyword("null").is_ok() {
723            return Ok(Dynamic::Null);
724        }
725        Err(ExprErr::ExpectExpr.into())
726    }
727
728    fn static_dynamic_list(&mut self) -> Result<Dynamic> {
729        self.take(b'[')?;
730        let mut values = Vec::new();
731        loop {
732            self.whitespace()?;
733            if self.take(b']').is_ok() {
734                break;
735            }
736            values.push(self.static_dynamic_value()?);
737            self.whitespace()?;
738            if self.take(b',').is_ok() {
739                continue;
740            }
741            self.until(b']')?;
742            break;
743        }
744        Ok(Dynamic::list(values))
745    }
746
747    fn static_dynamic_map(&mut self) -> Result<Dynamic> {
748        self.take(b'{')?;
749        let mut values = std::collections::BTreeMap::new();
750        loop {
751            self.whitespace()?;
752            if self.take(b'}').is_ok() {
753                break;
754            }
755            let key = if let Ok(key) = self.ident() { key } else { self.string()? };
756            self.until(b':')?;
757            let value = self.static_dynamic_value()?;
758            values.insert(key, value);
759            self.whitespace()?;
760            if self.take(b',').is_ok() {
761                continue;
762            }
763            self.until(b'}')?;
764            break;
765        }
766        Ok(Dynamic::map(values))
767    }
768
769    pub fn get_expr(&mut self) -> Result<Expr> {
770        self.expr(None, None).map(|(e, _)| e)
771    }
772
773    pub fn get_expr_without_struct_literal(&mut self) -> Result<Expr> {
774        self.expr_with_min_weight(None, None, 0, false).map(|(e, _)| e)
775    }
776
777    /// 类似 `get_expr_without_struct_literal`,但额外排除赋值类运算符
778    /// (`=`, `+=`, `-=` …)以便在 `match` arm body / guard 中 `=>` 不被吞成 `Assign`。
779    pub fn get_expr_no_assign(&mut self) -> Result<Expr> {
780        self.expr_with_min_weight(None, None, 1, false).map(|(e, _)| e)
781    }
782
783    pub fn expr(&mut self, left: Option<(Expr, bool)>, left_op: Option<BinaryOp>) -> Result<(Expr, bool)> {
784        self.expr_with_min_weight(left, left_op, 0, true)
785    }
786
787    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)> {
788        self.check_fatal()?;
789        self.enter_depth()?;
790        let result = self.expr_with_min_weight_inner(left, left_op, min_weight, allow_struct_literal);
791        self.exit_depth();
792        result
793    }
794
795    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)> {
796        self.whitespace()?;
797        if self.is_eof() {
798            return left.ok_or_else(|| ParserErr::at("左操作数缺失", self.current_pos()).into());
799        }
800        let start = self.current_pos();
801        let ch = self.get()?;
802        let mut expr = if ch == b'(' {
803            let start = self.current_pos();
804            self.pos += 1;
805            self.whitespace()?;
806            if self.take(b')').is_ok() {
807                let expr = Expr::new(ExprKind::Tuple(Vec::new()), Span::new(start, self.current_pos()));
808                return Ok((self.postfix_expr(start, expr)?, true));
809            }
810            let (e, _closed) = self.expr_with_min_weight(None, None, 0, true)?;
811            self.whitespace()?;
812            if self.get()? == b',' {
813                self.pos += 1;
814                let list = crate::parse_list!(self, vec![e], b')', b',', self.expr_with_min_weight(None, None, 0, true)?.0);
815                let expr = Expr::new(ExprKind::Tuple(list), Span::new(start, self.current_pos()));
816                Ok((self.postfix_expr(start, expr)?, true))
817            } else {
818                self.until(b')')?;
819                let expr = e.with_span(Span::new(start, self.current_pos()));
820                Ok((self.postfix_expr(start, expr)?, true))
821            }
822        } else if ch == b'!' && self.ahead().map(|a| a != b'=').unwrap_or(true) {
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::Not, value: Box::new(value) }, Span::new(start, self.current_pos())), false))
827        } else if ch == b'-' && self.ahead().map(|a| a != b'=').unwrap_or(true) && (left.is_none() || (left.is_some() && left_op.is_some())) {
828            let start = self.current_pos();
829            self.pos += 1;
830            let value = self.expr_with_min_weight(None, None, BinaryOp::Mul.weight() + 1, allow_struct_literal)?.0;
831            Ok((Expr::new(ExprKind::Unary { op: UnaryOp::Neg, value: Box::new(value) }, Span::new(start, self.current_pos())), false))
832        } else if ch == b'[' {
833            if let Ok(expr) = try_parse!(self, self.static_dynamic_literal_expr()) {
834                Ok((self.postfix_expr(start, expr)?, false))
835            } else {
836                let start = self.current_pos();
837                self.pos += 1;
838                self.whitespace()?;
839                if self.take(b']').is_ok() {
840                    let expr = Expr::new(ExprKind::List(Vec::new()), Span::new(start, self.current_pos()));
841                    Ok((self.postfix_expr(start, expr)?, false))
842                } else {
843                    let first = self.expr_with_min_weight(None, None, 0, true)?.0;
844                    self.whitespace()?;
845                    if self.take(b';').is_ok() {
846                        let len = self.get_type_param()?;
847                        self.until(b']')?;
848                        let expr = Expr::new(ExprKind::Repeat { value: Box::new(first), len }, Span::new(start, self.current_pos()));
849                        Ok((self.postfix_expr(start, expr)?, false))
850                    } else {
851                        let mut items = vec![first];
852                        let mut closed = false;
853                        while self.take(b',').is_ok() {
854                            self.whitespace()?;
855                            if self.take(b']').is_ok() {
856                                closed = true;
857                                break;
858                            }
859                            items.push(self.expr_with_min_weight(None, None, 0, true)?.0);
860                            self.whitespace()?;
861                        }
862                        if !closed {
863                            self.until(b']')?;
864                        }
865                        let expr = Expr::new(ExprKind::List(items), Span::new(start, self.current_pos()));
866                        Ok((self.postfix_expr(start, expr)?, false))
867                    }
868                }
869            }
870        } else if ch == b'{'
871            && (left.is_none() || left_op.is_some())
872            && let Ok(expr) = try_parse!(self, self.static_dynamic_literal_expr())
873        {
874            Ok((self.postfix_expr(start, expr)?, false))
875        } else if ch == b'{'
876            && (left.is_none() || left_op.is_some())
877            && let Ok(dict) = try_parse!(self, self.dict())
878        {
879            Ok((self.postfix_expr(start, dict)?, false))
880        } else if (left.is_none() || left_op.is_some()) && self.keyword("if").is_ok() {
881            let stmt = self.if_block()?;
882            Ok((Expr::new(ExprKind::Stmt(Box::new(stmt)), Span::new(start, self.current_pos())), true))
883        } else if (left.is_none() || left_op.is_some()) && self.keyword("match").is_ok() {
884            let stmt = self.match_block(start)?;
885            Ok((Expr::new(ExprKind::Stmt(Box::new(stmt)), Span::new(start, self.current_pos())), true))
886        } else if ch == b'|' && left.is_none() {
887            let start = self.current_pos();
888            self.pos += 1;
889            let args = crate::parse_list!(self, Vec::new(), b'|', b',', self.ident_typed()?);
890            let body = Box::new(self.function_body(&args)?);
891            let expr = Expr::new(ExprKind::Closure { args, body }, Span::new(start, self.current_pos()));
892            Ok((self.postfix_expr(start, expr)?, true))
893        } else if let Some(this_op) = self.binary_op() {
894            let (left, close) = left.ok_or(anyhow!("{:?} need left value", this_op))?;
895            if this_op == BinaryOp::RangeOpen {
896                self.whitespace()?;
897                if self.get()? == b']' {
898                    let span = Span::new(left.span.start, self.current_pos());
899                    let stop = Expr::new(ExprKind::Value(Dynamic::Null), Span::empty(self.current_pos()));
900                    return Ok((Expr::new(ExprKind::Range { start: Box::new(left), stop: Box::new(stop), inclusive: false }, span), false));
901                }
902            }
903            if this_op.weight() < min_weight {
904                self.pos = start;
905                return Ok((left, close));
906            }
907            // range 的上界要按完整子表达式解析(优先级降到 range 之上),
908            // 否则 `0 .. n * 2` 只会把 `n` 当上界,`* 2` 反而套在整个 range 外面。
909            if matches!(this_op, BinaryOp::RangeOpen | BinaryOp::RangeClose) {
910                let stop = self.expr_with_min_weight(None, None, this_op.weight() + 1, allow_struct_literal)?.0;
911                let span = left.span.merge(stop.span);
912                let inclusive = this_op == BinaryOp::RangeClose;
913                let range = Expr::new(ExprKind::Range { start: Box::new(left), stop: Box::new(stop), inclusive }, span);
914                return self.expr_with_min_weight(Some((range, false)), None, min_weight, allow_struct_literal);
915            }
916            // 赋值右结合:右侧按完整表达式解析,min_weight 取赋值自身权重(0),
917            // 使得 `a = b = c` 解析为 `a = (b = c)`、`a = b + c` 为 `a = (b + c)`。
918            if this_op.is_assign() {
919                let rhs = self.expr_with_min_weight(None, None, this_op.weight(), allow_struct_literal)?.0;
920                let span = left.span.merge(rhs.span);
921                let expr = Expr::new(ExprKind::Binary { left: Box::new(left), op: this_op, right: Box::new(rhs) }, span);
922                return self.expr_with_min_weight(Some((expr, false)), None, min_weight, allow_struct_literal);
923            }
924            if left_op.is_some() {
925                return Err(anyhow!("unexpected binary op {:?}", this_op));
926            }
927            return if !close && left.binary_op().map(|op| op.weight() < this_op.weight()).unwrap_or(false) {
928                let (binary_left, op, right) = left.binary().unwrap();
929                let this_weight = this_op.weight();
930                let new_right = self.expr_with_min_weight(Some((right, false)), Some(this_op), this_weight, allow_struct_literal)?.0;
931                let span = binary_left.span.merge(new_right.span);
932                let expr = Expr::new(ExprKind::Binary { left: Box::new(binary_left), op, right: Box::new(new_right) }, span);
933                self.expr_with_min_weight(Some((expr, false)), None, min_weight, allow_struct_literal)
934            } else {
935                self.expr_with_min_weight(Some((left, false)), Some(this_op), min_weight, allow_struct_literal)
936            };
937        } else {
938            // 注:`as` 现在由 postfix_expr 紧绑定到原子处理,不再在二元位置兜底。
939            self.base_expr(allow_struct_literal).map(|e| (e, false))
940        };
941
942        if left.is_some() {
943            if let Some(op) = left_op {
944                let left = left.unwrap().0;
945                let right = expr?.0;
946                let span = left.span.merge(right.span);
947                expr = Ok((
948                    match op {
949                        BinaryOp::RangeOpen => Expr::new(ExprKind::Range { start: Box::new(left), stop: Box::new(right), inclusive: false }, span),
950                        BinaryOp::RangeClose => Expr::new(ExprKind::Range { start: Box::new(left), stop: Box::new(right), inclusive: true }, span),
951                        _ => Expr::new(ExprKind::Binary { left: Box::new(left), op, right: Box::new(right) }, span),
952                    },
953                    false,
954                ));
955            } else if expr.is_ok() {
956                return Err(anyhow!("unexpected {:?}", expr));
957            } else {
958                return Ok((left.unwrap().0, false));
959            }
960        }
961        let result = self.expr_with_min_weight(Some(expr?), None, min_weight, allow_struct_literal)?;
962        Ok(result)
963    }
964}