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, buf: Vec<u8>, 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; 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_in_current_scope(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 self.buf.get(self.pos).cloned().ok_or(ParserErr::EndofInput.into())
221 }
222
223 pub fn take(&mut self, ch: u8) -> Result<()> {
224 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 self.whitespace()?;
236 self.take(ch)
237 }
238
239 pub fn ahead(&self) -> Result<u8> {
240 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.get()? != b'"' {
464 return Err(ParserErr::NotString.into());
465 }
466 self.pos += 1;
467 let mut text_buf = Vec::new();
468 while self.pos < self.buf.len() {
469 if self.buf[self.pos] == b'\\' {
470 self.pos += 1;
472 match self.buf[self.pos] {
473 b'n' => { text_buf.push(b'\n'); self.pos += 1; }
474 b'r' => { text_buf.push(b'\r'); self.pos += 1; }
475 b't' => { text_buf.push(b'\t'); self.pos += 1; }
476 ch @ (b'\\' | b'"') => {
477 text_buf.push(ch);
478 self.pos += 1;
479 }
480 b'u' => {
481 self.pos += 1;
482 let unicode = if self.take(b'{').is_ok() {
483 let code = self.hex()?;
484 self.pos += 1;
485 code
486 } else {
487 self.hex()?
488 };
489 let ch = char::from_u32(unicode as u32).ok_or(anyhow!("非法 unicode {}", unicode))?;
490 let mut utf8_buf = [0u8; 4];
491 let s = ch.encode_utf8(&mut utf8_buf);
492 text_buf.extend_from_slice(s.as_bytes());
493 }
494 b'x' => {
495 self.pos += 1;
496 if self.pos + 2 < self.buf.len() {
497 let start = self.pos;
498 self.pos += 2;
499 let hex = &self.buf[start..self.pos];
500 let code = u32::from_str_radix(String::from_utf8_lossy(hex).as_ref(), 16)?;
501 text_buf.push(code as u8);
502 }
503 }
504 other => {
505 return Err(anyhow!("invalid escape character: {}", other as char));
506 }
507 }
508 } else {
509 if self.buf[self.pos] == b'"' {
510 self.pos += 1;
511 return Ok(String::from_utf8(text_buf)?.into());
512 }
513 text_buf.push(self.buf[self.pos]);
514 self.pos += 1;
515 }
516 }
517 Err(ParserErr::UnclosedString.into())
518 }
519
520 pub fn text(&mut self) -> Result<SmolStr> {
521 if self.get()? == b'r' && [b'#', b'"'].contains(&self.ahead()?) {
522 self.pos += 1;
523 let mut end = String::from("\"");
524 while self.buf[self.pos] == b'#' {
525 end.push('#');
526 self.pos += 1;
527 }
528 if self.get()? != b'"' {
529 return Err(ParserErr::IllegalRawString.into());
530 }
531 self.pos += 1;
532 let start_pos = self.pos;
533 while self.pos < self.buf.len() {
534 if self.just(&end).is_ok() {
535 break;
536 }
537 self.pos += 1;
538 }
539 Ok(self.get_str(start_pos, self.pos - end.len()))
540 } else {
541 self.string()
542 }
543 }
544
545 fn hex(&mut self) -> Result<i32> {
546 let (start, stop) = self.collect(|ch| (ch >= b'0' && ch <= b'9') || (ch >= b'a' && ch <= b'f') || (ch >= b'A' && ch <= b'F'))?;
548 Ok(i32::from_str_radix(&String::from_utf8_lossy(&self.buf[start..stop]), 16)?)
549 }
550
551 fn numeric_suffix(&mut self) -> Option<Type> {
552 let save = self.pos;
553 for (name, ty) in TYPES {
554 if !ty.is_native() || *ty == Type::F16 {
555 continue;
556 }
557 if self.buf.len() >= self.pos + name.len() && self.buf[self.pos..self.pos + name.len()].eq(name.as_bytes()) {
558 self.pos += name.len();
559 return Some(ty.clone());
560 }
561 }
562 self.pos = save;
563 None
564 }
565
566 fn int_literal(&mut self, digits: &str, radix: u32, suffix: Option<Type>) -> Result<Dynamic> {
567 Ok(match suffix.unwrap_or(Type::I32) {
568 Type::I8 => Dynamic::I8(i128::from_str_radix(digits, radix)? as i8),
569 Type::I16 => Dynamic::I16(i128::from_str_radix(digits, radix)? as i16),
570 Type::I32 => Dynamic::I32(i128::from_str_radix(digits, radix)? as i32),
571 Type::I64 => Dynamic::I64(i128::from_str_radix(digits, radix)? as i64),
572 Type::U8 => Dynamic::U8(u128::from_str_radix(digits, radix)? as u8),
573 Type::U16 => Dynamic::U16(u128::from_str_radix(digits, radix)? as u16),
574 Type::U32 => Dynamic::U32(u128::from_str_radix(digits, radix)? as u32),
575 Type::U64 => Dynamic::U64(u128::from_str_radix(digits, radix)? as u64),
576 Type::F32 => Dynamic::F32(u128::from_str_radix(digits, radix)? as f32),
577 Type::F64 => Dynamic::F64(u128::from_str_radix(digits, radix)? as f64),
578 ty => return Err(anyhow!("{:?} 不能作为数字后缀", ty)),
579 })
580 }
581
582 fn float_literal(&mut self, digits: &str, suffix: Option<Type>) -> Result<Dynamic> {
583 let value: f64 = digits.parse()?;
584 Ok(match suffix.unwrap_or(Type::F32) {
585 Type::I8 => Dynamic::I8(value as i8),
586 Type::I16 => Dynamic::I16(value as i16),
587 Type::I32 => Dynamic::I32(value as i32),
588 Type::I64 => Dynamic::I64(value as i64),
589 Type::U8 => Dynamic::U8(value as u8),
590 Type::U16 => Dynamic::U16(value as u16),
591 Type::U32 => Dynamic::U32(value as u32),
592 Type::U64 => Dynamic::U64(value as u64),
593 Type::F32 => Dynamic::F32(value as f32),
594 Type::F64 => Dynamic::F64(value),
595 ty => return Err(anyhow!("{:?} 不能作为浮点数字后缀", ty)),
596 })
597 }
598
599 pub fn number(&mut self) -> Result<Dynamic> {
600 if self.get()? == b'0' {
601 if [b'b', b'B'].contains(&self.ahead()?) {
602 self.pos += 2;
603 let (start, stop) = self.collect(|ch| ch == b'0' || ch == b'1')?;
604 let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
605 let suffix = self.numeric_suffix();
606 return self.int_literal(&s, 2, suffix);
607 } else if [b'o', b'O'].contains(&self.ahead()?) {
608 self.pos += 2;
609 let (start, stop) = self.collect(|ch| ch >= b'0' && ch <= b'7')?;
610 let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
611 let suffix = self.numeric_suffix();
612 return self.int_literal(&s, 8, suffix);
613 } else if [b'x', b'X'].contains(&self.ahead()?) {
614 self.pos += 2;
615 let (start, stop) = self.collect(|ch| (ch >= b'0' && ch <= b'9') || (ch >= b'a' && ch <= b'f') || (ch >= b'A' && ch <= b'F'))?;
616 let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
617 let suffix = self.numeric_suffix();
618 return self.int_literal(&s, 16, suffix);
619 }
620 }
621 let start = self.pos;
622 while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
623 self.pos += 1;
624 }
625 let mut is_float = false;
626 if self.pos < self.buf.len() && self.buf[self.pos] == b'.' && self.ahead().map(|ch| ch <= b'9' && ch >= b'0').unwrap_or(false) {
627 is_float = true;
628 self.pos += 1;
629 while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
630 self.pos += 1;
631 }
632 }
633 if self.pos < self.buf.len() && (self.buf[self.pos] == b'e' || self.buf[self.pos] == b'E') {
634 let mut exp_pos = self.pos + 1;
635 if exp_pos < self.buf.len() && (self.buf[exp_pos] == b'+' || self.buf[exp_pos] == b'-') {
636 exp_pos += 1;
637 }
638 if exp_pos < self.buf.len() && self.buf[exp_pos] <= b'9' && self.buf[exp_pos] >= b'0' {
639 is_float = true;
640 self.pos = exp_pos + 1;
641 while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
642 self.pos += 1;
643 }
644 }
645 }
646 if self.pos > start {
647 let text = String::from_utf8_lossy(&self.buf[start..self.pos]).to_string();
648 let suffix = self.numeric_suffix();
649 if is_float {
650 return self.float_literal(&text, suffix);
651 }
652 return self.int_literal(&text, 10, suffix);
653 }
654 Err(ParserErr::NotNumber.into())
655 }
656}
657
658#[cfg(test)]
659mod tests {
660 use super::*;
661
662 fn parse_all(code: &str) -> Result<Vec<Stmt>> {
663 let mut parser = Parser::new(code.as_bytes().to_vec());
664 let mut stmts = Vec::new();
665 loop {
666 match parser.stmt(false) {
667 Ok(stmt) => stmts.push(stmt),
668 Err(err) => {
669 if parser.is_eof() {
670 return Ok(stmts);
671 }
672 return Err(err);
673 }
674 }
675 }
676 }
677
678 #[test]
679 fn allows_local_name_to_shadow_prior_function() {
680 parse_all(
681 r#"
682 fn chunk_id(x, y) {
683 x + y
684 }
685
686 fn open() {
687 let chunk_id = 1;
688 chunk_id
689 }
690 "#,
691 )
692 .unwrap();
693 }
694
695 #[test]
696 fn rejects_duplicate_function_args() {
697 let err = parse_all("fn open(value, value) { value }").unwrap_err();
698 assert!(err.to_string().contains("符号 value 已经声明"));
699 }
700
701 #[test]
702 fn rejects_duplicate_local_let_names() {
703 let err = parse_all(
704 r#"
705 fn open() {
706 let value = 1;
707 let value = 2;
708 value
709 }
710 "#,
711 )
712 .unwrap_err();
713 assert!(err.to_string().contains("符号 value 已经声明"));
714 }
715
716 #[test]
717 fn allows_same_method_name_in_different_impl_blocks() {
718 parse_all(
719 r#"
720 struct A {}
721 struct B {}
722
723 impl A {
724 fn zero() { 0 }
725 }
726
727 impl B {
728 fn zero() { 0 }
729 }
730 "#,
731 )
732 .unwrap();
733 }
734
735 #[test]
736 fn parses_scientific_float_suffixes() {
737 let mut parser = Parser::new(b"1.7976931348623157e308f64".to_vec());
738 assert_eq!(parser.number().unwrap(), Dynamic::F64(1.7976931348623157e308));
739
740 let mut parser = Parser::new(b"1e-3f32".to_vec());
741 assert_eq!(parser.number().unwrap(), Dynamic::F32(1e-3f32));
742 }
743
744 #[test]
745 fn parses_immediate_closure_call() {
746 let mut parser = Parser::new(b"|| { 1i32 }()".to_vec());
747 let expr = parser.get_expr().unwrap();
748 let ExprKind::Call { obj, params } = expr.kind else {
749 panic!("expected closure call, got {expr:?}");
750 };
751 assert!(params.is_empty());
752 let ExprKind::Closure { args, .. } = obj.kind else {
753 panic!("expected closure callee, got {obj:?}");
754 };
755 assert!(args.is_empty());
756 }
757
758 #[test]
759 fn parses_empty_tuple_expression() {
760 let mut parser = Parser::new(b"()".to_vec());
761 let expr = parser.get_expr().unwrap();
762 let ExprKind::Tuple(items) = expr.kind else {
763 panic!("expected empty tuple, got {expr:?}");
764 };
765 assert!(items.is_empty());
766 }
767
768 #[test]
769 fn parses_explicit_generic_function_call() {
770 let mut parser = Parser::new(b"value::<4>()".to_vec());
771 let expr = parser.get_expr().unwrap();
772 let ExprKind::Call { obj, params } = expr.kind else {
773 panic!("expected function call, got {expr:?}");
774 };
775 assert!(params.is_empty());
776 let ExprKind::Generic { obj, params } = obj.kind else {
777 panic!("expected generic callee, got {obj:?}");
778 };
779 assert!(matches!(obj.kind, ExprKind::Ident(name) if name.as_str() == "value"));
780 assert!(matches!(params.as_slice(), [Type::ConstInt(4)]));
781 }
782
783 #[test]
784 fn parses_bigfloat_cmp_context_segment() {
785 let code = r#"
786 struct BigFloat<N> { data: [u32; N], exp: i32, sign: bool }
787
788 impl BigFloat<N> {
789 fn abs_cmp(self: BigFloat<N>, rhs: BigFloat<N>) {
790 let self_high = self.exp + ((N - 1) as i32);
791 let rhs_high = rhs.exp + ((N - 1) as i32);
792 let high = if self_high >= rhs_high { self_high } else { rhs_high };
793 let low = if self.exp <= rhs.exp { self.exp } else { rhs.exp };
794 let result = 0i32;
795 let power = high;
796
797 while power >= low && result == 0i32 {
798 let a_idx = power - self.exp;
799 let b_idx = power - rhs.exp;
800 let a_limb = 0u32;
801 let b_limb = 0u32;
802
803 if a_idx >= 0i32 && a_idx < (N as i32) {
804 a_limb = self.data[a_idx as u32];
805 }
806 if b_idx >= 0i32 && b_idx < (N as i32) {
807 b_limb = rhs.data[b_idx as u32];
808 }
809
810 if a_limb > b_limb {
811 result = 1i32;
812 } else if a_limb < b_limb {
813 result = -1i32;
814 }
815
816 power -= 1i32;
817 }
818
819 result
820 }
821
822 pub fn cmp(self: BigFloat<N>, rhs: BigFloat<N>) {
823 if self.is_zero() && rhs.is_zero() {
824 0i32
825 } else if self.sign != rhs.sign {
826 if self.sign { -1i32 } else { 1i32 }
827 } else {
828 let cmp = self.abs_cmp(rhs);
829 if self.sign { -cmp } else { cmp }
830 }
831 }
832 }
833 "#;
834 parse_all(code).unwrap();
835 }
836
837 #[test]
838 fn parses_bigfloat_file() {
839 let code = include_str!("../../zusts/bigfloat.zs");
840 parse_all(code).unwrap();
841 }
842}