program    <- _ block '.' _

block      <- const var procedure statement
const      <- ('CONST' __ ident '=' _ number (',' _ ident '=' _ number)* ';' _)?
var        <- ('VAR' __ ident (',' _ ident)* ';' _)?
procedure  <- ('PROCEDURE' __ ident ';' _ block ';' _)*

statement  <- (assignment / call / statements / if / while / out / in)?
assignment <- ident ':=' _ expression
call       <- 'CALL' __ ident
statements <- 'BEGIN' __ statement (';' _ statement )* 'END' __
if         <- 'IF' __ condition 'THEN' __ statement
while      <- 'WHILE' __ condition 'DO' __ statement
out        <- ('out' __ / 'write' __ / '!' _) expression
in         <- ('in' __ / 'read' __ / '?' _) ident

condition  <- odd / compare
odd        <- 'ODD' __ expression
compare    <- expression compare_op expression
compare_op <- < '=' / '#' / '<=' / '<' / '>=' / '>' > _

expression <- sign term (term_op term)*
sign       <- < [-+]? > _
term_op    <- < [-+] > _

term       <- factor (factor_op factor)*
factor_op  <- < [*/] > _

factor     <- ident / number / '(' _ expression ')' _

ident      <- < [a-z] [a-z0-9]* > _
number     <- < [0-9]+ > _

~_         <- [ \t\r\n]*
~__        <- ![a-z0-9_] _