# Aleo Shim Grammar This is an initial draft grammar for the Aleo shim language (consider Aleo+), based on an examination of the Rust code in snarkVM, particularly the abstract syntax data types and the parsing code. This grammar is written in quasi-ABNF notation, i.e. not quite ABNF, but close. This makes the grammar lighter-weight for now, but facilitates its transition to a more formal version. The grammar ignores whitespace issues (i.e. where it is allowed, where it is required) and comments. These will need to be handled in a more formal version, either by separating the grammar into a lexical and a syntactic part as done in Leo, or by incorporating whitespace and comments into the rules below (similarly to how the `nom` parser handles that). There are different ways to formulate the grammar, and different ways to partition requirements between grammar (i.e. parsing) and static semantics (i.e. post-parsing checks). This is one formulation, but it is easy to change. As in the Leo grammar, the rule names are chosen so that they establish a terminology for the constructs. They are partly based on the snarkVM code, but sometimes intentionally depart from those to suggest slightly different nomenclature (e.g. 'input/output type' instead of 'value type', since the former seems more descriptive than the latter). Short rule names are chosen to keep the grammar shorter; we could go with longer, more descriptive names as in the Leo grammar. ``` program = *import title 1*definition import = "import" program-id ";" title = "program" program-id ";" program-id = identifier [ "." identifier ] definition = interface / record / function / closure interface = "interface" identifier ":" 1*interface-component interface-component = identifier "as" plain-type ";" record = "record" identifier ":" "owner" "as" ( "address.private" / "address.public" ) "gates" "as" ( "u64.private" / "u64.public" ) *record-entry record-entry = identifier "as" entry-type ";" function = "function" identifier "(" input-list? ")" "{" 1*instruction *output "}" closure = "closure" identifier ":" 1*input 1*instruction *output input-list = input ("," input)* input = visibility identifer ":" plain-type output = "output" register "as" in-out-type ";" instruction = unary / binary / ternary / assert / cast / call unary = unary-op operand "into" register ";" binary = binary-op 2operand "into" register ";" ternary = ternary-op 3operand "into" register ";" assert = assert-op 2operand ";" unary-op = "abs" / "abs.w" / "double" / "inv" / "neg" / "not" / "square" / "sqrt" / "hash.bhp" ( "256" / "512" / "768" / "1024" ) / "hash.ped" ( "64" / "128" ) / "hash.psd" ( "2" / "4" / "8" ) binary-op = "add" / "add.w" / "sub" / "sub.w" / "mul" / "mul.w" / "div" / "div.w" / "rem" / "rem.w" / "pow" / "pow.w" / "shl" / "shl.w" / "shr" / "shr.w" / "and" / "or" / "xor" / "nand" / "nor" / "gt" / "gte" / "lt" / "lte" / "is.eq" / "is.neq" / "commit.bhp" ( "256" / "512" / "768" / "1024" ) / "commit.ped" ( "64" / "128" ) ternary-op = "ternary" assert-op = "assert.eq" / "assert.neq" cast = "cast" 1*operand "into" register "as" register-type ";" call = "call" callee *operand "into" *registers ";" callee = identifier / external operand = literal / register literal = "aleo1" 58( lowercase / digit ) ; address / "true" / "false" ; boolean / %x22 *string-element %x22 ; string "..." / [ "-" ] numeral arithmetic-type ; arithmetic string-element = %x0-21 / #x23-5b / %x5d-10ffff ; anything but " or \ / %x5c.22 ; escape for " / %x5c.5c ; escape for \ register = base-register *( "." identifier ) base-register = %"r" numeral arithmetic-type = "field" / "group" / "scalar" / "u8" / "u16" / "u32" / "u64" / "u128" / "i8" / "i16" / "i32" / "i64" / "i128" primitive-type = arithmetic-type / "address" / "bool" / "string" plain-type = primitive-type / identifier entry-type = plain-type ( ".constant" / ".public" / ".private" ) record-type = ( identifier / external ) ".record" register-type = plain-type / record-type in-out-type = entry-type / record-type external = program-id "/" identifier visibility = "public" / "private" digit = "0"-"9" numeral = 1*digit uppercase = "A"-"Z" lowercase = "a"-"z" letter = uppercase / lowercase identifier = (letter / "_") *( letter / digit / "_" ) ; but not a keyword ```