Note: the command-line version of Why3 is also supporting this input format, for files with suffix .c.
Logical annotations are inserted in special comments starting with //@ or /*@. In the following grammar, we only use the former kind, for simplicity, but both kinds are allowed.
file ::= decl* decl ::= c-include | c-function | logic-declaration c-include ::= "#include" "<" file-name ">"Directives #include are ignored during the translation to Why3. They are allowed anyway, such that a C source code using functions such as printf (see below) is accepted by a C compiler.
c-function ::= return_type identifier "(" [ params ] ")" { spec } block return_type ::= "void" | "int" params ::= param { "," param } param ::= "int" identifier | "int" identifier "[]"
spec ::= "requires" term ";" | "ensures" term ";" | "variant" term { "," term } ";"
expr ::= integer-literal | string-literal | identifier | identifier ( "++" | "--" ) | ( "++" | "--" ) identifier | identifier "[" expr "]" | identifier "[" expr "]" ( "++" | "--") | ( "++" | "--") identifier "[" expr "]" | "-" expr | "!" expr | expr ( "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | "<=" | ">" | ">=" | "&&" | "||" ) expr | identifier "(" [ expr { "," expr } ] ")" | "scanf" "(" "\"%d\"" "," "&" identifier ")" | "(" expr ")"
stmt ::= ";" | "return" expr ";" | "int" identifier ";" | "int" identifier "[" expr "]" ";" | "break" ";" | "if" "(" expr ")" stmt | "if" "(" expr ")" stmt "else" stmt | "while" "(" expr ")" loop_body | "for" "(" expr_stmt ";" expr ";" expr_stmt ")" loop_body | expr_stmt ";" | block | "//@" "label" identifier ";" | "//@" ( "assert" | "assume" | "check" ) term ";" block ::= "{" { stmt } "}" expr_stmt ::= "int" identifier "=" expr | identifier assignop exor | identifier "[" expr "]" assignop expr | expr assignop ::= "=" | "+=" | "-=" | "*=" | "/=" loop_body ::= { loop_annot } stmt | "{" { loop_annot } { stmt } "}" loop_annot ::= "//@" "invariant" term ";" | "//@" "variant" term { "," term } ";"Note that the syntax for loop bodies allows the loop annotations to be placed either before the block or right at the beginning of the block.
logic-declaration ::= "//@" "function" "int" identifier "(" params ")" ";" | "//@" "function" "int" identifier "(" params ")" "=" term ";" | "//@" "predicate" identifier "(" params ")" ";" | "//@" "predicate" identifier "(" params ")" "=" term ";" | "//@" "axiom" identifier ":" term ";" | "//@" "lemma" identifier ":" term ";" | "//@" "goal" identifier ":" term ";"
term ::= identifier | integer-literal | "true" | "false" | "(" term ")" | term "[" term "]" | term "[" term "<-" term "]" | "!" term | "old" "(" term ")" | "at" "(" term "," identifier ")" | "-" term | term ( "->" | "<->" | "||" | "&&" ) term | term ( "==" | "!=" | "<" | "<=" | ">" | ">=" ) term | term ( "+" | "-" | "*" | "/" | "% ) term | "if" term "then" term "else term | "let" identifier "=" term "in" term | ( "forall" | "exists" ) binder { "," binder } "." term | identifier "(" [ term { "," term } ] ")" binder ::= identifier | identifier "[]"
Click on the gears button to launch the verification. Verification conditions (VCs) then appear in the right panel, in the Task List tab, and Alt-Ergo is run on each of them with a default time limit (that can be set in the Settings menu).
When a VC is not proved, there are several options: