program = program_header, { include | global_const | global_func | component } ;
program_header = "#dialect", identifier ;
include = "#include", ? path ? ;
global_const = identifier, ":=", const_expr, ";" , [ annotation ] ;
global_func = "function.def", identifier, parameters, "->", type, body ;
component = "struct", identifier, [ struct_params ],
"{", fields, funcs, "}", [ annotation ] ;
struct_params = "<", [ identifier, { "," , identifier }], ">" ;
fields = { identifier, ":", type, "," , [ annotation ] } ;
funcs = ( compute , constrain ) | ( constrain, compute ) ;
compute = "function.def compute", parameters, body ;
constrain = "function.def constrain", parameters, body ;
parameters = "(", [ param, { "," , param }], ")" ;
param = identifier, ":", type ;
body = "{", { statement, ";", [ annotation ] }, "}" ;
statement = emit | return | while | if | assign | expr_call ;
emit = "emit", ( expr_contains | ( expr, "=", expr ) ) ;
return = "return", expr ;
while = "while", expr , body ;
if = "if", expr, body, [ "else", body ] ;
assign = lvalue, ":=", expr ;
const_expr = expr ; (* semantics require const type *)
expr = literal | lvalue | expr_array | expr_call | expr_ref |
expr_contains | expr_binop | expr_monop | expr_special ;
expr_array = "[", list_of_expr, "]" ;
expr_call = [ expr_call_base ], expr_call_target ;
expr_call_base = lvalue, [ "<", const_expr, ">" ], "." ;
expr_call_target = identifier, "(", list_of_expr, ")" ;
expr_ref = lvalue, ".", identifier ;
expr_contains = lvalue, "in", lvalue ;
expr_binop = expr, binop, expr ;
list_of_expr = [ expr, { "," , expr }] ;
binop = binop_arith | binop_bit | binop_compare | binop_logic ;
binop_arith = "+" | "-" | "*" | "/" | "%" ;
binop_bit = "&" | "|" | "^" | "<<" | ">>" ;
binop_compare = ">" | "<" | ">=" | "<=" | "==" | "!=" ;
binop_logic = "&&" | "||" ;
expr_monop = ( "(", expr, ")" ) | ( monop, expr ) ;
monop = monop_arith | monop_bit | monop_logic ;
monop_arith = "-" ;
monop_bit = "~" ;
monop_logic = "!" ;
expr_special = "nondetFelt()";
lvalue = identifier | lvalue_array ;
lvalue_array = lvalue, "[", lvalue, "]" ;
type = { type_modifier }, type_base ;
type_modifier = "pub" | "const" ;
type_base = identifier | ( type, "[", const_expr, "]" ) ;
constant = literal | identifier ;
identifier = letter, { letter | digit } ; (* and symbols if needed *)
annotation = "#", ? anything except newline ? ;
letter = ? all capital and lowercase characters ? ;
literal = ( digit, { digit } ) | ( "0x", hexit, { hexit } ) ;
hexit = digit | "A" | "B" | "C" | "D" | "E" | "F"
| "a" | "b" | "c" | "d" | "e" | "f" ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;