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)]
37pub struct Parser {
38    pos: usize,   //当前解析的位置
39    buf: Vec<u8>, //待解析的字符串
40    spans: Vec<usize>,
41    decl_scopes: Vec<BTreeSet<SmolStr>>,
42    impl_depth: usize,
43}
44
45const 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'\''];
46const WHITE_SPACE: &[u8] = &[b' ', b'\t', b'\n', b'\r'];
47const TYPES: &[(&str, Type)] = &[
48    ("bool", Type::Bool),
49    ("string", Type::Str),
50    ("i8", Type::I8),
51    ("i16", Type::I16),
52    ("i32", Type::I32),
53    ("i64", Type::I64),
54    ("u8", Type::U8),
55    ("u16", Type::U16),
56    ("u32", Type::U32),
57    ("u64", Type::U64),
58    ("f16", Type::F16),
59    ("f32", Type::F32),
60    ("f64", Type::F64),
61];
62const KEYWORDS: &[&str] = &["true", "false", "null", "let", "if", "else", "for", "in", "while", "pub", "fn", "struct", "impl", "const", "static", "continue", "return", "break"];
63
64#[macro_export]
65macro_rules! parse_list {
66    ($self: ident, $start: expr, $end: expr, $sep: expr, $item_expr: expr) => {{
67        let mut items = $start;
68        loop {
69            $self.whitespace()?;
70            if $self.get()? == $end {
71                $self.pos += 1;
72                break;
73            }
74            let item = $item_expr;
75            items.push(item);
76            $self.whitespace()?;
77            if $self.get()? == $sep {
78                $self.pos += 1;
79            }
80        }
81        items
82    }};
83}
84
85#[macro_export]
86macro_rules! try_parse {
87    ($self: ident, $method: expr) => {{
88        let save_pos = $self.pos; //保存当前 pos
89        let save_decl_scopes = $self.decl_scopes.clone();
90        let save_impl_depth = $self.impl_depth;
91        match $method {
92            Ok(expr) => Ok(expr),
93            Err(e) => {
94                $self.pos = save_pos;
95                $self.decl_scopes = save_decl_scopes;
96                $self.impl_depth = save_impl_depth;
97                Err(e)
98            }
99        }
100    }};
101}
102
103#[derive(Debug, thiserror::Error)]
104pub enum ParserErr {
105    #[error("期望字符 {0} 实际字符 {1}")]
106    ExpectChar(char, char),
107    #[error("未发现期望字符")]
108    NoCharCollect,
109    #[error("期望字符串 {0}")]
110    ExpectedString(SmolStr),
111    #[error("输入结束")]
112    EndofInput,
113    #[error("未关闭的注释")]
114    UncloseComment,
115    #[error("非法的原始字符串")]
116    IllegalRawString,
117    #[error("未关闭字符串")]
118    UnclosedString,
119    #[error("非字符串")]
120    NotString,
121    #[error("非数字")]
122    NotNumber,
123    #[error("符号 {0} 已经声明")]
124    DuplicateSymbol(SmolStr),
125}
126
127impl Parser {
128    pub fn new(buf: Vec<u8>) -> Self {
129        Self { pos: 0, buf, spans: Vec::new(), decl_scopes: vec![BTreeSet::new()], impl_depth: 0 }
130    }
131
132    fn push_decl_scope(&mut self) {
133        self.decl_scopes.push(BTreeSet::new());
134    }
135
136    fn pop_decl_scope(&mut self) {
137        if self.decl_scopes.len() > 1 {
138            self.decl_scopes.pop();
139        }
140    }
141
142    fn declare_symbol(&mut self, name: &SmolStr) -> Result<()> {
143        if name.is_empty() {
144            return Ok(());
145        }
146        if self.decl_scopes.iter().rev().any(|scope| scope.contains(name)) {
147            return Err(ParserErr::DuplicateSymbol(name.clone()).into());
148        }
149        self.decl_scopes.last_mut().expect("parser always has a declaration scope").insert(name.clone());
150        Ok(())
151    }
152
153    fn declare_symbol_in_current_scope(&mut self, name: &SmolStr) -> Result<()> {
154        if name.is_empty() {
155            return Ok(());
156        }
157        let scope = self.decl_scopes.last_mut().expect("parser always has a declaration scope");
158        if scope.contains(name) {
159            return Err(ParserErr::DuplicateSymbol(name.clone()).into());
160        }
161        scope.insert(name.clone());
162        Ok(())
163    }
164
165    fn declare_function_name(&mut self, name: &SmolStr) -> Result<()> {
166        if self.impl_depth > 0 { self.declare_symbol_in_current_scope(name) } else { self.declare_symbol(name) }
167    }
168
169    fn declare_args(&mut self, args: &[(SmolStr, Type)]) -> Result<()> {
170        for (name, _) in args {
171            self.declare_symbol(name)?;
172        }
173        Ok(())
174    }
175
176    fn declare_pattern_symbols(&mut self, pat: &Pattern) -> Result<()> {
177        match &pat.kind {
178            PatternKind::Ident { name, .. } => self.declare_symbol(name),
179            PatternKind::Tuple(items) => {
180                for item in items {
181                    self.declare_pattern_symbols(item)?;
182                }
183                Ok(())
184            }
185            PatternKind::List { elems, .. } => {
186                for item in elems {
187                    self.declare_pattern_symbols(item)?;
188                }
189                Ok(())
190            }
191            PatternKind::Wildcard | PatternKind::Var { .. } | PatternKind::Literal(_) | PatternKind::Member(_, _) | PatternKind::Idx(_, _) => Ok(()),
192        }
193    }
194
195    fn function_body(&mut self, args: &[(SmolStr, Type)]) -> Result<Stmt> {
196        self.push_decl_scope();
197        let result = (|| {
198            self.declare_args(args)?;
199            self.block()
200        })();
201        self.pop_decl_scope();
202        result
203    }
204
205    fn impl_body(&mut self) -> Result<Stmt> {
206        self.push_decl_scope();
207        self.impl_depth += 1;
208        let result = self.block();
209        self.impl_depth -= 1;
210        self.pop_decl_scope();
211        result
212    }
213
214    pub fn is_eof(&self) -> bool {
215        self.pos >= self.buf.len()
216    }
217
218    pub fn get(&self) -> Result<u8> {
219        //查看当前字符
220        self.buf.get(self.pos).cloned().ok_or(ParserErr::EndofInput.into())
221    }
222
223    pub fn take(&mut self, ch: u8) -> Result<()> {
224        //如果当前字符为 ch 消费该字符 返回 Ok(())
225        if self.buf.get(self.pos).map(|b| *b == ch).unwrap_or(false) {
226            self.pos += 1;
227            Ok(())
228        } else {
229            Err(ParserErr::ExpectChar(ch as char, self.buf.get(self.pos as usize).cloned().unwrap_or(0) as char).into())
230        }
231    }
232
233    pub fn until(&mut self, ch: u8) -> Result<()> {
234        //消费直到指定字符 ch 忽略空白和注释
235        self.whitespace()?;
236        self.take(ch)
237    }
238
239    pub fn ahead(&self) -> Result<u8> {
240        //朝前看
241        self.buf.get(self.pos + 1).cloned().ok_or(ParserErr::EndofInput.into())
242    }
243
244    pub fn get_str(&self, start: usize, stop: usize) -> SmolStr {
245        SmolStr::from(String::from_utf8_lossy(&self.buf[start..stop]))
246    }
247
248    pub fn error_stmt(&self) -> SmolStr {
249        SmolStr::from(String::from_utf8_lossy(&self.buf[self.spans.last().cloned().unwrap_or(0)..self.pos]))
250    }
251
252    pub fn current_pos(&self) -> usize {
253        self.pos
254    }
255
256    pub fn span_from(&self, start: usize) -> Span {
257        Span::new(start, self.pos)
258    }
259
260    pub fn collect<F: Fn(u8) -> bool>(&mut self, f: F) -> Result<(usize, usize)> {
261        let start = self.pos;
262        while self.pos < self.buf.len() && f(self.buf[self.pos]) {
263            self.pos += 1;
264        }
265        if self.pos > start { Ok((start, self.pos)) } else { Err(ParserErr::NoCharCollect.into()) }
266    }
267
268    pub fn just(&mut self, pattern: &str) -> Result<()> {
269        if self.buf.len() - self.pos >= pattern.len() && self.buf[self.pos..self.pos + pattern.len()].eq(pattern.as_bytes()) {
270            self.pos += pattern.len();
271            Ok(())
272        } else {
273            Err(ParserErr::ExpectedString(SmolStr::new(pattern)).into())
274        }
275    }
276
277    pub fn keyword(&mut self, pattern: &str) -> Result<()> {
278        self.just(pattern)?;
279        if self.pos < self.buf.len() && !NOT_IDENT.contains(&self.buf[self.pos]) {
280            self.pos -= pattern.len();
281            return Err(ParserErr::ExpectedString(SmolStr::new(pattern)).into());
282        }
283        Ok(())
284    }
285
286    pub fn get_type(&mut self) -> Result<Type> {
287        self.whitespace()?;
288        if self.get()? == b'[' {
289            self.pos += 1;
290            let ty = self.get_type()?;
291            self.until(b';')?;
292            self.whitespace()?;
293            let len = self.get_type_param()?;
294            self.until(b']')?;
295            if let Type::ConstInt(number) = len {
296                let number = u32::try_from(number).map_err(|_| anyhow!("数组长度超出 u32 范围"))?;
297                Ok(Type::Array(std::rc::Rc::new(ty), number))
298            } else {
299                Ok(Type::ArrayParam(std::rc::Rc::new(ty), std::rc::Rc::new(len)))
300            }
301        } else {
302            for ty in TYPES {
303                if self.just(ty.0).is_ok() {
304                    return Ok(ty.1.clone());
305                }
306            }
307            let name = self.ident()?;
308            if self.take(b'<').is_ok() {
309                let params = crate::parse_list!(self, Vec::new(), b'>', b',', self.get_type_param()?);
310                Ok(Type::Ident { name, params })
311            } else {
312                Ok(Type::Ident { name, params: Vec::new() })
313            }
314        }
315    }
316
317    pub fn get_type_param(&mut self) -> Result<Type> {
318        self.const_type_param_add()
319    }
320
321    fn const_type_param_add(&mut self) -> Result<Type> {
322        let mut left = self.const_type_param_mul()?;
323        loop {
324            self.whitespace()?;
325            let op = if self.take(b'+').is_ok() {
326                Some(ConstIntOp::Add)
327            } else if self.take(b'-').is_ok() {
328                Some(ConstIntOp::Sub)
329            } else {
330                None
331            };
332            let Some(op) = op else { break };
333            let right = self.const_type_param_mul()?;
334            left = Self::fold_const_type_binary(op, left, right)?;
335        }
336        Ok(left)
337    }
338
339    fn const_type_param_mul(&mut self) -> Result<Type> {
340        let mut left = self.const_type_param_primary()?;
341        loop {
342            self.whitespace()?;
343            let op = if self.take(b'*').is_ok() {
344                Some(ConstIntOp::Mul)
345            } else if self.take(b'/').is_ok() {
346                Some(ConstIntOp::Div)
347            } else if self.take(b'%').is_ok() {
348                Some(ConstIntOp::Mod)
349            } else {
350                None
351            };
352            let Some(op) = op else { break };
353            let right = self.const_type_param_primary()?;
354            left = Self::fold_const_type_binary(op, left, right)?;
355        }
356        Ok(left)
357    }
358
359    fn const_type_param_primary(&mut self) -> Result<Type> {
360        self.whitespace()?;
361        if self.take(b'(').is_ok() {
362            let ty = self.get_type_param()?;
363            self.until(b')')?;
364            return Ok(ty);
365        }
366        if self.get()?.is_ascii_digit() {
367            let value = self.number()?;
368            if let Some(value) = value.as_uint() {
369                let value = i64::try_from(value).map_err(|_| anyhow!("模板数字参数超出 i64 范围"))?;
370                Ok(Type::ConstInt(value))
371            } else if let Some(value) = value.as_int() {
372                Ok(Type::ConstInt(value))
373            } else {
374                Err(anyhow!("模板数字参数必须是整数"))
375            }
376        } else {
377            self.get_type()
378        }
379    }
380
381    fn fold_const_type_binary(op: ConstIntOp, left: Type, right: Type) -> Result<Type> {
382        if let (Type::ConstInt(left), Type::ConstInt(right)) = (&left, &right) {
383            let value = match op {
384                ConstIntOp::Add => left + right,
385                ConstIntOp::Sub => left - right,
386                ConstIntOp::Mul => left * right,
387                ConstIntOp::Div => {
388                    if *right == 0 {
389                        return Err(anyhow!("模板整数除以 0"));
390                    }
391                    left / right
392                }
393                ConstIntOp::Mod => {
394                    if *right == 0 {
395                        return Err(anyhow!("模板整数取模 0"));
396                    }
397                    left % right
398                }
399            };
400            Ok(Type::ConstInt(value))
401        } else {
402            Ok(Type::ConstBinary { op, left: std::rc::Rc::new(left), right: std::rc::Rc::new(right) })
403        }
404    }
405
406    pub fn comment(&mut self) -> Result<()> {
407        if self.get()? == b'/' && self.ahead()? == b'/' {
408            self.pos += 2;
409            while self.pos < self.buf.len() && self.buf[self.pos] != b'\n' {
410                self.pos += 1;
411            }
412            Ok(())
413        } else if self.get()? == b'/' && self.ahead()? == b'*' {
414            self.pos += 2;
415            while self.pos + 1 < self.buf.len() {
416                if self.buf[self.pos] == b'*' && self.buf[self.pos + 1] == b'/' {
417                    self.pos += 2;
418                    return Ok(());
419                }
420                self.pos += 1;
421            }
422            Err(ParserErr::UncloseComment.into())
423        } else {
424            Ok(())
425        }
426    }
427
428    pub fn whitespace(&mut self) -> Result<()> {
429        while self.pos < self.buf.len() {
430            self.comment()?;
431            if self.pos >= self.buf.len() || !WHITE_SPACE.contains(&self.buf[self.pos]) {
432                break;
433            }
434            self.pos += 1;
435        }
436        Ok(())
437    }
438
439    pub fn ident(&mut self) -> Result<SmolStr> {
440        let (start, mut stop) = self.collect(|ch| !NOT_IDENT.contains(&ch))?;
441        loop {
442            let save_pos = self.pos;
443            if self.just("::").is_err() {
444                break;
445            }
446            match self.collect(|ch| !NOT_IDENT.contains(&ch)) {
447                Ok((_, next_stop)) => {
448                    stop = next_stop;
449                }
450                Err(_) => {
451                    self.pos = save_pos;
452                    break;
453                }
454            }
455        }
456        if KEYWORDS.iter().position(|k| k.as_bytes() == &self.buf[start..stop]).is_some() {
457            return Err(anyhow!("发现关键字{}", String::from_utf8_lossy(&self.buf[start..stop])));
458        }
459        Ok(self.get_str(start, stop))
460    }
461
462    pub fn string(&mut self) -> Result<SmolStr> {
463        if self.buf[self.pos] == b'"' {
464            self.pos += 1;
465            let mut text_buf = Vec::new();
466            while self.pos < self.buf.len() {
467                if self.buf[self.pos] == b'\\' {
468                    //转义字符
469                    self.pos += 1;
470                    match self.buf[self.pos] {
471                        ch @ (b'n' | b'r' | b't' | b'\\' | b'"') => {
472                            text_buf.push(ch);
473                            self.pos += 1;
474                        }
475                        b'u' => {
476                            self.pos += 1;
477                            let unicode = if self.take(b'{').is_ok() {
478                                let code = self.hex()?;
479                                self.pos += 1;
480                                code
481                            } else {
482                                self.hex()?
483                            };
484                            let ch = char::from_u32(unicode as u32).ok_or(anyhow!("非法 unicode {}", unicode))?;
485                            let mut utf8_buf = [0u8; 4];
486                            let s = ch.encode_utf8(&mut utf8_buf);
487                            text_buf.extend_from_slice(s.as_bytes());
488                        }
489                        b'x' => {
490                            self.pos += 1;
491                            if self.pos + 2 < self.buf.len() {
492                                let start = self.pos;
493                                self.pos += 2;
494                                let hex = &self.buf[start..self.pos];
495                                let code = u32::from_str_radix(String::from_utf8_lossy(hex).as_ref(), 16)?;
496                                text_buf.push(code as u8);
497                            }
498                        }
499                        other => {
500                            return Err(anyhow!("invalid escape character: {}", other as char));
501                        }
502                    }
503                } else {
504                    if self.buf[self.pos] == b'"' {
505                        self.pos += 1;
506                        return Ok(String::from_utf8(text_buf)?.into());
507                    }
508                    text_buf.push(self.buf[self.pos]);
509                    self.pos += 1;
510                }
511            }
512            Err(ParserErr::UnclosedString.into())
513        } else {
514            Err(ParserErr::NotString.into())
515        }
516    }
517
518    pub fn text(&mut self) -> Result<SmolStr> {
519        if self.get()? == b'r' && [b'#', b'"'].contains(&self.ahead()?) {
520            self.pos += 1;
521            let mut end = String::new();
522            while self.buf[self.pos] == b'#' {
523                end.push('#');
524                self.pos += 1;
525            }
526            if self.get()? != b'"' {
527                return Err(ParserErr::IllegalRawString.into());
528            }
529            self.pos += 1;
530            let start_pos = self.pos;
531            while self.pos < self.buf.len() {
532                if self.just(&end).is_ok() {
533                    break;
534                }
535                self.pos += 1;
536            }
537            Ok(self.get_str(start_pos, self.pos - end.len()))
538        } else {
539            self.string()
540        }
541    }
542
543    fn hex(&mut self) -> Result<i32> {
544        //注意 hex 会消耗当前字符 设置新的 self.pos
545        let (start, stop) = self.collect(|ch| (ch >= b'0' && ch <= b'9') || (ch >= b'a' && ch <= b'f') || (ch >= b'A' && ch <= b'F'))?;
546        Ok(i32::from_str_radix(&String::from_utf8_lossy(&self.buf[start..stop]), 16)?)
547    }
548
549    fn numeric_suffix(&mut self) -> Option<Type> {
550        let save = self.pos;
551        for (name, ty) in TYPES {
552            if !ty.is_native() || *ty == Type::F16 {
553                continue;
554            }
555            if self.buf.len() >= self.pos + name.len() && self.buf[self.pos..self.pos + name.len()].eq(name.as_bytes()) {
556                self.pos += name.len();
557                return Some(ty.clone());
558            }
559        }
560        self.pos = save;
561        None
562    }
563
564    fn int_literal(&mut self, digits: &str, radix: u32, suffix: Option<Type>) -> Result<Dynamic> {
565        Ok(match suffix.unwrap_or(Type::I32) {
566            Type::I8 => Dynamic::I8(i128::from_str_radix(digits, radix)? as i8),
567            Type::I16 => Dynamic::I16(i128::from_str_radix(digits, radix)? as i16),
568            Type::I32 => Dynamic::I32(i128::from_str_radix(digits, radix)? as i32),
569            Type::I64 => Dynamic::I64(i128::from_str_radix(digits, radix)? as i64),
570            Type::U8 => Dynamic::U8(u128::from_str_radix(digits, radix)? as u8),
571            Type::U16 => Dynamic::U16(u128::from_str_radix(digits, radix)? as u16),
572            Type::U32 => Dynamic::U32(u128::from_str_radix(digits, radix)? as u32),
573            Type::U64 => Dynamic::U64(u128::from_str_radix(digits, radix)? as u64),
574            Type::F32 => Dynamic::F32(u128::from_str_radix(digits, radix)? as f32),
575            Type::F64 => Dynamic::F64(u128::from_str_radix(digits, radix)? as f64),
576            ty => return Err(anyhow!("{:?} 不能作为数字后缀", ty)),
577        })
578    }
579
580    fn float_literal(&mut self, digits: &str, suffix: Option<Type>) -> Result<Dynamic> {
581        let value: f64 = digits.parse()?;
582        Ok(match suffix.unwrap_or(Type::F32) {
583            Type::I8 => Dynamic::I8(value as i8),
584            Type::I16 => Dynamic::I16(value as i16),
585            Type::I32 => Dynamic::I32(value as i32),
586            Type::I64 => Dynamic::I64(value as i64),
587            Type::U8 => Dynamic::U8(value as u8),
588            Type::U16 => Dynamic::U16(value as u16),
589            Type::U32 => Dynamic::U32(value as u32),
590            Type::U64 => Dynamic::U64(value as u64),
591            Type::F32 => Dynamic::F32(value as f32),
592            Type::F64 => Dynamic::F64(value),
593            ty => return Err(anyhow!("{:?} 不能作为浮点数字后缀", ty)),
594        })
595    }
596
597    pub fn number(&mut self) -> Result<Dynamic> {
598        if self.get()? == b'0' {
599            if [b'b', b'B'].contains(&self.ahead()?) {
600                self.pos += 2;
601                let (start, stop) = self.collect(|ch| ch == b'0' || ch == b'1')?;
602                let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
603                let suffix = self.numeric_suffix();
604                return self.int_literal(&s, 2, suffix);
605            } else if [b'o', b'O'].contains(&self.ahead()?) {
606                self.pos += 2;
607                let (start, stop) = self.collect(|ch| ch >= b'0' && ch <= b'7')?;
608                let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
609                let suffix = self.numeric_suffix();
610                return self.int_literal(&s, 8, suffix);
611            } else if [b'x', b'X'].contains(&self.ahead()?) {
612                self.pos += 2;
613                let (start, stop) = self.collect(|ch| (ch >= b'0' && ch <= b'9') || (ch >= b'a' && ch <= b'f') || (ch >= b'A' && ch <= b'F'))?;
614                let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
615                let suffix = self.numeric_suffix();
616                return self.int_literal(&s, 16, suffix);
617            }
618        }
619        let start = self.pos;
620        while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
621            self.pos += 1;
622        }
623        let mut is_float = false;
624        if self.pos < self.buf.len() && self.buf[self.pos] == b'.' && self.ahead().map(|ch| ch <= b'9' && ch >= b'0').unwrap_or(false) {
625            is_float = true;
626            self.pos += 1;
627            while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
628                self.pos += 1;
629            }
630        }
631        if self.pos < self.buf.len() && (self.buf[self.pos] == b'e' || self.buf[self.pos] == b'E') {
632            let mut exp_pos = self.pos + 1;
633            if exp_pos < self.buf.len() && (self.buf[exp_pos] == b'+' || self.buf[exp_pos] == b'-') {
634                exp_pos += 1;
635            }
636            if exp_pos < self.buf.len() && self.buf[exp_pos] <= b'9' && self.buf[exp_pos] >= b'0' {
637                is_float = true;
638                self.pos = exp_pos + 1;
639                while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
640                    self.pos += 1;
641                }
642            }
643        }
644        if self.pos > start {
645            let text = String::from_utf8_lossy(&self.buf[start..self.pos]).to_string();
646            let suffix = self.numeric_suffix();
647            if is_float {
648                return self.float_literal(&text, suffix);
649            }
650            return self.int_literal(&text, 10, suffix);
651        }
652        Err(ParserErr::NotNumber.into())
653    }
654}
655
656#[cfg(test)]
657mod tests {
658    use super::*;
659
660    fn parse_all(code: &str) -> Result<Vec<Stmt>> {
661        let mut parser = Parser::new(code.as_bytes().to_vec());
662        let mut stmts = Vec::new();
663        loop {
664            match parser.stmt(false) {
665                Ok(stmt) => stmts.push(stmt),
666                Err(err) => {
667                    if parser.is_eof() {
668                        return Ok(stmts);
669                    }
670                    return Err(err);
671                }
672            }
673        }
674    }
675
676    #[test]
677    fn rejects_local_name_that_redeclares_prior_function() {
678        let err = parse_all(
679            r#"
680            fn chunk_id(x, y) {
681                x + y
682            }
683
684            fn open() {
685                let chunk_id = 1;
686                chunk_id
687            }
688            "#,
689        )
690        .unwrap_err();
691        assert!(err.to_string().contains("符号 chunk_id 已经声明"));
692    }
693
694    #[test]
695    fn rejects_duplicate_function_args() {
696        let err = parse_all("fn open(value, value) { value }").unwrap_err();
697        assert!(err.to_string().contains("符号 value 已经声明"));
698    }
699
700    #[test]
701    fn rejects_duplicate_local_let_names() {
702        let err = parse_all(
703            r#"
704            fn open() {
705                let value = 1;
706                let value = 2;
707                value
708            }
709            "#,
710        )
711        .unwrap_err();
712        assert!(err.to_string().contains("符号 value 已经声明"));
713    }
714
715    #[test]
716    fn allows_same_method_name_in_different_impl_blocks() {
717        parse_all(
718            r#"
719            struct A {}
720            struct B {}
721
722            impl A {
723                fn zero() { 0 }
724            }
725
726            impl B {
727                fn zero() { 0 }
728            }
729            "#,
730        )
731        .unwrap();
732    }
733
734    #[test]
735    fn parses_scientific_float_suffixes() {
736        let mut parser = Parser::new(b"1.7976931348623157e308f64".to_vec());
737        assert_eq!(parser.number().unwrap(), Dynamic::F64(1.7976931348623157e308));
738
739        let mut parser = Parser::new(b"1e-3f32".to_vec());
740        assert_eq!(parser.number().unwrap(), Dynamic::F32(1e-3f32));
741    }
742
743    #[test]
744    fn parses_immediate_closure_call() {
745        let mut parser = Parser::new(b"|| { 1i32 }()".to_vec());
746        let expr = parser.get_expr().unwrap();
747        let ExprKind::Call { obj, params } = expr.kind else {
748            panic!("expected closure call, got {expr:?}");
749        };
750        assert!(params.is_empty());
751        let ExprKind::Closure { args, .. } = obj.kind else {
752            panic!("expected closure callee, got {obj:?}");
753        };
754        assert!(args.is_empty());
755    }
756
757    #[test]
758    fn parses_empty_tuple_expression() {
759        let mut parser = Parser::new(b"()".to_vec());
760        let expr = parser.get_expr().unwrap();
761        let ExprKind::Tuple(items) = expr.kind else {
762            panic!("expected empty tuple, got {expr:?}");
763        };
764        assert!(items.is_empty());
765    }
766
767    #[test]
768    fn parses_explicit_generic_function_call() {
769        let mut parser = Parser::new(b"value::<4>()".to_vec());
770        let expr = parser.get_expr().unwrap();
771        let ExprKind::Call { obj, params } = expr.kind else {
772            panic!("expected function call, got {expr:?}");
773        };
774        assert!(params.is_empty());
775        let ExprKind::Generic { obj, params } = obj.kind else {
776            panic!("expected generic callee, got {obj:?}");
777        };
778        assert!(matches!(obj.kind, ExprKind::Ident(name) if name.as_str() == "value"));
779        assert!(matches!(params.as_slice(), [Type::ConstInt(4)]));
780    }
781}