1use crate::annotation;
6use crate::lexer::Float;
7use crate::parser::{Cursor, Parse, Parser, Peek, Result};
8use std::fmt;
9use std::hash::{Hash, Hasher};
10use std::str;
11
12#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
14pub struct Span {
15 pub(crate) offset: usize,
16}
17
18impl Span {
19 pub fn from_offset(offset: usize) -> Self {
21 Span { offset }
22 }
23
24 pub fn linecol_in(&self, text: &str) -> (usize, usize) {
29 let mut cur = 0;
30 for (i, line) in text.split_terminator('\n').enumerate() {
34 if cur + line.len() + 1 > self.offset {
35 return (i, self.offset - cur);
36 }
37 cur += line.len() + 1;
38 }
39 (text.lines().count(), 0)
40 }
41
42 pub fn offset(&self) -> usize {
44 self.offset
45 }
46}
47
48#[derive(Copy, Clone)]
54pub struct Id<'a> {
55 name: &'a str,
56 generation: u32,
57 span: Span,
58}
59
60impl<'a> Id<'a> {
61 pub fn new(name: &'a str, span: Span) -> Id<'a> {
66 Id {
67 name,
68 generation: 0,
69 span,
70 }
71 }
72
73 #[cfg(feature = "wasm-module")]
74 pub(crate) fn gensym(span: Span, generation: u32) -> Id<'a> {
75 Id {
76 name: "gensym",
77 generation,
78 span,
79 }
80 }
81
82 pub fn name(&self) -> &'a str {
86 self.name
87 }
88
89 pub fn span(&self) -> Span {
91 self.span
92 }
93
94 #[cfg(feature = "wasm-module")]
95 pub(crate) fn is_gensym(&self) -> bool {
96 self.generation != 0
97 }
98}
99
100impl<'a> Hash for Id<'a> {
101 fn hash<H: Hasher>(&self, hasher: &mut H) {
102 self.name.hash(hasher);
103 self.generation.hash(hasher);
104 }
105}
106
107impl<'a> PartialEq for Id<'a> {
108 fn eq(&self, other: &Id<'a>) -> bool {
109 self.name == other.name && self.generation == other.generation
110 }
111}
112
113impl<'a> Eq for Id<'a> {}
114
115impl<'a> Parse<'a> for Id<'a> {
116 fn parse(parser: Parser<'a>) -> Result<Self> {
117 parser.step(|c| {
118 if let Some((name, rest)) = c.id()? {
119 return Ok((
120 Id {
121 name,
122 generation: 0,
123 span: c.cur_span(),
124 },
125 rest,
126 ));
127 }
128 Err(c.error("expected an identifier"))
129 })
130 }
131}
132
133impl fmt::Debug for Id<'_> {
134 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135 if self.generation != 0 {
136 f.debug_struct("Id")
137 .field("generation", &self.generation)
138 .finish()
139 } else {
140 self.name.fmt(f)
141 }
142 }
143}
144
145impl Peek for Id<'_> {
146 fn peek(cursor: Cursor<'_>) -> Result<bool> {
147 cursor.peek_id()
148 }
149
150 fn display() -> &'static str {
151 "an identifier"
152 }
153}
154
155#[derive(Copy, Clone, Debug)]
164pub enum Index<'a> {
165 Num(u32, Span),
168 Id(Id<'a>),
171}
172
173impl Index<'_> {
174 pub fn span(&self) -> Span {
176 match self {
177 Index::Num(_, span) => *span,
178 Index::Id(id) => id.span(),
179 }
180 }
181
182 #[cfg(feature = "wasm-module")]
183 pub(crate) fn is_resolved(&self) -> bool {
184 matches!(self, Index::Num(..))
185 }
186}
187
188impl<'a> Parse<'a> for Index<'a> {
189 fn parse(parser: Parser<'a>) -> Result<Self> {
190 if parser.peek::<Id>()? {
191 Ok(Index::Id(parser.parse()?))
192 } else if parser.peek::<u32>()? {
193 let (val, span) = parser.parse()?;
194 Ok(Index::Num(val, span))
195 } else {
196 Err(parser.error(format!(
197 "unexpected token, expected an index or an identifier"
198 )))
199 }
200 }
201}
202
203impl Peek for Index<'_> {
204 fn peek(cursor: Cursor<'_>) -> Result<bool> {
205 Ok(u32::peek(cursor)? || Id::peek(cursor)?)
206 }
207
208 fn display() -> &'static str {
209 "an index"
210 }
211}
212
213impl<'a> From<Id<'a>> for Index<'a> {
214 fn from(id: Id<'a>) -> Index<'a> {
215 Index::Id(id)
216 }
217}
218
219impl PartialEq for Index<'_> {
220 fn eq(&self, other: &Index<'_>) -> bool {
221 match (self, other) {
222 (Index::Num(a, _), Index::Num(b, _)) => a == b,
223 (Index::Id(a), Index::Id(b)) => a == b,
224 _ => false,
225 }
226 }
227}
228
229impl Eq for Index<'_> {}
230
231impl Hash for Index<'_> {
232 fn hash<H: Hasher>(&self, hasher: &mut H) {
233 match self {
234 Index::Num(a, _) => {
235 0u8.hash(hasher);
236 a.hash(hasher);
237 }
238 Index::Id(a) => {
239 1u8.hash(hasher);
240 a.hash(hasher);
241 }
242 }
243 }
244}
245
246#[derive(Clone, Debug)]
248#[allow(missing_docs)]
249pub struct ItemRef<'a, K> {
250 pub kind: K,
251 pub idx: Index<'a>,
252}
253
254impl<'a, K: Parse<'a>> Parse<'a> for ItemRef<'a, K> {
255 fn parse(parser: Parser<'a>) -> Result<Self> {
256 parser.parens(|parser| {
257 let kind = parser.parse::<K>()?;
258 let idx = parser.parse()?;
259 Ok(ItemRef { kind, idx })
260 })
261 }
262}
263
264impl<'a, K: Peek> Peek for ItemRef<'a, K> {
265 fn peek(cursor: Cursor<'_>) -> Result<bool> {
266 match cursor.lparen()? {
267 Some(remaining) => K::peek(remaining),
268 None => Ok(false),
269 }
270 }
271
272 fn display() -> &'static str {
273 "an item reference"
274 }
275}
276
277#[derive(Copy, Clone, PartialEq, Eq, Debug)]
279pub struct NameAnnotation<'a> {
280 pub name: &'a str,
282}
283
284impl<'a> Parse<'a> for NameAnnotation<'a> {
285 fn parse(parser: Parser<'a>) -> Result<Self> {
286 parser.parse::<annotation::name>()?;
287 let name = parser.parse()?;
288 Ok(NameAnnotation { name })
289 }
290}
291
292impl<'a> Parse<'a> for Option<NameAnnotation<'a>> {
293 fn parse(parser: Parser<'a>) -> Result<Self> {
294 Ok(if parser.peek2::<annotation::name>()? {
295 Some(parser.parens(|p| p.parse())?)
296 } else {
297 None
298 })
299 }
300}
301
302macro_rules! integers {
303 ($($i:ident($u:ident))*) => ($(
304 impl<'a> Parse<'a> for $i {
305 fn parse(parser: Parser<'a>) -> Result<Self> {
306 Ok(parser.parse::<($i, Span)>()?.0)
307 }
308 }
309
310 impl<'a> Parse<'a> for ($i, Span) {
311 fn parse(parser: Parser<'a>) -> Result<Self> {
312 parser.step(|c| {
313 if let Some((i, rest)) = c.integer()? {
314 let (s, base) = i.val();
315 let val = $i::from_str_radix(s, base)
316 .or_else(|_| {
317 $u::from_str_radix(s, base).map(|i| i as $i)
318 });
319 return match val {
320 Ok(n) => Ok(((n, c.cur_span()), rest)),
321 Err(_) => Err(c.error(concat!(
322 "invalid ",
323 stringify!($i),
324 " number: constant out of range",
325 ))),
326 };
327 }
328 Err(c.error(concat!("expected a ", stringify!($i))))
329 })
330 }
331 }
332
333 impl Peek for $i {
334 fn peek(cursor: Cursor<'_>) -> Result<bool> {
335 cursor.peek_integer()
336 }
337
338 fn display() -> &'static str {
339 stringify!($i)
340 }
341 }
342 )*)
343}
344
345integers! {
346 u8(u8) u16(u16) u32(u32) u64(u64)
347 i8(u8) i16(u16) i32(u32) i64(u64)
348}
349
350impl<'a> Parse<'a> for &'a [u8] {
351 fn parse(parser: Parser<'a>) -> Result<Self> {
352 parser.step(|c| {
353 if let Some((i, rest)) = c.string()? {
354 return Ok((i, rest));
355 }
356 Err(c.error("expected a string"))
357 })
358 }
359}
360
361impl Peek for &'_ [u8] {
362 fn peek(cursor: Cursor<'_>) -> Result<bool> {
363 cursor.peek_string()
364 }
365
366 fn display() -> &'static str {
367 "string"
368 }
369}
370
371impl<'a> Parse<'a> for &'a str {
372 fn parse(parser: Parser<'a>) -> Result<Self> {
373 str::from_utf8(parser.parse()?)
374 .map_err(|_| parser.error_at(parser.prev_span(), "malformed UTF-8 encoding"))
375 }
376}
377
378impl Parse<'_> for String {
379 fn parse(parser: Parser<'_>) -> Result<Self> {
380 Ok(<&str>::parse(parser)?.to_string())
381 }
382}
383
384impl Peek for &'_ str {
385 fn peek(cursor: Cursor<'_>) -> Result<bool> {
386 <&[u8]>::peek(cursor)
387 }
388
389 fn display() -> &'static str {
390 <&[u8]>::display()
391 }
392}
393
394macro_rules! float {
395 ($($name:ident => {
396 bits: $int:ident,
397 float: $float:ident,
398 exponent_bits: $exp_bits:tt,
399 name: $parse:ident,
400 })*) => ($(
401 #[derive(Debug, Copy, Clone)]
403 pub struct $name {
404 pub bits: $int,
406 }
407
408 impl<'a> Parse<'a> for $name {
409 fn parse(parser: Parser<'a>) -> Result<Self> {
410 parser.step(|c| {
411 let (val, rest) = if let Some((f, rest)) = c.float()? {
412 ($parse(&f), rest)
413 } else if let Some((i, rest)) = c.integer()? {
414 let (s, base) = i.val();
415 (
416 $parse(&Float::Val {
417 hex: base == 16,
418 integral: s.into(),
419 fractional: None,
420 exponent: None,
421 }),
422 rest,
423 )
424 } else {
425 return Err(c.error("expected a float"));
426 };
427 match val {
428 Some(bits) => Ok(($name { bits }, rest)),
429 None => Err(c.error("invalid float value: constant out of range")),
430 }
431 })
432 }
433 }
434
435 fn $parse(val: &Float<'_>) -> Option<$int> {
436 let width = std::mem::size_of::<$int>() * 8;
439 let neg_offset = width - 1;
440 let exp_offset = neg_offset - $exp_bits;
441 let signif_bits = width - 1 - $exp_bits;
442 let signif_mask = (1 << exp_offset) - 1;
443 let bias = (1 << ($exp_bits - 1)) - 1;
444 let msb = 1 << neg_offset;
445
446 let (hex, integral, fractional, exponent_str) = match val {
447 Float::Inf { negative } => {
450 let exp_bits = (1 << $exp_bits) - 1;
451 let neg_bit = *negative as $int;
452 return Some(
453 (neg_bit << neg_offset) |
454 (exp_bits << exp_offset)
455 );
456 }
457
458 Float::Nan { negative, val } => {
462 let exp_bits = (1 << $exp_bits) - 1;
463 let neg_bit = *negative as $int;
464 let signif = match val {
465 Some(val) => $int::from_str_radix(val,16).ok()?,
466 None => 1 << (signif_bits - 1),
467 };
468 if signif & signif_mask == 0 {
471 return None;
472 }
473 return Some(
474 (neg_bit << neg_offset) |
475 (exp_bits << exp_offset) |
476 (signif & signif_mask)
477 );
478 }
479
480 Float::Val { hex, integral, fractional, exponent } => {
482 (hex, integral, fractional, exponent)
483 }
484 };
485
486 if !*hex {
489 let mut s = integral.to_string();
490 if let Some(fractional) = fractional {
491 s.push_str(".");
492 s.push_str(&fractional);
493 }
494 if let Some(exponent) = exponent_str {
495 s.push_str("e");
496 s.push_str(&exponent);
497 }
498 let float = s.parse::<$float>().ok()?;
499 if float.is_infinite() {
502 return None;
503 }
504 return Some(float.to_bits());
505 }
506
507 let is_negative = integral.starts_with('-');
521 let integral = integral.trim_start_matches('-').trim_start_matches('0');
522 let fractional = fractional.as_ref().map(|s| &**s).unwrap_or("");
523
524 let fractional_no_leading = fractional.trim_start_matches('0');
531 let fractional_iter = if integral.is_empty() {
532 fractional_no_leading.chars()
533 } else {
534 fractional.chars()
535 };
536
537 let mut digits = integral.chars()
541 .map(|c| (to_hex(c) as $int, false))
542 .chain(fractional_iter.map(|c| (to_hex(c) as $int, true)));
543
544 let lead_nonzero_digit = match digits.next() {
548 Some((c, _)) => c,
549 None if is_negative => return Some(msb),
552 None => return Some(0),
553 };
554 let lz = (lead_nonzero_digit as u8).leading_zeros() as i32 - 4;
555
556 let mut exponent = if !integral.is_empty() {
559 1
560 } else {
561 -((fractional.len() - fractional_no_leading.len() + 1) as i32) + 1
564 };
565 let mut significand_pos = (width - (4 - (lz as usize))) as isize;
566 let mut significand: $int = lead_nonzero_digit << significand_pos;
567 let mut discarded_extra_nonzero = false;
568
569 assert!(significand_pos >= 0, "$int should be at least 4 bits wide");
570
571 exponent = exponent.checked_mul(4)?.checked_sub(lz + 1)?;
573
574 for (digit, in_fractional) in digits {
577 if !in_fractional {
578 exponent += 4;
579 }
580 if significand_pos > -4 {
581 significand_pos -= 4;
582 }
583
584 if significand_pos >= 0 {
585 significand |= digit << significand_pos;
586 } else if significand_pos > -4 {
587 significand |= digit >> (4 - significand_pos);
588 discarded_extra_nonzero = (digit & !((!0) >> (4 - significand_pos))) != 0;
589 } else if digit != 0 {
590 discarded_extra_nonzero = true;
591 }
592 }
593
594 debug_assert!(significand != 0, "The case of no non-zero digits should have been handled above");
595
596 exponent = exponent.checked_add(match exponent_str {
600 Some(s) => s.parse::<i32>().ok()?,
601 None => 0,
602 })?;
603
604 let (encoded_exponent, encoded_significand, discarded_significand) =
608 if exponent <= -bias {
609 let shift = exp_offset as i32 + exponent + bias;
611 if shift == 0 {
612 (0, 0, significand)
613 } else if shift < 0 || shift >= width as i32 {
614 (0, 0, 0)
615 } else {
616 (
617 0,
618 significand >> (width as i32 - shift),
619 significand << shift,
620 )
621 }
622 } else if exponent <= bias {
623 (
626 ((exponent + bias) as $int) << exp_offset,
627 (significand >> (width - exp_offset - 1)) & signif_mask,
628 significand << (exp_offset + 1),
629 )
630 } else {
631 (
633 ((1 << $exp_bits) - 1) << exp_offset,
634 0,
635 0,
636 )
637 };
638
639 let bits = encoded_exponent | encoded_significand;
643
644 let bits = bits
652 + (((discarded_significand & msb != 0)
653 && ((discarded_significand & !msb != 0) ||
654 discarded_extra_nonzero ||
655 (encoded_significand & 1 != 0))) as $int);
657
658 let bits = if is_negative {
661 bits | msb
662 } else {
663 bits
664 };
665 if $float::from_bits(bits).is_infinite() {
668 return None;
669 }
670 Some(bits)
671 }
672
673 )*)
674}
675
676float! {
677 F32 => {
678 bits: u32,
679 float: f32,
680 exponent_bits: 8,
681 name: strtof,
682 }
683 F64 => {
684 bits: u64,
685 float: f64,
686 exponent_bits: 11,
687 name: strtod,
688 }
689}
690
691fn to_hex(c: char) -> u8 {
692 match c {
693 'a'..='f' => c as u8 - b'a' + 10,
694 'A'..='F' => c as u8 - b'A' + 10,
695 _ => c as u8 - b'0',
696 }
697}
698
699pub struct LParen {
702 _priv: (),
703}
704
705impl Peek for LParen {
706 fn peek(cursor: Cursor<'_>) -> Result<bool> {
707 cursor.peek_lparen()
708 }
709
710 fn display() -> &'static str {
711 "left paren"
712 }
713}
714
715pub struct RParen {
718 _priv: (),
719}
720
721impl Peek for RParen {
722 fn peek(cursor: Cursor<'_>) -> Result<bool> {
723 cursor.peek_rparen()
724 }
725
726 fn display() -> &'static str {
727 "right paren"
728 }
729}
730
731#[cfg(test)]
732mod tests {
733 #[test]
734 fn hex_strtof() {
735 macro_rules! f {
736 ($a:tt) => (f!(@mk $a, None, None));
737 ($a:tt p $e:tt) => (f!(@mk $a, None, Some($e.into())));
738 ($a:tt . $b:tt) => (f!(@mk $a, Some($b.into()), None));
739 ($a:tt . $b:tt p $e:tt) => (f!(@mk $a, Some($b.into()), Some($e.into())));
740 (@mk $a:tt, $b:expr, $e:expr) => (crate::lexer::Float::Val {
741 hex: true,
742 integral: $a.into(),
743 fractional: $b,
744 exponent: $e
745 });
746 }
747 assert_eq!(super::strtof(&f!("0")), Some(0));
748 assert_eq!(super::strtof(&f!("0" . "0")), Some(0));
749 assert_eq!(super::strtof(&f!("0" . "0" p "2354")), Some(0));
750 assert_eq!(super::strtof(&f!("-0")), Some(1 << 31));
751 assert_eq!(super::strtof(&f!("f32")), Some(0x45732000));
752 assert_eq!(super::strtof(&f!("0" . "f32")), Some(0x3f732000));
753 assert_eq!(super::strtof(&f!("1" . "2")), Some(0x3f900000));
754 assert_eq!(
755 super::strtof(&f!("0" . "00000100000000000" p "-126")),
756 Some(0)
757 );
758 assert_eq!(
759 super::strtof(&f!("1" . "fffff4" p "-106")),
760 Some(0x0afffffa)
761 );
762 assert_eq!(super::strtof(&f!("fffff98" p "-133")), Some(0x0afffffa));
763 assert_eq!(super::strtof(&f!("0" . "081" p "023")), Some(0x48810000));
764 assert_eq!(
765 super::strtof(&f!("1" . "00000100000000000" p "-50")),
766 Some(0x26800000)
767 );
768 }
769}