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