diff options
author | Adrian Thurston <thurston@colm.net> | 2019-12-01 09:05:03 -0800 |
---|---|---|
committer | Adrian Thurston <thurston@colm.net> | 2019-12-01 09:05:03 -0800 |
commit | 5a4407de2c4c03083f1c25b5c7fdb849cdc08a12 (patch) | |
tree | 4436efeb998fd54de016723d92d74c400d48e070 /grammar/rust | |
parent | 479376c313208ee764d212846892cb904b8e5b89 (diff) | |
download | colm-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/.gitignore | 4 | ||||
-rw-r--r-- | grammar/rust/Makefile | 7 | ||||
-rw-r--r-- | grammar/rust/parserust.lm | 81 | ||||
-rw-r--r-- | grammar/rust/rust.lm | 1305 |
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*] + |