Skip to main content

parser/
lib.rs

1use std::{collections::BTreeSet, fmt::Debug};
2
3use anyhow::{Result, anyhow};
4use dynamic::{ConstIntOp, Dynamic, Type};
5use smol_str::SmolStr;
6
7mod expr;
8pub use expr::{BinaryOp, Expr, ExprKind, UnaryOp};
9
10mod pattern;
11pub use pattern::{Pattern, PatternKind};
12
13mod stmt;
14pub use stmt::{Stmt, StmtKind};
15
16#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
17pub struct Span {
18    pub start: usize,
19    pub end: usize,
20}
21
22impl Span {
23    pub const fn new(start: usize, end: usize) -> Self {
24        Self { start, end }
25    }
26
27    pub const fn empty(pos: usize) -> Self {
28        Self { start: pos, end: pos }
29    }
30
31    pub fn merge(self, other: Self) -> Self {
32        Self { start: self.start.min(other.start), end: self.end.max(other.end) }
33    }
34}
35
36#[derive(Debug)]
37/// 解析器内的作用域嵌套深度。把同类 depth 字段打包成一个子结构,
38/// 让 Parser struct 字段更扁平、四个 depth 字段不再散落、调用方一看就懂这是"嵌套深度"
39/// 而不是别的状态。
40#[derive(Default, Clone)]
41pub(crate) struct ScopeDepths {
42    /// impl 体嵌套深度。>0 表示当前 stmt 处于 `impl { ... }` 内,
43    /// 拒绝嵌套 `struct / impl / const / static`(fn 仍允许,即方法)。
44    pub(crate) impl_depth: usize,
45    /// impl body 嵌套深度,和 impl_depth 同周期,但语义不同:
46    /// 允许方法定义,只拒绝 struct/impl/const/static。
47    pub(crate) impl_body_depth: usize,
48    /// 函数体嵌套深度。>0 表示当前 stmt 处于某个 `fn body` 内,需要拒绝
49    /// `fn / struct / impl / const / static` 等顶层声明关键字。
50    pub(crate) fn_body_depth: usize,
51    /// 当前表达式/语句递归深度,防止恶意深嵌套输入打爆调用栈
52    pub(crate) depth: usize,
53}
54
55pub struct Parser {
56    pos: usize,   //当前解析的位置
57    buf: Vec<u8>, //待解析的字符串
58    spans: Vec<usize>,
59    decl_scopes: Vec<BTreeSet<SmolStr>>,
60    scope_depths: ScopeDepths,
61    /// `match` 块顶层临时变量(__m_scrut_N / __m_done_N / __m_out_N)的后缀计数器,
62    /// 用于避免嵌套 match 重名。
63    pub(crate) match_counter: usize,
64    fatal: bool,  //递归过深等不可恢复错误;置位后所有解析入口立即失败,避免回溯重试导致死循环
65}
66
67/// [`Parser::spans`] 的 RAII 守卫。
68///
69/// 由 [`Parser::with_stmt_span`] 创建。Drop 时无论如何(包括错误冒泡)都会
70/// 弹出一个栈帧,保证 spans 不会跨 stmt 累积。
71///
72/// 设计要点:`parser` 字段不持有 `&mut Parser`(那会阻塞 stmt 内部其他
73/// `&mut self` 调用),而是用 `*mut Parser` 配合 `unsafe` 在 drop 时调用 `pop`。
74/// `stmt()` 是唯一调用点,且调用顺序是:`push` → 内部全部 `&mut self` 操作
75/// → drop 时再 `pop`,保证 pop 永远发生在最后一次 `&mut self` 之后。
76struct SpanGuard {
77    parser: *mut Parser,
78}
79
80// SAFETY:`SpanGuard` 只在单线程的解析器栈里使用,`stmt()` 是同步代码,
81// `parser` 在 drop 之前不会被其他代码路径释放。Drop 只调用 `Vec::pop`,
82// 不读 `Parser` 的任何其他字段。
83unsafe impl Send for SpanGuard {}
84unsafe impl Sync for SpanGuard {}
85
86impl Drop for SpanGuard {
87    fn drop(&mut self) {
88        // SAFETY:`parser` 来自 `with_stmt_span` 的入参,生命周期与 guard 一致;
89        // stmt() 退出时 guard 才 drop,期间无其他借用。
90        unsafe {
91            if !(*self.parser).spans.is_empty() {
92                (*self.parser).spans.pop();
93            }
94        }
95    }
96}
97
98/// 解析递归深度上限。超过即返回 [`ParserErr::TooDeep`],把"栈溢出崩溃"降级为
99/// 普通解析错误。
100///
101/// 单层 `expr_with_min_weight` 帧约 7KB,worker 线程默认栈仅 2MB,因此上限取
102/// 128(与 rustc 默认 `recursion_limit` 一致):128×7KB≈0.9MB,在最小栈上仍有
103/// 余量,而正常代码极少超过几十层嵌套。
104pub const MAX_PARSE_DEPTH: usize = 128;
105
106const NOT_IDENT: &[u8] = &[b' ', b'\t', b'\n', b'\r', b'/', b'*', b'+', b'-', b'=', b'(', b')', b'{', b'}', b'[', b']', b';', b':', b',', b'.', b'<', b'>', b'!', b'#', b'$', b'%', b'^', b'&', b'|', b'\\', b'"', b'\''];
107const WHITE_SPACE: &[u8] = &[b' ', b'\t', b'\n', b'\r'];
108const TYPES: &[(&str, Type)] = &[
109    ("bool", Type::Bool),
110    ("string", Type::Str),
111    ("i8", Type::I8),
112    ("i16", Type::I16),
113    ("i32", Type::I32),
114    ("i64", Type::I64),
115    ("u8", Type::U8),
116    ("u16", Type::U16),
117    ("u32", Type::U32),
118    ("u64", Type::U64),
119    ("f16", Type::F16),
120    ("f32", Type::F32),
121    ("f64", Type::F64),
122];
123const KEYWORDS: &[&str] = &["true", "false", "null", "let", "if", "else", "for", "in", "while", "loop", "pub", "fn", "struct", "impl", "const", "static", "continue", "return", "break", "match"];
124
125#[macro_export]
126macro_rules! parse_list {
127    ($self: ident, $start: expr, $end: expr, $sep: expr, $item_expr: expr) => {{
128        let mut items = $start;
129        loop {
130            $self.whitespace()?;
131            if $self.get()? == $end {
132                $self.pos += 1;
133                break;
134            }
135            let item = $item_expr;
136            items.push(item);
137            $self.whitespace()?;
138            if $self.get()? == $sep {
139                $self.pos += 1;
140            }
141        }
142        items
143    }};
144}
145
146#[macro_export]
147macro_rules! try_parse {
148    ($self: ident, $method: expr) => {{
149        let save_pos = $self.pos; //保存当前 pos
150        let save_decl_scopes = $self.decl_scopes.clone();
151        let save_impl_depth = $self.scope_depths.impl_depth;
152        match $method {
153            Ok(expr) => Ok(expr),
154            // fatal(如递归过深)不可恢复:不回退 pos,直接上抛,避免外层换产生式重试导致死循环
155            Err(e) if $self.fatal => Err(e),
156            Err(e) => {
157                $self.pos = save_pos;
158                $self.decl_scopes = save_decl_scopes;
159                $self.scope_depths.impl_depth = save_impl_depth;
160                Err(e)
161            }
162        }
163    }};
164}
165
166#[derive(Debug, thiserror::Error)]
167pub enum ParserErr {
168    #[error("{message}")]
169    Spanned { message: String, span: Span },
170}
171
172impl ParserErr {
173    /// 构造携带 span 的解析错误。所有 ParserErr 错误都应该走这个构造。
174    pub fn new(message: impl Into<String>, span: Span) -> Self {
175        Self::Spanned { message: message.into(), span }
176    }
177
178    /// 便捷构造:span 是 [pos, pos) 的零长 span,用于"在当前位置报错"的场景。
179    pub fn at(message: impl Into<String>, pos: usize) -> Self {
180        Self::Spanned { message: message.into(), span: Span::new(pos, pos) }
181    }
182
183    pub fn span(&self) -> Span {
184        match self {
185            Self::Spanned { span, .. } => *span,
186        }
187    }
188
189    pub fn message(&self) -> &str {
190        match self {
191            Self::Spanned { message, .. } => message,
192        }
193    }
194}
195
196/// 在 ParserErr 基础上附带 parser 当前光标位置。
197/// parse_code 顶层 downcast 此类型,做精确的 LSP-style 错误高亮。
198#[derive(Debug, thiserror::Error)]
199#[error("{err}")]
200pub struct SpannedParseError {
201    pub err: ParserErr,
202    pub pos: usize,
203}
204
205impl SpannedParseError {
206    pub fn new(err: ParserErr, pos: usize) -> Self {
207        Self { err, pos }
208    }
209}
210
211impl Parser {
212    pub fn new(buf: Vec<u8>) -> Self {
213        Self { pos: 0, buf, spans: Vec::new(), decl_scopes: vec![BTreeSet::new()], scope_depths: ScopeDepths::default(), match_counter: 0, fatal: false }
214    }
215
216    /// RAII 守卫:在构造时把当前 `pos` 推入 `spans`,在 drop 时弹出。
217    ///
218    /// 设计动机:`spans` 栈之前是手动 `push` + `pop`,但 `stmt()` 内部有十多个
219    /// `?` 提前返回路径(import / let / fn …),任何一条错误路径走完时都
220    /// 不会清理 `spans`,导致下次错误消息的 [`error_stmt`] 把上一个 stmt 的
221    /// 内容误当成当前错误的上下文 —— 错误定位严重漂移。
222    ///
223    /// 用 RAII guard:无论函数是 `Ok` 还是 `Err` 返回,`Drop` 总会清理栈帧,
224    /// 把 `spans.last()` 始终精确指向"当前正在解析的 stmt"。
225    ///
226    /// 实现细节:guard 持有 `*mut Parser` 而不是 `&mut Parser`,这样不阻塞
227    /// stmt 内部其他 `&mut self` 调用(否则 borrow checker 会失败)。
228    fn with_stmt_span(&mut self) -> SpanGuard {
229        self.spans.push(self.pos);
230        SpanGuard { parser: self as *mut Parser }
231    }
232
233    /// 进入一层递归:自增深度并校验上限。配合 [`Parser::exit_depth`] 使用。
234    ///
235    /// 超限时置 [`Parser::fatal`]:这是不可恢复错误。否则 `try_parse!` 的回溯会
236    /// 把 [`ParserErr::TooDeep`] 当成"换个产生式再试",pos 回退后外层循环原地重试,
237    /// 形成死循环。置位后 [`Parser::check_fatal`] 让每个解析入口立即失败,错误一路
238    /// 通过 `?` 上抛终止解析。
239    fn enter_depth(&mut self) -> Result<()> {
240        self.scope_depths.depth += 1;
241        if self.scope_depths.depth > MAX_PARSE_DEPTH {
242            self.scope_depths.depth -= 1;
243            self.fatal = true;
244            return Err(ParserErr::at("表达式嵌套过深", self.current_pos()).into());
245        }
246        Ok(())
247    }
248
249    fn exit_depth(&mut self) {
250        self.scope_depths.depth = self.scope_depths.depth.saturating_sub(1);
251    }
252
253    /// 解析入口的快速失败检查:一旦进入 fatal 状态,立即返回错误,阻止任何回溯重试。
254    fn check_fatal(&self) -> Result<()> {
255        if self.fatal { Err(ParserErr::at("表达式嵌套过深", self.current_pos()).into()) } else { Ok(()) }
256    }
257
258    pub(crate) fn push_decl_scope(&mut self) {
259        self.decl_scopes.push(BTreeSet::new());
260    }
261
262    pub(crate) fn pop_decl_scope(&mut self) {
263        if self.decl_scopes.len() > 1 {
264            self.decl_scopes.pop();
265        }
266    }
267
268    fn declare_symbol(&mut self, name: &SmolStr) -> Result<()> {
269        if name.is_empty() {
270            return Ok(());
271        }
272        if self.decl_scopes.iter().rev().any(|scope| scope.contains(name)) {
273            return Err(ParserErr::at(format!("符号 {} 已经声明", name), self.current_pos()).into());
274        }
275        self.decl_scopes.last_mut().expect("parser always has a declaration scope").insert(name.clone());
276        Ok(())
277    }
278
279    pub(crate) fn declare_symbol_in_current_scope(&mut self, name: &SmolStr) -> Result<()> {
280        if name.is_empty() {
281            return Ok(());
282        }
283        let scope = self.decl_scopes.last_mut().expect("parser always has a declaration scope");
284        if scope.contains(name) {
285            return Err(ParserErr::at(format!("符号 {} 已经声明", name), self.current_pos()).into());
286        }
287        scope.insert(name.clone());
288        Ok(())
289    }
290
291    fn declare_function_name(&mut self, name: &SmolStr) -> Result<()> {
292        if self.scope_depths.impl_depth > 0 { self.declare_symbol_in_current_scope(name) } else { self.declare_symbol(name) }
293    }
294
295    fn declare_args(&mut self, args: &[(SmolStr, Type)]) -> Result<()> {
296        for (name, _) in args {
297            self.declare_symbol(name)?;
298        }
299        Ok(())
300    }
301
302    pub(crate) fn declare_pattern_symbols(&mut self, pat: &Pattern) -> Result<()> {
303        match &pat.kind {
304            PatternKind::Ident { name, .. } => self.declare_symbol_in_current_scope(name),
305            PatternKind::Tuple(items) => {
306                for item in items {
307                    self.declare_pattern_symbols(item)?;
308                }
309                Ok(())
310            }
311            PatternKind::List { elems, .. } => {
312                for item in elems {
313                    self.declare_pattern_symbols(item)?;
314                }
315                Ok(())
316            }
317            PatternKind::Struct { fields, .. } => {
318                for (name, sub) in fields {
319                    if let Some(sub) = sub {
320                        self.declare_pattern_symbols(sub)?;
321                    } else {
322                        self.declare_symbol_in_current_scope(name)?;
323                    }
324                }
325                Ok(())
326            }
327            PatternKind::Wildcard | PatternKind::Var { .. } | PatternKind::Literal(_) | PatternKind::Member(_, _) | PatternKind::Idx(_, _) => Ok(()),
328        }
329    }
330
331    fn function_body(&mut self, args: &[(SmolStr, Type)]) -> Result<Stmt> {
332        self.push_decl_scope();
333        self.scope_depths.fn_body_depth += 1;
334        let result = (|| {
335            self.declare_args(args)?;
336            self.block()
337        })();
338        self.scope_depths.fn_body_depth -= 1;
339        self.pop_decl_scope();
340        result
341    }
342
343    fn impl_body(&mut self) -> Result<Stmt> {
344        self.push_decl_scope();
345        self.scope_depths.impl_depth += 1;
346        self.scope_depths.impl_body_depth += 1;
347        let result = self.block();
348        self.scope_depths.impl_body_depth -= 1;
349        self.scope_depths.impl_depth -= 1;
350        self.pop_decl_scope();
351        result
352    }
353
354    pub fn is_eof(&self) -> bool {
355        self.pos >= self.buf.len()
356    }
357
358    pub fn get(&self) -> Result<u8> {
359        //查看当前字符
360        self.buf.get(self.pos).cloned().ok_or_else(|| ParserErr::at("输入结束", self.pos).into())
361    }
362
363    pub fn take(&mut self, ch: u8) -> Result<()> {
364        //如果当前字符为 ch 消费该字符 返回 Ok(())
365        if self.buf.get(self.pos).map(|b| *b == ch).unwrap_or(false) {
366            self.pos += 1;
367            Ok(())
368        } else {
369            // 修复:EOF 时 `buf.get(self.pos)` 返回 None,原代码用 `unwrap_or(0)`
370            // 把字符报成 `\0`(控制字符),误导用户。改为显式判断 EOF,报"已到文件末尾"。
371            let actual_desc = match self.buf.get(self.pos) {
372                Some(byte) => format!("实际字符 {}", *byte as char),
373                None => "已到文件末尾".to_string(),
374            };
375            Err(SpannedParseError::new(ParserErr::at(format!("期望字符 {} {}", ch as char, actual_desc), self.pos), self.pos).into())
376        }
377    }
378
379    pub fn until(&mut self, ch: u8) -> Result<()> {
380        //消费直到指定字符 ch 忽略空白和注释
381        self.whitespace()?;
382        self.take(ch)
383    }
384
385    pub fn ahead(&self) -> Result<u8> {
386        //朝前看
387        self.buf.get(self.pos + 1).cloned().ok_or_else(|| ParserErr::at("输入结束", self.pos).into())
388    }
389
390    pub fn get_str(&self, start: usize, stop: usize) -> SmolStr {
391        SmolStr::from(String::from_utf8_lossy(&self.buf[start..stop]))
392    }
393
394    pub fn error_stmt(&self) -> SmolStr {
395        SmolStr::from(String::from_utf8_lossy(&self.buf[self.spans.last().cloned().unwrap_or(0)..self.pos]))
396    }
397
398    pub fn current_pos(&self) -> usize {
399        self.pos
400    }
401
402    pub fn span_from(&self, start: usize) -> Span {
403        Span::new(start, self.pos)
404    }
405
406    pub fn collect<F: Fn(u8) -> bool>(&mut self, f: F) -> Result<(usize, usize)> {
407        let start = self.pos;
408        while self.pos < self.buf.len() && f(self.buf[self.pos]) {
409            self.pos += 1;
410        }
411        if self.pos > start { Ok((start, self.pos)) } else { Err(ParserErr::at("未发现期望字符", start).into()) }
412    }
413
414    pub fn just(&mut self, pattern: &str) -> Result<()> {
415        if self.buf.len() - self.pos >= pattern.len() && self.buf[self.pos..self.pos + pattern.len()].eq(pattern.as_bytes()) {
416            self.pos += pattern.len();
417            Ok(())
418        } else {
419            Err(ParserErr::at(format!("期望字符串 {}", pattern), self.pos).into())
420        }
421    }
422
423    pub fn keyword(&mut self, pattern: &str) -> Result<()> {
424        self.just(pattern)?;
425        if self.pos < self.buf.len() && !NOT_IDENT.contains(&self.buf[self.pos]) {
426            self.pos -= pattern.len();
427            return Err(ParserErr::at(format!("期望字符串 {}", pattern), self.pos).into());
428        }
429        Ok(())
430    }
431
432    pub fn get_type(&mut self) -> Result<Type> {
433        self.whitespace()?;
434        if self.get()? == b'[' {
435            self.pos += 1;
436            let ty = self.get_type()?;
437            self.until(b';')?;
438            self.whitespace()?;
439            let len = self.get_type_param()?;
440            self.until(b']')?;
441            if let Type::ConstInt(number) = len {
442                let number = u32::try_from(number).map_err(|_| anyhow!("数组长度超出 u32 范围"))?;
443                Ok(Type::Array(std::rc::Rc::new(ty), number))
444            } else {
445                Ok(Type::ArrayParam(std::rc::Rc::new(ty), std::rc::Rc::new(len)))
446            }
447        } else {
448            for ty in TYPES {
449                if self.just(ty.0).is_ok() {
450                    return Ok(ty.1.clone());
451                }
452            }
453            let name = self.ident()?;
454            if self.take(b'<').is_ok() {
455                let params = crate::parse_list!(self, Vec::new(), b'>', b',', self.get_type_param()?);
456                Ok(Type::Ident { name, params })
457            } else {
458                Ok(Type::Ident { name, params: Vec::new() })
459            }
460        }
461    }
462
463    pub fn get_type_param(&mut self) -> Result<Type> {
464        self.const_type_param_add()
465    }
466
467    fn const_type_param_add(&mut self) -> Result<Type> {
468        let mut left = self.const_type_param_mul()?;
469        loop {
470            self.whitespace()?;
471            let op = if self.take(b'+').is_ok() {
472                Some(ConstIntOp::Add)
473            } else if self.take(b'-').is_ok() {
474                Some(ConstIntOp::Sub)
475            } else {
476                None
477            };
478            let Some(op) = op else { break };
479            let right = self.const_type_param_mul()?;
480            left = Self::fold_const_type_binary(op, left, right)?;
481        }
482        Ok(left)
483    }
484
485    fn const_type_param_mul(&mut self) -> Result<Type> {
486        let mut left = self.const_type_param_primary()?;
487        loop {
488            self.whitespace()?;
489            let op = if self.take(b'*').is_ok() {
490                Some(ConstIntOp::Mul)
491            } else if self.take(b'/').is_ok() {
492                Some(ConstIntOp::Div)
493            } else if self.take(b'%').is_ok() {
494                Some(ConstIntOp::Mod)
495            } else {
496                None
497            };
498            let Some(op) = op else { break };
499            let right = self.const_type_param_primary()?;
500            left = Self::fold_const_type_binary(op, left, right)?;
501        }
502        Ok(left)
503    }
504
505    fn const_type_param_primary(&mut self) -> Result<Type> {
506        self.whitespace()?;
507        if self.take(b'(').is_ok() {
508            let ty = self.get_type_param()?;
509            self.until(b')')?;
510            return Ok(ty);
511        }
512        if self.get()?.is_ascii_digit() {
513            let value = self.number()?;
514            if let Some(value) = value.as_uint() {
515                let value = i64::try_from(value).map_err(|_| anyhow!("模板数字参数超出 i64 范围"))?;
516                Ok(Type::ConstInt(value))
517            } else if let Some(value) = value.as_int() {
518                Ok(Type::ConstInt(value))
519            } else {
520                Err(anyhow!("模板数字参数必须是整数"))
521            }
522        } else {
523            self.get_type()
524        }
525    }
526
527    fn fold_const_type_binary(op: ConstIntOp, left: Type, right: Type) -> Result<Type> {
528        if let (Type::ConstInt(left), Type::ConstInt(right)) = (&left, &right) {
529            let value = match op {
530                ConstIntOp::Add => left + right,
531                ConstIntOp::Sub => left - right,
532                ConstIntOp::Mul => left * right,
533                ConstIntOp::Div => {
534                    if *right == 0 {
535                        return Err(anyhow!("模板整数除以 0"));
536                    }
537                    left / right
538                }
539                ConstIntOp::Mod => {
540                    if *right == 0 {
541                        return Err(anyhow!("模板整数取模 0"));
542                    }
543                    left % right
544                }
545            };
546            Ok(Type::ConstInt(value))
547        } else {
548            Ok(Type::ConstBinary { op, left: std::rc::Rc::new(left), right: std::rc::Rc::new(right) })
549        }
550    }
551
552    pub fn comment(&mut self) -> Result<()> {
553        if self.get()? == b'/' && self.ahead()? == b'/' {
554            self.pos += 2;
555            while self.pos < self.buf.len() && self.buf[self.pos] != b'\n' {
556                self.pos += 1;
557            }
558            Ok(())
559        } else if self.get()? == b'/' && self.ahead()? == b'*' {
560            self.pos += 2;
561            while self.pos + 1 < self.buf.len() {
562                if self.buf[self.pos] == b'*' && self.buf[self.pos + 1] == b'/' {
563                    self.pos += 2;
564                    return Ok(());
565                }
566                self.pos += 1;
567            }
568            Err(ParserErr::at("未关闭的注释", self.pos).into())
569        } else {
570            Ok(())
571        }
572    }
573
574    pub fn whitespace(&mut self) -> Result<()> {
575        while self.pos < self.buf.len() {
576            self.comment()?;
577            if self.pos >= self.buf.len() || !WHITE_SPACE.contains(&self.buf[self.pos]) {
578                break;
579            }
580            self.pos += 1;
581        }
582        Ok(())
583    }
584
585    pub fn ident(&mut self) -> Result<SmolStr> {
586        let (start, mut stop) = self.collect(|ch| !NOT_IDENT.contains(&ch))?;
587        loop {
588            let save_pos = self.pos;
589            if self.just("::").is_err() {
590                break;
591            }
592            match self.collect(|ch| !NOT_IDENT.contains(&ch)) {
593                Ok((_, next_stop)) => {
594                    stop = next_stop;
595                }
596                Err(_) => {
597                    self.pos = save_pos;
598                    break;
599                }
600            }
601        }
602        if KEYWORDS.iter().position(|k| k.as_bytes() == &self.buf[start..stop]).is_some() {
603            return Err(anyhow!("发现关键字{}", String::from_utf8_lossy(&self.buf[start..stop])));
604        }
605        Ok(self.get_str(start, stop))
606    }
607
608    pub fn string(&mut self) -> Result<SmolStr> {
609        if self.get()? != b'"' {
610            return Err(ParserErr::at("非字符串", self.current_pos()).into());
611        }
612        self.pos += 1;
613        let mut text_buf = Vec::new();
614        while self.pos < self.buf.len() {
615            if self.buf[self.pos] == b'\\' {
616                //转义字符
617                self.pos += 1;
618                match self.buf[self.pos] {
619                    b'n' => {
620                        text_buf.push(b'\n');
621                        self.pos += 1;
622                    }
623                    b'r' => {
624                        text_buf.push(b'\r');
625                        self.pos += 1;
626                    }
627                    b't' => {
628                        text_buf.push(b'\t');
629                        self.pos += 1;
630                    }
631                    ch @ (b'\\' | b'"') => {
632                        text_buf.push(ch);
633                        self.pos += 1;
634                    }
635                    b'u' => {
636                        self.pos += 1;
637                        let unicode = if self.take(b'{').is_ok() {
638                            let code = self.hex()?;
639                            self.pos += 1;
640                            code
641                        } else {
642                            self.hex()?
643                        };
644                        let ch = char::from_u32(unicode as u32).ok_or(anyhow!("非法 unicode {}", unicode))?;
645                        let mut utf8_buf = [0u8; 4];
646                        let s = ch.encode_utf8(&mut utf8_buf);
647                        text_buf.extend_from_slice(s.as_bytes());
648                    }
649                    b'x' => {
650                        self.pos += 1;
651                        if self.pos + 2 > self.buf.len() {
652                            return Err(anyhow!("非法 \\x 转义:需要 2 位十六进制"));
653                        }
654                        let start = self.pos;
655                        self.pos += 2;
656                        let hex = &self.buf[start..self.pos];
657                        if hex.iter().any(|b| !b.is_ascii_hexdigit()) {
658                            return Err(anyhow!("非法 \\x 转义:仅允许十六进制字符"));
659                        }
660                        let code = u32::from_str_radix(String::from_utf8_lossy(hex).as_ref(), 16)?;
661                        if code > 0xFF {
662                            return Err(anyhow!("\\x 转义值 0x{:02X} 超出 0xFF", code));
663                        }
664                        text_buf.push(code as u8);
665                    }
666                    other => {
667                        return Err(anyhow!("invalid escape character: {}", other as char));
668                    }
669                }
670            } else {
671                if self.buf[self.pos] == b'"' {
672                    self.pos += 1;
673                    return Ok(String::from_utf8(text_buf)?.into());
674                }
675                text_buf.push(self.buf[self.pos]);
676                self.pos += 1;
677            }
678        }
679        Err(ParserErr::at("未关闭字符串", self.pos).into())
680    }
681
682    pub fn text(&mut self) -> Result<SmolStr> {
683        if self.get()? == b'r' && [b'#', b'"'].contains(&self.ahead()?) {
684            self.pos += 1;
685            // 收集 `#` 前缀:`r#####` 是 Rust 风格的原始字符串语法。原先
686            // 漏掉 `self.pos < self.buf.len()` 边界检查,会在 `r##` /
687            // `r#####` 后跟 EOF(没有匹配的 `"`)时越过 buf 末尾 panic。
688            // 用 `lookahead == b'#'` 判断继续/停止,免去直接下标的越界。
689            let mut hash_count: usize = 0;
690            while self.pos < self.buf.len() && self.buf[self.pos] == b'#' {
691                hash_count += 1;
692                self.pos += 1;
693            }
694            // `r#"(abc)` 形式 — 若下一个字符不是 `"`,直接报错。不强行构造 end,
695            // 因为后面若抛错,builder 也用不到 end,避免再触发"start>stop" panic。
696            if self.get()? != b'"' {
697                return Err(ParserErr::at("非法的原始字符串", self.current_pos()).into());
698            }
699            self.pos += 1;
700            // 收尾的 `#...#"` 序列必须与前缀数量一致才算闭合。注意顺序:
701            // 闭合是 `"` 在前、N 个 `#` 在后(`r#"..."#` 的右边是 `"#`),
702            // 不是 `#"#`(前者才是 Rust/曾用方案的形态)。
703            let mut end: Vec<u8> = Vec::with_capacity(hash_count + 1);
704            end.push(b'"');
705            for _ in 0..hash_count {
706                end.push(b'#');
707            }
708            let start_pos = self.pos;
709            while self.pos < self.buf.len() {
710                if self.pos + end.len() <= self.buf.len() && self.buf[self.pos..self.pos + end.len()].eq(&end) {
711                    break;
712                }
713                self.pos += 1;
714            }
715            // 走到末尾仍未闭合 — 报"未关闭字符串"而不是悄悄 panic。
716            if self.pos + end.len() > self.buf.len() {
717                return Err(ParserErr::at("未关闭字符串", self.current_pos()).into());
718            }
719            // 这里一定有 `self.pos <= start_pos`(闭合,内层可能就直接相等)。
720            let stop = self.pos;
721            self.pos += end.len();
722            Ok(self.get_str(start_pos, stop))
723        } else {
724            self.string()
725        }
726    }
727
728    fn hex(&mut self) -> Result<i32> {
729        //注意 hex 会消耗当前字符 设置新的 self.pos
730        let (start, stop) = self.collect(|ch| (ch >= b'0' && ch <= b'9') || (ch >= b'a' && ch <= b'f') || (ch >= b'A' && ch <= b'F'))?;
731        Ok(i32::from_str_radix(&String::from_utf8_lossy(&self.buf[start..stop]), 16)?)
732    }
733
734    fn numeric_suffix(&mut self) -> Option<Type> {
735        let save = self.pos;
736        for (name, ty) in TYPES {
737            if !ty.is_native() {
738                continue;
739            }
740            if self.buf.len() >= self.pos + name.len() && self.buf[self.pos..self.pos + name.len()].eq(name.as_bytes()) {
741                self.pos += name.len();
742                return Some(ty.clone());
743            }
744        }
745        self.pos = save;
746        None
747    }
748
749    fn int_literal(&mut self, digits: &str, radix: u32, suffix: Option<Type>) -> Result<Dynamic> {
750        // 默认整数类型为 I64:常见的较大十进制数(如 30 亿)不再静默回绕成负数。
751        let ty = suffix.unwrap_or(Type::I64);
752        // 负号由一元运算符单独解析,这里的字面量恒为非负,因此统一解析成 u128。
753        let magnitude = u128::from_str_radix(digits, radix).map_err(|_| anyhow!("整数字面量 {} 超出可表示范围", digits))?;
754        let (signed, bits) = match ty {
755            Type::I8 => (true, 8u32),
756            Type::I16 => (true, 16),
757            Type::I32 => (true, 32),
758            Type::I64 => (true, 64),
759            Type::U8 => (false, 8),
760            Type::U16 => (false, 16),
761            Type::U32 => (false, 32),
762            Type::U64 => (false, 64),
763            Type::F16 => return Ok(Dynamic::F16(dynamic::f64_to_f16(magnitude as f64))),
764            Type::F32 => return Ok(Dynamic::F32(magnitude as f32)),
765            Type::F64 => return Ok(Dynamic::F64(magnitude as f64)),
766            ty => return Err(anyhow!("{:?} 不能作为数字后缀", ty)),
767        };
768        let unsigned_max = (1u128 << bits) - 1;
769        // 十进制按数值语义判界(有符号允许到 |MIN|,即 2^(bits-1),以支持 -128i8、i64::MIN);
770        // 十六/八/二进制按位模式语义判界,允许写满整型位宽(如 0xFFFFFFFF 仍是合法的位掩码)。
771        let max_allowed = if radix == 10 { if signed { unsigned_max / 2 + 1 } else { unsigned_max } } else { unsigned_max };
772        if magnitude > max_allowed {
773            return Err(anyhow!("整数字面量 {} 超出 {:?} 的范围", digits, ty));
774        }
775        Ok(match ty {
776            Type::I8 => Dynamic::I8(magnitude as i8),
777            Type::I16 => Dynamic::I16(magnitude as i16),
778            Type::I32 => Dynamic::I32(magnitude as i32),
779            Type::I64 => Dynamic::I64(magnitude as i64),
780            Type::U8 => Dynamic::U8(magnitude as u8),
781            Type::U16 => Dynamic::U16(magnitude as u16),
782            Type::U32 => Dynamic::U32(magnitude as u32),
783            Type::U64 => Dynamic::U64(magnitude as u64),
784            _ => unreachable!(),
785        })
786    }
787
788    fn float_literal(&mut self, digits: &str, suffix: Option<Type>) -> Result<Dynamic> {
789        let value: f64 = digits.parse()?;
790        if let Some(ref ty) = suffix {
791            // 整数类后缀:校验是否在目标范围内。NaN / Inf 一律拒绝;
792            // 不允许小数部分。F16/F32/F64 不做范围 / 整数性校验。
793            let is_int_suffix = matches!(ty, Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::U8 | Type::U16 | Type::U32 | Type::U64);
794            if is_int_suffix {
795                let (min, max): (f64, f64) = match ty {
796                    Type::I8 => (i8::MIN as f64, i8::MAX as f64),
797                    Type::I16 => (i16::MIN as f64, i16::MAX as f64),
798                    Type::I32 => (i32::MIN as f64, i32::MAX as f64),
799                    Type::I64 => (i64::MIN as f64, i64::MAX as f64),
800                    Type::U8 => (0.0, u8::MAX as f64),
801                    Type::U16 => (0.0, u16::MAX as f64),
802                    Type::U32 => (0.0, u32::MAX as f64),
803                    Type::U64 => (0.0, u64::MAX as f64),
804                    _ => unreachable!(),
805                };
806                if !value.is_finite() || value < min || value > max || value.fract() != 0.0 {
807                    return Err(anyhow!("浮点字面量 {:?} 超出 {:?} 范围", value, ty));
808                }
809            } else if !value.is_finite() {
810                return Err(anyhow!("非法浮点字面量: {:?}", value));
811            }
812        }
813        Ok(match suffix.unwrap_or(Type::F32) {
814            Type::I8 => Dynamic::I8(value as i8),
815            Type::I16 => Dynamic::I16(value as i16),
816            Type::I32 => Dynamic::I32(value as i32),
817            Type::I64 => Dynamic::I64(value as i64),
818            Type::U8 => Dynamic::U8(value as u8),
819            Type::U16 => Dynamic::U16(value as u16),
820            Type::U32 => Dynamic::U32(value as u32),
821            Type::U64 => Dynamic::U64(value as u64),
822            Type::F16 => Dynamic::F16(dynamic::f64_to_f16(value)),
823            Type::F32 => Dynamic::F32(value as f32),
824            Type::F64 => Dynamic::F64(value),
825            ty => return Err(anyhow!("{:?} 不能作为浮点数字后缀", ty)),
826        })
827    }
828
829    pub fn number(&mut self) -> Result<Dynamic> {
830        if self.get()? == b'0' {
831            if [b'b', b'B'].contains(&self.ahead()?) {
832                self.pos += 2;
833                let (start, stop) = self.collect(|ch| ch == b'0' || ch == b'1')?;
834                let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
835                let suffix = self.numeric_suffix();
836                return self.int_literal(&s, 2, suffix);
837            } else if [b'o', b'O'].contains(&self.ahead()?) {
838                self.pos += 2;
839                let (start, stop) = self.collect(|ch| ch >= b'0' && ch <= b'7')?;
840                let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
841                let suffix = self.numeric_suffix();
842                return self.int_literal(&s, 8, suffix);
843            } else if [b'x', b'X'].contains(&self.ahead()?) {
844                self.pos += 2;
845                let (start, stop) = self.collect(|ch| (ch >= b'0' && ch <= b'9') || (ch >= b'a' && ch <= b'f') || (ch >= b'A' && ch <= b'F'))?;
846                let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
847                let suffix = self.numeric_suffix();
848                return self.int_literal(&s, 16, suffix);
849            }
850        }
851        let start = self.pos;
852        while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
853            self.pos += 1;
854        }
855        let mut is_float = false;
856        if self.pos < self.buf.len() && self.buf[self.pos] == b'.' && self.ahead().map(|ch| ch <= b'9' && ch >= b'0').unwrap_or(false) {
857            is_float = true;
858            self.pos += 1;
859            while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
860                self.pos += 1;
861            }
862        }
863        if self.pos < self.buf.len() && (self.buf[self.pos] == b'e' || self.buf[self.pos] == b'E') {
864            let mut exp_pos = self.pos + 1;
865            if exp_pos < self.buf.len() && (self.buf[exp_pos] == b'+' || self.buf[exp_pos] == b'-') {
866                exp_pos += 1;
867            }
868            if exp_pos < self.buf.len() && self.buf[exp_pos] <= b'9' && self.buf[exp_pos] >= b'0' {
869                is_float = true;
870                self.pos = exp_pos + 1;
871                while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
872                    self.pos += 1;
873                }
874            }
875        }
876        if self.pos > start {
877            let text = String::from_utf8_lossy(&self.buf[start..self.pos]).to_string();
878            let suffix = self.numeric_suffix();
879            if is_float {
880                return self.float_literal(&text, suffix);
881            }
882            return self.int_literal(&text, 10, suffix);
883        }
884        Err(ParserErr::at("非数字", start).into())
885    }
886}
887
888#[cfg(test)]
889mod tests {
890    use super::*;
891
892    fn parse_all(code: &str) -> Result<Vec<Stmt>> {
893        let mut parser = Parser::new(code.as_bytes().to_vec());
894        let mut stmts = Vec::new();
895        loop {
896            match parser.stmt(false) {
897                Ok(stmt) => stmts.push(stmt),
898                Err(err) => {
899                    if parser.is_eof() {
900                        return Ok(stmts);
901                    }
902                    return Err(err);
903                }
904            }
905        }
906    }
907
908    // 调试构建里单帧约 16KB,病态深嵌套即便有深度守卫也会在守卫触发"之前"打爆
909    // 测试线程默认 2MB 栈;因此用大栈线程跑,验证守卫确实返回 TooDeep(而非崩溃)。
910    // 生产是 release 构建,单帧仅数 KB,128 层上限在 8MB 主栈上余量充足。
911    fn run_with_big_stack(f: impl FnOnce() + Send + 'static) {
912        std::thread::Builder::new().stack_size(64 * 1024 * 1024).spawn(f).unwrap().join().unwrap();
913    }
914
915    #[test]
916    fn deeply_nested_parens_error_instead_of_stack_overflow() {
917        run_with_big_stack(|| {
918            let depth = MAX_PARSE_DEPTH + 50;
919            let code = format!("{}1{}", "(".repeat(depth), ")".repeat(depth));
920            let mut parser = Parser::new(code.into_bytes());
921            let err = parser.get_expr().unwrap_err();
922            assert!(err.to_string().contains("嵌套过深"), "got: {err}");
923        });
924    }
925
926    #[test]
927    fn deeply_nested_blocks_error_instead_of_stack_overflow() {
928        run_with_big_stack(|| {
929            let depth = MAX_PARSE_DEPTH + 50;
930            let code = format!("fn f() {}{}{}", "{".repeat(depth), "1", "}".repeat(depth));
931            let err = parse_all(&code).unwrap_err();
932            assert!(err.to_string().contains("嵌套过深"), "got: {err}");
933        });
934    }
935
936    #[test]
937    fn normal_nesting_within_limit_parses() {
938        // 远低于上限的正常嵌套不受影响
939        let code = format!("{}1{}", "(".repeat(32), ")".repeat(32));
940        let mut parser = Parser::new(code.into_bytes());
941        parser.get_expr().unwrap();
942    }
943
944    fn parse_literal(code: &str) -> Result<Dynamic> {
945        let mut parser = Parser::new(code.as_bytes().to_vec());
946        match parser.get_expr()?.kind {
947            crate::ExprKind::Value(value) => Ok(value),
948            other => Err(anyhow!("不是字面量: {:?}", other)),
949        }
950    }
951
952    #[test]
953    fn unsuffixed_integer_defaults_to_i64() {
954        assert_eq!(parse_literal("5").unwrap(), Dynamic::I64(5));
955        // 30 亿:旧的 I32 默认会静默回绕成负数,I64 默认保留正确数值
956        assert_eq!(parse_literal("3000000000").unwrap(), Dynamic::I64(3000000000));
957    }
958
959    #[test]
960    fn out_of_range_integer_literals_error() {
961        // 超出 u64,连 i128 解析也容纳不下 → 报错而非回绕
962        assert!(parse_literal("99999999999999999999999999999999999999999").is_err());
963        // 窄后缀越界
964        assert!(parse_literal("255i8").unwrap_err().to_string().contains("超出"));
965        assert!(parse_literal("70000i16").unwrap_err().to_string().contains("超出"));
966        assert!(parse_literal("256u8").unwrap_err().to_string().contains("超出"));
967    }
968
969    #[test]
970    fn signed_min_magnitude_literals_allowed() {
971        // -128i8 由一元负号 + 字面量 128 组成,字面量 128 必须可被接受
972        assert_eq!(parse_literal("128i8").unwrap(), Dynamic::I8(-128));
973        assert_eq!(parse_literal("9223372036854775808").unwrap(), Dynamic::I64(i64::MIN));
974    }
975
976    #[test]
977    fn hex_literals_keep_bit_pattern() {
978        // 十六进制按位模式语义:0xFFFFFFFF 是合法掩码,默认 I64 容纳为正值
979        assert_eq!(parse_literal("0xFFFFFFFF").unwrap(), Dynamic::I64(0xFFFFFFFF));
980        // 写满目标位宽的掩码允许通过(0xFF -> i8 的 -1)
981        assert_eq!(parse_literal("0xFFi8").unwrap(), Dynamic::I8(-1));
982        assert_eq!(parse_literal("0xFFFFFFFFu32").unwrap(), Dynamic::U32(u32::MAX));
983    }
984
985    // 把表达式 AST 渲染成 S 表达式,用来锁定优先级/结合性(expr.rs 手写树旋转逻辑)。
986    fn shape(code: &str) -> String {
987        let mut parser = Parser::new(code.as_bytes().to_vec());
988        let expr = parser.get_expr().expect("parse");
989        fmt_shape(&expr)
990    }
991
992    fn binop_sym(op: &crate::BinaryOp) -> &'static str {
993        op.symbol()
994    }
995
996    fn fmt_shape(expr: &crate::Expr) -> String {
997        use crate::ExprKind::*;
998        match &expr.kind {
999            Value(v) => format!("{:?}", v).replace("I64(", "").replace("I32(", "").trim_end_matches(')').to_string(),
1000            Ident(name) => name.to_string(),
1001            Unary { op, value } => {
1002                let s = if matches!(op, crate::UnaryOp::Neg) { "-" } else { "!" };
1003                format!("({} {})", s, fmt_shape(value))
1004            }
1005            Binary { left, op, right } => format!("({} {} {})", binop_sym(op), fmt_shape(left), fmt_shape(right)),
1006            Range { start, stop, inclusive } => format!("({} {} {})", if *inclusive { "..=" } else { ".." }, fmt_shape(start), fmt_shape(stop)),
1007            Typed { value, ty } => format!("(as {} {:?})", fmt_shape(value), ty),
1008            other => format!("{:?}", other),
1009        }
1010    }
1011
1012    #[test]
1013    fn precedence_and_associativity_golden() {
1014        // 乘法高于加法
1015        assert_eq!(shape("1 + 2 * 3"), "(+ 1 (* 2 3))");
1016        assert_eq!(shape("1 * 2 + 3"), "(+ (* 1 2) 3)");
1017        // 同级左结合
1018        assert_eq!(shape("1 - 2 - 3"), "(- (- 1 2) 3)");
1019        assert_eq!(shape("8 / 4 / 2"), "(/ (/ 8 4) 2)");
1020        // 移位低于加法
1021        assert_eq!(shape("2 + 3 << 4"), "(<< (+ 2 3) 4)");
1022        // 位运算优先级:& 高于 ^ 高于 |
1023        assert_eq!(shape("1 | 2 ^ 3 & 4"), "(| 1 (^ 2 (& 3 4)))");
1024        // 比较低于算术
1025        assert_eq!(shape("1 + 2 == 3"), "(== (+ 1 2) 3)");
1026        // 逻辑:&& 高于 ||
1027        assert_eq!(shape("a && b || c"), "(|| (&& a b) c)");
1028        // 一元高于乘法
1029        assert_eq!(shape("-a * b"), "(* (- a) b)");
1030        assert_eq!(shape("!a == b"), "(== (! a) b)");
1031    }
1032
1033    #[test]
1034    fn assignment_range_and_as_precedence_golden() {
1035        // 赋值最低优先级,右结合
1036        assert_eq!(shape("a = b + c"), "(= a (+ b c))");
1037        assert_eq!(shape("a = b = c"), "(= a (= b c))");
1038        assert_eq!(shape("a = b = c = d"), "(= a (= b (= c d)))");
1039        // 复合赋值
1040        assert_eq!(shape("a += b * c"), "(+= a (* b c))");
1041        // range 边界是完整算术表达式(上界按完整子表达式解析)
1042        assert_eq!(shape("1 + 1 .. n * 2"), "(.. (+ 1 1) (* n 2))");
1043        assert_eq!(shape("0 ..= n - 1"), "(..= 0 (- n 1))");
1044        // as 紧绑定到操作数,优先级高于二元算术(Rust 语义)
1045        assert_eq!(shape("a + b as i64"), "(+ a (as b I64))");
1046        assert_eq!(shape("a as i64 + b"), "(+ (as a I64) b)");
1047        assert_eq!(shape("(a + b) as i64"), "(as (+ a b) I64)");
1048    }
1049
1050    // 轻量 fuzz:用确定性 PRNG 生成大量随机/半结构化输入喂给解析器,断言它永远
1051    // 不 panic、不崩溃(返回 Ok 或 Err 都可),也不卡死(B2 的深度守卫保证有界)。
1052    // 在大栈线程上跑,避免深嵌套合法解析在调试构建里耗尽测试线程的 2MB 栈。
1053    #[test]
1054    fn parser_never_panics_on_random_input() {
1055        run_with_big_stack(|| {
1056            const FRAGMENTS: &[&str] = &[
1057                "fn", "let", "if", "else", "for", "in", "while", "return", "struct", "impl", "pub", "(", ")", "{", "}", "[", "]", "<", ">", "+", "-", "*", "/", "%", "=", "==", "&&", "||", "..", "..=", "as", "i32",
1058                "u64", "f64", ".", ",", ";", ":", "::", "x", "0", "1", "255i8", "0xFF", "\"s\"", "true", "null", "|a|", "->",
1059            ];
1060            // xorshift64* 确定性 PRNG
1061            let mut state: u64 = 0x9E3779B97F4A7C15;
1062            let mut next = || {
1063                state ^= state >> 12;
1064                state ^= state << 25;
1065                state ^= state >> 27;
1066                state = state.wrapping_mul(0x2545F4914F6CDD1D);
1067                state
1068            };
1069
1070            for _ in 0..4000 {
1071                let mut code = String::new();
1072                let tokens = (next() % 40) as usize;
1073                for _ in 0..tokens {
1074                    code.push_str(FRAGMENTS[(next() as usize) % FRAGMENTS.len()]);
1075                    if next() % 2 == 0 {
1076                        code.push(' ');
1077                    }
1078                }
1079                // 解析全程不应 panic;parse_all 返回 Ok/Err 均可接受。
1080                let result = std::panic::catch_unwind(|| {
1081                    let mut parser = Parser::new(code.clone().into_bytes());
1082                    let mut count = 0;
1083                    loop {
1084                        match parser.stmt(false) {
1085                            Ok(_) => {
1086                                count += 1;
1087                                if parser.is_eof() || count > 1000 {
1088                                    break;
1089                                }
1090                            }
1091                            Err(_) => break,
1092                        }
1093                    }
1094                });
1095                assert!(result.is_ok(), "parser panicked on input: {:?}", code);
1096            }
1097        });
1098    }
1099
1100    #[test]
1101    fn allows_local_name_to_shadow_prior_function() {
1102        parse_all(
1103            r#"
1104            fn chunk_id(x, y) {
1105                x + y
1106            }
1107
1108            fn open() {
1109                let chunk_id = 1;
1110                chunk_id
1111            }
1112            "#,
1113        )
1114        .unwrap();
1115    }
1116
1117    #[test]
1118    fn rejects_duplicate_function_args() {
1119        let err = parse_all("fn open(value, value) { value }").unwrap_err();
1120        assert!(err.to_string().contains("符号 value 已经声明"));
1121    }
1122
1123    #[test]
1124    fn rejects_duplicate_local_let_names() {
1125        let err = parse_all(
1126            r#"
1127            fn open() {
1128                let value = 1;
1129                let value = 2;
1130                value
1131            }
1132            "#,
1133        )
1134        .unwrap_err();
1135        assert!(err.to_string().contains("符号 value 已经声明"));
1136    }
1137
1138    #[test]
1139    fn allows_same_method_name_in_different_impl_blocks() {
1140        parse_all(
1141            r#"
1142            struct A {}
1143            struct B {}
1144
1145            impl A {
1146                fn zero() { 0 }
1147            }
1148
1149            impl B {
1150                fn zero() { 0 }
1151            }
1152            "#,
1153        )
1154        .unwrap();
1155    }
1156
1157    #[test]
1158    fn rejects_nested_fn_inside_function_body() {
1159        let err = parse_all("fn outer() { fn inner() { 1 } }").unwrap_err();
1160        assert!(err.to_string().contains("函数体内不能定义"), "got: {err}");
1161    }
1162
1163    #[test]
1164    fn rejects_nested_struct_inside_function_body() {
1165        let err = parse_all("fn outer() { struct S { x: i32 } S{x: 1} }").unwrap_err();
1166        assert!(err.to_string().contains("函数体内不能定义"), "got: {err}");
1167    }
1168
1169    #[test]
1170    fn rejects_nested_const_inside_function_body() {
1171        let err = parse_all("fn outer() { const K = 1 } K").unwrap_err();
1172        assert!(err.to_string().contains("函数体内不能定义"), "got: {err}");
1173    }
1174
1175    /// 修复回归:`r#` / `r####` 后续 EOF 不再越界 panic,只返回 Err。
1176    /// 修复前会在 `text()` 收集 `#` 前缀时直接 `self.buf[self.pos]` 越界。
1177    #[test]
1178    fn raw_string_with_only_hashes_does_not_panic_at_eof() {
1179        for input in [b"r#" as &[u8], b"r##", b"r###", b"r########", b"r#\"", b"r#\"unterminated"] {
1180            let mut p = Parser::new(input.to_vec());
1181            // 不应 panic;Ok 或 Err 均可接受。
1182            let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| p.text()));
1183            assert!(result.is_ok(), "raw-string parser panicked on input {:?}", input);
1184        }
1185    }
1186
1187    #[test]
1188    fn raw_string_unterminated_returns_error_not_panic() {
1189        // `r#"abc` 缺闭合 → 应当返回 Err 而不是 panic。
1190        let mut p = Parser::new(b"r#\"abc".to_vec());
1191        let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| p.text()));
1192        assert!(result.is_ok(), "raw-string unterminated input should not panic");
1193        let err = result.unwrap().expect_err("unterminated raw string should error");
1194        assert!(err.to_string().contains("未关闭") || err.to_string().contains("unclosed"), "got: {err}");
1195    }
1196
1197    #[test]
1198    fn raw_string_simple_still_parses() {
1199        // 保证正常路径没被破坏:`r"abc"` / `r#"a"#` / `r##"b"##` 都能解析。
1200        let mut p = Parser::new(b"r\"abc\"".to_vec());
1201        assert_eq!(p.text().unwrap().as_str(), "abc");
1202        let mut p = Parser::new(b"r#\"a\"#".to_vec());
1203        assert_eq!(p.text().unwrap().as_str(), "a");
1204        let mut p = Parser::new(b"r##\"b\"##".to_vec());
1205        assert_eq!(p.text().unwrap().as_str(), "b");
1206    }
1207
1208    #[test]
1209    fn hex_escape_at_end_of_string_preserves_byte() {
1210        let mut p = Parser::new(br#""abc\x41""#.to_vec());
1211        let s = p.string().unwrap();
1212        assert_eq!(s.as_str(), "abcA");
1213    }
1214
1215    #[test]
1216    fn hex_escape_truncated_reports_clear_error() {
1217        let mut p = Parser::new(br#""abc\x""#.to_vec());
1218        let err = p.string().unwrap_err();
1219        assert!(err.to_string().contains("\\x"), "got: {err}");
1220    }
1221
1222    #[test]
1223    fn hex_escape_non_hex_char_reports_clear_error() {
1224        let mut p = Parser::new(br#""abc\xZZ""#.to_vec());
1225        let err = p.string().unwrap_err();
1226        assert!(err.to_string().contains("\\x"), "got: {err}");
1227    }
1228
1229    #[test]
1230    fn else_with_invalid_body_reports_error() {
1231        // 让 block() 在 else 后失败:解析到 '}' 紧跟一个无闭的 '{' 触发 "not code block"
1232        let err = parse_all("fn f() { if true { 1 } else }").unwrap_err();
1233        let msg = err.to_string();
1234        assert!(msg.contains("not code block") || msg.contains("未结束的"), "got: {msg}");
1235    }
1236
1237    #[test]
1238    fn float_literal_with_int_suffix_out_of_range_errors() {
1239        let mut p = Parser::new(b"1e30u8".to_vec());
1240        let err = p.number().unwrap_err();
1241        assert!(err.to_string().contains("超出"), "got: {err}");
1242    }
1243
1244    #[test]
1245    fn float_literal_with_int_suffix_fractional_errors() {
1246        let mut p = Parser::new(b"1.5i32".to_vec());
1247        let err = p.number().unwrap_err();
1248        assert!(err.to_string().contains("超出"), "got: {err}");
1249    }
1250
1251    #[test]
1252    fn float_literal_with_float_suffix_accepts_fractional() {
1253        let mut p = Parser::new(b"1e-3f32".to_vec());
1254        assert!(matches!(p.number().unwrap(), Dynamic::F32(v) if (v - 1e-3).abs() < 1e-8));
1255    }
1256
1257    #[test]
1258    fn allows_closure_inside_function_body() {
1259        parse_all("fn outer() { let f = |x: i32| { x + 1 }; f(1) }").unwrap();
1260    }
1261
1262    /// 修复 Bug 4 回归测试:Unicode 首字符的 ident 在 dict 简写里也能识别。
1263    /// 修复前 `is_shorthand_field_name` 只看首字节是否为 ASCII 字母,
1264    /// 中文 key 用 `{ 中文: 1 }` 形式能 dict 化(因为有 `:` 而非 shorthand),
1265    /// 但 `{ 中文key }` shorthand 会被错误识别。
1266    #[test]
1267    fn dict_shorthand_accepts_unicode_first_char() {
1268        // 简写形式:`{ 中文key }` 必须解析成 `{ "中文key": "中文key" }`,而不是当成块。
1269        let stmts = parse_all("fn f() { let d = { 中文key }; d }").expect("unicode shorthand should parse");
1270        assert_eq!(stmts.len(), 1);
1271    }
1272
1273    /// 修复 spans 累积回归测试:stmt 内部 `?` 提前返回时必须清理 spans 栈。
1274    /// 修复前:`spans` 是手动 push/pop,任何 `?` 冒泡都漏 pop,跨 stmt
1275    /// 反复调用会让 spans 栈深度单调增长。该 bug 在 LSP/multi-error 报告
1276    /// 或在 stmt 自己直接递归调用 `Parser::stmt` 的工具场景下尤其敏感。
1277    #[test]
1278    fn stmt_spans_cleaned_up_after_partial_failure() {
1279        let mut p = Parser::new(b"fn f() { 1".to_vec());
1280        // 第一个 stmt 失败(缺 `}`)。spans 应当被 RAII 守卫清空。
1281        let _ = p.stmt(false).expect_err("first stmt should fail (unclosed brace)");
1282        assert!(p.spans.is_empty(), "第一个 stmt 失败后 spans 应被清空。got: {:?}", p.spans);
1283
1284        // 模拟"忽略第一个错误继续解析" — 反复失败 N 次,spans 应保持空。
1285        for _ in 0..5 {
1286            let _ = p.stmt(false);
1287            assert!(p.spans.is_empty(), "spans 应保持空(没有累积)。got: {:?}", p.spans);
1288        }
1289    }
1290
1291    #[test]
1292    fn rejects_const_inside_impl_body() {
1293        let err = parse_all("struct S {}\nimpl S { const K = 1 }").unwrap_err();
1294        let msg = err.to_string();
1295        assert!(msg.contains("impl 体内不能定义") && msg.contains("const"), "got: {msg}");
1296    }
1297
1298    #[test]
1299    fn allows_fn_inside_impl_body() {
1300        parse_all("struct S {}\nimpl S { pub fn m(self: S) { 1 } }").unwrap();
1301    }
1302
1303    /// 修复 Bug 3 回归测试:`take` 在 EOF 处不应报"实际字符 `\0`",
1304    /// 而应报"已到文件末尾"。
1305    #[test]
1306    fn take_at_eof_reports_clean_eof_message() {
1307        let mut p = Parser::new(b"fn f(".to_vec());
1308        // 把 pos 推到 EOF
1309        p.whitespace().unwrap();
1310        while p.current_pos() < p.buf.len() {
1311            // consume any leftover
1312            p.whitespace().unwrap();
1313            break;
1314        }
1315        // 直接到末尾:`fn f(` 解析到 `(` 之后,`f` 后续需要 args,会调用 take 期望 `)`,但当前是 EOF。
1316        let mut p = Parser::new(b"fn f(".to_vec());
1317        // 跳到末尾直接调用 take。
1318        p.pos = p.buf.len();
1319        let err = p.take(b')').expect_err("take at EOF should error");
1320        let msg = err.downcast_ref::<crate::ParserErr>().map(|e| e.message().to_string()).unwrap_or_else(|| format!("{err:#}"));
1321        assert!(msg.contains("已到文件末尾") || msg.contains("末尾"), "expected EOF message, got: {msg}");
1322        assert!(!msg.contains(''), "should not contain NUL char, got: {msg}");
1323    }
1324
1325    #[test]
1326    fn parser_err_carries_span() {
1327        // 用 fn 重复声明触发 DuplicateSymbol,ParserErr span 应当指向重复位置。
1328        let src = "fn f() {}\nfn f() {}\n";
1329        let err = parse_all(src).unwrap_err();
1330        eprintln!("err display: {err}");
1331        let downcast = err.downcast_ref::<ParserErr>().expect("ParserErr");
1332        eprintln!("message: {}", downcast.message());
1333        eprintln!("span: {:?}", downcast.span());
1334        assert!(downcast.message().contains("f"));
1335        // span 应当在文件范围内
1336        assert!(downcast.span().start < src.len());
1337    }
1338
1339    #[test]
1340    fn block_as_let_value_is_expression() {
1341        parse_all("pub fn f() { let x = { let y = 1; y + 1 }; x }").unwrap();
1342    }
1343
1344    #[test]
1345    fn dict_still_takes_priority_over_block() {
1346        // dict 仍是 dict,不能误判为 block
1347        parse_all("pub fn f() { let d = { key: 1 }; d }").unwrap();
1348    }
1349
1350    #[test]
1351    fn list_pattern_with_rest_parses() {
1352        parse_all("pub fn f(items) { let [first, ..rest] = items; first }").unwrap();
1353    }
1354
1355    #[test]
1356    fn list_pattern_with_only_rest_parses() {
1357        parse_all("pub fn f(items) { let [..all] = items; all }").unwrap();
1358    }
1359
1360    #[test]
1361    fn take_error_carries_precise_pos() {
1362        // take 失败时,SpannedParseError.pos 应该指向缺失字符的位置,
1363        // 而不是 parse_code 默认的 parser.current_pos。
1364        use crate::SpannedParseError;
1365        let mut p = Parser::new(b"ab".to_vec());
1366        let pos_before = p.current_pos();
1367        let err = p.take(b'c').unwrap_err();
1368        let spanned = err.downcast_ref::<SpannedParseError>().expect("take should wrap in SpannedParseError");
1369        // take 在 pos_before 处失败,期望 pos == pos_before(0)
1370        assert_eq!(spanned.pos, pos_before);
1371    }
1372
1373    #[test]
1374    fn parses_scientific_float_suffixes() {
1375        let mut parser = Parser::new(b"1.7976931348623157e308f64".to_vec());
1376        assert_eq!(parser.number().unwrap(), Dynamic::F64(1.7976931348623157e308));
1377
1378        let mut parser = Parser::new(b"1e-3f32".to_vec());
1379        assert_eq!(parser.number().unwrap(), Dynamic::F32(1e-3f32));
1380    }
1381
1382    #[test]
1383    fn parses_immediate_closure_call() {
1384        let mut parser = Parser::new(b"|| { 1i32 }()".to_vec());
1385        let expr = parser.get_expr().unwrap();
1386        let ExprKind::Call { obj, params } = expr.kind else {
1387            panic!("expected closure call, got {expr:?}");
1388        };
1389        assert!(params.is_empty());
1390        let ExprKind::Closure { args, .. } = obj.kind else {
1391            panic!("expected closure callee, got {obj:?}");
1392        };
1393        assert!(args.is_empty());
1394    }
1395
1396    #[test]
1397    fn parses_empty_tuple_expression() {
1398        let mut parser = Parser::new(b"()".to_vec());
1399        let expr = parser.get_expr().unwrap();
1400        let ExprKind::Tuple(items) = expr.kind else {
1401            panic!("expected empty tuple, got {expr:?}");
1402        };
1403        assert!(items.is_empty());
1404    }
1405
1406    #[test]
1407    fn parses_explicit_generic_function_call() {
1408        let mut parser = Parser::new(b"value::<4>()".to_vec());
1409        let expr = parser.get_expr().unwrap();
1410        let ExprKind::Call { obj, params } = expr.kind else {
1411            panic!("expected function call, got {expr:?}");
1412        };
1413        assert!(params.is_empty());
1414        let ExprKind::Generic { obj, params } = obj.kind else {
1415            panic!("expected generic callee, got {obj:?}");
1416        };
1417        assert!(matches!(obj.kind, ExprKind::Ident(name) if name.as_str() == "value"));
1418        assert!(matches!(params.as_slice(), [Type::ConstInt(4)]));
1419    }
1420
1421    #[test]
1422    fn parses_import_top_level_declaration() {
1423        // 顶层 import 声明:`import "module";` 和 `import "module", "path";`。
1424        let stmts = parse_all(r#"import "foo";"#).expect("parse import decl");
1425        assert_eq!(stmts.len(), 1);
1426        let StmtKind::Import { module, path, is_pub } = &stmts[0].kind else {
1427            panic!("expected StmtKind::Import, got {:?}", stmts[0].kind);
1428        };
1429        assert_eq!(module.as_str(), "foo");
1430        assert_eq!(path.as_str(), "foo.zs", "省略路径时默认 <module>.zs");
1431        assert!(!*is_pub);
1432
1433        let stmts = parse_all(r#"import "foo", "bar.zs";"#).expect("parse import decl with path");
1434        let StmtKind::Import { module, path, .. } = &stmts[0].kind else {
1435            panic!("expected StmtKind::Import, got {:?}", stmts[0].kind);
1436        };
1437        assert_eq!(module.as_str(), "foo");
1438        assert_eq!(path.as_str(), "bar.zs");
1439
1440        let stmts = parse_all(r#"pub import "foo";"#).expect("parse pub import");
1441        let StmtKind::Import { module, is_pub, .. } = &stmts[0].kind else {
1442            panic!("expected StmtKind::Import, got {:?}", stmts[0].kind);
1443        };
1444        assert_eq!(module.as_str(), "foo");
1445        assert!(*is_pub);
1446    }
1447
1448    #[test]
1449    fn import_call_form_is_still_recognized_as_expression() {
1450        // 兼容旧 `import("name", "path");` 函数调用形式 —— 仍要能解析
1451        // 成 `Expr(Call(import, ...))`,不应当成 import 顶层声明。
1452        // 因为 `import` 后面紧跟 `(`(不是空白+字符串),peek 走 fall-through。
1453        let stmts = parse_all(r#"import("foo", "foo.zs");"#).expect("parse import call");
1454        assert_eq!(stmts.len(), 1);
1455        let StmtKind::Expr(expr, _) = &stmts[0].kind else {
1456            panic!("expected StmtKind::Expr, got {:?}", stmts[0].kind);
1457        };
1458        let ExprKind::Call { obj, params } = &expr.kind else {
1459            panic!("expected ExprKind::Call, got {expr:?}");
1460        };
1461        let ExprKind::Ident(name) = &obj.kind else {
1462            panic!("expected ident callee, got {:?}", obj.kind);
1463        };
1464        assert_eq!(name.as_str(), "import");
1465        assert_eq!(params.len(), 2);
1466    }
1467
1468    #[test]
1469    fn parses_bigfloat_cmp_context_segment() {
1470        let code = r#"
1471            struct BigFloat<N> { data: [u32; N], exp: i32, sign: bool }
1472
1473            impl BigFloat<N> {
1474                fn abs_cmp(self: BigFloat<N>, rhs: BigFloat<N>) {
1475                    let self_high = self.exp + ((N - 1) as i32);
1476                    let rhs_high = rhs.exp + ((N - 1) as i32);
1477                    let high = if self_high >= rhs_high { self_high } else { rhs_high };
1478                    let low = if self.exp <= rhs.exp { self.exp } else { rhs.exp };
1479                    let result = 0i32;
1480                    let power = high;
1481
1482                    while power >= low && result == 0i32 {
1483                        let a_idx = power - self.exp;
1484                        let b_idx = power - rhs.exp;
1485                        let a_limb = 0u32;
1486                        let b_limb = 0u32;
1487
1488                        if a_idx >= 0i32 && a_idx < (N as i32) {
1489                            a_limb = self.data[a_idx as u32];
1490                        }
1491                        if b_idx >= 0i32 && b_idx < (N as i32) {
1492                            b_limb = rhs.data[b_idx as u32];
1493                        }
1494
1495                        if a_limb > b_limb {
1496                            result = 1i32;
1497                        } else if a_limb < b_limb {
1498                            result = -1i32;
1499                        }
1500
1501                        power -= 1i32;
1502                    }
1503
1504                    result
1505                }
1506
1507                pub fn cmp(self: BigFloat<N>, rhs: BigFloat<N>) {
1508                    if self.is_zero() && rhs.is_zero() {
1509                        0i32
1510                    } else if self.sign != rhs.sign {
1511                        if self.sign { -1i32 } else { 1i32 }
1512                    } else {
1513                        let cmp = self.abs_cmp(rhs);
1514                        if self.sign { -cmp } else { cmp }
1515                    }
1516                }
1517            }
1518            "#;
1519        parse_all(code).unwrap();
1520    }
1521
1522    #[test]
1523    fn parses_bigfloat_file() {
1524        let code = include_str!("../../zusts/bigfloat.zs");
1525        parse_all(code).unwrap();
1526    }
1527}