1use super::{AbendId, CondId, ConstId, Count, IntExpr, MovePlan, Operand, PlaceId, RangeId, StorePlan, SymId};
6use crate::storage::Kind;
7use crate::vocab::Figurative;
8use crate::{codec_enum, codec_struct};
9use zarch::hfp::Precision;
10
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub enum Markup {
13 JsonGenerate(JsonGenerate),
14 XmlGenerate(XmlGenerate),
15 XmlParse(XmlParse),
16 JsonParse(JsonParse),
17}
18
19impl Markup {
20 pub fn phrases(&self) -> (bool, bool) {
23 match self {
24 Markup::JsonGenerate(g) => (g.on_exception, g.not_on_exception),
25 Markup::XmlGenerate(g) => (g.on_exception, g.not_on_exception),
26 Markup::XmlParse(p) => (p.on_exception, p.not_on_exception),
27 Markup::JsonParse(p) => (p.on_exception, p.not_on_exception),
28 }
29 }
30}
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
35pub enum Ccsid {
36 Unnamed,
37 CodePage,
38 Operand(Operand),
39}
40
41#[derive(Clone, Copy, Debug, PartialEq, Eq)]
43pub enum Convert {
44 Chars { justified: bool },
47 National,
49 Float(Precision),
51 Fixed { integers: u32 },
54 Refused(AbendId),
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Eq)]
60pub enum Marker {
61 Byte(Option<u8>),
64 Condition(CondId),
66 Refused(AbendId),
68}
69
70#[derive(Clone, Debug, PartialEq, Eq)]
74pub struct JsonGenerate {
75 pub from: PlaceId,
77 pub subscripts: Vec<IntExpr>,
78 pub nodes: Vec<JsonNode>,
80 pub name: Option<SymId>,
82 pub receiver: PlaceId,
83 pub encoding: Ccsid,
84 pub count: Option<(PlaceId, StorePlan)>,
85 pub code: (PlaceId, StorePlan),
86 pub on_exception: bool,
87 pub not_on_exception: bool,
88}
89
90#[derive(Clone, Debug, PartialEq, Eq)]
93pub struct JsonNode {
94 pub offset: u32,
95 pub len: u32,
96 pub kind: Kind,
97 pub name: SymId,
98 pub occurs: Option<Count>,
99 pub value: JsonValue,
100}
101
102#[derive(Clone, Debug, PartialEq, Eq)]
103pub enum JsonValue {
104 Object { members: Vec<u32>, eligible: bool },
108 Leaf(JsonLeaf),
109}
110
111#[derive(Clone, Debug, PartialEq, Eq)]
113pub struct JsonLeaf {
114 pub indicator: Option<(Result<PlaceId, AbendId>, Marker)>,
117 pub null: Option<Figurative>,
119 pub suppress: Vec<Figurative>,
121 pub boolean: Option<Marker>,
123 pub convert: Convert,
124}
125
126#[derive(Clone, Debug, PartialEq, Eq)]
132pub struct XmlGenerate {
133 pub receiver: PlaceId,
134 pub encoding: Ccsid,
136 pub namespace: Option<Operand>,
137 pub prefix: Option<Operand>,
138 pub declaration: bool,
139 pub from: PlaceId,
140 pub subscripts: Vec<IntExpr>,
141 pub nodes: Vec<XmlNode>,
144 pub suppressing: bool,
146 pub count: Option<(PlaceId, StorePlan)>,
147 pub code: (PlaceId, StorePlan),
148 pub on_exception: bool,
149 pub not_on_exception: bool,
150}
151
152#[derive(Clone, Debug, PartialEq, Eq)]
154pub struct XmlNode {
155 pub offset: u32,
156 pub len: u32,
157 pub kind: Kind,
158 pub name: SymId,
159 pub occurs: Option<Count>,
160 pub value: XmlValue,
161}
162
163#[derive(Clone, Debug, PartialEq, Eq)]
164pub enum XmlValue {
165 Element { members: Vec<u32> },
167 Members { members: Vec<u32> },
169 Leaf { form: XmlForm, suppress: Vec<Figurative>, convert: Convert },
173}
174
175#[derive(Clone, Copy, Debug, PartialEq, Eq)]
176pub enum XmlForm {
177 Attribute,
178 Element,
179 Content,
180}
181
182#[derive(Clone, Debug, PartialEq, Eq)]
193pub struct XmlParse {
194 pub document: PlaceId,
195 pub encoding: Option<Operand>,
196 pub national: bool,
198 pub procedure: RangeId,
199 pub event: PlaceId,
200 pub code: (PlaceId, StorePlan),
201 pub information: (PlaceId, StorePlan),
202 pub code_value: IntExpr,
204 pub on_exception: bool,
205 pub not_on_exception: bool,
206}
207
208#[derive(Clone, Debug, PartialEq, Eq)]
214pub struct JsonParse {
215 pub source: PlaceId,
216 pub encoding: Ccsid,
217 pub into: PlaceId,
219 pub subscripts: Vec<IntExpr>,
220 pub nodes: Vec<ParseNode>,
224 pub ignore_all: bool,
226 pub code: (PlaceId, StorePlan),
227 pub status: (PlaceId, StorePlan),
228 pub on_exception: bool,
229 pub not_on_exception: bool,
230}
231
232#[derive(Clone, Debug, PartialEq, Eq)]
236pub struct ParseNode {
237 pub offset: u32,
238 pub len: u32,
239 pub kind: Kind,
240 pub name: Named,
241 pub occurs: Option<Count>,
242 pub ignored: bool,
244 pub indicator: Option<Indicator>,
245 pub null: Option<(Figurative, MovePlan)>,
247 pub value: ParseValue,
248}
249
250#[derive(Clone, Copy, Debug, PartialEq, Eq)]
253pub enum Named {
254 Exactly(SymId),
255 Folded(SymId),
256 Omitted,
257}
258
259#[derive(Clone, Debug, PartialEq, Eq)]
260pub enum ParseValue {
261 Object { members: Vec<u32> },
263 Leaf(ParseLeaf),
264 Suppressed,
266}
267
268#[derive(Clone, Debug, PartialEq, Eq)]
269pub struct ParseLeaf {
270 pub boolean: Option<Flag>,
272 pub text: Option<MovePlan>,
276 pub number: NumberInto,
277}
278
279#[derive(Clone, Copy, Debug, PartialEq, Eq)]
281pub enum NumberInto {
282 Float(MovePlan),
283 Store(StorePlan),
285 Edited(MovePlan),
287 Digits,
290 Incompatible,
291}
292
293#[derive(Clone, Debug, PartialEq, Eq)]
296pub struct Indicator {
297 pub place: Option<Result<PlaceId, AbendId>>,
298 pub flag: Flag,
299}
300
301#[derive(Clone, Copy, Debug, PartialEq, Eq)]
303pub enum Flag {
304 Set { on: SetTo, off: SetTo },
306 Literals { on: (ConstId, MovePlan), off: (ConstId, MovePlan) },
308}
309
310#[derive(Clone, Copy, Debug, PartialEq, Eq)]
312pub enum SetTo {
313 Nothing,
315 Move { place: PlaceId, value: ConstId, plan: MovePlan },
316 Refused(AbendId),
318}
319
320#[derive(Clone, Copy, Debug, PartialEq, Eq)]
323pub enum XmlRegister {
324 Text,
325 NText,
326 Namespace,
327 NNamespace,
328 Prefix,
329 NPrefix,
330}
331
332impl XmlRegister {
333 pub fn national(self) -> bool {
334 matches!(self, XmlRegister::NText | XmlRegister::NNamespace | XmlRegister::NPrefix)
335 }
336}
337
338codec_enum!(Markup { JsonGenerate(g) = 0, XmlGenerate(g) = 1, XmlParse(p) = 2, JsonParse(p) = 3 });
339codec_enum!(Ccsid { Unnamed = 0, CodePage = 1, Operand(o) = 2 });
340codec_enum!(Convert { Chars { justified } = 0, National = 1, Float(precision) = 2, Fixed { integers } = 3, Refused(abend) = 4 });
341codec_enum!(Marker { Byte(b) = 0, Condition(c) = 1, Refused(abend) = 2 });
342codec_struct!(JsonGenerate { from, subscripts, nodes, name, receiver, encoding, count, code, on_exception, not_on_exception } check json_valid);
343codec_struct!(JsonNode { offset, len, kind, name, occurs, value });
344codec_enum!(JsonValue { Object { members, eligible } = 0, Leaf(leaf) = 1 });
345codec_struct!(JsonLeaf { indicator, null, suppress, boolean, convert });
346codec_struct!(XmlGenerate {
347 receiver, encoding, namespace, prefix, declaration, from, subscripts, nodes, suppressing, count, code, on_exception, not_on_exception,
348} check xml_valid);
349codec_struct!(XmlNode { offset, len, kind, name, occurs, value });
350codec_enum!(XmlValue { Element { members } = 0, Members { members } = 1, Leaf { form, suppress, convert } = 2 });
351codec_enum!(XmlForm { Attribute = 0, Element = 1, Content = 2 });
352codec_struct!(XmlParse { document, encoding, national, procedure, event, code, information, code_value, on_exception, not_on_exception });
353codec_struct!(JsonParse { source, encoding, into, subscripts, nodes, ignore_all, code, status, on_exception, not_on_exception } check parse_valid);
354codec_struct!(ParseNode { offset, len, kind, name, occurs, ignored, indicator, null, value });
355codec_enum!(Named { Exactly(name) = 0, Folded(name) = 1, Omitted = 2 });
356codec_enum!(ParseValue { Object { members } = 0, Leaf(leaf) = 1, Suppressed = 2 });
357codec_struct!(ParseLeaf { boolean, text, number });
358codec_enum!(NumberInto { Float(plan) = 0, Store(store) = 1, Edited(plan) = 2, Digits = 3, Incompatible = 4 });
359codec_struct!(Indicator { place, flag });
360codec_enum!(Flag { Set { on, off } = 0, Literals { on, off } = 1 });
361codec_enum!(SetTo { Nothing = 0, Move { place, value, plan } = 1, Refused(abend) = 2 });
362codec_enum!(XmlRegister { Text = 0, NText = 1, Namespace = 2, NNamespace = 3, Prefix = 4, NPrefix = 5 });
363
364fn tree_valid<'n>(nodes: usize, members: impl Iterator<Item = (usize, &'n [u32])>) -> Result<(), String> {
366 if nodes == 0 {
367 return Err("a markup tree with no root".into());
368 }
369 for (k, list) in members {
370 if let Some(&m) = list.iter().find(|&&m| m as usize <= k || m as usize >= nodes) {
371 return Err(format!("markup node {k} holds node {m} of {nodes}"));
372 }
373 }
374 Ok(())
375}
376
377fn json_valid(g: &JsonGenerate) -> Result<(), String> {
378 tree_valid(g.nodes.len(), g.nodes.iter().enumerate().filter_map(|(k, n)| match &n.value {
379 JsonValue::Object { members, .. } => Some((k, &members[..])),
380 JsonValue::Leaf(_) => None,
381 }))
382}
383
384fn xml_valid(g: &XmlGenerate) -> Result<(), String> {
385 tree_valid(g.nodes.len(), g.nodes.iter().enumerate().filter_map(|(k, n)| match &n.value {
386 XmlValue::Element { members } | XmlValue::Members { members } => Some((k, &members[..])),
387 XmlValue::Leaf { .. } => None,
388 }))
389}
390
391fn parse_valid(p: &JsonParse) -> Result<(), String> {
392 tree_valid(p.nodes.len(), p.nodes.iter().enumerate().filter_map(|(k, n)| match &n.value {
393 ParseValue::Object { members } => Some((k, &members[..])),
394 _ => None,
395 }))
396}