%import starkware.cairo.lang.compiler.cairo.IDENTIFIER
%import starkware.cairo.lang.compiler.cairo.COMMENT
%import starkware.cairo.lang.compiler.cairo.HEXINT
%import starkware.cairo.lang.compiler.cairo.INT
%import starkware.cairo.lang.compiler.cairo.COMMA
%import starkware.cairo.lang.compiler.cairo.cairo_file 
%import starkware.cairo.lang.compiler.cairo.code_block
%import starkware.cairo.lang.compiler.cairo.instruction
%import starkware.cairo.lang.compiler.cairo.identifier
%import starkware.cairo.lang.compiler.cairo.identifier_def
%import starkware.cairo.lang.compiler.cairo.expr
%import starkware.cairo.lang.compiler.cairo.bool_expr
%import starkware.cairo.lang.compiler.cairo.atom
%import starkware.cairo.lang.compiler.cairo.type
%import starkware.cairo.lang.compiler.cairo.code_element
%import starkware.cairo.lang.compiler.cairo.typed_identifier
%import starkware.cairo.lang.compiler.cairo.arg_list
%import starkware.cairo.lang.compiler.cairo.bool_atom

%import common.WS_INLINE

%ignore WS_INLINE

LOGICAL_IDENTIFIER: "$"IDENTIFIER

logical_identifier_def: LOGICAL_IDENTIFIER
logical_identifier: LOGICAL_IDENTIFIER ("." IDENTIFIER)*
%extend ?atom: logical_identifier -> atom_logical_identifier

?horus_bool_formula: horus_bool_or
             | horus_bool_or "->" horus_bool_formula -> bool_formula_impl

?horus_bool_or: horus_bool_and
        | horus_bool_or "or" horus_bool_and -> bool_formula_or

?horus_bool_and: horus_bool_unary
         | horus_bool_and "and" horus_bool_unary -> bool_formula_and

?horus_bool_unary: horus_bool_atom
           | "not" horus_bool_atom -> bool_unary_neg

?horus_bool_atom: bool_atom
         | expr "<=" expr   -> bool_expr_le
         | expr "<" expr    -> bool_expr_lt
         | expr ">=" expr   -> bool_expr_ge
         | expr ">" expr    -> bool_expr_gt
         | "True"           -> bool_expr_true
         | "False"          -> bool_expr_false
         | "(" horus_bool_formula ")" -> bool_expr_parentheses


annotation: "@pre" horus_bool_formula  -> precond_annotation
          | "@post" horus_bool_formula -> postcond_annotation
          | "@assert" horus_bool_formula -> assert_annotation
          | "@invariant" horus_bool_formula -> invariant_annotation
          | "@declare" logical_identifier_def ":" type -> declare_annotation
          | "@storage_update" identifier "(" arg_list ")" ":=" expr -> storage_update_annotation