1use crate::Pos;
2
3#[derive(Clone, Debug, PartialEq, Eq)]
4pub struct Program {
5 pub id: String,
6 pub options: Vec<String>,
8 pub initial: bool,
10 pub recursive: bool,
11 pub working_storage: Vec<DataEntry>,
12 pub local_storage: Vec<DataEntry>,
14 pub linkage: Vec<DataEntry>,
15 pub using: Vec<Param>,
17 pub returning: Option<String>,
18 pub paragraphs: Vec<Paragraph>,
19 pub files: Vec<FileDecl>,
21 pub sources: Vec<String>,
23 pub exec_declarations: Vec<ExecBlock>,
25}
26
27#[derive(Clone, Debug, PartialEq, Eq)]
28pub struct Param {
29 pub by_value: bool,
30 pub name: String,
31}
32
33#[derive(Clone, Copy, Debug, PartialEq, Eq)]
34pub enum Organization {
35 Sequential,
36 LineSequential,
37 Indexed,
38 Relative,
39}
40
41#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
42pub enum Access {
43 #[default]
44 Sequential,
45 Random,
46 Dynamic,
47}
48
49#[derive(Clone, Debug, PartialEq, Eq)]
50pub struct FileDecl {
51 pub name: String,
52 pub assign: String,
54 pub organization: Organization,
55 pub access: Access,
56 pub record_key: Option<Ref>,
57 pub alternate_keys: Vec<(Ref, bool)>,
59 pub relative_key: Option<Ref>,
60 pub optional: bool,
61 pub status: Option<Ref>,
62 pub recording: Option<char>,
64 pub record_min: Option<u32>,
65 pub record_max: Option<u32>,
66 pub records: Vec<DataEntry>,
67 pub pos: Pos,
68}
69
70#[derive(Clone, Copy, Debug, PartialEq, Eq)]
71pub enum OpenMode {
72 Input,
73 Output,
74 Extend,
75 InputOutput,
76}
77
78#[derive(Clone, Debug, PartialEq, Eq)]
79pub enum Advancing {
80 Lines { before: bool, count: Expr },
81 Page { before: bool },
82}
83
84#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
85pub enum Usage {
86 #[default]
87 Display,
88 Binary,
89 NativeBinary,
91 Packed,
92 Float1,
93 Float2,
94 National,
95 Pointer,
96 Index,
97}
98
99#[derive(Clone, Copy, Debug, PartialEq, Eq)]
100pub enum SignPosition {
101 Leading,
102 Trailing,
103}
104
105#[derive(Clone, Copy, Debug, PartialEq, Eq)]
106pub struct SignClause {
107 pub position: SignPosition,
108 pub separate: bool,
109}
110
111#[derive(Clone, Debug, PartialEq, Eq)]
112pub struct DataEntry {
113 pub level: u8,
114 pub name: Option<String>,
116 pub picture: Option<String>,
117 pub usage: Option<Usage>,
119 pub value: Option<Literal>,
120 pub redefines: Option<String>,
121 pub occurs: Option<u32>,
123 pub depending_on: Option<Ref>,
125 pub sign: Option<SignClause>,
126 pub justified: bool,
127 pub sync: bool,
128 pub blank_when_zero: bool,
129 pub indexed_by: Vec<String>,
131 pub keys: Vec<(bool, Ref)>,
133 pub condition_values: Vec<(Literal, Option<Literal>)>,
136 pub pos: Pos,
137}
138
139#[derive(Clone, Copy, Debug, PartialEq, Eq)]
140pub enum Figurative {
141 Zero,
142 Space,
143 HighValue,
144 LowValue,
145 Quote,
146 Null,
147}
148
149#[derive(Clone, Debug, PartialEq, Eq)]
150pub enum Literal {
151 Alnum(String),
152 Hex(Vec<u8>),
153 National(String),
154 Number(String),
156 Figurative(Figurative),
157 All(Box<Literal>),
158}
159
160#[derive(Clone, Debug, PartialEq, Eq)]
162pub struct Paragraph {
163 pub name: String,
164 pub statements: Vec<Stmt>,
165 pub section: Option<String>,
167 pub is_section: bool,
168 pub pos: Pos,
169}
170
171#[derive(Clone, Debug, PartialEq, Eq)]
173pub struct ProcName {
174 pub name: String,
175 pub section: Option<String>,
176}
177
178#[derive(Clone, Copy, Debug, PartialEq, Eq)]
179pub enum ExitKind {
180 Plain,
181 Paragraph,
182 Section,
183 Perform,
184 PerformCycle,
185}
186
187#[derive(Clone, Debug, PartialEq, Eq)]
188pub enum Subject {
189 Bool(bool),
190 Expr(Expr),
191 Cond(Cond),
192}
193
194#[derive(Clone, Debug, PartialEq, Eq)]
195pub enum Object {
196 Any,
197 Bool(bool),
198 Cond(Cond),
199 Value { not: bool, from: Expr, thru: Option<Expr> },
200}
201
202#[derive(Clone, Debug, PartialEq, Eq)]
204pub struct When {
205 pub alternatives: Vec<Vec<Object>>,
206 pub body: Vec<Stmt>,
207}
208
209#[derive(Clone, Debug, PartialEq, Eq)]
210pub struct Ref {
211 pub name: String,
212 pub qualifiers: Vec<String>,
213 pub subscripts: Vec<Expr>,
214 pub refmod: Option<RefMod>,
215 pub pos: Pos,
216}
217
218#[derive(Clone, Debug, PartialEq, Eq)]
219pub struct RefMod {
220 pub start: Box<Expr>,
221 pub length: Option<Box<Expr>>,
222}
223
224#[derive(Clone, Debug, PartialEq, Eq)]
225pub struct FunctionCall {
226 pub name: String,
227 pub args: Vec<Expr>,
228 pub modifier: Option<String>,
230 pub refmod: Option<RefMod>,
231 pub pos: Pos,
232}
233
234#[derive(Clone, Debug, PartialEq, Eq)]
235pub enum Operand {
236 Ref(Ref),
237 Literal(Literal),
238 Function(FunctionCall),
239 LengthOf(Ref),
240 AddressOf(Ref),
241}
242
243#[derive(Clone, Copy, Debug, PartialEq, Eq)]
244pub enum BinOp {
245 Add,
246 Sub,
247 Mul,
248 Div,
249 Pow,
250}
251
252#[derive(Clone, Debug, PartialEq, Eq)]
253pub enum Expr {
254 Operand(Operand),
255 Neg(Box<Expr>),
256 Bin(Box<Expr>, BinOp, Box<Expr>),
257}
258
259#[derive(Clone, Copy, Debug, PartialEq, Eq)]
260pub enum RelOp {
261 Eq,
262 Ne,
263 Lt,
264 Le,
265 Gt,
266 Ge,
267}
268
269#[derive(Clone, Copy, Debug, PartialEq, Eq)]
270pub enum Class {
271 Numeric,
272 Alphabetic,
273 Positive,
274 Negative,
275 Zero,
276}
277
278#[derive(Clone, Debug, PartialEq, Eq)]
279pub enum Cond {
280 Rel(Expr, RelOp, Expr),
281 Class(Expr, Class),
282 Name(Ref),
283 NameOrRel { subject: Expr, op: RelOp, name: Ref },
286 Not(Box<Cond>),
287 And(Box<Cond>, Box<Cond>),
288 Or(Box<Cond>, Box<Cond>),
289}
290
291#[derive(Clone, Debug, PartialEq, Eq)]
292pub struct Target {
293 pub r: Ref,
294 pub rounded: bool,
295}
296
297#[derive(Clone, Debug, PartialEq, Eq)]
298pub struct Varying {
299 pub var: Ref,
300 pub from: Expr,
301 pub by: Expr,
302 pub until: Cond,
303}
304
305#[derive(Clone, Debug, PartialEq, Eq)]
306pub enum Loop {
307 Once,
308 Times(Expr),
309 Until { cond: Cond, test_after: bool },
310 Varying { varying: Box<Varying>, test_after: bool },
311}
312
313#[derive(Clone, Debug, PartialEq, Eq)]
314pub enum Stmt {
315 Move { from: Operand, to: Vec<Ref>, pos: Pos },
316 Compute { targets: Vec<Target>, expr: Expr, size_error: Option<SizeError>, pos: Pos },
317 Arith(Box<Arith>),
319 If { cond: Cond, then: Vec<Stmt>, otherwise: Vec<Stmt>, pos: Pos },
320 PerformInline { body: Vec<Stmt>, repeat: Loop, pos: Pos },
321 PerformProc { from: ProcName, thru: Option<ProcName>, repeat: Loop, pos: Pos },
322 Evaluate { subjects: Vec<Subject>, whens: Vec<When>, other: Vec<Stmt>, pos: Pos },
323 Display { items: Vec<Operand>, no_advancing: bool, pos: Pos },
324 Open { files: Vec<(OpenMode, String)>, pos: Pos },
325 Close { files: Vec<String>, pos: Pos },
326 Read(Box<ReadStmt>),
327 Write { record: Ref, from: Option<Operand>, advancing: Option<Advancing>, invalid: Handlers, pos: Pos },
328 Rewrite { record: Ref, from: Option<Operand>, invalid: Handlers, pos: Pos },
329 Delete { file: String, invalid: Handlers, pos: Pos },
330 Start { file: String, key: Option<(RelOp, Ref)>, invalid: Handlers, pos: Pos },
331 Initialize { targets: Vec<Ref>, pos: Pos },
332 GoTo { target: ProcName, pos: Pos },
333 Goback { pos: Pos },
334 ExitProgram { pos: Pos },
336 Call(Box<Call>),
337 Cancel { targets: Vec<Operand>, pos: Pos },
338 Set { set: SetStmt, pos: Pos },
339 Accept { target: Ref, from: AcceptFrom, pos: Pos },
340 String(Box<StringStmt>),
341 Unstring(Box<Unstring>),
342 Inspect(Box<Inspect>),
343 Search(Box<Search>),
344 NextSentence,
346 SentenceEnd,
348 Exec(Box<ExecBlock>),
349 StopRun { pos: Pos },
350 Continue,
351 Exit(ExitKind),
352}
353
354#[derive(Clone, Debug, PartialEq, Eq)]
355pub struct SizeError {
356 pub on: Vec<Stmt>,
357 pub not_on: Vec<Stmt>,
358}
359
360#[derive(Clone, Copy, Debug, PartialEq, Eq)]
361pub enum ArithVerb {
362 Add,
363 Subtract,
364 Multiply,
365 Divide,
366}
367
368#[derive(Clone, Debug, PartialEq, Eq)]
372pub struct Arith {
373 pub verb: ArithVerb,
374 pub computations: Vec<(Target, Expr)>,
375 pub remainder: Option<(Target, Expr, Expr)>,
376 pub size_error: Option<SizeError>,
377 pub pos: Pos,
378}
379
380#[derive(Clone, Copy, Debug, PartialEq, Eq)]
381pub enum ArgMode {
382 Reference,
383 Content,
384 Value,
385}
386
387#[derive(Clone, Debug, PartialEq, Eq)]
389pub struct Arg {
390 pub mode: ArgMode,
391 pub value: Option<Operand>,
392}
393
394#[derive(Clone, Debug, PartialEq, Eq)]
395pub struct Call {
396 pub target: Operand,
397 pub using: Vec<Arg>,
398 pub returning: Option<Ref>,
399 pub on_exception: Option<Vec<Stmt>>,
400 pub not_on_exception: Option<Vec<Stmt>>,
401 pub pos: Pos,
402}
403
404#[derive(Clone, Debug, PartialEq, Eq)]
405pub enum SetStmt {
406 ConditionTrue(Vec<Ref>),
407 To { targets: Vec<Ref>, value: Operand },
409 AddressOf { targets: Vec<Ref>, value: Operand },
411 UpDown { targets: Vec<Ref>, down: bool, by: Expr },
412}
413
414#[derive(Clone, Copy, Debug, PartialEq, Eq)]
415pub enum AcceptFrom {
416 Sysin,
417 Date { four_digit_year: bool },
418 Day { four_digit_year: bool },
419 DayOfWeek,
420 Time,
421}
422
423#[derive(Clone, Debug, PartialEq, Eq)]
424pub enum Delimiter {
425 Size,
426 By(Operand),
427}
428
429#[derive(Clone, Debug, PartialEq, Eq)]
430pub struct StringStmt {
431 pub sources: Vec<(Operand, Delimiter)>,
432 pub into: Ref,
433 pub pointer: Option<Ref>,
434 pub on_overflow: Option<Vec<Stmt>>,
435 pub not_on_overflow: Option<Vec<Stmt>>,
436 pub pos: Pos,
437}
438
439#[derive(Clone, Debug, PartialEq, Eq)]
440pub struct UnstringInto {
441 pub target: Ref,
442 pub delimiter_in: Option<Ref>,
443 pub count_in: Option<Ref>,
444}
445
446#[derive(Clone, Debug, PartialEq, Eq)]
447pub struct Unstring {
448 pub source: Ref,
449 pub delimiters: Vec<(bool, Operand)>,
451 pub into: Vec<UnstringInto>,
452 pub pointer: Option<Ref>,
453 pub tallying: Option<Ref>,
454 pub on_overflow: Option<Vec<Stmt>>,
455 pub not_on_overflow: Option<Vec<Stmt>>,
456 pub pos: Pos,
457}
458
459#[derive(Clone, Debug, PartialEq, Eq)]
461pub struct Bound {
462 pub after: bool,
463 pub value: Operand,
464}
465
466#[derive(Clone, Copy, Debug, PartialEq, Eq)]
467pub enum InspectMode {
468 Characters,
469 All,
470 Leading,
471 First,
472}
473
474#[derive(Clone, Debug, PartialEq, Eq)]
476pub struct InspectPhrase {
477 pub mode: InspectMode,
478 pub pattern: Option<Operand>,
479 pub by: Option<Operand>,
480 pub counter: Option<Ref>,
481 pub bounds: Vec<Bound>,
482}
483
484#[derive(Clone, Debug, PartialEq, Eq)]
485pub struct Inspect {
486 pub target: Ref,
487 pub tallying: Vec<InspectPhrase>,
488 pub replacing: Vec<InspectPhrase>,
489 pub converting: Option<(Operand, Operand, Vec<Bound>)>,
490 pub pos: Pos,
491}
492
493#[derive(Clone, Debug, PartialEq, Eq)]
494pub struct Search {
495 pub table: Ref,
496 pub all: bool,
497 pub varying: Option<Ref>,
498 pub at_end: Option<Vec<Stmt>>,
499 pub whens: Vec<(Cond, Vec<Stmt>)>,
500 pub pos: Pos,
501}
502
503#[derive(Clone, Copy, Debug, PartialEq, Eq)]
504pub enum ExecKind {
505 Sql,
506 Cics,
507 Dli,
508 Other,
509}
510
511#[derive(Clone, Debug, PartialEq, Eq)]
512pub enum ExecArg {
513 Operand(Operand),
514 Text(String),
516}
517
518#[derive(Clone, Debug, PartialEq, Eq)]
520pub struct ExecBlock {
521 pub kind: ExecKind,
522 pub command: String,
524 pub options: Vec<(String, Option<ExecArg>)>,
526 pub host_variables: Vec<Ref>,
528 pub text: String,
529 pub pos: Pos,
530}
531
532impl ExecBlock {
533 pub fn declarative(&self) -> bool {
535 self.kind == ExecKind::Sql
536 && matches!(self.command.as_str(), "INCLUDE" | "BEGIN DECLARE SECTION" | "END DECLARE SECTION" | "WHENEVER" | "DECLARE CURSOR" | "DECLARE TABLE" | "DECLARE STATEMENT")
537 }
538}
539
540#[derive(Clone, Debug, Default, PartialEq, Eq)]
542pub struct Handlers {
543 pub on: Option<Vec<Stmt>>,
544 pub not_on: Option<Vec<Stmt>>,
545}
546
547#[derive(Clone, Debug, PartialEq, Eq)]
548pub struct ReadStmt {
549 pub file: String,
550 pub next: bool,
552 pub previous: bool,
553 pub into: Option<Ref>,
554 pub key: Option<Ref>,
556 pub at_end: Handlers,
557 pub invalid: Handlers,
558 pub pos: Pos,
559}
560