program -> {recordtype-decl} block recordtype-decl -> record ID [extends ID] '{' [ids-and-types] '}' ';' ids-and-types -> id-and-type {',' id-and-type} id-and-type -> ID ':' type-expr block -> '{' block-items '}' block-items -> [block-item {';' block-item}] block-item -> declaration | statement declaration -> var-decl | funcs-decl var-decl -> var ID [':' type-expr] ':=' expression funcs-decl -> func func-decl {and func-decl} func-decl -> ID '(' [ids-and-types] ')' [ '->' type-expr] block type-expr -> ID -> '@' type-expr -> type-args '->' type-expr -> '(' type-expr ')' type-args -> '(' ')' -> type-expr -> '(' type-expr {',' type-expr} ')' statement -> lvalue ':=' expression -> expression '(' expressions ')' -> read '(' lvalue {',' lvalue} ')' -> write '(' write-params ')' -> if expression then statement {elsif expression then statement} [else statement] -> while expression do statement -> loop statement -> for ID ':=' expression to expression [ by expression] do statement -> exit -> return [expression] -> block write-params -> [write-expr {',' write-expr}] write-expr -> STRING | expression expression -> number -> lvalue -> '(' expression ')' -> unary-op expression -> expression binary-op expression -> expression '(' expressions ')' -> ID '{' comp-inits '}' -> '@' type-expr '{' array-inits '}' expressions -> [ expression {',' expression}] lvalue -> ID -> lvalue '[' expression ']' -> lvalue '.' ID comp-inits -> comp-init {',' comp-init} comp-init -> ID ':=' expression array-inits -> array-init { ',' array-init} array-init -> [ expression of ] expression number -> INTEGER | REAL unary-op -> '-' | not binary-op -> '+' | '-' | '*' | '/' | div | mod | or | and -> '>' | '<' | '=' | '>=' | '<=' | '<>'