summaryrefslogtreecommitdiff
path: root/grammar/rust
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@colm.net>2019-12-01 09:05:03 -0800
committerAdrian Thurston <thurston@colm.net>2019-12-01 09:05:03 -0800
commit5a4407de2c4c03083f1c25b5c7fdb849cdc08a12 (patch)
tree4436efeb998fd54de016723d92d74c400d48e070 /grammar/rust
parent479376c313208ee764d212846892cb904b8e5b89 (diff)
downloadcolm-5a4407de2c4c03083f1c25b5c7fdb849cdc08a12.tar.gz
moved grammars out to their own dirs
We also want some testing/validation support for each grammar. This dir will get quite messy if we move files.
Diffstat (limited to 'grammar/rust')
-rw-r--r--grammar/rust/.gitignore4
-rw-r--r--grammar/rust/Makefile7
-rw-r--r--grammar/rust/parserust.lm81
-rw-r--r--grammar/rust/rust.lm1305
4 files changed, 1397 insertions, 0 deletions
diff --git a/grammar/rust/.gitignore b/grammar/rust/.gitignore
new file mode 100644
index 00000000..5bf8231b
--- /dev/null
+++ b/grammar/rust/.gitignore
@@ -0,0 +1,4 @@
+/rust.c
+/rust
+/query.c
+/query
diff --git a/grammar/rust/Makefile b/grammar/rust/Makefile
new file mode 100644
index 00000000..20e3edeb
--- /dev/null
+++ b/grammar/rust/Makefile
@@ -0,0 +1,7 @@
+COLM = ../../colm/colm
+RAGEL = ../../ragel/ragel
+
+all: rust
+
+rust: rust.lm parserust.lm $(COLM)
+ $(COLM) -o rust parserust.lm
diff --git a/grammar/rust/parserust.lm b/grammar/rust/parserust.lm
new file mode 100644
index 00000000..3e17a3b6
--- /dev/null
+++ b/grammar/rust/parserust.lm
@@ -0,0 +1,81 @@
+include 'rust.lm'
+
+parse P: program [stdin]
+
+if P {
+ for FN: function in P {
+ print "function: [FN.id]
+
+ for CE: compound_expression in FN {
+ if match CE [assignment_expression compound_op compound_expression]
+ print " compound expression: [CE]
+ }
+
+ for AE: assignment_expression in FN {
+ if match AE [range_expression `= assignment_expression]
+ print " assignment expression: [AE]
+ }
+
+ for RE: range_expression in FN {
+ if !match RE [lazy_disjunction]
+ print " range expression: [RE]
+ }
+
+ for LD: lazy_disjunction in FN {
+ if !match LD [lazy_conjunction]
+ print " lazy disjunction: [LD]
+ }
+
+ for LC: lazy_conjunction in FN {
+ if !match LC [comparison]
+ print " lazy conjunction: [LC]
+ }
+
+ for C: comparison in FN {
+ if !match C [bitwise_or]
+ print " comparison: [C]
+ }
+
+ for P: pattern in FN {
+ print " pattern: [P]
+ }
+
+ for MA: match_arm in FN {
+ print " match_arm: [MA]
+ }
+
+ for CL: cons_list in FN {
+ print " construct list: [^CL]
+ }
+
+ for M: mult in FN {
+ if !match M [as]
+ print " mult: [^M]
+ }
+
+ for TP: tuple_pattern in FN {
+ print " tuple pattern: [TP]
+ }
+
+ for TP: grouped_pattern in FN {
+ print " grouped pattern: [TP]
+ }
+
+ for CP: closure_param in FN {
+ print " closure param: [CP]
+ }
+ }
+
+ for M: method in P {
+ print "method: [M.id]
+ }
+
+ for MR: macro_rule in P {
+ print " macro matcher: [MR.macro_matcher]
+ }
+}
+else {
+ send stderr "failed to parse input [error]
+ exit(1)
+}
+
diff --git a/grammar/rust/rust.lm b/grammar/rust/rust.lm
new file mode 100644
index 00000000..f6dd8c15
--- /dev/null
+++ b/grammar/rust/rust.lm
@@ -0,0 +1,1305 @@
+lex
+ literal `as `break `const `continue `crate
+ literal `$crate `dyn `else `enum `extern
+ literal `false `fn `for `if `impl `in `let
+ literal `loop `macro_rules `match `mod `move
+ literal `mut `pub `ref `return `self `static
+ literal `struct `super `trait `true `type
+ literal `unsafe `use `where `while
+
+ literal `; `: `:: `( `) `{ `} `[ `] `< `>
+ literal `. `, `@ `-> `=> `?
+ literal `- `+ `/ `* `% `! `^ `| `&
+
+ literal `<< `== `!= `>= `<= `|| `&&
+ literal `.. `..= `...
+ literal `= `+= `-= `*= `/= `%= `&= `|= `^= `<<= `>>=
+
+ literal `# `_
+
+ token id / [A-Za-z_] [A-Za-z_0-9]* /
+ token string / 'b'? '"' ( [^\"] | '\\' any )* '"' /
+ token char / 'b'? "'" ( [^\'] | '\\' any ) "'" /
+ token lifetime / "'" id /
+ token number /
+ (
+ [0-9] [_0-9]* |
+ '0x' [_a-fA-F0-9]+ |
+ '0b' [_0-1]+ |
+ '0o' [_0-7]+
+ )
+ ( ( 'u' | 'i' ) [a-z0-9]+ )?
+ /
+
+ rl float_exponent
+ / ( [eE] [+\-]? [0-9_]* [0-9] [0-9_]* )? /
+
+ rl float_suffix
+ / ( 'f32' | 'f64' )? /
+
+ # Handles: DEC_LITERAL . (not immediately followed by ., _ or an identifier)
+ token hanging_float
+ / [0-9]+ '.' [^0-9._a-zA-Z] /
+ {
+ Float: str = input->pull( match_length - 1 )
+ input->push( make_token( typeid<float>, Float ) )
+ }
+
+ token float/
+ [0-9]+ float_exponent |
+ [0-9]+ '.' [0-9]+ float_exponent? |
+ [0-9]+ ( '.' [0-9]+ )? float_exponent? float_suffix
+ /
+
+ # Raw open. Rest handled in a its own lexical region.
+ token raw_open / 'r' '#' * '"' /
+ {
+ # Stash the length (not including r) for comparison against potential
+ # close strings.
+ RawOpenLength = match_length - 1
+ RawOpen: str = input->pull( match_length )
+ input->push( make_token( typeid<raw_open>, RawOpen ) )
+ }
+
+ ignore / "//" [^\n]* '\n' /
+ ignore / "/*" any* :>> "*/" /
+ ignore / [ \t\n]+ /
+end
+
+# Raw strings.
+def raw_string
+ [raw_open raw_content* raw_close]
+
+global RawOpenLength: int = 0
+
+# Lexical region dedicated to raw strings. Attempts to close by matching
+# candidates and then testing the length.
+lex
+ token raw_close / '"' '#'* /
+ {
+ # Check the length. We use >= to match the close because rust is lazy
+ # in matching it. If it is longer we just chop it. Probably will result
+ # in a parse error.
+ if match_length >= RawOpenLength {
+ # Chop it by using RawOpenLength in the pull from input.
+ Candidate: str = input->pull( RawOpenLength )
+ input->push( make_token( typeid<raw_close>, Candidate ) )
+ }
+ else {
+ # Otherwise just send it as raw content.
+ Candidate: str = input->pull( match_length )
+ input->push( make_token( typeid<raw_content>, Candidate ) )
+ }
+ }
+
+ # Content, send out strings not containing # or ". Or single such chars
+ # that are not part of a sequence that is first matched by close candidate.
+ token raw_content / [^"#]+ | any /
+end
+
+namespace attr
+ lex
+ token id / [A-Za-z_] [A-Za-z_0-9]* /
+ token string / '"' ( [^\"] | '\\' any )* '"' /
+ token char / "'" ( [^\'] | '\\' any ) "'" /
+ token lifetime / "'" id /
+ token number / [0-9]+ /
+ token float / [0-9]+ '.' [0-9]+ /
+
+ literal `[ `]
+
+ ignore / "//" [^\n]* '\n' /
+ ignore / "/*" any* :>> "*/" /
+ ignore / [ \t\n]+ /
+
+ token sym / any /
+ end
+
+ def item
+ [id]
+ | [string]
+ | [char]
+ | [lifetime]
+ | [number]
+ | [float]
+ | [sym]
+ | [_list]
+
+ def _list
+ [ `[ item* `] ]
+end
+
+def attribute
+ [`# `! attr::_list]
+| [`# attr::_list]
+
+namespace macro
+ lex
+ token id / [A-Za-z_] [A-Za-z_0-9]* /
+ token string / '"' ( [^\"] | '\\' any )* '"' /
+ token char / "'" ( [^\'] | '\\' any ) "'" /
+ token lifetime / "'" id /
+ token number / [0-9]+ /
+ token float / [0-9]+ '.' [0-9]+ /
+
+ literal `( `) `[ `] `{ `} `;
+
+ ignore / "//" [^\n]* '\n' /
+ ignore / "/*" any* :>> "*/" /
+ ignore / [ \t\n]+ /
+
+ token sym / any /
+ end
+
+ def item
+ [id]
+ | [string]
+ | [char]
+ | [lifetime]
+ | [number]
+ | [float]
+ | [sym]
+ | [macro]
+ | [`;]
+
+ def macro_semi
+ [ `( item* `) `; ]
+ | [ `[ item* `] `; ]
+ | [ `{ item* `} ]
+
+ def macro
+ [ `( item* `) ]
+ | [ `[ item* `] ]
+ | [ `{ item* `} ]
+end
+
+def macro_invocation
+ [simple_path `! macro::macro]
+
+def macro_invocation_semi
+ [simple_path `! macro::macro_semi]
+
+#
+# Macro Defition
+#
+
+def macro_matcher
+ [macro::macro]
+
+def macro_transcriber
+ [macro::macro]
+
+def macro_rule
+ [macro_matcher `=> macro_transcriber]
+
+def macro_rules_tail
+ [macro_rules_tail `; macro_rule]
+| []
+
+def macro_rules
+ [macro_rule macro_rules_tail `;`?]
+
+def macro_rules_def
+ [`( macro_rules `) `;]
+| [`[ macro_rules `] `;]
+| [`{ macro_rules `}]
+
+def macro_rules_definition
+ [`macro_rules `! id macro_rules_def]
+
+#
+# Use statments
+#
+
+
+def simple_path_segment
+ [id]
+| [`super]
+| [`self]
+| [`crate]
+| [`$crate]
+
+def sp_tail
+ [sp_tail `:: simple_path_segment]
+| []
+
+def simple_path
+ [opt_sep simple_path_segment sp_tail]
+
+def use_list_tail
+ [use_list_tail `, use_tree]
+| []
+
+def use_path_opt
+ [simple_path `::]
+| [`::]
+| []
+
+def use_as_opt
+ [`as id]
+| [`as `_]
+| []
+
+def use_tree
+ [use_path_opt `*]
+| [use_path_opt `{ use_tree use_list_tail `,`? `}]
+| [simple_path use_as_opt]
+
+def use_declaration
+ [`use use_tree `;]
+
+#
+# Patterns
+#
+
+def literal_pattern
+ [`true]
+| [`false]
+| [char]
+| [string]
+| [raw_string]
+| [`-`? number]
+| [`-`? float]
+
+def identifier_pattern
+ [`ref`? `mut`? id]
+| [`ref`? `mut`? id `@ pattern]
+
+def wildcard_pattern
+ [`_]
+
+def range_pattern_bound
+ [literal_pattern]
+
+def range_pattern
+ [range_pattern_bound `..= range_pattern_bound]
+| [range_pattern_bound `... range_pattern_bound]
+
+def reference_pattern
+ [`& `mut`? pattern]
+| [`&& `mut`? pattern]
+
+#
+# struct pattern
+#
+def struct_pattern_field
+ [number `: pattern]
+| [id `: pattern]
+| [`ref`? `mut`? id]
+
+def struct_pattern_fields
+ [struct_pattern_fields `, struct_pattern_field]
+| [struct_pattern_field]
+
+def struct_pattern_et_cetera
+ [`..]
+
+def struct_pattern_elements
+ [struct_pattern_fields]
+| [struct_pattern_fields `, ]
+| [struct_pattern_fields `, struct_pattern_et_cetera]
+| [struct_pattern_et_cetera]
+
+def opt_struct_pattern_elements
+ [struct_pattern_elements]
+| []
+
+def struct_pattern
+ [path_in_expression `{ opt_struct_pattern_elements `}]
+
+def tuple_struct_item
+ [pattern]
+| [`..]
+
+def tuple_struct_items
+ [tuple_struct_items `, tuple_struct_item]
+| [tuple_struct_item]
+
+def tuple_struct_pattern
+ [path_in_expression `( tuple_struct_items `,`? `)]
+
+def tuple_pattern_item
+ [pattern]
+| [`..]
+
+def tuple_pattern_items
+ [tuple_pattern_items `, tuple_pattern_item]
+| [tuple_pattern_item]
+
+def tuple_pattern
+ [`( `)]
+| [`( tuple_pattern_item `, `)]
+| [`( tuple_pattern_item `, tuple_pattern_items `,`? `)]
+
+def grouped_pattern
+ [`( pattern `)]
+
+def pattern_list
+ [pattern_list `, pattern]
+| [pattern]
+
+#
+# Grammar doesnt seem to support empty slice patterns, but found some code
+# allowing it.
+#
+def slice_pattern
+ [`[ pattern `, pattern_list `,`? `]]
+| [`[ pattern `, `]]
+| [`[ pattern `]]
+| [`[ `]]
+
+def path_pattern
+ [path_in_expression]
+| [qualified_path_in_expression]
+
+def pattern
+ [literal_pattern]
+| [identifier_pattern]
+| [wildcard_pattern]
+| [range_pattern]
+| [reference_pattern]
+| [struct_pattern]
+| [tuple_struct_pattern]
+| [tuple_pattern]
+| [grouped_pattern]
+| [slice_pattern]
+| [path_pattern]
+
+# Range Pattern
+
+
+#
+# Match Expressions.
+#
+
+def match_expression
+ [`match expression `{ match_arms? `}]
+
+def match_arms_last
+ [match_arm `=> block_expression `,`?]
+| [match_arm `=> expression `,`?]
+
+def match_arms_first_case
+ [match_arm `=> block_expression `,`?]
+| [match_arm `=> expression `,]
+
+def match_arms_first_list
+ [match_arms_first_list match_arms_first_case]
+| []
+
+def match_arms
+ [match_arms_first_list match_arms_last]
+
+def match_arm
+ [match_arm_patterns opt_match_arm_guard]
+
+def match_arms_pattern_tail
+ [match_arms_pattern_tail `| pattern]
+| []
+
+def match_arm_patterns
+ [`|`? pattern match_arms_pattern_tail]
+
+def opt_match_arm_guard
+ [`if expression]
+| []
+
+#
+# Return expressions
+#
+def return_expression
+ [`return expression]
+| [`return]
+
+#
+# Break expression
+#
+def break_expression
+ [`break expression]
+| [`break lifetime expression]
+| [`break lifetime]
+| [`break]
+
+#
+# Continue expression
+#
+def continue_expression
+ [`continue lifetime]
+| [`continue]
+
+#
+# Generic Args
+#
+
+def lifetime_tail
+ [lifetime_tail `, lifetime]
+| []
+
+def lifetime_list
+ [lifetime lifetime_tail]
+
+def opt_type_params
+ [`< lifetime_list `,`? `>]
+| [`< type_list `,`? `>]
+| [`< lifetime_list `, type_list `,`? `>]
+| []
+
+
+#
+# Function declaration
+#
+
+def opt_return
+ []
+| [ `-> type]
+
+def extern_abi
+ [`extern string]
+
+def function_qualifiers
+ [`const ? `unsafe ? extern_abi?]
+
+def function_param
+ [pattern `: type]
+
+def func_param_tail
+ [func_param_tail `, function_param]
+| []
+
+def function_parameters
+ [function_param func_param_tail `,`?]
+
+def function
+ [
+ function_qualifiers `fn id opt_generics `( function_parameters? `)
+ opt_return opt_where_clause block_expression
+ ]
+
+#
+# Method declaration
+#
+
+def self_param
+ [`mut`? `self]
+| [`& `mut`? `self]
+| [`& lifetime `mut`? `self]
+| [`mut`? `self `: type]
+
+def opt_method_params
+ [`, function_parameters]
+| [`,]
+| []
+
+def method
+ [
+ function_qualifiers `fn id opt_generics `( self_param opt_method_params `)
+ opt_return opt_where_clause block_expression
+ ]
+
+#
+# Types
+#
+
+def qual_tail
+ [qual_tail `:: id]
+| []
+
+def qual_id
+ [id qual_tail]
+
+def type_id
+ [id opt_type_params]
+
+def type_path_segment
+ [path_ident_segment `:: ? generic_args]
+| [path_ident_segment `:: ? type_path_fn]
+| [path_ident_segment `:: ?]
+
+def type_path_fn
+ [`( type_path_fn_inputs? `) opt_arrow_type]
+
+def opt_arrow_type
+ [`-> type]
+| []
+
+def type_path_fn_inputs
+ [type_list `,`?]
+
+def type_path_tail
+ [type_path_tail `:: type_path_segment]
+| []
+
+def opt_sep
+ [`::]
+| []
+
+def type_path
+ [opt_sep type_path_segment type_path_tail]
+
+def opt_lifetime
+ [lifetime]
+| []
+
+def array_type
+ [`[ type `; expression `]]
+
+def slice_type
+ [`[ type `]]
+
+def raw_pointer_type
+ [`* `mut type_no_bounds]
+| [`* `const type_no_bounds]
+
+def tuple_type
+ [`( `)]
+| [`( type `, `)]
+| [`( type `, type_list `,`? `)]
+
+def trait_object_type
+ [`dyn ? type_param_bounds]
+
+def impl_trait_type
+ [`impl type_param_bounds]
+
+def impl_trait_type_one_bound
+ [`impl trait_bound]
+
+def qualified_path_type
+ [`< type `as type_path `>]
+| [`< type `>]
+
+def type_path_segment_list
+ []
+
+def qualified_path_in_type
+ [qualified_path_type type_path_tail]
+
+#
+# Bare Function Type
+#
+
+def bare_function_return_type
+ [`-> type_no_bounds]
+
+def function_parameters_maybe_named_variadic
+ [maybe_named_function_parameters]
+| [maybe_named_function_parameters_variadic]
+
+def maybe_named_param_tail
+ [maybe_named_param_tail `, maybe_named_param]
+| []
+
+def maybe_named_function_parameters
+ [maybe_named_param maybe_named_param_tail `,`?]
+
+def maybe_named_param
+ [id `: type]
+| [`_ `: type]
+| [type]
+
+def maybe_named_function_parameters_variadic
+ [maybe_named_param maybe_named_param_tail `, `...]
+
+def bare_function_type
+ [
+ for_lifetimes? function_qualifiers `fn
+ `( function_parameters_maybe_named_variadic? `) bare_function_return_type?
+ ]
+
+#
+# Type
+#
+
+def type
+ [type_no_bounds]
+| [impl_trait_type]
+| [trait_object_type]
+
+def type_no_bounds
+ [impl_trait_type_one_bound]
+| [type_path]
+| [array_type]
+| [slice_type]
+| [raw_pointer_type]
+| [`& opt_lifetime type]
+| [`& `mut type]
+| [`& lifetime `mut type]
+| [tuple_type]
+| [`_]
+| [`!]
+| [qualified_path_in_type]
+| [bare_function_type]
+
+def type_list
+ [type_list `, type]
+| [type]
+
+def opt_type
+ [`: type]
+| []
+
+def let_rvalue
+ [expression]
+| [`{ statements `}]
+
+def expr_tail
+ [expr_tail `, expression]
+| []
+
+def expr_list
+ [expression expr_tail]
+| []
+
+def _construct
+ [attribute* id]
+| [attribute* id `: expression]
+
+def cons_plus
+ [cons_plus `, _construct]
+| [_construct]
+
+def cons_list
+ [cons_plus `,`?]
+| []
+
+
+#
+# Expression
+#
+
+def path_ident_segment
+ [id]
+| [`self]
+| [`crate]
+| [`super]
+
+def path_expr_segment
+ [path_ident_segment]
+| [path_ident_segment `:: generic_args]
+
+def generic_args
+ [`< `>]
+| [`< generic_args_lifetimes `,`? `>]
+| [`< generic_args_types `,`? `>]
+| [`< generic_args_bindings `,`? `>]
+| [`< generic_args_types `, generic_args_bindings `,`? `>]
+| [`< generic_args_lifetimes `, generic_args_types `,`? `>]
+| [`< generic_args_lifetimes `, generic_args_bindings `,`? `>]
+| [`< generic_args_lifetimes `, generic_args_types `, generic_args_bindings `,`? `>]
+
+def generic_args_lifetimes
+ [lifetime_list]
+
+def generic_args_types
+ [type_list]
+
+def generic_args_binding
+ [id `= type]
+
+def generic_args_bindings
+ [generic_args_bindings `, generic_args_binding]
+| [generic_args_binding]
+
+def pie_tail
+ [pie_tail `:: path_expr_segment]
+| []
+
+def opt_path_sep
+ [`::]
+| []
+
+def path_in_expression
+ [opt_path_sep path_expr_segment pie_tail]
+
+def qualified_path_in_expression
+ [qualified_path_type type_path_tail]
+
+def path_expression
+ [path_in_expression]
+| [qualified_path_in_expression]
+
+def tuple_expression
+ [`( expression `, `)]
+| [`( expression `, expr_list `,`? `)]
+
+def array_expression
+ [`[ expr_list `,`? `]]
+| [`[ expression `; expression `]]
+
+def closure_parameters
+ [closure_parameters `, closure_param]
+| [closure_param]
+
+def closure_param
+ [pattern]
+| [pattern `: type]
+
+def closure_expression_param_forms
+ [`| closure_parameters `,`? `|]
+| [`||]
+
+def closure_expression
+ [`move ? closure_expression_param_forms expression]
+| [`move ? closure_expression_param_forms `-> type_no_bounds block_expression]
+
+def paths
+ [path_expression]
+| [char]
+| [string]
+| [raw_string]
+| [number]
+| [float]
+| [path_in_expression `{ cons_list `}]
+| [path_in_expression `{ `.. expression `}]
+| [path_in_expression `{ cons_list `, `.. expression `}]
+| [`( `)]
+| [`true]
+| [`false]
+| [`( expression `)]
+| [tuple_expression]
+| [array_expression]
+| [macro_invocation]
+| [closure_expression]
+| [block_expression]
+| [match_expression]
+| [if_expression]
+| [if_let_expression]
+
+
+def func_index
+ [func_index `. path_expr_segment]
+| [func_index `. number]
+| [func_index `( expr_list `,`? `)]
+| [func_index `[ expr_list `,`? `]]
+| [func_index `?]
+| [paths]
+
+def question
+ [func_index]
+
+def unary
+ [question]
+| [`- unary]
+| [`* unary]
+| [`! unary]
+| [`& unary]
+| [`& `mut unary]
+| [`mut unary]
+
+def as
+ [as `as type_no_bounds]
+| [unary]
+
+def mult
+ [mult `* as]
+| [mult `/ as]
+| [mult `% as]
+| [as]
+
+def add_sub
+ [add_sub `- mult]
+| [add_sub `+ mult]
+| [mult]
+
+def shift
+ [shift `> `> add_sub]
+| [shift `<< add_sub]
+| [add_sub]
+
+def bitwise_and
+ [bitwise_and `& shift]
+| [shift]
+
+def bitwise_xor
+ [bitwise_xor `^ bitwise_and]
+| [bitwise_and]
+
+def bitwise_or
+ [bitwise_or `| bitwise_xor]
+| [bitwise_xor]
+
+def comp_op
+ [`==] | [`!=]
+| [`>] | [`<]
+| [`>=] | [`<=]
+
+def comparison
+ [comparison comp_op bitwise_or]
+| [bitwise_or]
+
+def lazy_conjunction
+ [lazy_conjunction `&& comparison]
+| [comparison]
+
+def lazy_disjunction
+ [lazy_disjunction `|| lazy_conjunction]
+| [lazy_conjunction]
+
+def range_expression
+ [range_expression `.. lazy_disjunction]
+| [lazy_disjunction `..]
+| [`.. lazy_disjunction]
+| [`..]
+| [range_expression `..= lazy_disjunction]
+| [`..= lazy_disjunction]
+| [lazy_disjunction]
+
+# Evaluates right to left.
+def assignment_expression
+ [range_expression `= expression]
+| [range_expression]
+
+def compound_op
+ [`+=] | [`-=] | [`*=] | [`/=] | [`%=]
+| [`&=] | [`|=] | [`^=] | [`<<=] | [`>>=]
+
+# Evaluates right to left.
+def compound_expression
+ [assignment_expression compound_op compound_expression]
+| [assignment_expression]
+
+def expression
+ [expression_without_block]
+| [expression_with_block]
+
+#
+# Statements
+#
+
+def block_expression
+ [`unsafe ? `{ statements? `}]
+
+def let_statement
+ [`let pattern opt_type `= let_rvalue `;]
+| [`let pattern opt_type `;]
+
+def expression_without_block
+ [compound_expression `? ?]
+| [return_expression]
+| [break_expression]
+| [continue_expression]
+
+def expression_with_block
+ [block_expression]
+| [loop_expression]
+| [if_expression]
+| [if_let_expression]
+| [match_expression]
+
+def expression_statement
+ [expression_without_block `;]
+| [expression_with_block]
+
+def statement
+ [`;]
+| [item]
+| [let_statement]
+| [expression_statement]
+| [use_declaration]
+| [macro_invocation_semi]
+
+def statement_list
+ [statement_list statement]
+| [statement]
+
+def statements
+ [statement_list]
+| [statement_list expression_without_block]
+| [expression_without_block]
+
+def loop_label
+ [lifetime `:]
+
+def loop_expression
+ [loop_label? `loop block_expression]
+| [loop_label? `while expression block_expression]
+| [loop_label? `while `let match_arm_patterns `= expression block_expression]
+| [loop_label? `for pattern `in expression block_expression]
+
+def if_expression
+ [`if expression block_expression opt_else_expression]
+
+def opt_else_expression
+ [`else block_expression]
+| [`else if_expression]
+| [`else if_let_expression]
+| []
+
+def if_let_expression
+ [
+ `if `let match_arm_patterns `= expression block_expression
+ opt_else_expression
+ ]
+
+def visibility
+ [`pub]
+| [`pub `( `crate `)]
+| [`pub `( `self `)]
+| [`pub `( `super `)]
+| [`pub `( `in simple_path `)]
+
+def field
+ [attribute* visibility? id `: type]
+
+def field_plus
+ [field_plus `, field]
+| [field]
+
+def field_list
+ [field_plus]
+| []
+
+#
+# Lifetime Params
+#
+
+def colon_lifetime_bounds
+ [`: lifetime_bounds]
+
+def lifetime_param
+ [lifetime colon_lifetime_bounds?]
+
+def lifetime_param_list
+ [lifetime_param_list `, lifetime_param ]
+| [lifetime_param]
+
+#
+# Type param bounds
+#
+
+def trait_bound
+ [`? ? for_lifetimes? type_path]
+| [`( `? ? for_lifetimes? type_path `)]
+
+def type_param_bound
+ [lifetime]
+| [trait_bound]
+
+def tpb_tail
+ [`+ type_param_bound]
+
+def type_param_bounds
+ [type_param_bound tpb_tail* `+`?]
+
+#
+# Type Params
+#
+
+def opt_eq_type
+ [`= type]
+| []
+
+def opt_type_param_bounds
+ [`: type_param_bounds]
+| []
+
+def type_param
+ [id opt_type_param_bounds opt_eq_type]
+
+def type_param_tail
+ [type_param_tail `, type_param]
+| []
+
+def type_param_list
+ [type_param type_param_tail]
+
+#
+# Generics
+#
+
+def generic_params
+ [lifetime_param_list `, type_param_list]
+| [lifetime_param_list]
+| [type_param_list]
+| []
+
+def opt_generics
+ [`< generic_params `>]
+| []
+
+#
+# Where clause
+#
+
+def lifetime_params
+ [lifetime_param_list? `,`?]
+
+def for_lifetimes
+ [`for `< lifetime_params `>]
+
+def lifetime_bounds_list
+ [lifetime_bounds_list `+ lifetime]
+| [lifetime]
+
+def lifetime_bounds
+ [lifetime_bounds_list? `+`?]
+
+def lifetime_where_clause_item
+ [lifetime `: lifetime_bounds]
+
+def type_bound_where_clause_item
+ [for_lifetimes? type `: type_param_bounds?]
+
+def where_clause_item
+ [lifetime_where_clause_item]
+| [type_bound_where_clause_item]
+
+def where_clause_item_list
+ [where_clause_item_list `, where_clause_item]
+| [where_clause_item]
+
+def opt_where_clause
+ [`where where_clause_item_list `,`? ]
+| []
+
+
+#
+# Tuple List
+#
+
+def tuple_field
+ [attribute* visibility? type]
+
+def tuple_field_list
+ [tuple_field_list `, tuple_field]
+| [tuple_field]
+
+def tuple_fields
+ [tuple_field_list `,`?]
+
+#
+# Structure
+#
+
+def struct_field
+ [attribute* visibility? id `: type]
+
+def struct_field_list
+ [struct_field_list `, struct_field]
+| [struct_field]
+
+def struct_fields
+ [struct_field_list `,`?]
+
+def struct_struct
+ [`struct id opt_generics opt_where_clause `{ struct_fields? `}]
+| [`struct id opt_generics opt_where_clause `;]
+
+def tuple_struct
+ [`struct id opt_generics `( tuple_fields? `) opt_where_clause `; ]
+
+def structure
+ [struct_struct]
+| [tuple_struct]
+
+#
+# Union
+#
+def union
+ [Union: id id opt_generics opt_where_clause `{ struct_fields? `}]
+ {
+ if $lhs.Union != "union"
+ reject
+ }
+
+#
+# Trait
+#
+
+def opt_type_param_bounds_opt
+ [`: type_param_bounds?]
+| []
+
+def trait
+ [
+ `trait id opt_generics opt_type_param_bounds_opt opt_where_clause
+ `{
+ trait_item*
+ `}
+ ]
+
+def trait_item
+ [attribute* trait_func]
+| [attribute* trait_method]
+| [attribute* trait_const]
+| [attribute* trait_type]
+| [attribute* macro_invocation_semi]
+
+def trait_func
+ [trait_func_decl `;]
+| [trait_func_decl block_expression]
+
+def trait_method
+ [trait_method_decl `;]
+| [trait_method_decl block_expression]
+
+def trait_func_decl
+ [function_qualifiers `fn id opt_generics
+ `( trait_function_parameters `) opt_return opt_where_clause]
+
+def trait_method_decl
+ [function_qualifiers `fn id opt_generics
+ `( self_param trait_method_parameters `) opt_return opt_where_clause]
+
+def trait_function_parameters
+ [trait_param_list `,]
+| [trait_param_list ]
+| []
+
+def trait_method_parameters
+ [`, trait_param_list `,]
+| [`, trait_param_list ]
+| [`,]
+| []
+
+def trait_param_list
+ [trait_param_list `, trait_function_param]
+| [trait_function_param]
+
+def trait_function_param
+ [pattern `: type]
+| [type]
+
+def trait_const
+ [`const id `: type `;]
+| [`const id `: type `= expression `;]
+
+def trait_type
+ [`type id opt_type_param_bounds_opt `;]
+
+#
+# Implementation
+#
+
+def inherent_impl_item
+ [attribute* visibility? function] commit
+| [attribute* visibility? method] commit
+
+def inherent_impl
+ [`impl opt_generics type opt_where_clause `{ inherent_impl_item* `}]
+
+def trait_impl_item
+ [attribute* visibility? type_alias]
+| [attribute* visibility? constant_item]
+| [attribute* visibility? function]
+| [attribute* visibility? method]
+
+def constant_item
+ [`const id `: type `= expression `;]
+| [`const `_ `: type `= expression `;]
+
+def trait_impl
+ [`unsafe ? `impl opt_generics `! ? type_path `for type opt_where_clause `{ trait_impl_item* `}]
+
+def implementation
+ [inherent_impl]
+| [trait_impl]
+
+def type_alias
+ [`type id opt_generics opt_where_clause `= type `;]
+
+def const_item
+ [`const id `: type `= expression `;]
+| [`const `_ `: type `= expression `;]
+
+def module
+ [`mod id `;]
+| [`mod id `{ item* `}]
+
+def crate_ref
+ [id] | [`self]
+
+def as_clause
+ [`as id]
+| [`as `_]
+
+def extern_crate
+ [`extern `crate crate_ref as_clause? `;]
+
+def enum
+ [`enum id opt_generics opt_where_clause `{ enum_items? `,`? `}]
+
+def enum_items
+ [enum_items `, enum_item]
+| [enum_item]
+
+def enum_item
+ [attribute* id enum_item_tuple]
+| [attribute* id enum_item_struct]
+| [attribute* id enum_item_discriminant]
+| [attribute* id]
+
+def enum_item_tuple
+ [`( tuple_fields? `)]
+
+def enum_item_struct
+ [`{ field_list `,`? `}]
+
+def enum_item_discriminant
+ [`= expression]
+
+def static_item
+ [`static `mut`? id `: type `= expression `;]
+
+def abi
+ [string]
+| [raw_string]
+
+def external_static_item
+ [`static `mut`? id `: type `;]
+
+def function_return_type
+ [`-> type]
+
+def external_function_item
+ [`fn id opt_generics `( named_function_parameters? `) function_return_type? opt_where_clause `;]
+
+def named_function_param
+ [id `: type]
+| [`_ `: type]
+
+def named_function_parameters
+ [named_function_parameter_list `, `...]
+| [named_function_parameter_list `,]
+| [named_function_parameter_list ]
+
+def named_function_parameter_list
+ [named_function_parameter_list `, named_function_param]
+| [named_function_param]
+
+def external_item
+ [attribute* visibility? external_static_item]
+| [attribute* visibility? external_function_item]
+
+def extern_block
+ [`extern abi? `{ external_item* `}]
+
+
+#
+# All Items.
+#
+
+def item
+ [visibility? vis_item] commit
+| [macro_invocation_semi] commit
+| [macro_rules_definition] commit
+
+def vis_item
+ [attribute] commit
+| [function] commit
+| [structure] commit
+| [union] commit
+| [trait] commit
+| [implementation] commit
+| [use_declaration] commit
+| [type_alias] commit
+| [const_item] commit
+| [static_item] commit
+| [module] commit
+| [extern_crate] commit
+| [extern_block] commit
+| [enum] commit
+
+def program
+ [item*]
+