1use crate::vocab::{Figurative, SignClause};
5use numeric::precision::{Fixed, Places};
6use zarch::hfp::{Hfp, Precision};
7use zarch::wide::U256;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum Kind {
11 Group,
12 Alnum { justified: bool },
13 National,
14 Dbcs { justified: bool, edit: Option<u32> },
17 Zoned { digits: u32, scale: u32, signed: bool, sign: Option<SignClause> },
18 Packed { digits: u32, scale: u32, signed: bool },
19 Binary { digits: u32, scale: u32, signed: bool, native: bool },
20 Float(Precision),
21 NumericEdited { edit: u32, digits: u32, scale: u32, blank_when_zero: bool },
23 AlnumEdited { edit: u32 },
24 Pointer,
26 Index,
28 ObjectReference,
30 ProgramPointer,
32}
33
34impl Kind {
35 pub fn is_numeric(self) -> bool {
36 matches!(self, Kind::Zoned { .. } | Kind::Packed { .. } | Kind::Binary { .. } | Kind::Float(_) | Kind::Index)
37 }
38
39 pub fn digits_scale(self) -> Option<(u32, u32)> {
41 match self {
42 Kind::Zoned { digits, scale, .. }
43 | Kind::Packed { digits, scale, .. }
44 | Kind::Binary { digits, scale, .. }
45 | Kind::NumericEdited { digits, scale, .. } => Some((digits, scale)),
46 Kind::Index => Some((9, 0)),
47 _ => None,
48 }
49 }
50}
51
52#[derive(Clone, Copy, Debug)]
53pub struct Loc {
54 pub offset: usize,
55 pub len: usize,
56 pub kind: Kind,
57 pub item: usize,
58}
59
60#[derive(Clone, Debug)]
61pub enum Val {
62 Bytes(Vec<u8>),
63 National(Vec<u8>),
64 Dbcs(Vec<u8>),
66 Num(Fixed),
67 Float(Hfp),
68 Fig(Figurative),
69 All(Vec<u8>),
70 AllNational(Vec<u8>),
72 Address(u32),
74}
75
76pub fn literal_fixed(text: &str) -> Option<Fixed> {
78 let (negative, body) = match text.as_bytes().first() {
79 Some(b'-') => (true, &text[1..]),
80 Some(b'+') => (false, &text[1..]),
81 _ => (false, text),
82 };
83 let (int, frac) = body.split_once('.').unwrap_or((body, ""));
84 let digits = format!("{int}{frac}");
85 if digits.is_empty() || digits.len() > 31 {
86 return None;
87 }
88 let magnitude = U256::from_u128(digits.parse().ok()?);
89 Some(Fixed { negative: negative && !magnitude.is_zero(), magnitude, places: Places::new(int.len().max(1) as u32, frac.len() as u32) })
90}