[[global_attr]]

[rust_derive(Copy, Clone, Debug)]
[rust_serde]
[rust_rkyv]
[doc = "A program is a list of statements"]
Stmt : [doc = "if-then-else statement"]
       [boxed]
       IfStmt(
         [doc = "if condition"]
         cond: Expr,
         [doc = "then statement"]
         then: Stmt,
         [doc = "else statement, can be empty"]
         otherwise?: Stmt
       )
     | [doc = "an expression is also sometimes considered a statement"]
       [boxed]
       ExprStmt(expr: Expr)
     | [doc = "a block is a list of statements"]
       [boxed]
       BlockStmt(stmts: list<Stmt>)

[rust_derive(Copy, Clone, Debug)]
[rust_serde]
[rust_rkyv]
[doc = "An expression is a literal, an identifier, or a binary expression"]
[doc = ""]
[doc = "All I want is a room somewhere,"]
[doc = "Far away from the cold night air,"]
[doc = "With one enormous chair,"]
[doc = "Aow, wouldn't it be loverly?"]
Expr : [doc = "numeric literal expression"]
       NumericLiteral(value: int)
     | [doc = "string literal expression"]
       StringLiteral(value: str)
     | [doc = "boolean literal expression"]
       BoolLiteral(value: bool)
     | [doc = "identifier expression"]
       Identifier(name: str)
     | [doc = "binary expression"]
       [boxed]
       BinaryExpr(
         [doc = "binary operator"]
         op: str,
         [doc = "left operand"]
         left: Expr,
         [doc = "right operand"]
         right: Expr
       )
     -- the following line won't compile with Rust target, because `fn` is
     -- a keyword in Rust
     -- | [doc = "function call expression"]
     --   [boxed]
     --   CallExpr(fn: Expr, args: list<Expr>)
