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#[derive(Default, Clone)]
41pub(crate) struct ScopeDepths {
42 pub(crate) impl_depth: usize,
45 pub(crate) impl_body_depth: usize,
48 pub(crate) fn_body_depth: usize,
51 pub(crate) depth: usize,
53}
54
55pub struct Parser {
56 pos: usize, buf: Vec<u8>, spans: Vec<usize>,
59 decl_scopes: Vec<BTreeSet<SmolStr>>,
60 scope_depths: ScopeDepths,
61 pub(crate) match_counter: usize,
64 fatal: bool, }
66
67pub const MAX_PARSE_DEPTH: usize = 128;
74
75const 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'\''];
76const WHITE_SPACE: &[u8] = &[b' ', b'\t', b'\n', b'\r'];
77const TYPES: &[(&str, Type)] = &[
78 ("bool", Type::Bool),
79 ("string", Type::Str),
80 ("i8", Type::I8),
81 ("i16", Type::I16),
82 ("i32", Type::I32),
83 ("i64", Type::I64),
84 ("u8", Type::U8),
85 ("u16", Type::U16),
86 ("u32", Type::U32),
87 ("u64", Type::U64),
88 ("f16", Type::F16),
89 ("f32", Type::F32),
90 ("f64", Type::F64),
91];
92const KEYWORDS: &[&str] = &["true", "false", "null", "let", "if", "else", "for", "in", "while", "loop", "pub", "fn", "struct", "impl", "const", "static", "continue", "return", "break", "match"];
93
94#[macro_export]
95macro_rules! parse_list {
96 ($self: ident, $start: expr, $end: expr, $sep: expr, $item_expr: expr) => {{
97 let mut items = $start;
98 loop {
99 $self.whitespace()?;
100 if $self.get()? == $end {
101 $self.pos += 1;
102 break;
103 }
104 let item = $item_expr;
105 items.push(item);
106 $self.whitespace()?;
107 if $self.get()? == $sep {
108 $self.pos += 1;
109 }
110 }
111 items
112 }};
113}
114
115#[macro_export]
116macro_rules! try_parse {
117 ($self: ident, $method: expr) => {{
118 let save_pos = $self.pos; let save_decl_scopes = $self.decl_scopes.clone();
120 let save_impl_depth = $self.scope_depths.impl_depth;
121 match $method {
122 Ok(expr) => Ok(expr),
123 Err(e) if $self.fatal => Err(e),
125 Err(e) => {
126 $self.pos = save_pos;
127 $self.decl_scopes = save_decl_scopes;
128 $self.scope_depths.impl_depth = save_impl_depth;
129 Err(e)
130 }
131 }
132 }};
133}
134
135#[derive(Debug, thiserror::Error)]
136pub enum ParserErr {
137 #[error("{message}")]
138 Spanned { message: String, span: Span },
139}
140
141impl ParserErr {
142 pub fn new(message: impl Into<String>, span: Span) -> Self {
144 Self::Spanned { message: message.into(), span }
145 }
146
147 pub fn at(message: impl Into<String>, pos: usize) -> Self {
149 Self::Spanned { message: message.into(), span: Span::new(pos, pos) }
150 }
151
152 pub fn span(&self) -> Span {
153 match self {
154 Self::Spanned { span, .. } => *span,
155 }
156 }
157
158 pub fn message(&self) -> &str {
159 match self {
160 Self::Spanned { message, .. } => message,
161 }
162 }
163}
164
165#[derive(Debug, thiserror::Error)]
168#[error("{err}")]
169pub struct SpannedParseError {
170 pub err: ParserErr,
171 pub pos: usize,
172}
173
174impl SpannedParseError {
175 pub fn new(err: ParserErr, pos: usize) -> Self {
176 Self { err, pos }
177 }
178}
179
180impl Parser {
181 pub fn new(buf: Vec<u8>) -> Self {
182 Self { pos: 0, buf, spans: Vec::new(), decl_scopes: vec![BTreeSet::new()], scope_depths: ScopeDepths::default(), match_counter: 0, fatal: false }
183 }
184
185 fn enter_depth(&mut self) -> Result<()> {
192 self.scope_depths.depth += 1;
193 if self.scope_depths.depth > MAX_PARSE_DEPTH {
194 self.scope_depths.depth -= 1;
195 self.fatal = true;
196 return Err(ParserErr::at("表达式嵌套过深", self.current_pos()).into());
197 }
198 Ok(())
199 }
200
201 fn exit_depth(&mut self) {
202 self.scope_depths.depth = self.scope_depths.depth.saturating_sub(1);
203 }
204
205 fn check_fatal(&self) -> Result<()> {
207 if self.fatal { Err(ParserErr::at("表达式嵌套过深", self.current_pos()).into()) } else { Ok(()) }
208 }
209
210 pub(crate) fn push_decl_scope(&mut self) {
211 self.decl_scopes.push(BTreeSet::new());
212 }
213
214 pub(crate) fn pop_decl_scope(&mut self) {
215 if self.decl_scopes.len() > 1 {
216 self.decl_scopes.pop();
217 }
218 }
219
220 fn declare_symbol(&mut self, name: &SmolStr) -> Result<()> {
221 if name.is_empty() {
222 return Ok(());
223 }
224 if self.decl_scopes.iter().rev().any(|scope| scope.contains(name)) {
225 return Err(ParserErr::at(format!("符号 {} 已经声明", name), self.current_pos()).into());
226 }
227 self.decl_scopes.last_mut().expect("parser always has a declaration scope").insert(name.clone());
228 Ok(())
229 }
230
231 pub(crate) fn declare_symbol_in_current_scope(&mut self, name: &SmolStr) -> Result<()> {
232 if name.is_empty() {
233 return Ok(());
234 }
235 let scope = self.decl_scopes.last_mut().expect("parser always has a declaration scope");
236 if scope.contains(name) {
237 return Err(ParserErr::at(format!("符号 {} 已经声明", name), self.current_pos()).into());
238 }
239 scope.insert(name.clone());
240 Ok(())
241 }
242
243 fn declare_function_name(&mut self, name: &SmolStr) -> Result<()> {
244 if self.scope_depths.impl_depth > 0 { self.declare_symbol_in_current_scope(name) } else { self.declare_symbol(name) }
245 }
246
247 fn declare_args(&mut self, args: &[(SmolStr, Type)]) -> Result<()> {
248 for (name, _) in args {
249 self.declare_symbol(name)?;
250 }
251 Ok(())
252 }
253
254 pub(crate) fn declare_pattern_symbols(&mut self, pat: &Pattern) -> Result<()> {
255 match &pat.kind {
256 PatternKind::Ident { name, .. } => self.declare_symbol_in_current_scope(name),
257 PatternKind::Tuple(items) => {
258 for item in items {
259 self.declare_pattern_symbols(item)?;
260 }
261 Ok(())
262 }
263 PatternKind::List { elems, .. } => {
264 for item in elems {
265 self.declare_pattern_symbols(item)?;
266 }
267 Ok(())
268 }
269 PatternKind::Struct { fields, .. } => {
270 for (name, sub) in fields {
271 if let Some(sub) = sub {
272 self.declare_pattern_symbols(sub)?;
273 } else {
274 self.declare_symbol_in_current_scope(name)?;
275 }
276 }
277 Ok(())
278 }
279 PatternKind::Wildcard | PatternKind::Var { .. } | PatternKind::Literal(_) | PatternKind::Member(_, _) | PatternKind::Idx(_, _) => Ok(()),
280 }
281 }
282
283 fn function_body(&mut self, args: &[(SmolStr, Type)]) -> Result<Stmt> {
284 self.push_decl_scope();
285 self.scope_depths.fn_body_depth += 1;
286 let result = (|| {
287 self.declare_args(args)?;
288 self.block()
289 })();
290 self.scope_depths.fn_body_depth -= 1;
291 self.pop_decl_scope();
292 result
293 }
294
295 fn impl_body(&mut self) -> Result<Stmt> {
296 self.push_decl_scope();
297 self.scope_depths.impl_depth += 1;
298 self.scope_depths.impl_body_depth += 1;
299 let result = self.block();
300 self.scope_depths.impl_body_depth -= 1;
301 self.scope_depths.impl_depth -= 1;
302 self.pop_decl_scope();
303 result
304 }
305
306 pub fn is_eof(&self) -> bool {
307 self.pos >= self.buf.len()
308 }
309
310 pub fn get(&self) -> Result<u8> {
311 self.buf.get(self.pos).cloned().ok_or_else(|| ParserErr::at("输入结束", self.pos).into())
313 }
314
315 pub fn take(&mut self, ch: u8) -> Result<()> {
316 if self.buf.get(self.pos).map(|b| *b == ch).unwrap_or(false) {
318 self.pos += 1;
319 Ok(())
320 } else {
321 Err(SpannedParseError::new(ParserErr::at(format!("期望字符 {} 实际字符 {}", ch as char, self.buf.get(self.pos as usize).cloned().unwrap_or(0) as char), self.pos), self.pos).into())
322 }
323 }
324
325 pub fn until(&mut self, ch: u8) -> Result<()> {
326 self.whitespace()?;
328 self.take(ch)
329 }
330
331 pub fn ahead(&self) -> Result<u8> {
332 self.buf.get(self.pos + 1).cloned().ok_or_else(|| ParserErr::at("输入结束", self.pos).into())
334 }
335
336 pub fn get_str(&self, start: usize, stop: usize) -> SmolStr {
337 SmolStr::from(String::from_utf8_lossy(&self.buf[start..stop]))
338 }
339
340 pub fn error_stmt(&self) -> SmolStr {
341 SmolStr::from(String::from_utf8_lossy(&self.buf[self.spans.last().cloned().unwrap_or(0)..self.pos]))
342 }
343
344 pub fn current_pos(&self) -> usize {
345 self.pos
346 }
347
348 pub fn span_from(&self, start: usize) -> Span {
349 Span::new(start, self.pos)
350 }
351
352 pub fn collect<F: Fn(u8) -> bool>(&mut self, f: F) -> Result<(usize, usize)> {
353 let start = self.pos;
354 while self.pos < self.buf.len() && f(self.buf[self.pos]) {
355 self.pos += 1;
356 }
357 if self.pos > start { Ok((start, self.pos)) } else { Err(ParserErr::at("未发现期望字符", start).into()) }
358 }
359
360 pub fn just(&mut self, pattern: &str) -> Result<()> {
361 if self.buf.len() - self.pos >= pattern.len() && self.buf[self.pos..self.pos + pattern.len()].eq(pattern.as_bytes()) {
362 self.pos += pattern.len();
363 Ok(())
364 } else {
365 Err(ParserErr::at(format!("期望字符串 {}", pattern), self.pos).into())
366 }
367 }
368
369 pub fn keyword(&mut self, pattern: &str) -> Result<()> {
370 self.just(pattern)?;
371 if self.pos < self.buf.len() && !NOT_IDENT.contains(&self.buf[self.pos]) {
372 self.pos -= pattern.len();
373 return Err(ParserErr::at(format!("期望字符串 {}", pattern), self.pos).into());
374 }
375 Ok(())
376 }
377
378 pub fn get_type(&mut self) -> Result<Type> {
379 self.whitespace()?;
380 if self.get()? == b'[' {
381 self.pos += 1;
382 let ty = self.get_type()?;
383 self.until(b';')?;
384 self.whitespace()?;
385 let len = self.get_type_param()?;
386 self.until(b']')?;
387 if let Type::ConstInt(number) = len {
388 let number = u32::try_from(number).map_err(|_| anyhow!("数组长度超出 u32 范围"))?;
389 Ok(Type::Array(std::rc::Rc::new(ty), number))
390 } else {
391 Ok(Type::ArrayParam(std::rc::Rc::new(ty), std::rc::Rc::new(len)))
392 }
393 } else {
394 for ty in TYPES {
395 if self.just(ty.0).is_ok() {
396 return Ok(ty.1.clone());
397 }
398 }
399 let name = self.ident()?;
400 if self.take(b'<').is_ok() {
401 let params = crate::parse_list!(self, Vec::new(), b'>', b',', self.get_type_param()?);
402 Ok(Type::Ident { name, params })
403 } else {
404 Ok(Type::Ident { name, params: Vec::new() })
405 }
406 }
407 }
408
409 pub fn get_type_param(&mut self) -> Result<Type> {
410 self.const_type_param_add()
411 }
412
413 fn const_type_param_add(&mut self) -> Result<Type> {
414 let mut left = self.const_type_param_mul()?;
415 loop {
416 self.whitespace()?;
417 let op = if self.take(b'+').is_ok() {
418 Some(ConstIntOp::Add)
419 } else if self.take(b'-').is_ok() {
420 Some(ConstIntOp::Sub)
421 } else {
422 None
423 };
424 let Some(op) = op else { break };
425 let right = self.const_type_param_mul()?;
426 left = Self::fold_const_type_binary(op, left, right)?;
427 }
428 Ok(left)
429 }
430
431 fn const_type_param_mul(&mut self) -> Result<Type> {
432 let mut left = self.const_type_param_primary()?;
433 loop {
434 self.whitespace()?;
435 let op = if self.take(b'*').is_ok() {
436 Some(ConstIntOp::Mul)
437 } else if self.take(b'/').is_ok() {
438 Some(ConstIntOp::Div)
439 } else if self.take(b'%').is_ok() {
440 Some(ConstIntOp::Mod)
441 } else {
442 None
443 };
444 let Some(op) = op else { break };
445 let right = self.const_type_param_primary()?;
446 left = Self::fold_const_type_binary(op, left, right)?;
447 }
448 Ok(left)
449 }
450
451 fn const_type_param_primary(&mut self) -> Result<Type> {
452 self.whitespace()?;
453 if self.take(b'(').is_ok() {
454 let ty = self.get_type_param()?;
455 self.until(b')')?;
456 return Ok(ty);
457 }
458 if self.get()?.is_ascii_digit() {
459 let value = self.number()?;
460 if let Some(value) = value.as_uint() {
461 let value = i64::try_from(value).map_err(|_| anyhow!("模板数字参数超出 i64 范围"))?;
462 Ok(Type::ConstInt(value))
463 } else if let Some(value) = value.as_int() {
464 Ok(Type::ConstInt(value))
465 } else {
466 Err(anyhow!("模板数字参数必须是整数"))
467 }
468 } else {
469 self.get_type()
470 }
471 }
472
473 fn fold_const_type_binary(op: ConstIntOp, left: Type, right: Type) -> Result<Type> {
474 if let (Type::ConstInt(left), Type::ConstInt(right)) = (&left, &right) {
475 let value = match op {
476 ConstIntOp::Add => left + right,
477 ConstIntOp::Sub => left - right,
478 ConstIntOp::Mul => left * right,
479 ConstIntOp::Div => {
480 if *right == 0 {
481 return Err(anyhow!("模板整数除以 0"));
482 }
483 left / right
484 }
485 ConstIntOp::Mod => {
486 if *right == 0 {
487 return Err(anyhow!("模板整数取模 0"));
488 }
489 left % right
490 }
491 };
492 Ok(Type::ConstInt(value))
493 } else {
494 Ok(Type::ConstBinary { op, left: std::rc::Rc::new(left), right: std::rc::Rc::new(right) })
495 }
496 }
497
498 pub fn comment(&mut self) -> Result<()> {
499 if self.get()? == b'/' && self.ahead()? == b'/' {
500 self.pos += 2;
501 while self.pos < self.buf.len() && self.buf[self.pos] != b'\n' {
502 self.pos += 1;
503 }
504 Ok(())
505 } else if self.get()? == b'/' && self.ahead()? == b'*' {
506 self.pos += 2;
507 while self.pos + 1 < self.buf.len() {
508 if self.buf[self.pos] == b'*' && self.buf[self.pos + 1] == b'/' {
509 self.pos += 2;
510 return Ok(());
511 }
512 self.pos += 1;
513 }
514 Err(ParserErr::at("未关闭的注释", self.pos).into())
515 } else {
516 Ok(())
517 }
518 }
519
520 pub fn whitespace(&mut self) -> Result<()> {
521 while self.pos < self.buf.len() {
522 self.comment()?;
523 if self.pos >= self.buf.len() || !WHITE_SPACE.contains(&self.buf[self.pos]) {
524 break;
525 }
526 self.pos += 1;
527 }
528 Ok(())
529 }
530
531 pub fn ident(&mut self) -> Result<SmolStr> {
532 let (start, mut stop) = self.collect(|ch| !NOT_IDENT.contains(&ch))?;
533 loop {
534 let save_pos = self.pos;
535 if self.just("::").is_err() {
536 break;
537 }
538 match self.collect(|ch| !NOT_IDENT.contains(&ch)) {
539 Ok((_, next_stop)) => {
540 stop = next_stop;
541 }
542 Err(_) => {
543 self.pos = save_pos;
544 break;
545 }
546 }
547 }
548 if KEYWORDS.iter().position(|k| k.as_bytes() == &self.buf[start..stop]).is_some() {
549 return Err(anyhow!("发现关键字{}", String::from_utf8_lossy(&self.buf[start..stop])));
550 }
551 Ok(self.get_str(start, stop))
552 }
553
554 pub fn string(&mut self) -> Result<SmolStr> {
555 if self.get()? != b'"' {
556 return Err(ParserErr::at("非字符串", self.current_pos()).into());
557 }
558 self.pos += 1;
559 let mut text_buf = Vec::new();
560 while self.pos < self.buf.len() {
561 if self.buf[self.pos] == b'\\' {
562 self.pos += 1;
564 match self.buf[self.pos] {
565 b'n' => {
566 text_buf.push(b'\n');
567 self.pos += 1;
568 }
569 b'r' => {
570 text_buf.push(b'\r');
571 self.pos += 1;
572 }
573 b't' => {
574 text_buf.push(b'\t');
575 self.pos += 1;
576 }
577 ch @ (b'\\' | b'"') => {
578 text_buf.push(ch);
579 self.pos += 1;
580 }
581 b'u' => {
582 self.pos += 1;
583 let unicode = if self.take(b'{').is_ok() {
584 let code = self.hex()?;
585 self.pos += 1;
586 code
587 } else {
588 self.hex()?
589 };
590 let ch = char::from_u32(unicode as u32).ok_or(anyhow!("非法 unicode {}", unicode))?;
591 let mut utf8_buf = [0u8; 4];
592 let s = ch.encode_utf8(&mut utf8_buf);
593 text_buf.extend_from_slice(s.as_bytes());
594 }
595 b'x' => {
596 self.pos += 1;
597 if self.pos + 2 > self.buf.len() {
598 return Err(anyhow!("非法 \\x 转义:需要 2 位十六进制"));
599 }
600 let start = self.pos;
601 self.pos += 2;
602 let hex = &self.buf[start..self.pos];
603 if hex.iter().any(|b| !b.is_ascii_hexdigit()) {
604 return Err(anyhow!("非法 \\x 转义:仅允许十六进制字符"));
605 }
606 let code = u32::from_str_radix(String::from_utf8_lossy(hex).as_ref(), 16)?;
607 if code > 0xFF {
608 return Err(anyhow!("\\x 转义值 0x{:02X} 超出 0xFF", code));
609 }
610 text_buf.push(code as u8);
611 }
612 other => {
613 return Err(anyhow!("invalid escape character: {}", other as char));
614 }
615 }
616 } else {
617 if self.buf[self.pos] == b'"' {
618 self.pos += 1;
619 return Ok(String::from_utf8(text_buf)?.into());
620 }
621 text_buf.push(self.buf[self.pos]);
622 self.pos += 1;
623 }
624 }
625 Err(ParserErr::at("未关闭字符串", self.pos).into())
626 }
627
628 pub fn text(&mut self) -> Result<SmolStr> {
629 if self.get()? == b'r' && [b'#', b'"'].contains(&self.ahead()?) {
630 self.pos += 1;
631 let mut end = String::from("\"");
632 while self.buf[self.pos] == b'#' {
633 end.push('#');
634 self.pos += 1;
635 }
636 if self.get()? != b'"' {
637 return Err(ParserErr::at("非法的原始字符串", self.current_pos()).into());
638 }
639 self.pos += 1;
640 let start_pos = self.pos;
641 while self.pos < self.buf.len() {
642 if self.just(&end).is_ok() {
643 break;
644 }
645 self.pos += 1;
646 }
647 Ok(self.get_str(start_pos, self.pos - end.len()))
648 } else {
649 self.string()
650 }
651 }
652
653 fn hex(&mut self) -> Result<i32> {
654 let (start, stop) = self.collect(|ch| (ch >= b'0' && ch <= b'9') || (ch >= b'a' && ch <= b'f') || (ch >= b'A' && ch <= b'F'))?;
656 Ok(i32::from_str_radix(&String::from_utf8_lossy(&self.buf[start..stop]), 16)?)
657 }
658
659 fn numeric_suffix(&mut self) -> Option<Type> {
660 let save = self.pos;
661 for (name, ty) in TYPES {
662 if !ty.is_native() {
663 continue;
664 }
665 if self.buf.len() >= self.pos + name.len() && self.buf[self.pos..self.pos + name.len()].eq(name.as_bytes()) {
666 self.pos += name.len();
667 return Some(ty.clone());
668 }
669 }
670 self.pos = save;
671 None
672 }
673
674 fn int_literal(&mut self, digits: &str, radix: u32, suffix: Option<Type>) -> Result<Dynamic> {
675 let ty = suffix.unwrap_or(Type::I64);
677 let magnitude = u128::from_str_radix(digits, radix).map_err(|_| anyhow!("整数字面量 {} 超出可表示范围", digits))?;
679 let (signed, bits) = match ty {
680 Type::I8 => (true, 8u32),
681 Type::I16 => (true, 16),
682 Type::I32 => (true, 32),
683 Type::I64 => (true, 64),
684 Type::U8 => (false, 8),
685 Type::U16 => (false, 16),
686 Type::U32 => (false, 32),
687 Type::U64 => (false, 64),
688 Type::F16 => return Ok(Dynamic::F16(dynamic::f64_to_f16(magnitude as f64))),
689 Type::F32 => return Ok(Dynamic::F32(magnitude as f32)),
690 Type::F64 => return Ok(Dynamic::F64(magnitude as f64)),
691 ty => return Err(anyhow!("{:?} 不能作为数字后缀", ty)),
692 };
693 let unsigned_max = (1u128 << bits) - 1;
694 let max_allowed = if radix == 10 { if signed { unsigned_max / 2 + 1 } else { unsigned_max } } else { unsigned_max };
697 if magnitude > max_allowed {
698 return Err(anyhow!("整数字面量 {} 超出 {:?} 的范围", digits, ty));
699 }
700 Ok(match ty {
701 Type::I8 => Dynamic::I8(magnitude as i8),
702 Type::I16 => Dynamic::I16(magnitude as i16),
703 Type::I32 => Dynamic::I32(magnitude as i32),
704 Type::I64 => Dynamic::I64(magnitude as i64),
705 Type::U8 => Dynamic::U8(magnitude as u8),
706 Type::U16 => Dynamic::U16(magnitude as u16),
707 Type::U32 => Dynamic::U32(magnitude as u32),
708 Type::U64 => Dynamic::U64(magnitude as u64),
709 _ => unreachable!(),
710 })
711 }
712
713 fn float_literal(&mut self, digits: &str, suffix: Option<Type>) -> Result<Dynamic> {
714 let value: f64 = digits.parse()?;
715 if let Some(ref ty) = suffix {
716 let is_int_suffix = matches!(ty, Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::U8 | Type::U16 | Type::U32 | Type::U64);
719 if is_int_suffix {
720 let (min, max): (f64, f64) = match ty {
721 Type::I8 => (i8::MIN as f64, i8::MAX as f64),
722 Type::I16 => (i16::MIN as f64, i16::MAX as f64),
723 Type::I32 => (i32::MIN as f64, i32::MAX as f64),
724 Type::I64 => (i64::MIN as f64, i64::MAX as f64),
725 Type::U8 => (0.0, u8::MAX as f64),
726 Type::U16 => (0.0, u16::MAX as f64),
727 Type::U32 => (0.0, u32::MAX as f64),
728 Type::U64 => (0.0, u64::MAX as f64),
729 _ => unreachable!(),
730 };
731 if !value.is_finite() || value < min || value > max || value.fract() != 0.0 {
732 return Err(anyhow!("浮点字面量 {:?} 超出 {:?} 范围", value, ty));
733 }
734 } else if !value.is_finite() {
735 return Err(anyhow!("非法浮点字面量: {:?}", value));
736 }
737 }
738 Ok(match suffix.unwrap_or(Type::F32) {
739 Type::I8 => Dynamic::I8(value as i8),
740 Type::I16 => Dynamic::I16(value as i16),
741 Type::I32 => Dynamic::I32(value as i32),
742 Type::I64 => Dynamic::I64(value as i64),
743 Type::U8 => Dynamic::U8(value as u8),
744 Type::U16 => Dynamic::U16(value as u16),
745 Type::U32 => Dynamic::U32(value as u32),
746 Type::U64 => Dynamic::U64(value as u64),
747 Type::F16 => Dynamic::F16(dynamic::f64_to_f16(value)),
748 Type::F32 => Dynamic::F32(value as f32),
749 Type::F64 => Dynamic::F64(value),
750 ty => return Err(anyhow!("{:?} 不能作为浮点数字后缀", ty)),
751 })
752 }
753
754 pub fn number(&mut self) -> Result<Dynamic> {
755 if self.get()? == b'0' {
756 if [b'b', b'B'].contains(&self.ahead()?) {
757 self.pos += 2;
758 let (start, stop) = self.collect(|ch| ch == b'0' || ch == b'1')?;
759 let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
760 let suffix = self.numeric_suffix();
761 return self.int_literal(&s, 2, suffix);
762 } else if [b'o', b'O'].contains(&self.ahead()?) {
763 self.pos += 2;
764 let (start, stop) = self.collect(|ch| ch >= b'0' && ch <= b'7')?;
765 let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
766 let suffix = self.numeric_suffix();
767 return self.int_literal(&s, 8, suffix);
768 } else if [b'x', b'X'].contains(&self.ahead()?) {
769 self.pos += 2;
770 let (start, stop) = self.collect(|ch| (ch >= b'0' && ch <= b'9') || (ch >= b'a' && ch <= b'f') || (ch >= b'A' && ch <= b'F'))?;
771 let s = String::from_utf8_lossy(&self.buf[start..stop]).to_string();
772 let suffix = self.numeric_suffix();
773 return self.int_literal(&s, 16, suffix);
774 }
775 }
776 let start = self.pos;
777 while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
778 self.pos += 1;
779 }
780 let mut is_float = false;
781 if self.pos < self.buf.len() && self.buf[self.pos] == b'.' && self.ahead().map(|ch| ch <= b'9' && ch >= b'0').unwrap_or(false) {
782 is_float = true;
783 self.pos += 1;
784 while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
785 self.pos += 1;
786 }
787 }
788 if self.pos < self.buf.len() && (self.buf[self.pos] == b'e' || self.buf[self.pos] == b'E') {
789 let mut exp_pos = self.pos + 1;
790 if exp_pos < self.buf.len() && (self.buf[exp_pos] == b'+' || self.buf[exp_pos] == b'-') {
791 exp_pos += 1;
792 }
793 if exp_pos < self.buf.len() && self.buf[exp_pos] <= b'9' && self.buf[exp_pos] >= b'0' {
794 is_float = true;
795 self.pos = exp_pos + 1;
796 while self.pos < self.buf.len() && self.buf[self.pos] <= b'9' && self.buf[self.pos] >= b'0' {
797 self.pos += 1;
798 }
799 }
800 }
801 if self.pos > start {
802 let text = String::from_utf8_lossy(&self.buf[start..self.pos]).to_string();
803 let suffix = self.numeric_suffix();
804 if is_float {
805 return self.float_literal(&text, suffix);
806 }
807 return self.int_literal(&text, 10, suffix);
808 }
809 Err(ParserErr::at("非数字", start).into())
810 }
811}
812
813#[cfg(test)]
814mod tests {
815 use super::*;
816
817 fn parse_all(code: &str) -> Result<Vec<Stmt>> {
818 let mut parser = Parser::new(code.as_bytes().to_vec());
819 let mut stmts = Vec::new();
820 loop {
821 match parser.stmt(false) {
822 Ok(stmt) => stmts.push(stmt),
823 Err(err) => {
824 if parser.is_eof() {
825 return Ok(stmts);
826 }
827 return Err(err);
828 }
829 }
830 }
831 }
832
833 fn run_with_big_stack(f: impl FnOnce() + Send + 'static) {
837 std::thread::Builder::new().stack_size(64 * 1024 * 1024).spawn(f).unwrap().join().unwrap();
838 }
839
840 #[test]
841 fn deeply_nested_parens_error_instead_of_stack_overflow() {
842 run_with_big_stack(|| {
843 let depth = MAX_PARSE_DEPTH + 50;
844 let code = format!("{}1{}", "(".repeat(depth), ")".repeat(depth));
845 let mut parser = Parser::new(code.into_bytes());
846 let err = parser.get_expr().unwrap_err();
847 assert!(err.to_string().contains("嵌套过深"), "got: {err}");
848 });
849 }
850
851 #[test]
852 fn deeply_nested_blocks_error_instead_of_stack_overflow() {
853 run_with_big_stack(|| {
854 let depth = MAX_PARSE_DEPTH + 50;
855 let code = format!("fn f() {}{}{}", "{".repeat(depth), "1", "}".repeat(depth));
856 let err = parse_all(&code).unwrap_err();
857 assert!(err.to_string().contains("嵌套过深"), "got: {err}");
858 });
859 }
860
861 #[test]
862 fn normal_nesting_within_limit_parses() {
863 let code = format!("{}1{}", "(".repeat(32), ")".repeat(32));
865 let mut parser = Parser::new(code.into_bytes());
866 parser.get_expr().unwrap();
867 }
868
869 fn parse_literal(code: &str) -> Result<Dynamic> {
870 let mut parser = Parser::new(code.as_bytes().to_vec());
871 match parser.get_expr()?.kind {
872 crate::ExprKind::Value(value) => Ok(value),
873 other => Err(anyhow!("不是字面量: {:?}", other)),
874 }
875 }
876
877 #[test]
878 fn unsuffixed_integer_defaults_to_i64() {
879 assert_eq!(parse_literal("5").unwrap(), Dynamic::I64(5));
880 assert_eq!(parse_literal("3000000000").unwrap(), Dynamic::I64(3000000000));
882 }
883
884 #[test]
885 fn out_of_range_integer_literals_error() {
886 assert!(parse_literal("99999999999999999999999999999999999999999").is_err());
888 assert!(parse_literal("255i8").unwrap_err().to_string().contains("超出"));
890 assert!(parse_literal("70000i16").unwrap_err().to_string().contains("超出"));
891 assert!(parse_literal("256u8").unwrap_err().to_string().contains("超出"));
892 }
893
894 #[test]
895 fn signed_min_magnitude_literals_allowed() {
896 assert_eq!(parse_literal("128i8").unwrap(), Dynamic::I8(-128));
898 assert_eq!(parse_literal("9223372036854775808").unwrap(), Dynamic::I64(i64::MIN));
899 }
900
901 #[test]
902 fn hex_literals_keep_bit_pattern() {
903 assert_eq!(parse_literal("0xFFFFFFFF").unwrap(), Dynamic::I64(0xFFFFFFFF));
905 assert_eq!(parse_literal("0xFFi8").unwrap(), Dynamic::I8(-1));
907 assert_eq!(parse_literal("0xFFFFFFFFu32").unwrap(), Dynamic::U32(u32::MAX));
908 }
909
910 fn shape(code: &str) -> String {
912 let mut parser = Parser::new(code.as_bytes().to_vec());
913 let expr = parser.get_expr().expect("parse");
914 fmt_shape(&expr)
915 }
916
917 fn binop_sym(op: &crate::BinaryOp) -> &'static str {
918 op.symbol()
919 }
920
921 fn fmt_shape(expr: &crate::Expr) -> String {
922 use crate::ExprKind::*;
923 match &expr.kind {
924 Value(v) => format!("{:?}", v).replace("I64(", "").replace("I32(", "").trim_end_matches(')').to_string(),
925 Ident(name) => name.to_string(),
926 Unary { op, value } => {
927 let s = if matches!(op, crate::UnaryOp::Neg) { "-" } else { "!" };
928 format!("({} {})", s, fmt_shape(value))
929 }
930 Binary { left, op, right } => format!("({} {} {})", binop_sym(op), fmt_shape(left), fmt_shape(right)),
931 Range { start, stop, inclusive } => format!("({} {} {})", if *inclusive { "..=" } else { ".." }, fmt_shape(start), fmt_shape(stop)),
932 Typed { value, ty } => format!("(as {} {:?})", fmt_shape(value), ty),
933 other => format!("{:?}", other),
934 }
935 }
936
937 #[test]
938 fn precedence_and_associativity_golden() {
939 assert_eq!(shape("1 + 2 * 3"), "(+ 1 (* 2 3))");
941 assert_eq!(shape("1 * 2 + 3"), "(+ (* 1 2) 3)");
942 assert_eq!(shape("1 - 2 - 3"), "(- (- 1 2) 3)");
944 assert_eq!(shape("8 / 4 / 2"), "(/ (/ 8 4) 2)");
945 assert_eq!(shape("2 + 3 << 4"), "(<< (+ 2 3) 4)");
947 assert_eq!(shape("1 | 2 ^ 3 & 4"), "(| 1 (^ 2 (& 3 4)))");
949 assert_eq!(shape("1 + 2 == 3"), "(== (+ 1 2) 3)");
951 assert_eq!(shape("a && b || c"), "(|| (&& a b) c)");
953 assert_eq!(shape("-a * b"), "(* (- a) b)");
955 assert_eq!(shape("!a == b"), "(== (! a) b)");
956 }
957
958 #[test]
959 fn assignment_range_and_as_precedence_golden() {
960 assert_eq!(shape("a = b + c"), "(= a (+ b c))");
962 assert_eq!(shape("a = b = c"), "(= a (= b c))");
963 assert_eq!(shape("a = b = c = d"), "(= a (= b (= c d)))");
964 assert_eq!(shape("a += b * c"), "(+= a (* b c))");
966 assert_eq!(shape("1 + 1 .. n * 2"), "(.. (+ 1 1) (* n 2))");
968 assert_eq!(shape("0 ..= n - 1"), "(..= 0 (- n 1))");
969 assert_eq!(shape("a + b as i64"), "(+ a (as b I64))");
971 assert_eq!(shape("a as i64 + b"), "(+ (as a I64) b)");
972 assert_eq!(shape("(a + b) as i64"), "(as (+ a b) I64)");
973 }
974
975 #[test]
979 fn parser_never_panics_on_random_input() {
980 run_with_big_stack(|| {
981 const FRAGMENTS: &[&str] = &[
982 "fn", "let", "if", "else", "for", "in", "while", "return", "struct", "impl", "pub", "(", ")", "{", "}", "[", "]", "<", ">", "+", "-", "*", "/", "%", "=", "==", "&&", "||", "..", "..=", "as", "i32",
983 "u64", "f64", ".", ",", ";", ":", "::", "x", "0", "1", "255i8", "0xFF", "\"s\"", "true", "null", "|a|", "->",
984 ];
985 let mut state: u64 = 0x9E3779B97F4A7C15;
987 let mut next = || {
988 state ^= state >> 12;
989 state ^= state << 25;
990 state ^= state >> 27;
991 state = state.wrapping_mul(0x2545F4914F6CDD1D);
992 state
993 };
994
995 for _ in 0..4000 {
996 let mut code = String::new();
997 let tokens = (next() % 40) as usize;
998 for _ in 0..tokens {
999 code.push_str(FRAGMENTS[(next() as usize) % FRAGMENTS.len()]);
1000 if next() % 2 == 0 {
1001 code.push(' ');
1002 }
1003 }
1004 let result = std::panic::catch_unwind(|| {
1006 let mut parser = Parser::new(code.clone().into_bytes());
1007 let mut count = 0;
1008 loop {
1009 match parser.stmt(false) {
1010 Ok(_) => {
1011 count += 1;
1012 if parser.is_eof() || count > 1000 {
1013 break;
1014 }
1015 }
1016 Err(_) => break,
1017 }
1018 }
1019 });
1020 assert!(result.is_ok(), "parser panicked on input: {:?}", code);
1021 }
1022 });
1023 }
1024
1025 #[test]
1026 fn allows_local_name_to_shadow_prior_function() {
1027 parse_all(
1028 r#"
1029 fn chunk_id(x, y) {
1030 x + y
1031 }
1032
1033 fn open() {
1034 let chunk_id = 1;
1035 chunk_id
1036 }
1037 "#,
1038 )
1039 .unwrap();
1040 }
1041
1042 #[test]
1043 fn rejects_duplicate_function_args() {
1044 let err = parse_all("fn open(value, value) { value }").unwrap_err();
1045 assert!(err.to_string().contains("符号 value 已经声明"));
1046 }
1047
1048 #[test]
1049 fn rejects_duplicate_local_let_names() {
1050 let err = parse_all(
1051 r#"
1052 fn open() {
1053 let value = 1;
1054 let value = 2;
1055 value
1056 }
1057 "#,
1058 )
1059 .unwrap_err();
1060 assert!(err.to_string().contains("符号 value 已经声明"));
1061 }
1062
1063 #[test]
1064 fn allows_same_method_name_in_different_impl_blocks() {
1065 parse_all(
1066 r#"
1067 struct A {}
1068 struct B {}
1069
1070 impl A {
1071 fn zero() { 0 }
1072 }
1073
1074 impl B {
1075 fn zero() { 0 }
1076 }
1077 "#,
1078 )
1079 .unwrap();
1080 }
1081
1082 #[test]
1083 fn rejects_nested_fn_inside_function_body() {
1084 let err = parse_all("fn outer() { fn inner() { 1 } }").unwrap_err();
1085 assert!(err.to_string().contains("函数体内不能定义"), "got: {err}");
1086 }
1087
1088 #[test]
1089 fn rejects_nested_struct_inside_function_body() {
1090 let err = parse_all("fn outer() { struct S { x: i32 } S{x: 1} }").unwrap_err();
1091 assert!(err.to_string().contains("函数体内不能定义"), "got: {err}");
1092 }
1093
1094 #[test]
1095 fn rejects_nested_const_inside_function_body() {
1096 let err = parse_all("fn outer() { const K = 1 } K").unwrap_err();
1097 assert!(err.to_string().contains("函数体内不能定义"), "got: {err}");
1098 }
1099
1100 #[test]
1101 fn hex_escape_at_end_of_string_preserves_byte() {
1102 let mut p = Parser::new(br#""abc\x41""#.to_vec());
1103 let s = p.string().unwrap();
1104 assert_eq!(s.as_str(), "abcA");
1105 }
1106
1107 #[test]
1108 fn hex_escape_truncated_reports_clear_error() {
1109 let mut p = Parser::new(br#""abc\x""#.to_vec());
1110 let err = p.string().unwrap_err();
1111 assert!(err.to_string().contains("\\x"), "got: {err}");
1112 }
1113
1114 #[test]
1115 fn hex_escape_non_hex_char_reports_clear_error() {
1116 let mut p = Parser::new(br#""abc\xZZ""#.to_vec());
1117 let err = p.string().unwrap_err();
1118 assert!(err.to_string().contains("\\x"), "got: {err}");
1119 }
1120
1121 #[test]
1122 fn else_with_invalid_body_reports_error() {
1123 let err = parse_all("fn f() { if true { 1 } else }").unwrap_err();
1125 let msg = err.to_string();
1126 assert!(msg.contains("not code block") || msg.contains("未结束的"), "got: {msg}");
1127 }
1128
1129 #[test]
1130 fn float_literal_with_int_suffix_out_of_range_errors() {
1131 let mut p = Parser::new(b"1e30u8".to_vec());
1132 let err = p.number().unwrap_err();
1133 assert!(err.to_string().contains("超出"), "got: {err}");
1134 }
1135
1136 #[test]
1137 fn float_literal_with_int_suffix_fractional_errors() {
1138 let mut p = Parser::new(b"1.5i32".to_vec());
1139 let err = p.number().unwrap_err();
1140 assert!(err.to_string().contains("超出"), "got: {err}");
1141 }
1142
1143 #[test]
1144 fn float_literal_with_float_suffix_accepts_fractional() {
1145 let mut p = Parser::new(b"1e-3f32".to_vec());
1146 assert!(matches!(p.number().unwrap(), Dynamic::F32(v) if (v - 1e-3).abs() < 1e-8));
1147 }
1148
1149 #[test]
1150 fn allows_closure_inside_function_body() {
1151 parse_all("fn outer() { let f = |x: i32| { x + 1 }; f(1) }").unwrap();
1152 }
1153
1154 #[test]
1155 fn rejects_const_inside_impl_body() {
1156 let err = parse_all("struct S {}\nimpl S { const K = 1 }").unwrap_err();
1157 let msg = err.to_string();
1158 assert!(msg.contains("impl 体内不能定义") && msg.contains("const"), "got: {msg}");
1159 }
1160
1161 #[test]
1162 fn allows_fn_inside_impl_body() {
1163 parse_all("struct S {}\nimpl S { pub fn m(self: S) { 1 } }").unwrap();
1164 }
1165
1166 #[test]
1167 fn parser_err_carries_span() {
1168 let src = "fn f() {}\nfn f() {}\n";
1170 let err = parse_all(src).unwrap_err();
1171 eprintln!("err display: {err}");
1172 let downcast = err.downcast_ref::<ParserErr>().expect("ParserErr");
1173 eprintln!("message: {}", downcast.message());
1174 eprintln!("span: {:?}", downcast.span());
1175 assert!(downcast.message().contains("f"));
1176 assert!(downcast.span().start < src.len());
1178 }
1179
1180 #[test]
1181 fn block_as_let_value_is_expression() {
1182 parse_all("pub fn f() { let x = { let y = 1; y + 1 }; x }").unwrap();
1183 }
1184
1185 #[test]
1186 fn dict_still_takes_priority_over_block() {
1187 parse_all("pub fn f() { let d = { key: 1 }; d }").unwrap();
1189 }
1190
1191 #[test]
1192 fn list_pattern_with_rest_parses() {
1193 parse_all("pub fn f(items) { let [first, ..rest] = items; first }").unwrap();
1194 }
1195
1196 #[test]
1197 fn list_pattern_with_only_rest_parses() {
1198 parse_all("pub fn f(items) { let [..all] = items; all }").unwrap();
1199 }
1200
1201 #[test]
1202 fn take_error_carries_precise_pos() {
1203 use crate::SpannedParseError;
1206 let mut p = Parser::new(b"ab".to_vec());
1207 let pos_before = p.current_pos();
1208 let err = p.take(b'c').unwrap_err();
1209 let spanned = err.downcast_ref::<SpannedParseError>().expect("take should wrap in SpannedParseError");
1210 assert_eq!(spanned.pos, pos_before);
1212 }
1213
1214 #[test]
1215 fn parses_scientific_float_suffixes() {
1216 let mut parser = Parser::new(b"1.7976931348623157e308f64".to_vec());
1217 assert_eq!(parser.number().unwrap(), Dynamic::F64(1.7976931348623157e308));
1218
1219 let mut parser = Parser::new(b"1e-3f32".to_vec());
1220 assert_eq!(parser.number().unwrap(), Dynamic::F32(1e-3f32));
1221 }
1222
1223 #[test]
1224 fn parses_immediate_closure_call() {
1225 let mut parser = Parser::new(b"|| { 1i32 }()".to_vec());
1226 let expr = parser.get_expr().unwrap();
1227 let ExprKind::Call { obj, params } = expr.kind else {
1228 panic!("expected closure call, got {expr:?}");
1229 };
1230 assert!(params.is_empty());
1231 let ExprKind::Closure { args, .. } = obj.kind else {
1232 panic!("expected closure callee, got {obj:?}");
1233 };
1234 assert!(args.is_empty());
1235 }
1236
1237 #[test]
1238 fn parses_empty_tuple_expression() {
1239 let mut parser = Parser::new(b"()".to_vec());
1240 let expr = parser.get_expr().unwrap();
1241 let ExprKind::Tuple(items) = expr.kind else {
1242 panic!("expected empty tuple, got {expr:?}");
1243 };
1244 assert!(items.is_empty());
1245 }
1246
1247 #[test]
1248 fn parses_explicit_generic_function_call() {
1249 let mut parser = Parser::new(b"value::<4>()".to_vec());
1250 let expr = parser.get_expr().unwrap();
1251 let ExprKind::Call { obj, params } = expr.kind else {
1252 panic!("expected function call, got {expr:?}");
1253 };
1254 assert!(params.is_empty());
1255 let ExprKind::Generic { obj, params } = obj.kind else {
1256 panic!("expected generic callee, got {obj:?}");
1257 };
1258 assert!(matches!(obj.kind, ExprKind::Ident(name) if name.as_str() == "value"));
1259 assert!(matches!(params.as_slice(), [Type::ConstInt(4)]));
1260 }
1261
1262 #[test]
1263 fn parses_import_top_level_declaration() {
1264 let stmts = parse_all(r#"import "foo";"#).expect("parse import decl");
1266 assert_eq!(stmts.len(), 1);
1267 let StmtKind::Import { module, path, is_pub } = &stmts[0].kind else {
1268 panic!("expected StmtKind::Import, got {:?}", stmts[0].kind);
1269 };
1270 assert_eq!(module.as_str(), "foo");
1271 assert_eq!(path.as_str(), "foo.zs", "省略路径时默认 <module>.zs");
1272 assert!(!*is_pub);
1273
1274 let stmts = parse_all(r#"import "foo", "bar.zs";"#).expect("parse import decl with path");
1275 let StmtKind::Import { module, path, .. } = &stmts[0].kind else {
1276 panic!("expected StmtKind::Import, got {:?}", stmts[0].kind);
1277 };
1278 assert_eq!(module.as_str(), "foo");
1279 assert_eq!(path.as_str(), "bar.zs");
1280
1281 let stmts = parse_all(r#"pub import "foo";"#).expect("parse pub import");
1282 let StmtKind::Import { module, is_pub, .. } = &stmts[0].kind else {
1283 panic!("expected StmtKind::Import, got {:?}", stmts[0].kind);
1284 };
1285 assert_eq!(module.as_str(), "foo");
1286 assert!(*is_pub);
1287 }
1288
1289 #[test]
1290 fn import_call_form_is_still_recognized_as_expression() {
1291 let stmts = parse_all(r#"import("foo", "foo.zs");"#).expect("parse import call");
1295 assert_eq!(stmts.len(), 1);
1296 let StmtKind::Expr(expr, _) = &stmts[0].kind else {
1297 panic!("expected StmtKind::Expr, got {:?}", stmts[0].kind);
1298 };
1299 let ExprKind::Call { obj, params } = &expr.kind else {
1300 panic!("expected ExprKind::Call, got {expr:?}");
1301 };
1302 let ExprKind::Ident(name) = &obj.kind else {
1303 panic!("expected ident callee, got {:?}", obj.kind);
1304 };
1305 assert_eq!(name.as_str(), "import");
1306 assert_eq!(params.len(), 2);
1307 }
1308
1309 #[test]
1310 fn parses_bigfloat_cmp_context_segment() {
1311 let code = r#"
1312 struct BigFloat<N> { data: [u32; N], exp: i32, sign: bool }
1313
1314 impl BigFloat<N> {
1315 fn abs_cmp(self: BigFloat<N>, rhs: BigFloat<N>) {
1316 let self_high = self.exp + ((N - 1) as i32);
1317 let rhs_high = rhs.exp + ((N - 1) as i32);
1318 let high = if self_high >= rhs_high { self_high } else { rhs_high };
1319 let low = if self.exp <= rhs.exp { self.exp } else { rhs.exp };
1320 let result = 0i32;
1321 let power = high;
1322
1323 while power >= low && result == 0i32 {
1324 let a_idx = power - self.exp;
1325 let b_idx = power - rhs.exp;
1326 let a_limb = 0u32;
1327 let b_limb = 0u32;
1328
1329 if a_idx >= 0i32 && a_idx < (N as i32) {
1330 a_limb = self.data[a_idx as u32];
1331 }
1332 if b_idx >= 0i32 && b_idx < (N as i32) {
1333 b_limb = rhs.data[b_idx as u32];
1334 }
1335
1336 if a_limb > b_limb {
1337 result = 1i32;
1338 } else if a_limb < b_limb {
1339 result = -1i32;
1340 }
1341
1342 power -= 1i32;
1343 }
1344
1345 result
1346 }
1347
1348 pub fn cmp(self: BigFloat<N>, rhs: BigFloat<N>) {
1349 if self.is_zero() && rhs.is_zero() {
1350 0i32
1351 } else if self.sign != rhs.sign {
1352 if self.sign { -1i32 } else { 1i32 }
1353 } else {
1354 let cmp = self.abs_cmp(rhs);
1355 if self.sign { -cmp } else { cmp }
1356 }
1357 }
1358 }
1359 "#;
1360 parse_all(code).unwrap();
1361 }
1362
1363 #[test]
1364 fn parses_bigfloat_file() {
1365 let code = include_str!("../../zusts/bigfloat.zs");
1366 parse_all(code).unwrap();
1367 }
1368}