`llgen`, rather than the dialect given in ISO 14977. The dialect can be
defined self-referentially as follows:
-~~~~ {.ebnf .notation}
+~~~~ {.notrust .ebnf .notation}
grammar : rule + ;
rule : nonterminal ':' productionrule ';' ;
productionrule : production [ '|' production ] * ;
## Comments
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
comment : block_comment | line_comment ;
block_comment : "/*" block_comment_body * '*' + '/' ;
block_comment_body : (block_comment | character) * ;
## Whitespace
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
whitespace_char : '\x20' | '\x09' | '\x0a' | '\x0d' ;
whitespace : [ whitespace_char | comment ] + ;
~~~~
## Tokens
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
simple_token : keyword | unop | binop ;
token : simple_token | ident | literal | symbol | whitespace token ;
~~~~
The keywords are the following strings:
-~~~~ {.keyword}
+~~~~ {.notrust .keyword}
as
break
do
rule. A literal is a form of constant expression, so is evaluated (primarily)
at compile time.
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
literal : string_lit | char_lit | num_lit ;
~~~~
#### Character and string literals
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
char_lit : '\x27' char_body '\x27' ;
string_lit : '"' string_body * '"' | 'r' raw_string ;
#### Number literals
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
num_lit : nonzero_dec [ dec_digit | '_' ] * num_suffix ?
| '0' [ [ dec_digit | '_' ] * num_suffix ?
| 'b' [ '1' | '0' | '_' ] + int_suffix ?
### Symbols
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
symbol : "::" "->"
| '#' | '[' | ']' | '(' | ')' | '{' | '}'
| ',' | ';' ;
## Paths
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
expr_path : ident [ "::" expr_path_tail ] + ;
expr_path_tail : '<' type_expr [ ',' type_expr ] + '>'
| expr_path ;
## Macros
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')'
macro_rule : '(' matcher * ')' "=>" '(' transcriber * ')' ';'
matcher : '(' matcher * ')' | '[' matcher * ']'
## Items
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
item : mod_item | fn_item | type_item | struct_item | enum_item
| static_item | trait_item | impl_item | extern_block ;
~~~~
### Modules
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
mod_item : "mod" ident ( ';' | '{' mod '}' );
mod : [ view_item | item ] * ;
~~~~
mod math {
type Complex = (f64, f64);
fn sin(f: f64) -> f64 {
- ...
+ /* ... */
# fail!();
}
fn cos(f: f64) -> f64 {
- ...
+ /* ... */
# fail!();
}
fn tan(f: f64) -> f64 {
- ...
+ /* ... */
# fail!();
}
}
#### View items
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
view_item : extern_crate_decl | use_decl ;
~~~~
##### Extern crate declarations
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
extern_crate_decl : "extern" "crate" ident [ '(' link_attrs ')' ] ? [ '=' string_lit ] ? ;
link_attrs : link_attr [ ',' link_attrs ] + ;
link_attr : ident '=' literal ;
##### Use declarations
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
use_decl : "pub" ? "use" ident [ '=' path
| "::" path_glob ] ;
### Static items
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
static_item : "static" ident ':' type '=' expr ';' ;
~~~~
# trait Seq<T> { }
impl<T> Seq<T> for ~[T] {
- ...
+ /* ... */
}
impl Seq<bool> for u32 {
/* Treat the integer as a sequence of bits */
### External blocks
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
extern_block_item : "extern" '{' extern_block '} ;
extern_block : [ foreign_fn ] * ;
~~~~
## Attributes
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
attribute : '#' '[' attr_list ']' ;
attr_list : attr [ ',' attr_list ]*
attr : ident [ '=' literal
#### Slot declarations
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
let_decl : "let" pat [':' type ] ? [ init ] ? ';' ;
init : [ '=' ] expr ;
~~~~
### Structure expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
struct_expr : expr_path '{' ident ':' expr
[ ',' ident ':' expr ] *
[ ".." expr ] '}' |
### Block expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
block_expr : '{' [ view_item ] *
[ stmt ';' | item ] *
[ expr ] '}'
### Method-call expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
method_call_expr : expr '.' ident paren_expr_list ;
~~~~
### Field expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
field_expr : expr '.' ident
~~~~
when not immediately followed by a parenthesized expression-list (the latter is a [method call expression](#method-call-expressions)).
A field expression denotes a field of a [structure](#structure-types).
-~~~~ {.field}
+~~~~ {.ignore .field}
myrecord.myfield;
-{a: 10, b: 20}.a;
+foo().x;
+(Struct {a: 10, b: 20}).a;
~~~~
A field access on a record is an [lvalue](#lvalues-rvalues-and-temporaries) referring to the value of that field.
### Vector expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
vec_expr : '[' "mut" ? vec_elems? ']'
vec_elems : [expr [',' expr]*] | [expr ',' ".." expr]
### Index expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
idx_expr : expr '[' expr ']'
~~~~
### Binary operator expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
binop_expr : expr binop expr ;
~~~~
The precedence of Rust binary operators is ordered as follows, going
from strong to weak:
-~~~~ {.precedence}
+~~~~ {.notrust .precedence}
* / %
as
+ -
expression. Parentheses can be used to explicitly specify evaluation order
within an expression.
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
paren_expr : '(' expr ')' ;
~~~~
### Call expressions
-~~~~ {.abnf .gram}
+~~~~ {.notrust .ebnf .gram}
expr_list : [ expr [ ',' expr ]* ] ? ;
paren_expr_list : '(' expr_list ')' ;
call_expr : expr paren_expr_list ;
### Lambda expressions
-~~~~ {.abnf .gram}
+~~~~ {.notrust .ebnf .gram}
ident_list : [ ident [ ',' ident ]* ] ? ;
lambda_expr : '|' ident_list '|' expr ;
~~~~
### While loops
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
while_expr : "while" expr '{' block '}' ;
~~~~
A loop expression denotes an infinite loop;
see [Continue expressions](#continue-expressions) for continue expressions.
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
loop_expr : [ lifetime ':' ] "loop" '{' block '}';
~~~~
### Break expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
break_expr : "break" [ lifetime ];
~~~~
### Continue expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
continue_expr : "loop" [ lifetime ];
~~~~
### For expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
for_expr : "for" pat "in" expr '{' block '}' ;
~~~~
### If expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
if_expr : "if" expr '{' block '}'
else_tail ? ;
### Match expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
match_expr : "match" expr '{' match_arm [ '|' match_arm ] * '}' ;
match_arm : match_pat '=>' [ expr "," | '{' block '}' ] ;
### Return expressions
-~~~~ {.ebnf .gram}
+~~~~ {.notrust .ebnf .gram}
return_expr : "return" expr ? ;
~~~~
These four log levels correspond to levels 1-4, as controlled by `RUST_LOG`:
-```bash
+``` {.bash .notrust}
$ RUST_LOG=rust=3 ./rust
This is an error log
This is a warn log
immutable, the whole list is immutable. The memory allocation itself is the
box, while the owner holds onto a pointer to it:
- List box List box List box List box
- +--------------+ +--------------+ +--------------+ +--------------+
- list -> | Cons | 1 | ~ | -> | Cons | 2 | ~ | -> | Cons | 3 | ~ | -> | Nil |
- +--------------+ +--------------+ +--------------+ +--------------+
+~~~ {.notrust}
+ List box List box List box List box
+ +--------------+ +--------------+ +--------------+ +--------------+
+list -> | Cons | 1 | ~ | -> | Cons | 2 | ~ | -> | Cons | 3 | ~ | -> | Nil |
+ +--------------+ +--------------+ +--------------+ +--------------+
+~~~
> ***Note:*** the above diagram shows the logical contents of the enum. The actual
> memory layout of the enum may vary. For example, for the `List` enum shown
The obvious signature for a `List` equality comparison is the following:
~~~{.ignore}
-fn eq(xs: List, ys: List) -> bool { ... }
+fn eq(xs: List, ys: List) -> bool { /* ... */ }
~~~
However, this will cause both lists to be moved into the function. Ownership
(&T) instead.
~~~{.ignore}
-fn eq(xs: &List, ys: &List) -> bool { ... }
+fn eq(xs: &List, ys: &List) -> bool { /* ... */ }
~~~
A reference is a *non-owning* view of a value. A reference can be obtained with the `&` (address-of)
# Rectangle(Point, Point)
# }
impl Shape {
- fn draw_reference(&self) { ... }
- fn draw_owned(~self) { ... }
- fn draw_value(self) { ... }
+ fn draw_reference(&self) { /* ... */ }
+ fn draw_owned(~self) { /* ... */ }
+ fn draw_value(self) { /* ... */ }
}
let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);
# Rectangle(Point, Point)
# }
# impl Shape {
-# fn draw_reference(&self) { ... }
-# fn draw_owned(~self) { ... }
-# fn draw_value(self) { ... }
+# fn draw_reference(&self) { /* ... */ }
+# fn draw_owned(~self) { /* ... */ }
+# fn draw_value(self) { /* ... */ }
# }
# let s = Circle(Point { x: 1.0, y: 2.0 }, 3.0);
// As with typical function arguments, managed and owned pointers
~~~~ {.ignore}
impl Circle {
- fn area(&self) -> f64 { ... }
- fn new(area: f64) -> Circle { ... }
+ fn area(&self) -> f64 { /* ... */ }
+ fn new(area: f64) -> Circle { /* ... */ }
}
~~~~
# fn new_rectangle() -> Rectangle { true }
# fn draw_all(shapes: &[~Drawable]) {}
-impl Drawable for Circle { fn draw(&self) { ... } }
-impl Drawable for Rectangle { fn draw(&self) { ... } }
+impl Drawable for Circle { fn draw(&self) { /* ... */ } }
+impl Drawable for Rectangle { fn draw(&self) { /* ... */ } }
let c: ~Circle = ~new_circle();
let r: ~Rectangle = ~new_rectangle();
# impl Circle for CircleStruct { fn radius(&self) -> f64 { (self.area() / PI).sqrt() } }
# impl Shape for CircleStruct { fn area(&self) -> f64 { PI * square(self.radius) } }
-let concrete = @CircleStruct{center:Point{x:3f,y:4f},radius:5f};
+let concrete = @CircleStruct{center:Point{x:3.0,y:4.0},radius:5.0};
let mycircle: @Circle = concrete as @Circle;
let nonsense = mycircle.radius() * mycircle.area();
~~~
}
impl Farm {
- fn feed_chickens(&self) { ... }
- pub fn add_chicken(&self, c: Chicken) { ... }
+ fn feed_chickens(&self) { /* ... */ }
+ pub fn add_chicken(&self, c: Chicken) { /* ... */ }
}
pub fn feed_animals(farm: &Farm) {
We define two crates, and use one of them as a library in the other.
-~~~~
+~~~~{.ignore}
// `world.rs`
#[crate_id = "world#0.42"];
# extern crate extra;