use crate::Pos;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Program {
pub id: String,
pub options: Vec<String>,
pub initial: bool,
pub recursive: bool,
pub working_storage: Vec<DataEntry>,
pub local_storage: Vec<DataEntry>,
pub linkage: Vec<DataEntry>,
pub using: Vec<Param>,
pub returning: Option<String>,
pub paragraphs: Vec<Paragraph>,
pub files: Vec<FileDecl>,
pub sources: Vec<String>,
pub exec_declarations: Vec<ExecBlock>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Param {
pub by_value: bool,
pub name: String,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Organization {
Sequential,
LineSequential,
Indexed,
Relative,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum Access {
#[default]
Sequential,
Random,
Dynamic,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FileDecl {
pub name: String,
pub assign: String,
pub organization: Organization,
pub access: Access,
pub record_key: Option<Ref>,
pub alternate_keys: Vec<(Ref, bool)>,
pub relative_key: Option<Ref>,
pub optional: bool,
pub status: Option<Ref>,
pub recording: Option<char>,
pub record_min: Option<u32>,
pub record_max: Option<u32>,
pub records: Vec<DataEntry>,
pub pos: Pos,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum OpenMode {
Input,
Output,
Extend,
InputOutput,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Advancing {
Lines { before: bool, count: Expr },
Page { before: bool },
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum Usage {
#[default]
Display,
Binary,
NativeBinary,
Packed,
Float1,
Float2,
National,
Pointer,
Index,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SignPosition {
Leading,
Trailing,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct SignClause {
pub position: SignPosition,
pub separate: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DataEntry {
pub level: u8,
pub name: Option<String>,
pub picture: Option<String>,
pub usage: Option<Usage>,
pub value: Option<Literal>,
pub redefines: Option<String>,
pub occurs: Option<u32>,
pub depending_on: Option<Ref>,
pub sign: Option<SignClause>,
pub justified: bool,
pub sync: bool,
pub blank_when_zero: bool,
pub indexed_by: Vec<String>,
pub keys: Vec<(bool, Ref)>,
pub condition_values: Vec<(Literal, Option<Literal>)>,
pub pos: Pos,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Figurative {
Zero,
Space,
HighValue,
LowValue,
Quote,
Null,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Literal {
Alnum(String),
Hex(Vec<u8>),
National(String),
Number(String),
Figurative(Figurative),
All(Box<Literal>),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Paragraph {
pub name: String,
pub statements: Vec<Stmt>,
pub section: Option<String>,
pub is_section: bool,
pub pos: Pos,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ProcName {
pub name: String,
pub section: Option<String>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ExitKind {
Plain,
Paragraph,
Section,
Perform,
PerformCycle,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Subject {
Bool(bool),
Expr(Expr),
Cond(Cond),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Object {
Any,
Bool(bool),
Cond(Cond),
Value { not: bool, from: Expr, thru: Option<Expr> },
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct When {
pub alternatives: Vec<Vec<Object>>,
pub body: Vec<Stmt>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Ref {
pub name: String,
pub qualifiers: Vec<String>,
pub subscripts: Vec<Expr>,
pub refmod: Option<RefMod>,
pub pos: Pos,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RefMod {
pub start: Box<Expr>,
pub length: Option<Box<Expr>>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FunctionCall {
pub name: String,
pub args: Vec<Expr>,
pub modifier: Option<String>,
pub refmod: Option<RefMod>,
pub pos: Pos,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Operand {
Ref(Ref),
Literal(Literal),
Function(FunctionCall),
LengthOf(Ref),
AddressOf(Ref),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BinOp {
Add,
Sub,
Mul,
Div,
Pow,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Expr {
Operand(Operand),
Neg(Box<Expr>),
Bin(Box<Expr>, BinOp, Box<Expr>),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RelOp {
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Class {
Numeric,
Alphabetic,
Positive,
Negative,
Zero,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Cond {
Rel(Expr, RelOp, Expr),
Class(Expr, Class),
Name(Ref),
NameOrRel { subject: Expr, op: RelOp, name: Ref },
Not(Box<Cond>),
And(Box<Cond>, Box<Cond>),
Or(Box<Cond>, Box<Cond>),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Target {
pub r: Ref,
pub rounded: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Varying {
pub var: Ref,
pub from: Expr,
pub by: Expr,
pub until: Cond,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Loop {
Once,
Times(Expr),
Until { cond: Cond, test_after: bool },
Varying { varying: Box<Varying>, test_after: bool },
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Stmt {
Move { from: Operand, to: Vec<Ref>, pos: Pos },
Compute { targets: Vec<Target>, expr: Expr, size_error: Option<SizeError>, pos: Pos },
Arith(Box<Arith>),
If { cond: Cond, then: Vec<Stmt>, otherwise: Vec<Stmt>, pos: Pos },
PerformInline { body: Vec<Stmt>, repeat: Loop, pos: Pos },
PerformProc { from: ProcName, thru: Option<ProcName>, repeat: Loop, pos: Pos },
Evaluate { subjects: Vec<Subject>, whens: Vec<When>, other: Vec<Stmt>, pos: Pos },
Display { items: Vec<Operand>, no_advancing: bool, pos: Pos },
Open { files: Vec<(OpenMode, String)>, pos: Pos },
Close { files: Vec<String>, pos: Pos },
Read(Box<ReadStmt>),
Write { record: Ref, from: Option<Operand>, advancing: Option<Advancing>, invalid: Handlers, pos: Pos },
Rewrite { record: Ref, from: Option<Operand>, invalid: Handlers, pos: Pos },
Delete { file: String, invalid: Handlers, pos: Pos },
Start { file: String, key: Option<(RelOp, Ref)>, invalid: Handlers, pos: Pos },
Initialize { targets: Vec<Ref>, pos: Pos },
GoTo { target: ProcName, pos: Pos },
Goback { pos: Pos },
ExitProgram { pos: Pos },
Call(Box<Call>),
Cancel { targets: Vec<Operand>, pos: Pos },
Set { set: SetStmt, pos: Pos },
Accept { target: Ref, from: AcceptFrom, pos: Pos },
String(Box<StringStmt>),
Unstring(Box<Unstring>),
Inspect(Box<Inspect>),
Search(Box<Search>),
NextSentence,
SentenceEnd,
Exec(Box<ExecBlock>),
StopRun { pos: Pos },
Continue,
Exit(ExitKind),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SizeError {
pub on: Vec<Stmt>,
pub not_on: Vec<Stmt>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ArithVerb {
Add,
Subtract,
Multiply,
Divide,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Arith {
pub verb: ArithVerb,
pub computations: Vec<(Target, Expr)>,
pub remainder: Option<(Target, Expr, Expr)>,
pub size_error: Option<SizeError>,
pub pos: Pos,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ArgMode {
Reference,
Content,
Value,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Arg {
pub mode: ArgMode,
pub value: Option<Operand>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Call {
pub target: Operand,
pub using: Vec<Arg>,
pub returning: Option<Ref>,
pub on_exception: Option<Vec<Stmt>>,
pub not_on_exception: Option<Vec<Stmt>>,
pub pos: Pos,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SetStmt {
ConditionTrue(Vec<Ref>),
To { targets: Vec<Ref>, value: Operand },
AddressOf { targets: Vec<Ref>, value: Operand },
UpDown { targets: Vec<Ref>, down: bool, by: Expr },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AcceptFrom {
Sysin,
Date { four_digit_year: bool },
Day { four_digit_year: bool },
DayOfWeek,
Time,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Delimiter {
Size,
By(Operand),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StringStmt {
pub sources: Vec<(Operand, Delimiter)>,
pub into: Ref,
pub pointer: Option<Ref>,
pub on_overflow: Option<Vec<Stmt>>,
pub not_on_overflow: Option<Vec<Stmt>>,
pub pos: Pos,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct UnstringInto {
pub target: Ref,
pub delimiter_in: Option<Ref>,
pub count_in: Option<Ref>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Unstring {
pub source: Ref,
pub delimiters: Vec<(bool, Operand)>,
pub into: Vec<UnstringInto>,
pub pointer: Option<Ref>,
pub tallying: Option<Ref>,
pub on_overflow: Option<Vec<Stmt>>,
pub not_on_overflow: Option<Vec<Stmt>>,
pub pos: Pos,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Bound {
pub after: bool,
pub value: Operand,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum InspectMode {
Characters,
All,
Leading,
First,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct InspectPhrase {
pub mode: InspectMode,
pub pattern: Option<Operand>,
pub by: Option<Operand>,
pub counter: Option<Ref>,
pub bounds: Vec<Bound>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Inspect {
pub target: Ref,
pub tallying: Vec<InspectPhrase>,
pub replacing: Vec<InspectPhrase>,
pub converting: Option<(Operand, Operand, Vec<Bound>)>,
pub pos: Pos,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Search {
pub table: Ref,
pub all: bool,
pub varying: Option<Ref>,
pub at_end: Option<Vec<Stmt>>,
pub whens: Vec<(Cond, Vec<Stmt>)>,
pub pos: Pos,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ExecKind {
Sql,
Cics,
Dli,
Other,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ExecArg {
Operand(Operand),
Text(String),
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ExecBlock {
pub kind: ExecKind,
pub command: String,
pub options: Vec<(String, Option<ExecArg>)>,
pub host_variables: Vec<Ref>,
pub text: String,
pub pos: Pos,
}
impl ExecBlock {
pub fn declarative(&self) -> bool {
self.kind == ExecKind::Sql
&& matches!(self.command.as_str(), "INCLUDE" | "BEGIN DECLARE SECTION" | "END DECLARE SECTION" | "WHENEVER" | "DECLARE CURSOR" | "DECLARE TABLE" | "DECLARE STATEMENT")
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct Handlers {
pub on: Option<Vec<Stmt>>,
pub not_on: Option<Vec<Stmt>>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ReadStmt {
pub file: String,
pub next: bool,
pub previous: bool,
pub into: Option<Ref>,
pub key: Option<Ref>,
pub at_end: Handlers,
pub invalid: Handlers,
pub pos: Pos,
}