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