prog: [ vars ] funs;
prog: [ vars ] funs;
vars: 'var' names ';';
vars: 'var' names ';';
names: Name [{ ',' Name }];
names: Name [{ ',' Name }];
funs: { fun };
funs: { fun };
fun: head parms [ block ] ';';
fun: head parms [ block ] ';';
head: 'function' Name;
head: 'function' Name;
parms: '(' [ names ] ')';
parms: '(' [ names ] ')';
block: begin [ vars ] stmts 'end';
block: begin body 'end';
begin: 'begin';
begin: 'begin';

        
body: [ vars ] [ funs ] stmts;
stmts: stmt [{ ';' stmt }];
stmts: stmt [{ ';' stmt }];
stmt: assign | print | return | block | loop | select;
stmt: assign | print | return | block | loop | select;
assign: symbol action;
assign: symbol action;
action: store | call;
action: store | call;
store: '=' sum;
store: '=' sum;
call: args;
call: args;
args: '(' [ sums ] ')';
args: '(' [ sums ] ')';
print: 'print' sums;
print: 'print' sums;
sums: sum [{ ',' sum }];
sums: sum [{ ',' sum }];
return: 'return' [ sum ];
return: 'return' [ sum ];
loop: While cmp Do [ vars ] stmts 'od';
loop: While cmp Do body 'od';
While: 'while';
While: 'while';
Do: 'do';
Do: 'do';
select: 'if' cmp then [ else ] 'fi';
select: 'if' cmp then [ else ] 'fi';
then: Then [ [ vars ] stmts ];
then: Then [ body ];
else: Else [ vars ] stmts;
else: Else body;
Then: 'then';
Then: 'then';
Else: 'else';
Else: 'else';
cmp: sum rel;
cmp: sum rel;
rel: eq | ne | gt | ge | lt | le;
rel: eq | ne | gt | ge | lt | le;
eq: '=' sum;
eq: '=' sum;
ne: '<>' sum;
ne: '<>' sum;
gt: '>' sum;
gt: '>' sum;
ge: '>=' sum;
ge: '>=' sum;
lt: '<' sum;
lt: '<' sum;
le: '<=' sum;
le: '<=' sum;
sum: product [{ add | subtract }];
sum: product [{ add | subtract }];
add: '+' product;
add: '+' product;
subtract: '-' product;
subtract: '-' product;
product: signed [{ multiply | divide }];
product: signed [{ multiply | divide }];
multiply: '*' signed;
multiply: '*' signed;
divide: '/' signed;
divide: '/' signed;
signed: [ '-' ] term;
signed: [ '-' ] term;
term: input | number | name | '(' sum ')';
term: input | number | name | '(' sum ')';
input: 'input' [ Number ];
input: 'input' [ Number ];
number: Number;
number: Number;
name: symbol [ args ];
name: symbol [ args ];
symbol: Name;
symbol: Name;