add: bnf
This commit is contained in:
702
src/main.rs
702
src/main.rs
@@ -1,3 +1,701 @@
|
||||
fn main() {
|
||||
println!("Hello world!")
|
||||
//! rust-langrpg — RPG IV free-format parser
|
||||
//!
|
||||
//! Loads the BNF grammar embedded at compile time, builds a [`bnf::GrammarParser`],
|
||||
//! and demonstrates parsing a handful of RPG IV free-format snippets.
|
||||
|
||||
use bnf::{Grammar, Term};
|
||||
|
||||
/// The RPG IV BNF grammar, embedded at compile time from `src/rpg.bnf`.
|
||||
const RPG_BNF: &str = include_str!("rpg.bnf");
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Public API
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// Load and validate the RPG IV grammar.
|
||||
///
|
||||
/// Returns `Err` if the BNF source is malformed.
|
||||
pub fn load_grammar() -> Result<Grammar, bnf::Error> {
|
||||
RPG_BNF.parse::<Grammar>()
|
||||
}
|
||||
|
||||
/// Parse `source` as the given `rule` (a non-terminal name such as `"statement"`).
|
||||
///
|
||||
/// Returns `Some(parse_tree_string)` for the first successful parse, or `None`
|
||||
/// when the grammar cannot match the input.
|
||||
pub fn parse_as<'a>(
|
||||
parser: &'a bnf::GrammarParser,
|
||||
source: &str,
|
||||
rule: &str,
|
||||
) -> Option<String> {
|
||||
let target = Term::Nonterminal(rule.to_string());
|
||||
parser
|
||||
.parse_input_starting_with(source, &target)
|
||||
.next()
|
||||
.map(|tree| tree.to_string())
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Demo helpers
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
struct Example {
|
||||
label: &'static str,
|
||||
rule: &'static str,
|
||||
src: &'static str,
|
||||
}
|
||||
|
||||
fn run_example(parser: &bnf::GrammarParser, ex: &Example) {
|
||||
println!(" ┌─ {} ({}) ─────────────────────", ex.label, ex.rule);
|
||||
println!(" │ source : {:?}", ex.src);
|
||||
match parse_as(parser, ex.src, ex.rule) {
|
||||
Some(tree) => {
|
||||
// Only print the first line of a potentially huge tree.
|
||||
let preview: String = tree.lines().take(6).collect::<Vec<_>>().join("\n │ ");
|
||||
println!(" │ result : OK");
|
||||
println!(" │ tree : {}", preview);
|
||||
}
|
||||
None => println!(" │ result : NO PARSE"),
|
||||
}
|
||||
println!(" └──────────────────────────────────────────────");
|
||||
println!();
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// main
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
fn main() {
|
||||
// ── 1. Load grammar ────────────────────────────────────────────────────
|
||||
println!("=== RPG IV Free-Format Parser ===");
|
||||
println!();
|
||||
|
||||
let grammar = match load_grammar() {
|
||||
Ok(g) => {
|
||||
println!("[grammar] Loaded successfully.");
|
||||
g
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[grammar] Failed to parse BNF: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// ── 2. Build parser ────────────────────────────────────────────────────
|
||||
let parser = match grammar.build_parser() {
|
||||
Ok(p) => {
|
||||
println!("[parser] Built successfully (all non-terminals resolved).");
|
||||
p
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[parser] Failed to build: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
println!();
|
||||
|
||||
// ── 3. Example snippets ────────────────────────────────────────────────
|
||||
//
|
||||
// Each snippet is a *token stream* that matches the grammar rules.
|
||||
// Because the `bnf` crate performs character-level / terminal matching
|
||||
// the snippets are written exactly as the grammar expects them —
|
||||
// individual keyword tokens separated by spaces aren't needed; the BNF
|
||||
// uses quoted terminal strings so the parser works on the raw text.
|
||||
//
|
||||
// We showcase a range of rules from simple primitives all the way up to
|
||||
// compound statements so you can see the grammar in action.
|
||||
|
||||
println!("=== Parsing Examples ===");
|
||||
println!();
|
||||
|
||||
let examples: &[Example] = &[
|
||||
// ── Identifiers ─────────────────────────────────────────────────────
|
||||
Example {
|
||||
label: "simple identifier",
|
||||
rule: "identifier",
|
||||
src: "myVar",
|
||||
},
|
||||
Example {
|
||||
label: "identifier with digits and underscore",
|
||||
rule: "identifier",
|
||||
src: "calc_Total2",
|
||||
},
|
||||
// ── Literals ────────────────────────────────────────────────────────
|
||||
Example {
|
||||
label: "integer literal",
|
||||
rule: "integer-literal",
|
||||
src: "42",
|
||||
},
|
||||
Example {
|
||||
label: "numeric literal (decimal)",
|
||||
rule: "numeric-literal",
|
||||
src: "3.14",
|
||||
},
|
||||
// ── Named constants ──────────────────────────────────────────────────
|
||||
Example {
|
||||
label: "named constant *ON",
|
||||
rule: "named-constant",
|
||||
src: "*ON",
|
||||
},
|
||||
Example {
|
||||
label: "named constant *BLANKS",
|
||||
rule: "named-constant",
|
||||
src: "*BLANKS",
|
||||
},
|
||||
// ── Type specifications ──────────────────────────────────────────────
|
||||
Example {
|
||||
label: "CHAR type spec",
|
||||
rule: "type-spec",
|
||||
src: "CHAR(10)",
|
||||
},
|
||||
Example {
|
||||
label: "PACKED type spec",
|
||||
rule: "type-spec",
|
||||
src: "PACKED(7:2)",
|
||||
},
|
||||
Example {
|
||||
label: "INT type spec",
|
||||
rule: "type-spec",
|
||||
src: "INT(10)",
|
||||
},
|
||||
Example {
|
||||
label: "DATE type spec",
|
||||
rule: "type-spec",
|
||||
src: "DATE",
|
||||
},
|
||||
Example {
|
||||
label: "IND (indicator) type spec",
|
||||
rule: "type-spec",
|
||||
src: "IND",
|
||||
},
|
||||
// ── Declarations ─────────────────────────────────────────────────────
|
||||
Example {
|
||||
label: "standalone character variable",
|
||||
rule: "standalone-decl",
|
||||
src: "DCL-S myName CHAR(25);",
|
||||
},
|
||||
Example {
|
||||
label: "standalone integer with initialiser",
|
||||
rule: "standalone-decl",
|
||||
src: "DCL-S counter INT(10) INZ(0);",
|
||||
},
|
||||
Example {
|
||||
label: "constant declaration",
|
||||
rule: "constant-decl",
|
||||
src: "DCL-C MAX_SIZE CONST(100);",
|
||||
},
|
||||
// ── Control-option specification ─────────────────────────────────────
|
||||
Example {
|
||||
label: "CTL-OPT NOMAIN",
|
||||
rule: "control-spec",
|
||||
src: "CTL-OPT NOMAIN;",
|
||||
},
|
||||
Example {
|
||||
label: "CTL-OPT DFTACTGRP(*NO)",
|
||||
rule: "control-spec",
|
||||
src: "CTL-OPT DFTACTGRP(*NO);",
|
||||
},
|
||||
// ── Statements ───────────────────────────────────────────────────────
|
||||
Example {
|
||||
label: "assignment statement",
|
||||
rule: "assign-stmt",
|
||||
src: "result=a+b;",
|
||||
},
|
||||
Example {
|
||||
label: "EVAL assignment",
|
||||
rule: "assign-stmt",
|
||||
src: "EVAL result=42;",
|
||||
},
|
||||
Example {
|
||||
label: "RETURN with value",
|
||||
rule: "return-stmt",
|
||||
src: "RETURN result;",
|
||||
},
|
||||
Example {
|
||||
label: "bare RETURN",
|
||||
rule: "return-stmt",
|
||||
src: "RETURN;",
|
||||
},
|
||||
Example {
|
||||
label: "LEAVE statement",
|
||||
rule: "leave-stmt",
|
||||
src: "LEAVE;",
|
||||
},
|
||||
Example {
|
||||
label: "ITER statement",
|
||||
rule: "iter-stmt",
|
||||
src: "ITER;",
|
||||
},
|
||||
Example {
|
||||
label: "EXSR call",
|
||||
rule: "exsr-stmt",
|
||||
src: "EXSR calcTotals;",
|
||||
},
|
||||
// ── I/O statements ───────────────────────────────────────────────────
|
||||
Example {
|
||||
label: "READ file",
|
||||
rule: "read-stmt",
|
||||
src: "READ myFile;",
|
||||
},
|
||||
Example {
|
||||
label: "WRITE record",
|
||||
rule: "write-stmt",
|
||||
src: "WRITE outputRec;",
|
||||
},
|
||||
Example {
|
||||
label: "CHAIN key into file",
|
||||
rule: "chain-stmt",
|
||||
src: "CHAIN keyFld myFile;",
|
||||
},
|
||||
Example {
|
||||
label: "SETLL to beginning",
|
||||
rule: "setll-stmt",
|
||||
src: "SETLL *START myFile;",
|
||||
},
|
||||
Example {
|
||||
label: "OPEN file",
|
||||
rule: "open-stmt",
|
||||
src: "OPEN myFile;",
|
||||
},
|
||||
Example {
|
||||
label: "CLOSE file",
|
||||
rule: "close-stmt",
|
||||
src: "CLOSE myFile;",
|
||||
},
|
||||
Example {
|
||||
label: "CLOSE *ALL",
|
||||
rule: "close-stmt",
|
||||
src: "CLOSE *ALL;",
|
||||
},
|
||||
// ── Expressions ──────────────────────────────────────────────────────
|
||||
Example {
|
||||
label: "simple addition expression",
|
||||
rule: "expression",
|
||||
src: "a+b",
|
||||
},
|
||||
Example {
|
||||
label: "comparison expression",
|
||||
rule: "expression",
|
||||
src: "x>=10",
|
||||
},
|
||||
Example {
|
||||
label: "NOT expression",
|
||||
rule: "expression",
|
||||
src: "NOT flag",
|
||||
},
|
||||
Example {
|
||||
label: "combined AND / OR",
|
||||
rule: "expression",
|
||||
src: "a=1ANDb=2",
|
||||
},
|
||||
Example {
|
||||
label: "parenthesised expression",
|
||||
rule: "expression",
|
||||
src: "(x+y)",
|
||||
},
|
||||
// ── Built-in functions ───────────────────────────────────────────────
|
||||
Example {
|
||||
label: "%LEN built-in",
|
||||
rule: "built-in-function",
|
||||
src: "%LEN(myField)",
|
||||
},
|
||||
Example {
|
||||
label: "%TRIM built-in",
|
||||
rule: "built-in-function",
|
||||
src: "%TRIM(name)",
|
||||
},
|
||||
Example {
|
||||
label: "%EOF built-in (no arg)",
|
||||
rule: "built-in-function",
|
||||
src: "%EOF()",
|
||||
},
|
||||
Example {
|
||||
label: "%SUBST built-in (3-arg)",
|
||||
rule: "built-in-function",
|
||||
src: "%SUBST(str:1:5)",
|
||||
},
|
||||
Example {
|
||||
label: "%DEC built-in",
|
||||
rule: "built-in-function",
|
||||
src: "%DEC(value:9:2)",
|
||||
},
|
||||
// ── Duration codes ───────────────────────────────────────────────────
|
||||
Example {
|
||||
label: "duration code *DAYS",
|
||||
rule: "duration-code",
|
||||
src: "*DAYS",
|
||||
},
|
||||
// ── Date / time formats ──────────────────────────────────────────────
|
||||
Example {
|
||||
label: "date format *ISO",
|
||||
rule: "date-format",
|
||||
src: "*ISO",
|
||||
},
|
||||
Example {
|
||||
label: "time format *HMS",
|
||||
rule: "time-format",
|
||||
src: "*HMS",
|
||||
},
|
||||
// ── Qualified names ──────────────────────────────────────────────────
|
||||
Example {
|
||||
label: "simple qualified name",
|
||||
rule: "qualified-name",
|
||||
src: "myDs.field",
|
||||
},
|
||||
Example {
|
||||
label: "deeply qualified name",
|
||||
rule: "qualified-name",
|
||||
src: "ds.subDs.leaf",
|
||||
},
|
||||
];
|
||||
|
||||
let total = examples.len();
|
||||
let mut ok = 0usize;
|
||||
let mut bad = 0usize;
|
||||
|
||||
for ex in examples {
|
||||
let target = Term::Nonterminal(ex.rule.to_string());
|
||||
let matched = parser
|
||||
.parse_input_starting_with(ex.src, &target)
|
||||
.next()
|
||||
.is_some();
|
||||
|
||||
if matched {
|
||||
ok += 1;
|
||||
} else {
|
||||
bad += 1;
|
||||
}
|
||||
|
||||
run_example(&parser, ex);
|
||||
}
|
||||
|
||||
// ── 4. Summary ─────────────────────────────────────────────────────────
|
||||
println!("=== Summary ===");
|
||||
println!(" total : {}", total);
|
||||
println!(" matched : {}", ok);
|
||||
println!(" failed : {}", bad);
|
||||
println!();
|
||||
|
||||
if bad == 0 {
|
||||
println!("All examples parsed successfully.");
|
||||
} else {
|
||||
println!("{} example(s) did not parse — check the BNF or the snippet.", bad);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Unit tests
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// Leak a `Grammar` onto the heap so the returned `GrammarParser` can hold
|
||||
/// a `'static` reference to it. The tiny allocation is intentional: this
|
||||
/// is test-only code and the process exits shortly after.
|
||||
fn make_parser() -> bnf::GrammarParser<'static> {
|
||||
let grammar: &'static bnf::Grammar =
|
||||
Box::leak(Box::new(load_grammar().expect("BNF must be valid")));
|
||||
grammar
|
||||
.build_parser()
|
||||
.expect("all non-terminals must resolve")
|
||||
}
|
||||
|
||||
// ── Grammar loading ──────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn grammar_loads() {
|
||||
load_grammar().expect("grammar should parse without error");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parser_builds() {
|
||||
make_parser();
|
||||
}
|
||||
|
||||
// ── Identifiers ──────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn identifier_simple() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "abc", "identifier").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn identifier_with_underscore() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "my_var", "identifier").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn identifier_single_letter() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "x", "identifier").is_some());
|
||||
}
|
||||
|
||||
// ── Literals ─────────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn integer_literal() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "0", "integer-literal").is_some());
|
||||
assert!(parse_as(&p, "999", "integer-literal").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numeric_literal_decimal() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "3.14", "numeric-literal").is_some());
|
||||
}
|
||||
|
||||
// ── Named constants ───────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn named_constants() {
|
||||
let p = make_parser();
|
||||
for s in &["*ON", "*OFF", "*BLANK", "*BLANKS", "*ZEROS", "*ZERO",
|
||||
"*HIVAL", "*LOVAL", "*NULL"] {
|
||||
assert!(parse_as(&p, s, "named-constant").is_some(), "{} failed", s);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Type specs ────────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn type_spec_char() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "CHAR(50)", "type-spec").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_spec_packed() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "PACKED(9:2)", "type-spec").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_spec_date() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "DATE", "type-spec").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_spec_ind() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "IND", "type-spec").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn type_spec_pointer() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "POINTER", "type-spec").is_some());
|
||||
}
|
||||
|
||||
// ── Declarations ─────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn standalone_decl_no_inz() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "DCL-S total PACKED(9:2);", "standalone-decl").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standalone_decl_with_inz() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "DCL-S counter INT(10) INZ(0);", "standalone-decl").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constant_decl() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "DCL-C MAX CONST(100);", "constant-decl").is_some());
|
||||
}
|
||||
|
||||
// ── Control spec ──────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn ctl_opt_nomain() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "CTL-OPT NOMAIN;", "control-spec").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ctl_opt_dftactgrp_no() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "CTL-OPT DFTACTGRP(*NO);", "control-spec").is_some());
|
||||
}
|
||||
|
||||
// ── Statements ───────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn assign_simple() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "x=1;", "assign-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_with_expr() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "RETURN result;", "return-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn return_bare() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "RETURN;", "return-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn leave_stmt() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "LEAVE;", "leave-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter_stmt() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "ITER;", "iter-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exsr_stmt() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "EXSR myRoutine;", "exsr-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_stmt() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "READ myFile;", "read-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_stmt() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "WRITE outRec;", "write-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chain_stmt() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "CHAIN key myFile;", "chain-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn setll_start() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "SETLL *START myFile;", "setll-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn open_close() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "OPEN myFile;", "open-stmt").is_some());
|
||||
assert!(parse_as(&p, "CLOSE myFile;", "close-stmt").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn close_all() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "CLOSE *ALL;", "close-stmt").is_some());
|
||||
}
|
||||
|
||||
// ── Expressions ──────────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn expression_addition() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "a+b", "expression").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expression_comparison() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "x=1", "expression").is_some());
|
||||
assert!(parse_as(&p, "x<>0", "expression").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expression_not() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "NOT flag", "expression").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expression_parenthesised() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "(x+1)", "expression").is_some());
|
||||
}
|
||||
|
||||
// ── Built-in functions ───────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn builtin_len() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "%LEN(myField)", "built-in-function").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builtin_trim() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "%TRIM(s)", "built-in-function").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builtin_eof_no_arg() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "%EOF()", "built-in-function").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builtin_subst_3arg() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "%SUBST(s:1:5)", "built-in-function").is_some());
|
||||
}
|
||||
|
||||
// ── Date / time formats ──────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn date_formats() {
|
||||
let p = make_parser();
|
||||
for fmt in &["*MDY", "*DMY", "*YMD", "*JUL", "*ISO", "*USA", "*EUR", "*JIS"] {
|
||||
assert!(parse_as(&p, fmt, "date-format").is_some(), "{} failed", fmt);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_formats() {
|
||||
let p = make_parser();
|
||||
for fmt in &["*HMS", "*ISO", "*USA", "*EUR", "*JIS"] {
|
||||
assert!(parse_as(&p, fmt, "time-format").is_some(), "{} failed", fmt);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Qualified names ───────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn qualified_name_simple() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "myVar", "qualified-name").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn qualified_name_dotted() {
|
||||
let p = make_parser();
|
||||
assert!(parse_as(&p, "ds.field", "qualified-name").is_some());
|
||||
}
|
||||
|
||||
// ── Duration codes ───────────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn duration_codes() {
|
||||
let p = make_parser();
|
||||
for code in &["*YEARS", "*MONTHS", "*DAYS", "*HOURS", "*MINUTES",
|
||||
"*SECONDS", "*MSECONDS"] {
|
||||
assert!(parse_as(&p, code, "duration-code").is_some(), "{} failed", code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
693
src/rpg.bnf
Normal file
693
src/rpg.bnf
Normal file
@@ -0,0 +1,693 @@
|
||||
<wsc> ::= ' ' | '\t' | '\n' | '\r'
|
||||
<ws> ::= <wsc> | <wsc> <ws>
|
||||
<opt-ws> ::= <ws> | ''
|
||||
|
||||
<program> ::= <opt-ws> <program-body> <opt-ws>
|
||||
|
||||
<program-body> ::= <declaration-section> <opt-ws> <procedure-list>
|
||||
| <declaration-section>
|
||||
| <procedure-list>
|
||||
|
||||
<declaration-section> ::= <declaration> <opt-ws> <declaration-section>
|
||||
| <declaration>
|
||||
|
||||
<declaration> ::= <control-spec>
|
||||
| <file-decl>
|
||||
| <standalone-decl>
|
||||
| <constant-decl>
|
||||
| <data-structure-decl>
|
||||
| <named-constant-decl>
|
||||
| <subroutine>
|
||||
|
||||
<procedure-list> ::= <procedure> <opt-ws> <procedure-list>
|
||||
| <procedure>
|
||||
|
||||
<procedure> ::= 'DCL-PROC' <ws> <identifier> <opt-ws> ';' <opt-ws> <procedure-body> <opt-ws> 'END-PROC' <opt-ws> ';'
|
||||
| 'DCL-PROC' <ws> <identifier> <ws> <proc-keyword-list> <opt-ws> ';' <opt-ws> <procedure-body> <opt-ws> 'END-PROC' <opt-ws> ';'
|
||||
|
||||
<proc-keyword-list> ::= <proc-keyword> <ws> <proc-keyword-list>
|
||||
| <proc-keyword>
|
||||
|
||||
<proc-keyword> ::= 'EXPORT'
|
||||
| 'EXTPROC' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'EXTPROC' <opt-ws> '(' <opt-ws> '*CL' <opt-ws> ':' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'EXTPROC' <opt-ws> '(' <opt-ws> '*DCLCASE' <opt-ws> ')'
|
||||
|
||||
<procedure-body> ::= <pi-spec> <opt-ws> <declaration-section> <opt-ws> <statement-list>
|
||||
| <pi-spec> <opt-ws> <declaration-section>
|
||||
| <pi-spec> <opt-ws> <statement-list>
|
||||
| <declaration-section> <opt-ws> <statement-list>
|
||||
| <statement-list>
|
||||
| <pi-spec>
|
||||
| ''
|
||||
|
||||
<pi-spec> ::= 'DCL-PI' <ws> <identifier> <opt-ws> ';' <opt-ws> 'END-PI' <opt-ws> ';'
|
||||
| 'DCL-PI' <ws> <identifier> <ws> <type-spec> <opt-ws> ';' <opt-ws> 'END-PI' <opt-ws> ';'
|
||||
| 'DCL-PI' <ws> <identifier> <opt-ws> ';' <opt-ws> <pi-param-list> <opt-ws> 'END-PI' <opt-ws> ';'
|
||||
| 'DCL-PI' <ws> <identifier> <ws> <type-spec> <opt-ws> ';' <opt-ws> <pi-param-list> <opt-ws> 'END-PI' <opt-ws> ';'
|
||||
| 'DCL-PI' <ws> '*N' <opt-ws> ';' <opt-ws> 'END-PI' <opt-ws> ';'
|
||||
| 'DCL-PI' <ws> '*N' <ws> <type-spec> <opt-ws> ';' <opt-ws> 'END-PI' <opt-ws> ';'
|
||||
| 'DCL-PI' <ws> '*N' <opt-ws> ';' <opt-ws> <pi-param-list> <opt-ws> 'END-PI' <opt-ws> ';'
|
||||
| 'DCL-PI' <ws> '*N' <ws> <type-spec> <opt-ws> ';' <opt-ws> <pi-param-list> <opt-ws> 'END-PI' <opt-ws> ';'
|
||||
|
||||
<pi-param-list> ::= <pi-param> <opt-ws> <pi-param-list>
|
||||
| <pi-param>
|
||||
|
||||
<pi-param> ::= <identifier> <ws> <type-spec> <opt-ws> ';'
|
||||
| <identifier> <ws> <type-spec> <ws> <param-keyword-list> <opt-ws> ';'
|
||||
|
||||
<param-keyword-list> ::= <param-keyword> <ws> <param-keyword-list>
|
||||
| <param-keyword>
|
||||
|
||||
<param-keyword> ::= 'VALUE'
|
||||
| 'CONST'
|
||||
| 'OPTIONS' <opt-ws> '(' <opt-ws> '*NOPASS' <opt-ws> ')'
|
||||
| 'OPTIONS' <opt-ws> '(' <opt-ws> '*OMIT' <opt-ws> ')'
|
||||
| 'OPTIONS' <opt-ws> '(' <opt-ws> '*VARSIZE' <opt-ws> ')'
|
||||
|
||||
<subroutine> ::= 'BEG-SR' <ws> <identifier> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> 'END-SR' <opt-ws> ';'
|
||||
| 'BEG-SR' <ws> <identifier> <opt-ws> ';' <opt-ws> 'END-SR' <opt-ws> ';'
|
||||
|
||||
<control-spec> ::= 'CTL-OPT' <ws> <ctl-keyword-list> <opt-ws> ';'
|
||||
|
||||
<ctl-keyword-list> ::= <ctl-keyword> <ws> <ctl-keyword-list>
|
||||
| <ctl-keyword>
|
||||
|
||||
<ctl-keyword> ::= 'DFTACTGRP' <opt-ws> '(' <opt-ws> '*YES' <opt-ws> ')'
|
||||
| 'DFTACTGRP' <opt-ws> '(' <opt-ws> '*NO' <opt-ws> ')'
|
||||
| 'ACTGRP' <opt-ws> '(' <opt-ws> '*CALLER' <opt-ws> ')'
|
||||
| 'ACTGRP' <opt-ws> '(' <opt-ws> '*NEW' <opt-ws> ')'
|
||||
| 'ACTGRP' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'BNDDIR' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'OPTION' <opt-ws> '(' <opt-ws> <option-list> <opt-ws> ')'
|
||||
| 'DATFMT' <opt-ws> '(' <opt-ws> <date-format> <opt-ws> ')'
|
||||
| 'TIMFMT' <opt-ws> '(' <opt-ws> <time-format> <opt-ws> ')'
|
||||
| 'DECEDIT' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'ALWNULL' <opt-ws> '(' <opt-ws> '*USRCTL' <opt-ws> ')'
|
||||
| 'ALWNULL' <opt-ws> '(' <opt-ws> '*INPUTONLY' <opt-ws> ')'
|
||||
| 'ALWNULL' <opt-ws> '(' <opt-ws> '*NO' <opt-ws> ')'
|
||||
| 'DEBUG' <opt-ws> '(' <opt-ws> '*YES' <opt-ws> ')'
|
||||
| 'DEBUG' <opt-ws> '(' <opt-ws> '*NO' <opt-ws> ')'
|
||||
| 'EXPROPTS' <opt-ws> '(' <opt-ws> '*RESDECPOS' <opt-ws> ')'
|
||||
| 'MAIN' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'NOMAIN'
|
||||
| 'COPYRIGHT' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'STGMDL' <opt-ws> '(' <opt-ws> '*SNGLVL' <opt-ws> ')'
|
||||
| 'STGMDL' <opt-ws> '(' <opt-ws> '*TERASPACE' <opt-ws> ')'
|
||||
| 'STGMDL' <opt-ws> '(' <opt-ws> '*INHERIT' <opt-ws> ')'
|
||||
| 'TEXT' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'TRUNCNBR' <opt-ws> '(' <opt-ws> '*YES' <opt-ws> ')'
|
||||
| 'TRUNCNBR' <opt-ws> '(' <opt-ws> '*NO' <opt-ws> ')'
|
||||
|
||||
<option-list> ::= <option-item> <opt-ws> ':' <opt-ws> <option-list>
|
||||
| <option-item>
|
||||
|
||||
<option-item> ::= '*SRCSTMT'
|
||||
| '*NODEBUGIO'
|
||||
| '*NOUNREF'
|
||||
| '*NOSHOWCPY'
|
||||
|
||||
<file-decl> ::= 'DCL-F' <ws> <identifier> <ws> <file-keyword-list> <opt-ws> ';'
|
||||
| 'DCL-F' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<file-keyword-list> ::= <file-keyword> <ws> <file-keyword-list>
|
||||
| <file-keyword>
|
||||
|
||||
<file-keyword> ::= 'KEYED'
|
||||
| 'USAGE' <opt-ws> '(' <opt-ws> '*INPUT' <opt-ws> ')'
|
||||
| 'USAGE' <opt-ws> '(' <opt-ws> '*OUTPUT' <opt-ws> ')'
|
||||
| 'USAGE' <opt-ws> '(' <opt-ws> '*UPDATE' <opt-ws> ':' <opt-ws> '*DELETE' <opt-ws> ')'
|
||||
| 'USAGE' <opt-ws> '(' <opt-ws> '*UPDATE' <opt-ws> ')'
|
||||
| 'USAGE' <opt-ws> '(' <opt-ws> '*DELETE' <opt-ws> ')'
|
||||
| 'DISK'
|
||||
| 'PRINTER'
|
||||
| 'SEQ'
|
||||
| 'RENAME' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ':' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'QUALIFIED'
|
||||
| 'TEMPLATE'
|
||||
| 'EXTFILE' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'EXTFILE' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'EXTMBR' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'EXTMBR' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'EXTDESC' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'STATIC'
|
||||
| 'INFDS' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'BLOCK' <opt-ws> '(' <opt-ws> '*YES' <opt-ws> ')'
|
||||
| 'BLOCK' <opt-ws> '(' <opt-ws> '*NO' <opt-ws> ')'
|
||||
|
||||
<standalone-decl> ::= 'DCL-S' <ws> <identifier> <ws> <type-spec> <opt-ws> ';'
|
||||
| 'DCL-S' <ws> <identifier> <ws> <type-spec> <ws> <var-keyword-list> <opt-ws> ';'
|
||||
|
||||
<constant-decl> ::= 'DCL-C' <ws> <identifier> <ws> <literal> <opt-ws> ';'
|
||||
| 'DCL-C' <ws> <identifier> <ws> 'CONST' <opt-ws> '(' <opt-ws> <literal> <opt-ws> ')' <opt-ws> ';'
|
||||
|
||||
<named-constant-decl> ::= 'DCL-C' <ws> <identifier> <ws> <named-constant> <opt-ws> ';'
|
||||
|
||||
<named-constant> ::= '*ON'
|
||||
| '*OFF'
|
||||
| '*BLANKS'
|
||||
| '*BLANK'
|
||||
| '*ZEROS'
|
||||
| '*ZERO'
|
||||
| '*HIVAL'
|
||||
| '*LOVAL'
|
||||
| '*NULL'
|
||||
|
||||
<data-structure-decl> ::= 'DCL-DS' <ws> <identifier> <opt-ws> ';' <opt-ws> <ds-field-list> <opt-ws> 'END-DS' <opt-ws> ';'
|
||||
| 'DCL-DS' <ws> <identifier> <ws> <ds-keyword-list> <opt-ws> ';' <opt-ws> <ds-field-list> <opt-ws> 'END-DS' <opt-ws> ';'
|
||||
| 'DCL-DS' <ws> <identifier> <opt-ws> ';' <opt-ws> 'END-DS' <opt-ws> ';'
|
||||
| 'DCL-DS' <ws> <identifier> <ws> <ds-keyword-list> <opt-ws> ';' <opt-ws> 'END-DS' <opt-ws> ';'
|
||||
|
||||
<ds-keyword-list> ::= <ds-keyword> <ws> <ds-keyword-list>
|
||||
| <ds-keyword>
|
||||
|
||||
<ds-keyword> ::= 'QUALIFIED'
|
||||
| 'TEMPLATE'
|
||||
| 'LIKEDS' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'LIKEREC' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ':' <opt-ws> <rec-format> <opt-ws> ')'
|
||||
| 'EXTNAME' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ':' <opt-ws> <rec-format> <opt-ws> ')'
|
||||
| 'EXTNAME' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'BASED' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'INZ'
|
||||
| 'INZ' <opt-ws> '(' <opt-ws> '*EXTDFT' <opt-ws> ')'
|
||||
| 'DIM' <opt-ws> '(' <opt-ws> <integer-literal> <opt-ws> ')'
|
||||
| 'STATIC'
|
||||
|
||||
<rec-format> ::= '*INPUT'
|
||||
| '*OUTPUT'
|
||||
| '*ALL'
|
||||
| '*KEY'
|
||||
| <identifier>
|
||||
|
||||
<ds-field-list> ::= <ds-field> <opt-ws> <ds-field-list>
|
||||
| <ds-field>
|
||||
|
||||
<ds-field> ::= <identifier> <ws> <type-spec> <opt-ws> ';'
|
||||
| <identifier> <ws> <type-spec> <ws> <var-keyword-list> <opt-ws> ';'
|
||||
| <data-structure-decl>
|
||||
|
||||
<var-keyword-list> ::= <var-keyword> <ws> <var-keyword-list>
|
||||
| <var-keyword>
|
||||
|
||||
<var-keyword> ::= 'INZ'
|
||||
| 'INZ' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'INZ' <opt-ws> '(' <opt-ws> <named-constant> <opt-ws> ')'
|
||||
| 'STATIC'
|
||||
| 'BASED' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'DIM' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'LIKE' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'LIKEDS' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'ASCEND'
|
||||
| 'DESCEND'
|
||||
| 'ALTSEQ'
|
||||
| 'OPDESC'
|
||||
| 'NOOPT'
|
||||
| 'VOLATILE'
|
||||
|
||||
<type-spec> ::= 'CHAR' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'VARCHAR' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'GRAPH' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'VARGRAPH' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'UCS2' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'VARUCS2' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'PACKED' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'ZONED' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'BINDEC' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'INT' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'UNS' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'FLOAT' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'DATE'
|
||||
| 'DATE' <opt-ws> '(' <opt-ws> <date-format> <opt-ws> ')'
|
||||
| 'TIME'
|
||||
| 'TIME' <opt-ws> '(' <opt-ws> <time-format> <opt-ws> ')'
|
||||
| 'TIMESTAMP'
|
||||
| 'TIMESTAMP' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| 'IND'
|
||||
| 'POINTER'
|
||||
| 'POINTER' <ws> 'PROCPTR'
|
||||
| 'OBJECT' <opt-ws> '(' <opt-ws> '*JAVA' <opt-ws> ':' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| 'LIKE' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'LIKEDS' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| 'LIKEREC' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ':' <opt-ws> <rec-format> <opt-ws> ')'
|
||||
|
||||
<date-format> ::= '*MDY'
|
||||
| '*DMY'
|
||||
| '*YMD'
|
||||
| '*JUL'
|
||||
| '*ISO'
|
||||
| '*USA'
|
||||
| '*EUR'
|
||||
| '*JIS'
|
||||
|
||||
<time-format> ::= '*HMS'
|
||||
| '*ISO'
|
||||
| '*USA'
|
||||
| '*EUR'
|
||||
| '*JIS'
|
||||
|
||||
<statement-list> ::= <statement> <opt-ws> <statement-list>
|
||||
| <statement>
|
||||
|
||||
<statement> ::= <assign-stmt>
|
||||
| <if-stmt>
|
||||
| <dow-stmt>
|
||||
| <dou-stmt>
|
||||
| <for-stmt>
|
||||
| <select-stmt>
|
||||
| <monitor-stmt>
|
||||
| <callp-stmt>
|
||||
| <return-stmt>
|
||||
| <leave-stmt>
|
||||
| <iter-stmt>
|
||||
| <leavesr-stmt>
|
||||
| <exsr-stmt>
|
||||
| <read-stmt>
|
||||
| <readp-stmt>
|
||||
| <reade-stmt>
|
||||
| <readpe-stmt>
|
||||
| <write-stmt>
|
||||
| <update-stmt>
|
||||
| <delete-stmt>
|
||||
| <chain-stmt>
|
||||
| <setll-stmt>
|
||||
| <setgt-stmt>
|
||||
| <open-stmt>
|
||||
| <close-stmt>
|
||||
| <except-stmt>
|
||||
| <exfmt-stmt>
|
||||
| <dsply-stmt>
|
||||
| <reset-stmt>
|
||||
| <clear-stmt>
|
||||
| <sorta-stmt>
|
||||
| <dealloc-stmt>
|
||||
| <dump-stmt>
|
||||
| <force-stmt>
|
||||
| <post-stmt>
|
||||
| <feod-stmt>
|
||||
| <unlock-stmt>
|
||||
| <subroutine>
|
||||
|
||||
<assign-stmt> ::= <lvalue> <opt-ws> '=' <opt-ws> <expression> <opt-ws> ';'
|
||||
| 'EVAL' <ws> <lvalue> <opt-ws> '=' <opt-ws> <expression> <opt-ws> ';'
|
||||
| 'EVAL' <opt-ws> '(' <opt-ws> <eval-option> <opt-ws> ')' <ws> <lvalue> <opt-ws> '=' <opt-ws> <expression> <opt-ws> ';'
|
||||
| 'EVALR' <ws> <lvalue> <opt-ws> '=' <opt-ws> <expression> <opt-ws> ';'
|
||||
| 'EVAL-CORR' <ws> <lvalue> <opt-ws> '=' <opt-ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<eval-option> ::= 'H'
|
||||
| 'T'
|
||||
| 'E'
|
||||
|
||||
<lvalue> ::= <qualified-name>
|
||||
| <qualified-name> <opt-ws> '(' <opt-ws> <index-list> <opt-ws> ')'
|
||||
|
||||
<if-stmt> ::= 'IF' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> <elseif-list> <opt-ws> 'ENDIF' <opt-ws> ';'
|
||||
| 'IF' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> <elseif-list> <opt-ws> <else-clause> <opt-ws> 'ENDIF' <opt-ws> ';'
|
||||
| 'IF' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> 'ENDIF' <opt-ws> ';'
|
||||
| 'IF' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> <else-clause> <opt-ws> 'ENDIF' <opt-ws> ';'
|
||||
| 'IF' <ws> <expression> <opt-ws> ';' <opt-ws> <elseif-list> <opt-ws> 'ENDIF' <opt-ws> ';'
|
||||
| 'IF' <ws> <expression> <opt-ws> ';' <opt-ws> <elseif-list> <opt-ws> <else-clause> <opt-ws> 'ENDIF' <opt-ws> ';'
|
||||
| 'IF' <ws> <expression> <opt-ws> ';' <opt-ws> 'ENDIF' <opt-ws> ';'
|
||||
|
||||
<elseif-list> ::= <elseif-clause> <opt-ws> <elseif-list>
|
||||
| <elseif-clause>
|
||||
|
||||
<elseif-clause> ::= 'ELSEIF' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list>
|
||||
| 'ELSEIF' <ws> <expression> <opt-ws> ';'
|
||||
|
||||
<else-clause> ::= 'ELSE' <opt-ws> ';' <opt-ws> <statement-list>
|
||||
| 'ELSE' <opt-ws> ';'
|
||||
|
||||
<dow-stmt> ::= 'DOW' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> 'ENDDO' <opt-ws> ';'
|
||||
| 'DOW' <ws> <expression> <opt-ws> ';' <opt-ws> 'ENDDO' <opt-ws> ';'
|
||||
|
||||
<dou-stmt> ::= 'DOU' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> 'ENDDO' <opt-ws> ';'
|
||||
| 'DOU' <ws> <expression> <opt-ws> ';' <opt-ws> 'ENDDO' <opt-ws> ';'
|
||||
|
||||
<for-stmt> ::= 'FOR' <ws> <identifier> <opt-ws> '=' <opt-ws> <expression> <ws> 'TO' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> 'ENDFOR' <opt-ws> ';'
|
||||
| 'FOR' <ws> <identifier> <opt-ws> '=' <opt-ws> <expression> <ws> 'TO' <ws> <expression> <ws> 'BY' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> 'ENDFOR' <opt-ws> ';'
|
||||
| 'FOR' <ws> <identifier> <opt-ws> '=' <opt-ws> <expression> <ws> 'DOWNTO' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> 'ENDFOR' <opt-ws> ';'
|
||||
| 'FOR' <ws> <identifier> <opt-ws> '=' <opt-ws> <expression> <ws> 'DOWNTO' <ws> <expression> <ws> 'BY' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> 'ENDFOR' <opt-ws> ';'
|
||||
| 'FOR' <ws> <identifier> <opt-ws> '=' <opt-ws> <expression> <ws> 'TO' <ws> <expression> <opt-ws> ';' <opt-ws> 'ENDFOR' <opt-ws> ';'
|
||||
| 'FOR' <ws> <identifier> <opt-ws> '=' <opt-ws> <expression> <ws> 'DOWNTO' <ws> <expression> <opt-ws> ';' <opt-ws> 'ENDFOR' <opt-ws> ';'
|
||||
|
||||
<select-stmt> ::= 'SELECT' <opt-ws> ';' <opt-ws> <when-list> <opt-ws> 'ENDSL' <opt-ws> ';'
|
||||
| 'SELECT' <opt-ws> ';' <opt-ws> <when-list> <opt-ws> <other-clause> <opt-ws> 'ENDSL' <opt-ws> ';'
|
||||
| 'SELECT' <opt-ws> ';' <opt-ws> 'ENDSL' <opt-ws> ';'
|
||||
|
||||
<when-list> ::= <when-clause> <opt-ws> <when-list>
|
||||
| <when-clause>
|
||||
|
||||
<when-clause> ::= 'WHEN' <ws> <expression> <opt-ws> ';' <opt-ws> <statement-list>
|
||||
| 'WHEN' <ws> <expression> <opt-ws> ';'
|
||||
|
||||
<other-clause> ::= 'OTHER' <opt-ws> ';' <opt-ws> <statement-list>
|
||||
| 'OTHER' <opt-ws> ';'
|
||||
|
||||
<monitor-stmt> ::= 'MONITOR' <opt-ws> ';' <opt-ws> <statement-list> <opt-ws> <on-error-list> <opt-ws> 'ENDMON' <opt-ws> ';'
|
||||
| 'MONITOR' <opt-ws> ';' <opt-ws> <on-error-list> <opt-ws> 'ENDMON' <opt-ws> ';'
|
||||
|
||||
<on-error-list> ::= <on-error-clause> <opt-ws> <on-error-list>
|
||||
| <on-error-clause>
|
||||
|
||||
<on-error-clause> ::= 'ON-ERROR' <opt-ws> ';' <opt-ws> <statement-list>
|
||||
| 'ON-ERROR' <ws> <error-code-list> <opt-ws> ';' <opt-ws> <statement-list>
|
||||
| 'ON-ERROR' <opt-ws> ';'
|
||||
| 'ON-ERROR' <ws> <error-code-list> <opt-ws> ';'
|
||||
|
||||
<error-code-list> ::= <error-code> <opt-ws> ':' <opt-ws> <error-code-list>
|
||||
| <error-code>
|
||||
|
||||
<error-code> ::= <integer-literal>
|
||||
| '*PROGRAM'
|
||||
| '*FILE'
|
||||
| '*ALL'
|
||||
|
||||
<callp-stmt> ::= 'CALLP' <ws> <identifier> <opt-ws> '(' <opt-ws> <arg-list> <opt-ws> ')' <opt-ws> ';'
|
||||
| 'CALLP' <ws> <identifier> <opt-ws> '(' <opt-ws> ')' <opt-ws> ';'
|
||||
| 'CALLP' <ws> <identifier> <opt-ws> ';'
|
||||
| <identifier> <opt-ws> '(' <opt-ws> <arg-list> <opt-ws> ')' <opt-ws> ';'
|
||||
| <identifier> <opt-ws> '(' <opt-ws> ')' <opt-ws> ';'
|
||||
|
||||
<return-stmt> ::= 'RETURN' <opt-ws> ';'
|
||||
| 'RETURN' <ws> <expression> <opt-ws> ';'
|
||||
|
||||
<leave-stmt> ::= 'LEAVE' <opt-ws> ';'
|
||||
|
||||
<iter-stmt> ::= 'ITER' <opt-ws> ';'
|
||||
|
||||
<leavesr-stmt> ::= 'LEAVESR' <opt-ws> ';'
|
||||
|
||||
<exsr-stmt> ::= 'EXSR' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<read-stmt> ::= 'READ' <ws> <identifier> <opt-ws> ';'
|
||||
| 'READ' <ws> <identifier> <ws> <indicator-spec> <opt-ws> ';'
|
||||
| 'READ' <opt-ws> '(' <opt-ws> 'N' <opt-ws> ')' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<readp-stmt> ::= 'READP' <ws> <identifier> <opt-ws> ';'
|
||||
| 'READP' <ws> <identifier> <ws> <indicator-spec> <opt-ws> ';'
|
||||
|
||||
<reade-stmt> ::= 'READE' <ws> <expression> <ws> <identifier> <opt-ws> ';'
|
||||
| 'READE' <ws> <expression> <ws> <identifier> <ws> <indicator-spec> <opt-ws> ';'
|
||||
| 'READE' <opt-ws> '(' <opt-ws> 'N' <opt-ws> ')' <ws> <expression> <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<readpe-stmt> ::= 'READPE' <ws> <expression> <ws> <identifier> <opt-ws> ';'
|
||||
| 'READPE' <ws> <expression> <ws> <identifier> <ws> <indicator-spec> <opt-ws> ';'
|
||||
|
||||
<write-stmt> ::= 'WRITE' <ws> <identifier> <opt-ws> ';'
|
||||
| 'WRITE' <ws> <identifier> <ws> <indicator-spec> <opt-ws> ';'
|
||||
| 'WRITE' <opt-ws> '(' <opt-ws> 'E' <opt-ws> ')' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<update-stmt> ::= 'UPDATE' <ws> <identifier> <opt-ws> ';'
|
||||
| 'UPDATE' <ws> <identifier> <ws> <indicator-spec> <opt-ws> ';'
|
||||
| 'UPDATE' <opt-ws> '(' <opt-ws> 'E' <opt-ws> ')' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<delete-stmt> ::= 'DELETE' <ws> <expression> <ws> <identifier> <opt-ws> ';'
|
||||
| 'DELETE' <opt-ws> '(' <opt-ws> 'E' <opt-ws> ')' <ws> <expression> <ws> <identifier> <opt-ws> ';'
|
||||
| 'DELETE' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<chain-stmt> ::= 'CHAIN' <ws> <expression> <ws> <identifier> <opt-ws> ';'
|
||||
| 'CHAIN' <opt-ws> '(' <opt-ws> 'N' <opt-ws> ')' <ws> <expression> <ws> <identifier> <opt-ws> ';'
|
||||
| 'CHAIN' <opt-ws> '(' <opt-ws> 'E' <opt-ws> ')' <ws> <expression> <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<setll-stmt> ::= 'SETLL' <ws> <expression> <ws> <identifier> <opt-ws> ';'
|
||||
| 'SETLL' <ws> '*START' <ws> <identifier> <opt-ws> ';'
|
||||
| 'SETLL' <ws> '*END' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<setgt-stmt> ::= 'SETGT' <ws> <expression> <ws> <identifier> <opt-ws> ';'
|
||||
| 'SETGT' <ws> '*START' <ws> <identifier> <opt-ws> ';'
|
||||
| 'SETGT' <ws> '*END' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<open-stmt> ::= 'OPEN' <ws> <identifier> <opt-ws> ';'
|
||||
| 'OPEN' <opt-ws> '(' <opt-ws> 'E' <opt-ws> ')' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<close-stmt> ::= 'CLOSE' <ws> <identifier> <opt-ws> ';'
|
||||
| 'CLOSE' <opt-ws> '(' <opt-ws> 'E' <opt-ws> ')' <ws> <identifier> <opt-ws> ';'
|
||||
| 'CLOSE' <ws> '*ALL' <opt-ws> ';'
|
||||
|
||||
<except-stmt> ::= 'EXCEPT' <ws> <identifier> <opt-ws> ';'
|
||||
| 'EXCEPT' <opt-ws> ';'
|
||||
|
||||
<exfmt-stmt> ::= 'EXFMT' <ws> <identifier> <opt-ws> ';'
|
||||
| 'EXFMT' <opt-ws> '(' <opt-ws> 'E' <opt-ws> ')' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<dsply-stmt> ::= 'DSPLY' <ws> <expression> <opt-ws> ';'
|
||||
| 'DSPLY' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <identifier> <opt-ws> ':' <opt-ws> <identifier> <opt-ws> ')' <opt-ws> ';'
|
||||
| 'DSPLY' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')' <opt-ws> ';'
|
||||
|
||||
<reset-stmt> ::= 'RESET' <ws> <lvalue> <opt-ws> ';'
|
||||
| 'RESET' <ws> '*ALL' <opt-ws> ';'
|
||||
|
||||
<clear-stmt> ::= 'CLEAR' <ws> <lvalue> <opt-ws> ';'
|
||||
|
||||
<sorta-stmt> ::= 'SORTA' <ws> <identifier> <opt-ws> ';'
|
||||
| 'SORTA' <opt-ws> '(' <opt-ws> 'A' <opt-ws> ')' <ws> <identifier> <opt-ws> ';'
|
||||
| 'SORTA' <opt-ws> '(' <opt-ws> 'D' <opt-ws> ')' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<dealloc-stmt> ::= 'DEALLOC' <ws> <identifier> <opt-ws> ';'
|
||||
| 'DEALLOC' <opt-ws> '(' <opt-ws> 'N' <opt-ws> ')' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<dump-stmt> ::= 'DUMP' <opt-ws> ';'
|
||||
| 'DUMP' <opt-ws> '(' <opt-ws> 'A' <opt-ws> ')' <opt-ws> ';'
|
||||
|
||||
<force-stmt> ::= 'FORCE' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<post-stmt> ::= 'POST' <ws> <identifier> <opt-ws> ';'
|
||||
| 'POST' <opt-ws> '(' <opt-ws> 'E' <opt-ws> ')' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<feod-stmt> ::= 'FEOD' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<unlock-stmt> ::= 'UNLOCK' <ws> <identifier> <opt-ws> ';'
|
||||
|
||||
<indicator-spec> ::= <identifier>
|
||||
|
||||
<expression> ::= <or-expr>
|
||||
|
||||
<or-expr> ::= <or-expr> <opt-ws> 'OR' <opt-ws> <and-expr>
|
||||
| <and-expr>
|
||||
|
||||
<and-expr> ::= <and-expr> <opt-ws> 'AND' <opt-ws> <not-expr>
|
||||
| <not-expr>
|
||||
|
||||
<not-expr> ::= 'NOT' <ws> <comparison-expr>
|
||||
| <comparison-expr>
|
||||
|
||||
<comparison-expr> ::= <additive-expr> <opt-ws> '=' <opt-ws> <additive-expr>
|
||||
| <additive-expr> <opt-ws> '<>' <opt-ws> <additive-expr>
|
||||
| <additive-expr> <opt-ws> '>=' <opt-ws> <additive-expr>
|
||||
| <additive-expr> <opt-ws> '<=' <opt-ws> <additive-expr>
|
||||
| <additive-expr> <opt-ws> '>' <opt-ws> <additive-expr>
|
||||
| <additive-expr> <opt-ws> '<' <opt-ws> <additive-expr>
|
||||
| <additive-expr>
|
||||
|
||||
<additive-expr> ::= <additive-expr> <opt-ws> '+' <opt-ws> <multiplicative-expr>
|
||||
| <additive-expr> <opt-ws> '-' <opt-ws> <multiplicative-expr>
|
||||
| <multiplicative-expr>
|
||||
|
||||
<multiplicative-expr> ::= <multiplicative-expr> <opt-ws> '**' <opt-ws> <unary-expr>
|
||||
| <multiplicative-expr> <opt-ws> '*' <opt-ws> <unary-expr>
|
||||
| <multiplicative-expr> <opt-ws> '/' <opt-ws> <unary-expr>
|
||||
| <unary-expr>
|
||||
|
||||
<unary-expr> ::= '-' <opt-ws> <primary-expr>
|
||||
| '+' <opt-ws> <primary-expr>
|
||||
| <primary-expr>
|
||||
|
||||
<primary-expr> ::= <literal>
|
||||
| <named-constant>
|
||||
| <special-value>
|
||||
| <built-in-function>
|
||||
| <identifier> <opt-ws> '(' <opt-ws> <arg-list> <opt-ws> ')'
|
||||
| <identifier> <opt-ws> '(' <opt-ws> ')'
|
||||
| <qualified-name> <opt-ws> '(' <opt-ws> <index-list> <opt-ws> ')'
|
||||
| <qualified-name>
|
||||
| '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
|
||||
<special-value> ::= '*IN' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '*IN'
|
||||
| '*ON'
|
||||
| '*OFF'
|
||||
| '*BLANK'
|
||||
| '*BLANKS'
|
||||
| '*ZERO'
|
||||
| '*ZEROS'
|
||||
| '*HIVAL'
|
||||
| '*LOVAL'
|
||||
| '*NULL'
|
||||
| '*ALL' <string-literal>
|
||||
| '*OMIT'
|
||||
| '*THIS'
|
||||
| '*SAME'
|
||||
| '*START'
|
||||
| '*END'
|
||||
|
||||
<built-in-function> ::= '%ABS' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%ADDR' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%ALLOC' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%BITAND' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%BITNOT' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%BITOR' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%BITXOR' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%CHAR' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <date-format> <opt-ws> ')'
|
||||
| '%CHAR' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%CHECK' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%CHECK' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%CHECKR' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%DATE' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <date-format> <opt-ws> ')'
|
||||
| '%DATE' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%DATE' <opt-ws> '(' <opt-ws> ')'
|
||||
| '%DAYS' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%DEC' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%DECH' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%DECPOS' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%DIFF' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <duration-code> <opt-ws> ')'
|
||||
| '%DIV' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%EDITC' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| '%EDITFLT' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%EDITW' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| '%ELEM' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%EOF' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%EOF' <opt-ws> '(' <opt-ws> ')'
|
||||
| '%EQUAL' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%EQUAL' <opt-ws> '(' <opt-ws> ')'
|
||||
| '%ERROR' <opt-ws> '(' <opt-ws> ')'
|
||||
| '%FIELDS' <opt-ws> '(' <opt-ws> <field-list> <opt-ws> ')'
|
||||
| '%FLOAT' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%FOUND' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%FOUND' <opt-ws> '(' <opt-ws> ')'
|
||||
| '%GRAPH' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%HOURS' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%INT' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%INTH' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%KDS' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%KDS' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%LEN' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%MINUTES' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%MONTHS' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%MSECONDS' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%NULLIND' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%OCCUR' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%OPEN' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%PADDR' <opt-ws> '(' <opt-ws> '*DCLCASE' <opt-ws> ':' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%PADDR' <opt-ws> '(' <opt-ws> <string-literal> <opt-ws> ')'
|
||||
| '%REALLOC' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%REM' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%REPLACE' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%REPLACE' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%REPLACE' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%SCAN' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%SCAN' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%SCANR' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%SECONDS' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%SHTDN' <opt-ws> '(' <opt-ws> ')'
|
||||
| '%SIZE' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%SQRT' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%STATUS' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%STATUS' <opt-ws> '(' <opt-ws> ')'
|
||||
| '%STR' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%STR' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%SUBARR' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%SUBARR' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%SUBST' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%SUBST' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%THIS' <opt-ws> '(' <opt-ws> ')'
|
||||
| '%TIME' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%TIME' <opt-ws> '(' <opt-ws> ')'
|
||||
| '%TIMESTAMP' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%TIMESTAMP' <opt-ws> '(' <opt-ws> ')'
|
||||
| '%TRIM' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%TRIML' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%TRIMR' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%UCS2' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%UNS' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%UNSH' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%XFOOT' <opt-ws> '(' <opt-ws> <identifier> <opt-ws> ')'
|
||||
| '%XLATE' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ':' <opt-ws> <expression> <opt-ws> ')'
|
||||
| '%YEARS' <opt-ws> '(' <opt-ws> <expression> <opt-ws> ')'
|
||||
|
||||
<duration-code> ::= '*YEARS'
|
||||
| '*MONTHS'
|
||||
| '*DAYS'
|
||||
| '*HOURS'
|
||||
| '*MINUTES'
|
||||
| '*SECONDS'
|
||||
| '*MSECONDS'
|
||||
|
||||
<field-list> ::= <identifier> <opt-ws> ':' <opt-ws> <field-list>
|
||||
| <identifier>
|
||||
|
||||
<arg-list> ::= <arg> <opt-ws> ':' <opt-ws> <arg-list>
|
||||
| <arg>
|
||||
|
||||
<arg> ::= <expression>
|
||||
| '*OMIT'
|
||||
|
||||
<index-list> ::= <expression> <opt-ws> ':' <opt-ws> <index-list>
|
||||
| <expression>
|
||||
|
||||
<qualified-name> ::= <identifier> <opt-ws> '.' <opt-ws> <qualified-name>
|
||||
| <identifier>
|
||||
|
||||
<literal> ::= <string-literal>
|
||||
| <numeric-literal>
|
||||
| <integer-literal>
|
||||
| <hex-literal>
|
||||
| <indicator-literal>
|
||||
|
||||
<string-literal> ::= "'" <string-chars> "'"
|
||||
|
||||
<string-chars> ::= <string-char> <string-chars>
|
||||
| ''
|
||||
|
||||
<string-char> ::= <letter>
|
||||
| <digit>
|
||||
| <special-char>
|
||||
| "''"
|
||||
|
||||
<hex-literal> ::= 'X' "'" <hex-chars> "'"
|
||||
|
||||
<hex-chars> ::= <hex-char> <hex-chars>
|
||||
| <hex-char>
|
||||
|
||||
<hex-char> ::= <digit>
|
||||
| 'A'
|
||||
| 'B'
|
||||
| 'C'
|
||||
| 'D'
|
||||
| 'E'
|
||||
| 'F'
|
||||
|
||||
<numeric-literal> ::= <integer-literal> '.' <digits>
|
||||
| '.' <digits>
|
||||
|
||||
<integer-literal> ::= <digits>
|
||||
|
||||
<digits> ::= <digit> <digits>
|
||||
| <digit>
|
||||
|
||||
<indicator-literal> ::= '*ON'
|
||||
| '*OFF'
|
||||
|
||||
<identifier> ::= <letter> <id-chars>
|
||||
| <letter>
|
||||
|
||||
<id-chars> ::= <id-char> <id-chars>
|
||||
| <id-char>
|
||||
|
||||
<id-char> ::= <letter>
|
||||
| <digit>
|
||||
| '_'
|
||||
|
||||
<letter> ::= 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J'
|
||||
| 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T'
|
||||
| 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z'
|
||||
| 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j'
|
||||
| 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't'
|
||||
| 'u' | 'v' | 'w' | 'x' | 'y' | 'z'
|
||||
| '@' | '#' | '$'
|
||||
|
||||
<digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
|
||||
|
||||
<special-char> ::= ' ' | '!' | '"' | '#' | '$' | '%' | '&' | '('
|
||||
| ')' | '*' | '+' | ',' | '-' | '.' | '/' | ':'
|
||||
| '<' | '=' | '>' | '?' | '@' | '[' | '\\'
|
||||
| ']' | '^' | '_' | '`' | '{' | '|' | '}' | '~'
|
||||
Reference in New Issue
Block a user