-- COBOL Syntax Equations
-- Derived from:
-- "NPS MICRO-COBOL, an implementation of Navy Standard HYPO-COBOL
-- for a Microprocessor-Based Computer System"
-- Jim Farlee Jr. and Michael L. Rice
-- M.S. Thesis, Naval PostGraduate School, June '79
COBOL = id-division environment-division data-division 'PROCEDURE' ;

-- reserved COBOL words

-- 'ACCEPT'
-- 'ACCESS'
-- 'ADD'
-- 'ADVANCING'
-- 'AFTER'
-- 'ALPHABETIC'
-- 'ASSIGN'
-- 'AUTHOR'
-- 'BEFORE'
-- 'BLOCK'
-- 'BY'
-- 'CALL'
-- 'CLOSE'
-- 'COBOL'
-- 'COMP'
-- 'CONFIGURATION'
-- 'DATA'
-- 'DATE-WRITTEN'
-- 'DEBUGGING'
-- 'DELETE'
-- 'DEPENDING'
-- 'DISPLAY'
-- 'DIVIDE'
-- 'DIVISION'
-- 'ELSE'
-- 'END'
-- 'ENTER'
-- 'ENVIRONMENT'
-- 'EOF'
-- 'EQUAL'
-- 'ERROR'
-- 'EXIT'
-- 'FD'
-- 'FILE'
-- 'FILE-CONTROL'
-- 'FILLER'
-- 'FROM'
-- 'GO'
-- 'GREATER'
-- 'I-O'
-- 'I-O-CONTROL'
-- 'IDENTIFIFICATION'
-- 'IF'
-- 'INPUT'
-- 'INPUT-OUTPUT'
-- 'INVALID'
-- 'INTO'
-- 'LABEL'
-- 'LEADING'
-- 'LEFT'
-- 'LESS'
-- 'LINKAGE'
-- 'MODE'
-- 'MOVE'
-- 'MULTIPLY'
-- 'NEXT'
-- 'NOT'
-- 'NUMERIC'
-- 'OBJECT-COMPUTER'
-- 'OCCURS'
-- 'OF'
-- 'OMITTED'
-- 'OPEN'
-- 'ORGANIZATION'
-- 'OUTPUT'
-- 'PAGE'
-- 'PERFORM'
-- 'PIC'
-- 'PROCEDURE'
-- 'PROGRAM'
-- 'PROGRAM-ID'
-- 'QUOTE'
-- 'RANDOM'
-- 'READ'
-- 'RECORD'
-- 'RECORDS'
-- 'REDEFINES'
-- 'RELATIVE'
-- 'REWRITE'
-- 'RIGHT'
-- 'ROUNDED'
-- 'RUN'
-- 'SAME'
-- 'SECTION'
-- 'SECURITY'
-- 'SELECT'
-- 'SENTENCE'
-- 'SEPARATE'
-- 'SEQUENTIAL'
-- 'SIGN'
-- 'SIZE'
-- 'SOURCE-COMPUTER'
-- 'SPACE'
-- 'STANDARD'
-- 'STOP'
-- 'SUBTRACT'
-- 'SYNC'
-- 'THRU'
-- 'TIMES'
-- 'TOP'
-- 'TRAILING'
-- 'UNTIL'
-- 'USAGE'
-- 'USING'
-- 'VALUE'
-- 'WORKING-STORAGE'
-- 'WRITE'
-- 'ZERO'

id-division = 'IDENTIFICATION' 'DIVISION' '.' ...
&             'PROGRAM-ID' comment '.' ...
&             author date security ;

author = 'AUTHOR' '.' comment '.' ;
author = ;

date = 'DATE-WRITTEN' '.' comment '.' ;
date = ;

security = 'SECURITY' '.' comment '.' ;
security = ;

environment-division = 'ENVIRONMENT' 'DIVISION' '.' ...
&                      'CONFIGURATION' 'SECTION' '.' ...
&                      src-obj io-section ;

src-obj = 'SOURCE-COMPUTER' '.' comment debug '.' ...
&         'OBJECT-COMPUTER' '.' comment '.' ;

debug = 'DEBUGGING' 'MODE' ;
debug = empty ;

io-section = 'INPUT-OUTPUT' 'SECTION' '.' 'FILE-CONTROL' '.' ...
&            file-control-list io-control ;
io-section = ;

file-control-list = file-control-entry ;
file-control-list = file-control-list file-control-entry ;

file-control-entry = 'SELECT' identifier attribute-list ;

attribute-list = attribute ;
attribute-list = attribute-list attribute ;

attribute = 'ORGANIZATION' organization-type ;
attribute = 'ACCESS' access-type relative ;
attribute = 'ASSIGN' ; -- ?? needs more work

organization-type = 'SEQUENTIAL' ;
organization-type = 'RELATIVE' ;

access-type = 'SEQUENTIAL' ;
access-type = 'RELATIVE' ;

relative = 'RELATIVE' identifier ;
relative = ;

io-control = 'I-O-CONTROL' '.' same-list ;
io-control = ;

same-list = same-element ;
same-list = same-list same-element ;

same-element = 'SAME' id-string ;

id-string = identifier ;
id-string = id-string identifier ;

data-division = 'DATA' 'DIVISION' '.' ...
&               file-section working-storage linkage-section ;

file-section = 'FILE' 'SECTION' '.' file-list ;
file-section = ;

file-list = file-element ;
file-list = file-list file-element ;

files = 'FD' identifier file-control '.' record-description ;

file-control = file-list ;
file-control = ;

file-list = file-element ;
file-list = file-list file-element ;

file-element = 'BLOCK' integer 'RECORDS' ;
file-element = 'RECORD' rec-count ;
file-element = 'LABEL' 'RECORDS' 'STANDARD' ;
file-element = 'LABEL' 'RECORDS' 'OMITTED' ;
file-element = 'VALUE' 'OF' id-string ;

rec-count = integer ;
rec-count = integer 'TO' integer ;

working-storage = 'WORKING-STORAGE' 'SECTION' '.' record-description ;
working-storage = ;

linkage-section = 'LINKAGE' 'SECTION' '.' record-description ;
linkage-section = ;

record-description = level-entry ;
record-description = record-description level-entry ;

level-entry = integer data-id redefines data-type '.' ;

data-id = identifier ;
data-id = 'FILLER' ;

redefines = 'REDEFINES' identifier ;
redefines = ;

data-type = prop-list ;
data-type = ;

prop-list = data-element ;
prop-list = prop-list data-element ;

data-element = 'PICTURE' string ;
data-element = 'USAGE' 'COMPUTATIONAL' ;
data-element = 'USAGE' 'DISPLAY' ;
data-element = 'SIGN' 'LEADING' separate ;
data-element = 'SIGN' 'TRAILING' separate ;
data-element = 'OCCURS' integer ;
data-element = 'SYNCHRONIZED' direction ;
data-element = 'VALUE' literal ;

direction = 'LEFT' ;
direction = 'RIGHT' ;
direction = ;

separate = 'SEPARATE' ;
separate = ;

literal = numeric-constant ;
literal = string-constant ;
literal = 'ZERO' ;
literal = 'SPACE' ;
literal = 'QUOTE' ;

-- PROCEDURE DIVISION

procedure-division = 'PROCEDURE' 'DIVISION' using '.' procedure-body ;

using = 'USING' id-string ;
using = ;

procedure-body = paragraph ;
procedure-body = procedure-body paragraph ;

paragraph = identifier '.' sentence-list ;
paragraph = identifier 'SECTION' '.' ;

sentence-list = sentence '.' ;
sentence-list = sentence-list sentence '.' ;

sentence = imperative ;
sentence = conditional ;
sentence = 'ENTER' identifier opt-id ;

imperative = 'ACCEPT' subid ;
imperative = arithmetic ;
imperative = 'CALL' literal using ;
imperative = 'CLOSE' identifier ;
imperative = file-act ;
imperative = 'DISPLAY' literalorid opt-literalorid ;
imperative = 'EXIT' program-id ;
imperative = 'GO' identifier ;
imperative = 'GO' id-string 'DEPENDING' identifier ;
imperative = 'MOVE' literalorid 'TO' subid ;
imperative = 'OPEN' type-action identifier ;
imperative = 'PERFORM' identifier thru finish ;
imperative = read-id ;
imperative = 'STOP' terminate ;

conditional = arithmetic size-error imperative ;
conditional = file-act invalid imperative ;
conditional = if-nonterminal condition action 'ELSE' imperative ;
conditional = read-id special imperative ;

arithmetic = 'ADD' literalorid opt-literalorid 'TO' subid round ;
arithmetic = 'DIVIDE' literalorid 'INTO' subid round ;
arithmetic = 'MULTIPLY' literalorid 'BY' subid round ;
arithmetic = 'SUBTRACT' literalorid opt-literalorid 'FROM' subid round ;

file-act = 'DELETE' identifier ;
file-act = 'REWRITE' identifier ;
file-act = 'WRITE' identifier special-act ;

condition = literal not cond-type ;

cond-type = 'NUMERIC' ;
cond-type = 'ALPHABETIC' ;
cond-type = compare literalorid ;

not = 'NOT' ;
not = ;

compare = 'GREATER' ;
compare = 'LESS' ;
compare = 'EQUAL' ;

round = 'ROUNDED' ;
round = ;

terminate = literal ;
terminate = 'RUN' ;

special = invalid ;
special = 'END' ;

opt-id = subid ;
opt-id = ;

action = imperative ;
action = 'NEXT' 'SENTENCE' ;

thru = 'THRU' identifier ;
thru = ;

finish = literalorid 'TIMES' ;
finish = 'UNTIL' condition ;
finish = ;

invalid = 'INVALID' ;

size-error = 'SIZE' 'ERROR' ;

special-act = when 'ADVANCING' how-many ;
special-act = ;

when = 'BEFORE' ;
when = 'AFTER' ;

how-many = integer ;
how-many = 'PAGE' ;
how-many = 'I-O' ;

subid = subscript ;
subid = identifier ;

literalorid = identifier ;
literalorid = integer ; -- ??number??
literalorid = subscript ;
literalorid = 'ZERO' ;

subscript = identifier '(' literaloridentifier ')' ;

opt-literalorid = literalorid ;
opt-literalorid = ;

nn-lit = literal ;
nn-lit = 'SPACE' ;
nn-lit = 'QUOTE' ;

literal = nn-lit ;
literal = input ; -- ?? how does he do this?
literal = 'ZERO' ;

literalorid = literal ;
literalorid = nn-lit ;

opt-lit/id = lit/id ;
opt-lit/id = ;

program-id = identifier ;
program-id = ;

read-id = 'READ' identifier ;

if-nonterminal = 'IF' ;

-- End of COBOL grammer
