1913 lines
80 KiB
Plaintext
1913 lines
80 KiB
Plaintext
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
|||
|
// file at the top-level directory of this distribution and at
|
|||
|
// http://rust-lang.org/COPYRIGHT.
|
|||
|
//
|
|||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|||
|
// option. This file may not be copied, modified, or distributed
|
|||
|
// except according to those terms.
|
|||
|
|
|||
|
%{
|
|||
|
#define YYERROR_VERBOSE
|
|||
|
#define YYSTYPE struct node *
|
|||
|
struct node;
|
|||
|
extern int yylex();
|
|||
|
extern void yyerror(char const *s);
|
|||
|
extern struct node *mk_node(char const *name, int n, ...);
|
|||
|
extern struct node *mk_atom(char *text);
|
|||
|
extern struct node *mk_none();
|
|||
|
extern struct node *ext_node(struct node *nd, int n, ...);
|
|||
|
extern void push_back(char c);
|
|||
|
extern char *yytext;
|
|||
|
%}
|
|||
|
%debug
|
|||
|
|
|||
|
%token SHL
|
|||
|
%token SHR
|
|||
|
%token LE
|
|||
|
%token EQEQ
|
|||
|
%token NE
|
|||
|
%token GE
|
|||
|
%token ANDAND
|
|||
|
%token OROR
|
|||
|
%token SHLEQ
|
|||
|
%token SHREQ
|
|||
|
%token MINUSEQ
|
|||
|
%token ANDEQ
|
|||
|
%token OREQ
|
|||
|
%token PLUSEQ
|
|||
|
%token STAREQ
|
|||
|
%token SLASHEQ
|
|||
|
%token CARETEQ
|
|||
|
%token PERCENTEQ
|
|||
|
%token DOTDOT
|
|||
|
%token DOTDOTDOT
|
|||
|
%token MOD_SEP
|
|||
|
%token RARROW
|
|||
|
%token FAT_ARROW
|
|||
|
%token LIT_BYTE
|
|||
|
%token LIT_CHAR
|
|||
|
%token LIT_INTEGER
|
|||
|
%token LIT_FLOAT
|
|||
|
%token LIT_STR
|
|||
|
%token LIT_STR_RAW
|
|||
|
%token LIT_BINARY
|
|||
|
%token LIT_BINARY_RAW
|
|||
|
%token IDENT
|
|||
|
%token UNDERSCORE
|
|||
|
%token LIFETIME
|
|||
|
|
|||
|
// keywords
|
|||
|
%token SELF
|
|||
|
%token STATIC
|
|||
|
%token AS
|
|||
|
%token BREAK
|
|||
|
%token CRATE
|
|||
|
%token ELSE
|
|||
|
%token ENUM
|
|||
|
%token EXTERN
|
|||
|
%token FALSE
|
|||
|
%token FN
|
|||
|
%token FOR
|
|||
|
%token IF
|
|||
|
%token IMPL
|
|||
|
%token IN
|
|||
|
%token LET
|
|||
|
%token LOOP
|
|||
|
%token MATCH
|
|||
|
%token MOD
|
|||
|
%token MOVE
|
|||
|
%token MUT
|
|||
|
%token PRIV
|
|||
|
%token PUB
|
|||
|
%token REF
|
|||
|
%token RETURN
|
|||
|
%token STRUCT
|
|||
|
%token TRUE
|
|||
|
%token TRAIT
|
|||
|
%token TYPE
|
|||
|
%token UNSAFE
|
|||
|
%token USE
|
|||
|
%token WHILE
|
|||
|
%token CONTINUE
|
|||
|
%token PROC
|
|||
|
%token BOX
|
|||
|
%token CONST
|
|||
|
%token WHERE
|
|||
|
%token TYPEOF
|
|||
|
%token INNER_DOC_COMMENT
|
|||
|
%token OUTER_DOC_COMMENT
|
|||
|
|
|||
|
%token SHEBANG
|
|||
|
%token SHEBANG_LINE
|
|||
|
%token STATIC_LIFETIME
|
|||
|
|
|||
|
/*
|
|||
|
Quoting from the Bison manual:
|
|||
|
|
|||
|
"Finally, the resolution of conflicts works by comparing the precedence
|
|||
|
of the rule being considered with that of the lookahead token. If the
|
|||
|
token's precedence is higher, the choice is to shift. If the rule's
|
|||
|
precedence is higher, the choice is to reduce. If they have equal
|
|||
|
precedence, the choice is made based on the associativity of that
|
|||
|
precedence level. The verbose output file made by ‘-v’ (see Invoking
|
|||
|
Bison) says how each conflict was resolved"
|
|||
|
*/
|
|||
|
|
|||
|
// We expect no shift/reduce or reduce/reduce conflicts in this grammar;
|
|||
|
// all potential ambiguities are scrutinized and eliminated manually.
|
|||
|
%expect 0
|
|||
|
|
|||
|
// fake-precedence symbol to cause '|' bars in lambda context to parse
|
|||
|
// at low precedence, permit things like |x| foo = bar, where '=' is
|
|||
|
// otherwise lower-precedence than '|'. Also used for proc() to cause
|
|||
|
// things like proc() a + b to parse as proc() { a + b }.
|
|||
|
%precedence LAMBDA
|
|||
|
|
|||
|
%precedence SELF
|
|||
|
|
|||
|
// MUT should be lower precedence than IDENT so that in the pat rule,
|
|||
|
// "& MUT pat" has higher precedence than "binding_mode ident [@ pat]"
|
|||
|
%precedence MUT
|
|||
|
|
|||
|
// IDENT needs to be lower than '{' so that 'foo {' is shifted when
|
|||
|
// trying to decide if we've got a struct-construction expr (esp. in
|
|||
|
// contexts like 'if foo { .')
|
|||
|
//
|
|||
|
// IDENT also needs to be lower precedence than '<' so that '<' in
|
|||
|
// 'foo:bar . <' is shifted (in a trait reference occurring in a
|
|||
|
// bounds list), parsing as foo:(bar<baz>) rather than (foo:bar)<baz>.
|
|||
|
%precedence IDENT
|
|||
|
|
|||
|
// A couple fake-precedence symbols to use in rules associated with +
|
|||
|
// and < in trailing type contexts. These come up when you have a type
|
|||
|
// in the RHS of operator-AS, such as "foo as bar<baz>". The "<" there
|
|||
|
// has to be shifted so the parser keeps trying to parse a type, even
|
|||
|
// though it might well consider reducing the type "bar" and then
|
|||
|
// going on to "<" as a subsequent binop. The "+" case is with
|
|||
|
// trailing type-bounds ("foo as bar:A+B"), for the same reason.
|
|||
|
%precedence SHIFTPLUS
|
|||
|
|
|||
|
%precedence MOD_SEP
|
|||
|
%precedence RARROW ':'
|
|||
|
|
|||
|
// Binops & unops, and their precedences
|
|||
|
%precedence BOX
|
|||
|
%precedence BOXPLACE
|
|||
|
%nonassoc DOTDOT
|
|||
|
|
|||
|
// RETURN needs to be lower-precedence than tokens that start
|
|||
|
// prefix_exprs
|
|||
|
%precedence RETURN
|
|||
|
|
|||
|
%left '=' SHLEQ SHREQ MINUSEQ ANDEQ OREQ PLUSEQ STAREQ SLASHEQ CARETEQ PERCENTEQ
|
|||
|
%left OROR
|
|||
|
%left ANDAND
|
|||
|
%left EQEQ NE
|
|||
|
%left '<' '>' LE GE
|
|||
|
%left '|'
|
|||
|
%left '^'
|
|||
|
%left '&'
|
|||
|
%left SHL SHR
|
|||
|
%left '+' '-'
|
|||
|
%precedence AS
|
|||
|
%left '*' '/' '%'
|
|||
|
%precedence '!'
|
|||
|
|
|||
|
%precedence '{' '[' '(' '.'
|
|||
|
|
|||
|
%start crate
|
|||
|
|
|||
|
%%
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////
|
|||
|
// Part 1: Items and attributes
|
|||
|
////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
crate
|
|||
|
: maybe_shebang inner_attrs maybe_mod_items { mk_node("crate", 2, $2, $3); }
|
|||
|
| maybe_shebang maybe_mod_items { mk_node("crate", 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_shebang
|
|||
|
: SHEBANG_LINE
|
|||
|
| %empty
|
|||
|
;
|
|||
|
|
|||
|
maybe_inner_attrs
|
|||
|
: inner_attrs
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
inner_attrs
|
|||
|
: inner_attr { $$ = mk_node("InnerAttrs", 1, $1); }
|
|||
|
| inner_attrs inner_attr { $$ = ext_node($1, 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
inner_attr
|
|||
|
: SHEBANG '[' meta_item ']' { $$ = mk_node("InnerAttr", 1, $3); }
|
|||
|
| INNER_DOC_COMMENT { $$ = mk_node("InnerAttr", 1, mk_node("doc-comment", 1, mk_atom(yytext))); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_outer_attrs
|
|||
|
: outer_attrs
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
outer_attrs
|
|||
|
: outer_attr { $$ = mk_node("OuterAttrs", 1, $1); }
|
|||
|
| outer_attrs outer_attr { $$ = ext_node($1, 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
outer_attr
|
|||
|
: '#' '[' meta_item ']' { $$ = $3; }
|
|||
|
| OUTER_DOC_COMMENT { $$ = mk_node("doc-comment", 1, mk_atom(yytext)); }
|
|||
|
;
|
|||
|
|
|||
|
meta_item
|
|||
|
: ident { $$ = mk_node("MetaWord", 1, $1); }
|
|||
|
| ident '=' lit { $$ = mk_node("MetaNameValue", 2, $1, $3); }
|
|||
|
| ident '(' meta_seq ')' { $$ = mk_node("MetaList", 2, $1, $3); }
|
|||
|
| ident '(' meta_seq ',' ')' { $$ = mk_node("MetaList", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
meta_seq
|
|||
|
: %empty { $$ = mk_none(); }
|
|||
|
| meta_item { $$ = mk_node("MetaItems", 1, $1); }
|
|||
|
| meta_seq ',' meta_item { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_mod_items
|
|||
|
: mod_items
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
mod_items
|
|||
|
: mod_item { $$ = mk_node("Items", 1, $1); }
|
|||
|
| mod_items mod_item { $$ = ext_node($1, 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
attrs_and_vis
|
|||
|
: maybe_outer_attrs visibility { $$ = mk_node("AttrsAndVis", 2, $1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
mod_item
|
|||
|
: attrs_and_vis item { $$ = mk_node("Item", 2, $1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
// items that can appear outside of a fn block
|
|||
|
item
|
|||
|
: item_static
|
|||
|
| item_const
|
|||
|
| item_type
|
|||
|
| block_item
|
|||
|
| view_item
|
|||
|
| item_macro
|
|||
|
;
|
|||
|
|
|||
|
// items that can appear in "stmts"
|
|||
|
stmt_item
|
|||
|
: item_static
|
|||
|
| item_const
|
|||
|
| item_type
|
|||
|
| block_item
|
|||
|
| use_item
|
|||
|
| extern_fn_item
|
|||
|
;
|
|||
|
|
|||
|
item_static
|
|||
|
: STATIC ident ':' ty '=' expr ';' { $$ = mk_node("ItemStatic", 3, $2, $4, $6); }
|
|||
|
| STATIC MUT ident ':' ty '=' expr ';' { $$ = mk_node("ItemStatic", 3, $3, $5, $7); }
|
|||
|
;
|
|||
|
|
|||
|
item_const
|
|||
|
: CONST ident ':' ty '=' expr ';' { $$ = mk_node("ItemConst", 3, $2, $4, $6); }
|
|||
|
;
|
|||
|
|
|||
|
item_macro
|
|||
|
: path_expr '!' maybe_ident parens_delimited_token_trees ';'
|
|||
|
| path_expr '!' maybe_ident braces_delimited_token_trees
|
|||
|
| path_expr '!' maybe_ident brackets_delimited_token_trees ';'
|
|||
|
;
|
|||
|
|
|||
|
view_item
|
|||
|
: use_item
|
|||
|
| extern_fn_item
|
|||
|
| EXTERN CRATE ident ';' { $$ = mk_node("ViewItemExternCrate", 1, $3); }
|
|||
|
| EXTERN CRATE ident '=' str ';' { $$ = mk_node("ViewItemExternCrate", 2, $3, $5); }
|
|||
|
| EXTERN CRATE str AS ident ';' { $$ = mk_node("ViewItemExternCrate", 2, $3, $5); }
|
|||
|
;
|
|||
|
|
|||
|
extern_fn_item
|
|||
|
: EXTERN maybe_abi item_fn { $$ = mk_node("ViewItemExternFn", 2, $2, $3); }
|
|||
|
;
|
|||
|
|
|||
|
use_item
|
|||
|
: USE view_path ';' { $$ = mk_node("ViewItemUse", 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
view_path
|
|||
|
: path_no_types_allowed { $$ = mk_node("ViewPathSimple", 1, $1); }
|
|||
|
| path_no_types_allowed MOD_SEP '{' '}' { $$ = mk_node("ViewPathList", 2, $1, mk_atom("ViewPathListEmpty")); }
|
|||
|
| path_no_types_allowed MOD_SEP '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 2, $1, $4); }
|
|||
|
| path_no_types_allowed MOD_SEP '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 2, $1, $4); }
|
|||
|
| path_no_types_allowed MOD_SEP '*' { $$ = mk_node("ViewPathGlob", 1, $1); }
|
|||
|
| '{' '}' { $$ = mk_atom("ViewPathListEmpty"); }
|
|||
|
| '{' idents_or_self '}' { $$ = mk_node("ViewPathList", 1, $2); }
|
|||
|
| '{' idents_or_self ',' '}' { $$ = mk_node("ViewPathList", 1, $2); }
|
|||
|
| path_no_types_allowed AS ident { $$ = mk_node("ViewPathSimple", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
block_item
|
|||
|
: item_fn
|
|||
|
| item_unsafe_fn
|
|||
|
| item_mod
|
|||
|
| item_foreign_mod { $$ = mk_node("ItemForeignMod", 1, $1); }
|
|||
|
| item_struct
|
|||
|
| item_enum
|
|||
|
| item_trait
|
|||
|
| item_impl
|
|||
|
;
|
|||
|
|
|||
|
maybe_ty_ascription
|
|||
|
: ':' ty { $$ = $2; }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_init_expr
|
|||
|
: '=' expr { $$ = $2; }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
// structs
|
|||
|
item_struct
|
|||
|
: STRUCT ident generic_params maybe_where_clause struct_decl_args
|
|||
|
{
|
|||
|
$$ = mk_node("ItemStruct", 4, $2, $3, $4, $5);
|
|||
|
}
|
|||
|
| STRUCT ident generic_params struct_tuple_args maybe_where_clause ';'
|
|||
|
{
|
|||
|
$$ = mk_node("ItemStruct", 4, $2, $3, $4, $5);
|
|||
|
}
|
|||
|
| STRUCT ident generic_params maybe_where_clause ';'
|
|||
|
{
|
|||
|
$$ = mk_node("ItemStruct", 3, $2, $3, $4);
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
struct_decl_args
|
|||
|
: '{' struct_decl_fields '}' { $$ = $2; }
|
|||
|
| '{' struct_decl_fields ',' '}' { $$ = $2; }
|
|||
|
;
|
|||
|
|
|||
|
struct_tuple_args
|
|||
|
: '(' struct_tuple_fields ')' { $$ = $2; }
|
|||
|
| '(' struct_tuple_fields ',' ')' { $$ = $2; }
|
|||
|
;
|
|||
|
|
|||
|
struct_decl_fields
|
|||
|
: struct_decl_field { $$ = mk_node("StructFields", 1, $1); }
|
|||
|
| struct_decl_fields ',' struct_decl_field { $$ = ext_node($1, 1, $3); }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
struct_decl_field
|
|||
|
: attrs_and_vis ident ':' ty_sum { $$ = mk_node("StructField", 3, $1, $2, $4); }
|
|||
|
;
|
|||
|
|
|||
|
struct_tuple_fields
|
|||
|
: struct_tuple_field { $$ = mk_node("StructFields", 1, $1); }
|
|||
|
| struct_tuple_fields ',' struct_tuple_field { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
struct_tuple_field
|
|||
|
: attrs_and_vis ty_sum { $$ = mk_node("StructField", 2, $1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
// enums
|
|||
|
item_enum
|
|||
|
: ENUM ident generic_params maybe_where_clause '{' enum_defs '}' { $$ = mk_node("ItemEnum", 0); }
|
|||
|
| ENUM ident generic_params maybe_where_clause '{' enum_defs ',' '}' { $$ = mk_node("ItemEnum", 0); }
|
|||
|
;
|
|||
|
|
|||
|
enum_defs
|
|||
|
: enum_def { $$ = mk_node("EnumDefs", 1, $1); }
|
|||
|
| enum_defs ',' enum_def { $$ = ext_node($1, 1, $3); }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
enum_def
|
|||
|
: attrs_and_vis ident enum_args { $$ = mk_node("EnumDef", 3, $1, $2, $3); }
|
|||
|
;
|
|||
|
|
|||
|
enum_args
|
|||
|
: '{' struct_decl_fields '}' { $$ = mk_node("EnumArgs", 1, $2); }
|
|||
|
| '{' struct_decl_fields ',' '}' { $$ = mk_node("EnumArgs", 1, $2); }
|
|||
|
| '(' maybe_ty_sums ')' { $$ = mk_node("EnumArgs", 1, $2); }
|
|||
|
| '=' expr { $$ = mk_node("EnumArgs", 1, $2); }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
item_mod
|
|||
|
: MOD ident ';' { $$ = mk_node("ItemMod", 1, $2); }
|
|||
|
| MOD ident '{' maybe_mod_items '}' { $$ = mk_node("ItemMod", 2, $2, $4); }
|
|||
|
| MOD ident '{' inner_attrs maybe_mod_items '}' { $$ = mk_node("ItemMod", 3, $2, $4, $5); }
|
|||
|
;
|
|||
|
|
|||
|
item_foreign_mod
|
|||
|
: EXTERN maybe_abi '{' maybe_foreign_items '}' { $$ = mk_node("ItemForeignMod", 1, $4); }
|
|||
|
| EXTERN maybe_abi '{' inner_attrs maybe_foreign_items '}' { $$ = mk_node("ItemForeignMod", 2, $4, $5); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_abi
|
|||
|
: str
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_foreign_items
|
|||
|
: foreign_items
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
foreign_items
|
|||
|
: foreign_item { $$ = mk_node("ForeignItems", 1, $1); }
|
|||
|
| foreign_items foreign_item { $$ = ext_node($1, 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
foreign_item
|
|||
|
: attrs_and_vis STATIC item_foreign_static { $$ = mk_node("ForeignItem", 2, $1, $3); }
|
|||
|
| attrs_and_vis item_foreign_fn { $$ = mk_node("ForeignItem", 2, $1, $2); }
|
|||
|
| attrs_and_vis UNSAFE item_foreign_fn { $$ = mk_node("ForeignItem", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
item_foreign_static
|
|||
|
: maybe_mut ident ':' ty ';' { $$ = mk_node("StaticItem", 3, $1, $2, $4); }
|
|||
|
;
|
|||
|
|
|||
|
item_foreign_fn
|
|||
|
: FN ident generic_params fn_decl_allow_variadic maybe_where_clause ';' { $$ = mk_node("ForeignFn", 4, $2, $3, $4, $5); }
|
|||
|
;
|
|||
|
|
|||
|
fn_decl_allow_variadic
|
|||
|
: fn_params_allow_variadic ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
fn_params_allow_variadic
|
|||
|
: '(' ')' { $$ = mk_none(); }
|
|||
|
| '(' params ')' { $$ = $2; }
|
|||
|
| '(' params ',' ')' { $$ = $2; }
|
|||
|
| '(' params ',' DOTDOTDOT ')' { $$ = $2; }
|
|||
|
;
|
|||
|
|
|||
|
visibility
|
|||
|
: PUB { $$ = mk_atom("Public"); }
|
|||
|
| %empty { $$ = mk_atom("Inherited"); }
|
|||
|
;
|
|||
|
|
|||
|
idents_or_self
|
|||
|
: ident_or_self { $$ = mk_node("IdentsOrSelf", 1, $1); }
|
|||
|
| idents_or_self ',' ident_or_self { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
ident_or_self
|
|||
|
: ident
|
|||
|
| SELF { $$ = mk_atom(yytext); }
|
|||
|
;
|
|||
|
|
|||
|
item_type
|
|||
|
: TYPE ident generic_params maybe_where_clause '=' ty_sum ';' { $$ = mk_node("ItemTy", 4, $2, $3, $4, $6); }
|
|||
|
;
|
|||
|
|
|||
|
for_sized
|
|||
|
: FOR '?' ident { $$ = mk_node("ForSized", 1, $3); }
|
|||
|
| FOR ident '?' { $$ = mk_node("ForSized", 1, $2); }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
item_trait
|
|||
|
: maybe_unsafe TRAIT ident generic_params for_sized maybe_ty_param_bounds maybe_where_clause '{' maybe_trait_items '}'
|
|||
|
{
|
|||
|
$$ = mk_node("ItemTrait", 7, $1, $3, $4, $5, $6, $7, $9);
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
maybe_trait_items
|
|||
|
: trait_items
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
trait_items
|
|||
|
: trait_item { $$ = mk_node("TraitItems", 1, $1); }
|
|||
|
| trait_items trait_item { $$ = ext_node($1, 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
trait_item
|
|||
|
: trait_type
|
|||
|
| trait_method
|
|||
|
;
|
|||
|
|
|||
|
trait_type
|
|||
|
: maybe_outer_attrs TYPE ty_param ';' { $$ = mk_node("TypeTraitItem", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_unsafe
|
|||
|
: UNSAFE { $$ = mk_atom("Unsafe"); }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
trait_method
|
|||
|
: type_method { $$ = mk_node("Required", 1, $1); }
|
|||
|
| method { $$ = mk_node("Provided", 1, $1); }
|
|||
|
;
|
|||
|
|
|||
|
type_method
|
|||
|
: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';'
|
|||
|
{
|
|||
|
$$ = mk_node("TypeMethod", 6, $1, $2, $4, $5, $6, $7);
|
|||
|
}
|
|||
|
| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause ';'
|
|||
|
{
|
|||
|
$$ = mk_node("TypeMethod", 7, $1, $2, $4, $6, $7, $8, $9);
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
method
|
|||
|
: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block
|
|||
|
{
|
|||
|
$$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8);
|
|||
|
}
|
|||
|
| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self_allow_anon_params maybe_where_clause inner_attrs_and_block
|
|||
|
{
|
|||
|
$$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10);
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
impl_method
|
|||
|
: attrs_and_vis maybe_unsafe FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block
|
|||
|
{
|
|||
|
$$ = mk_node("Method", 7, $1, $2, $4, $5, $6, $7, $8);
|
|||
|
}
|
|||
|
| attrs_and_vis maybe_unsafe EXTERN maybe_abi FN ident generic_params fn_decl_with_self maybe_where_clause inner_attrs_and_block
|
|||
|
{
|
|||
|
$$ = mk_node("Method", 8, $1, $2, $4, $6, $7, $8, $9, $10);
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
// There are two forms of impl:
|
|||
|
//
|
|||
|
// impl (<...>)? TY { ... }
|
|||
|
// impl (<...>)? TRAIT for TY { ... }
|
|||
|
//
|
|||
|
// Unfortunately since TY can begin with '<' itself -- as part of a
|
|||
|
// TyQualifiedPath type -- there's an s/r conflict when we see '<' after IMPL:
|
|||
|
// should we reduce one of the early rules of TY (such as maybe_once)
|
|||
|
// or shall we continue shifting into the generic_params list for the
|
|||
|
// impl?
|
|||
|
//
|
|||
|
// The production parser disambiguates a different case here by
|
|||
|
// permitting / requiring the user to provide parens around types when
|
|||
|
// they are ambiguous with traits. We do the same here, regrettably,
|
|||
|
// by splitting ty into ty and ty_prim.
|
|||
|
item_impl
|
|||
|
: maybe_unsafe IMPL generic_params ty_prim_sum maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
|||
|
{
|
|||
|
$$ = mk_node("ItemImpl", 6, $1, $3, $4, $5, $7, $8);
|
|||
|
}
|
|||
|
| maybe_unsafe IMPL generic_params '(' ty ')' maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
|||
|
{
|
|||
|
$$ = mk_node("ItemImpl", 6, $1, $3, 5, $6, $9, $10);
|
|||
|
}
|
|||
|
| maybe_unsafe IMPL generic_params trait_ref FOR ty maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
|||
|
{
|
|||
|
$$ = mk_node("ItemImpl", 6, $3, $4, $6, $7, $9, $10);
|
|||
|
}
|
|||
|
| maybe_unsafe IMPL generic_params '!' trait_ref FOR ty maybe_where_clause '{' maybe_inner_attrs maybe_impl_items '}'
|
|||
|
{
|
|||
|
$$ = mk_node("ItemImplNeg", 7, $1, $3, $5, $7, $8, $10, $11);
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
maybe_impl_items
|
|||
|
: impl_items
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
impl_items
|
|||
|
: impl_item { $$ = mk_node("ImplItems", 1, $1); }
|
|||
|
| impl_item impl_items { $$ = ext_node($1, 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
impl_item
|
|||
|
: impl_method
|
|||
|
| item_macro
|
|||
|
| trait_type
|
|||
|
;
|
|||
|
|
|||
|
item_fn
|
|||
|
: FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block
|
|||
|
{
|
|||
|
$$ = mk_node("ItemFn", 5, $2, $3, $4, $5, $6);
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
item_unsafe_fn
|
|||
|
: UNSAFE FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block
|
|||
|
{
|
|||
|
$$ = mk_node("ItemUnsafeFn", 5, $3, $4, $5, $6, $7);
|
|||
|
}
|
|||
|
| UNSAFE EXTERN maybe_abi FN ident generic_params fn_decl maybe_where_clause inner_attrs_and_block
|
|||
|
{
|
|||
|
$$ = mk_node("ItemUnsafeFn", 6, $3, $5, $6, $7, $8, $9);
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
fn_decl
|
|||
|
: fn_params ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
fn_decl_with_self
|
|||
|
: fn_params_with_self ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
fn_decl_with_self_allow_anon_params
|
|||
|
: fn_anon_params_with_self ret_ty { $$ = mk_node("FnDecl", 2, $1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
fn_params
|
|||
|
: '(' maybe_params ')' { $$ = $2; }
|
|||
|
;
|
|||
|
|
|||
|
fn_anon_params
|
|||
|
: '(' anon_param anon_params_allow_variadic_tail ')' { $$ = ext_node($2, 1, $3); }
|
|||
|
| '(' ')' { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
fn_params_with_self
|
|||
|
: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfValue", 3, $2, $4, $5); }
|
|||
|
| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 3, $3, $5, $6); }
|
|||
|
| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); }
|
|||
|
| '(' maybe_params ')' { $$ = mk_node("SelfStatic", 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
fn_anon_params_with_self
|
|||
|
: '(' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfValue", 3, $2, $4, $5); }
|
|||
|
| '(' '&' maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 3, $3, $5, $6); }
|
|||
|
| '(' '&' lifetime maybe_mut SELF maybe_ty_ascription maybe_comma_anon_params ')' { $$ = mk_node("SelfRegion", 4, $3, $4, $6, $7); }
|
|||
|
| '(' maybe_anon_params ')' { $$ = mk_node("SelfStatic", 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_params
|
|||
|
: params
|
|||
|
| params ','
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
params
|
|||
|
: param { $$ = mk_node("Args", 1, $1); }
|
|||
|
| params ',' param { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
param
|
|||
|
: pat ':' ty { $$ = mk_node("Arg", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
inferrable_params
|
|||
|
: inferrable_param { $$ = mk_node("InferrableParams", 1, $1); }
|
|||
|
| inferrable_params ',' inferrable_param { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
inferrable_param
|
|||
|
: pat maybe_ty_ascription { $$ = mk_node("InferrableParam", 2, $1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_unboxed_closure_kind
|
|||
|
: %empty
|
|||
|
| ':'
|
|||
|
| '&' maybe_mut ':'
|
|||
|
;
|
|||
|
|
|||
|
maybe_comma_params
|
|||
|
: ',' { $$ = mk_none(); }
|
|||
|
| ',' params { $$ = $2; }
|
|||
|
| ',' params ',' { $$ = $2; }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_comma_anon_params
|
|||
|
: ',' { $$ = mk_none(); }
|
|||
|
| ',' anon_params { $$ = $2; }
|
|||
|
| ',' anon_params ',' { $$ = $2; }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_anon_params
|
|||
|
: anon_params
|
|||
|
| anon_params ','
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
anon_params
|
|||
|
: anon_param { $$ = mk_node("Args", 1, $1); }
|
|||
|
| anon_params ',' anon_param { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
// anon means it's allowed to be anonymous (type-only), but it can
|
|||
|
// still have a name
|
|||
|
anon_param
|
|||
|
: named_arg ':' ty { $$ = mk_node("Arg", 2, $1, $3); }
|
|||
|
| ty
|
|||
|
;
|
|||
|
|
|||
|
anon_params_allow_variadic_tail
|
|||
|
: ',' DOTDOTDOT { $$ = mk_none(); }
|
|||
|
| ',' anon_param anon_params_allow_variadic_tail { $$ = mk_node("Args", 2, $2, $3); }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
named_arg
|
|||
|
: ident
|
|||
|
| UNDERSCORE { $$ = mk_atom("PatWild"); }
|
|||
|
| '&' ident { $$ = $2; }
|
|||
|
| '&' UNDERSCORE { $$ = mk_atom("PatWild"); }
|
|||
|
| ANDAND ident { $$ = $2; }
|
|||
|
| ANDAND UNDERSCORE { $$ = mk_atom("PatWild"); }
|
|||
|
| MUT ident { $$ = $2; }
|
|||
|
;
|
|||
|
|
|||
|
ret_ty
|
|||
|
: RARROW '!' { $$ = mk_none(); }
|
|||
|
| RARROW ty { $$ = mk_node("ret-ty", 1, $2); }
|
|||
|
| %prec IDENT %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
generic_params
|
|||
|
: '<' lifetimes '>' { $$ = mk_node("Generics", 2, $2, mk_none()); }
|
|||
|
| '<' lifetimes ',' '>' { $$ = mk_node("Generics", 2, $2, mk_none()); }
|
|||
|
| '<' lifetimes SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); }
|
|||
|
| '<' lifetimes ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, mk_none()); }
|
|||
|
| '<' lifetimes ',' ty_params '>' { $$ = mk_node("Generics", 2, $2, $4); }
|
|||
|
| '<' lifetimes ',' ty_params ',' '>' { $$ = mk_node("Generics", 2, $2, $4); }
|
|||
|
| '<' lifetimes ',' ty_params SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); }
|
|||
|
| '<' lifetimes ',' ty_params ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, $2, $4); }
|
|||
|
| '<' ty_params '>' { $$ = mk_node("Generics", 2, mk_none(), $2); }
|
|||
|
| '<' ty_params ',' '>' { $$ = mk_node("Generics", 2, mk_none(), $2); }
|
|||
|
| '<' ty_params SHR { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); }
|
|||
|
| '<' ty_params ',' SHR { push_back('>'); $$ = mk_node("Generics", 2, mk_none(), $2); }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_where_clause
|
|||
|
: %empty { $$ = mk_none(); }
|
|||
|
| where_clause
|
|||
|
;
|
|||
|
|
|||
|
where_clause
|
|||
|
: WHERE where_predicates { $$ = mk_node("WhereClause", 1, $2); }
|
|||
|
| WHERE where_predicates ',' { $$ = mk_node("WhereClause", 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
where_predicates
|
|||
|
: where_predicate { $$ = mk_node("WherePredicates", 1, $1); }
|
|||
|
| where_predicates ',' where_predicate { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
where_predicate
|
|||
|
: lifetime ':' bounds { $$ = mk_node("WherePredicate", 2, $1, $3); }
|
|||
|
| ty ':' ty_param_bounds { $$ = mk_node("WherePredicate", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
ty_params
|
|||
|
: ty_param { $$ = mk_node("TyParams", 1, $1); }
|
|||
|
| ty_params ',' ty_param { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
// A path with no type parameters; e.g. `foo::bar::Baz`
|
|||
|
//
|
|||
|
// These show up in 'use' view-items, because these are processed
|
|||
|
// without respect to types.
|
|||
|
path_no_types_allowed
|
|||
|
: ident { $$ = mk_node("ViewPath", 1, $1); }
|
|||
|
| MOD_SEP ident { $$ = mk_node("ViewPath", 1, $2); }
|
|||
|
| SELF { $$ = mk_node("ViewPath", 1, mk_atom("Self")); }
|
|||
|
| MOD_SEP SELF { $$ = mk_node("ViewPath", 1, mk_atom("Self")); }
|
|||
|
| path_no_types_allowed MOD_SEP ident { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
// A path with a lifetime and type parameters, with no double colons
|
|||
|
// before the type parameters; e.g. `foo::bar<'a>::Baz<T>`
|
|||
|
//
|
|||
|
// These show up in "trait references", the components of
|
|||
|
// type-parameter bounds lists, as well as in the prefix of the
|
|||
|
// path_generic_args_and_bounds rule, which is the full form of a
|
|||
|
// named typed expression.
|
|||
|
//
|
|||
|
// They do not have (nor need) an extra '::' before '<' because
|
|||
|
// unlike in expr context, there are no "less-than" type exprs to
|
|||
|
// be ambiguous with.
|
|||
|
path_generic_args_without_colons
|
|||
|
: %prec IDENT
|
|||
|
ident { $$ = mk_node("components", 1, $1); }
|
|||
|
| %prec IDENT
|
|||
|
ident generic_args { $$ = mk_node("components", 2, $1, $2); }
|
|||
|
| %prec IDENT
|
|||
|
ident '(' maybe_ty_sums ')' ret_ty { $$ = mk_node("components", 2, $1, $3); }
|
|||
|
| %prec IDENT
|
|||
|
path_generic_args_without_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); }
|
|||
|
| %prec IDENT
|
|||
|
path_generic_args_without_colons MOD_SEP ident generic_args { $$ = ext_node($1, 2, $3, $4); }
|
|||
|
| %prec IDENT
|
|||
|
path_generic_args_without_colons MOD_SEP ident '(' maybe_ty_sums ')' ret_ty { $$ = ext_node($1, 2, $3, $5); }
|
|||
|
;
|
|||
|
|
|||
|
generic_args
|
|||
|
: '<' generic_values '>' { $$ = $2; }
|
|||
|
| '<' generic_values SHR { push_back('>'); $$ = $2; }
|
|||
|
| '<' generic_values GE { push_back('='); $$ = $2; }
|
|||
|
| '<' generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; }
|
|||
|
// If generic_args starts with "<<", the first arg must be a
|
|||
|
// TyQualifiedPath because that's the only type that can start with a
|
|||
|
// '<'. This rule parses that as the first ty_sum and then continues
|
|||
|
// with the rest of generic_values.
|
|||
|
| SHL ty_qualified_path_and_generic_values '>' { $$ = $2; }
|
|||
|
| SHL ty_qualified_path_and_generic_values SHR { push_back('>'); $$ = $2; }
|
|||
|
| SHL ty_qualified_path_and_generic_values GE { push_back('='); $$ = $2; }
|
|||
|
| SHL ty_qualified_path_and_generic_values SHREQ { push_back('>'); push_back('='); $$ = $2; }
|
|||
|
;
|
|||
|
|
|||
|
generic_values
|
|||
|
: maybe_lifetimes maybe_ty_sums_and_or_bindings { $$ = mk_node("GenericValues", 2, $1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_ty_sums_and_or_bindings
|
|||
|
: ty_sums
|
|||
|
| ty_sums ','
|
|||
|
| ty_sums ',' bindings { $$ = mk_node("TySumsAndBindings", 2, $1, $3); }
|
|||
|
| bindings
|
|||
|
| bindings ','
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_bindings
|
|||
|
: ',' bindings { $$ = $2; }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////
|
|||
|
// Part 2: Patterns
|
|||
|
////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
pat
|
|||
|
: UNDERSCORE { $$ = mk_atom("PatWild"); }
|
|||
|
| '&' pat { $$ = mk_node("PatRegion", 1, $2); }
|
|||
|
| '&' MUT pat { $$ = mk_node("PatRegion", 1, $3); }
|
|||
|
| ANDAND pat { $$ = mk_node("PatRegion", 1, mk_node("PatRegion", 1, $2)); }
|
|||
|
| '(' ')' { $$ = mk_atom("PatUnit"); }
|
|||
|
| '(' pat_tup ')' { $$ = mk_node("PatTup", 1, $2); }
|
|||
|
| '(' pat_tup ',' ')' { $$ = mk_node("PatTup", 1, $2); }
|
|||
|
| '[' pat_vec ']' { $$ = mk_node("PatVec", 1, $2); }
|
|||
|
| lit_or_path
|
|||
|
| lit_or_path DOTDOTDOT lit_or_path { $$ = mk_node("PatRange", 2, $1, $3); }
|
|||
|
| path_expr '{' pat_struct '}' { $$ = mk_node("PatStruct", 2, $1, $3); }
|
|||
|
| path_expr '(' DOTDOT ')' { $$ = mk_node("PatEnum", 1, $1); }
|
|||
|
| path_expr '(' pat_tup ')' { $$ = mk_node("PatEnum", 2, $1, $3); }
|
|||
|
| path_expr '!' maybe_ident delimited_token_trees { $$ = mk_node("PatMac", 3, $1, $3, $4); }
|
|||
|
| binding_mode ident { $$ = mk_node("PatIdent", 2, $1, $2); }
|
|||
|
| ident '@' pat { $$ = mk_node("PatIdent", 3, mk_node("BindByValue", 1, mk_atom("MutImmutable")), $1, $3); }
|
|||
|
| binding_mode ident '@' pat { $$ = mk_node("PatIdent", 3, $1, $2, $4); }
|
|||
|
| BOX pat { $$ = mk_node("PatUniq", 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
pats_or
|
|||
|
: pat { $$ = mk_node("Pats", 1, $1); }
|
|||
|
| pats_or '|' pat { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
binding_mode
|
|||
|
: REF { $$ = mk_node("BindByRef", 1, mk_atom("MutImmutable")); }
|
|||
|
| REF MUT { $$ = mk_node("BindByRef", 1, mk_atom("MutMutable")); }
|
|||
|
| MUT { $$ = mk_node("BindByValue", 1, mk_atom("MutMutable")); }
|
|||
|
;
|
|||
|
|
|||
|
lit_or_path
|
|||
|
: path_expr { $$ = mk_node("PatLit", 1, $1); }
|
|||
|
| lit { $$ = mk_node("PatLit", 1, $1); }
|
|||
|
| '-' lit { $$ = mk_node("PatLit", 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
pat_field
|
|||
|
: ident { $$ = mk_node("PatField", 1, $1); }
|
|||
|
| binding_mode ident { $$ = mk_node("PatField", 2, $1, $2); }
|
|||
|
| BOX ident { $$ = mk_node("PatField", 2, mk_atom("box"), $2); }
|
|||
|
| BOX binding_mode ident { $$ = mk_node("PatField", 3, mk_atom("box"), $2, $3); }
|
|||
|
| ident ':' pat { $$ = mk_node("PatField", 2, $1, $3); }
|
|||
|
| binding_mode ident ':' pat { $$ = mk_node("PatField", 3, $1, $2, $4); }
|
|||
|
;
|
|||
|
|
|||
|
pat_fields
|
|||
|
: pat_field { $$ = mk_node("PatFields", 1, $1); }
|
|||
|
| pat_fields ',' pat_field { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
pat_struct
|
|||
|
: pat_fields { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); }
|
|||
|
| pat_fields ',' { $$ = mk_node("PatStruct", 2, $1, mk_atom("false")); }
|
|||
|
| pat_fields ',' DOTDOT { $$ = mk_node("PatStruct", 2, $1, mk_atom("true")); }
|
|||
|
| DOTDOT { $$ = mk_node("PatStruct", 1, mk_atom("true")); }
|
|||
|
;
|
|||
|
|
|||
|
pat_tup
|
|||
|
: pat { $$ = mk_node("pat_tup", 1, $1); }
|
|||
|
| pat_tup ',' pat { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
pat_vec
|
|||
|
: pat_vec_elts { $$ = mk_node("PatVec", 2, $1, mk_none()); }
|
|||
|
| pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, mk_none()); }
|
|||
|
| pat_vec_elts DOTDOT { $$ = mk_node("PatVec", 2, $1, mk_none()); }
|
|||
|
| pat_vec_elts ',' DOTDOT { $$ = mk_node("PatVec", 2, $1, mk_none()); }
|
|||
|
| pat_vec_elts DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, $1, $4); }
|
|||
|
| pat_vec_elts DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, $4); }
|
|||
|
| pat_vec_elts ',' DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, $1, $5); }
|
|||
|
| pat_vec_elts ',' DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, $1, $5); }
|
|||
|
| DOTDOT ',' pat_vec_elts { $$ = mk_node("PatVec", 2, mk_none(), $3); }
|
|||
|
| DOTDOT ',' pat_vec_elts ',' { $$ = mk_node("PatVec", 2, mk_none(), $3); }
|
|||
|
| DOTDOT { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); }
|
|||
|
| %empty { $$ = mk_node("PatVec", 2, mk_none(), mk_none()); }
|
|||
|
;
|
|||
|
|
|||
|
pat_vec_elts
|
|||
|
: pat { $$ = mk_node("PatVecElts", 1, $1); }
|
|||
|
| pat_vec_elts ',' pat { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////
|
|||
|
// Part 3: Types
|
|||
|
////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
ty
|
|||
|
: ty_prim
|
|||
|
| ty_closure
|
|||
|
| '<' ty_sum AS trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, $2, $4, $7); }
|
|||
|
| SHL ty_sum AS trait_ref '>' MOD_SEP ident AS trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, mk_node("TyQualifiedPath", 3, $2, $4, $7), $9, $12); }
|
|||
|
| '(' ty_sums ')' { $$ = mk_node("TyTup", 1, $2); }
|
|||
|
| '(' ty_sums ',' ')' { $$ = mk_node("TyTup", 1, $2); }
|
|||
|
| '(' ')' { $$ = mk_atom("TyNil"); }
|
|||
|
;
|
|||
|
|
|||
|
ty_prim
|
|||
|
: %prec IDENT path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("false")), $1); }
|
|||
|
| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("global", 1, mk_atom("true")), $2); }
|
|||
|
| %prec IDENT SELF MOD_SEP path_generic_args_without_colons { $$ = mk_node("TyPath", 2, mk_node("self", 1, mk_atom("true")), $3); }
|
|||
|
| BOX ty { $$ = mk_node("TyBox", 1, $2); }
|
|||
|
| '*' maybe_mut_or_const ty { $$ = mk_node("TyPtr", 2, $2, $3); }
|
|||
|
| '&' ty { $$ = mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2); }
|
|||
|
| '&' MUT ty { $$ = mk_node("TyRptr", 2, mk_atom("MutMutable"), $3); }
|
|||
|
| ANDAND ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutImmutable"), $2)); }
|
|||
|
| ANDAND MUT ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 2, mk_atom("MutMutable"), $3)); }
|
|||
|
| '&' lifetime maybe_mut ty { $$ = mk_node("TyRptr", 3, $2, $3, $4); }
|
|||
|
| ANDAND lifetime maybe_mut ty { $$ = mk_node("TyRptr", 1, mk_node("TyRptr", 3, $2, $3, $4)); }
|
|||
|
| '[' ty ']' { $$ = mk_node("TyVec", 1, $2); }
|
|||
|
| '[' ty ',' DOTDOT expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $5); }
|
|||
|
| '[' ty ';' expr ']' { $$ = mk_node("TyFixedLengthVec", 2, $2, $4); }
|
|||
|
| TYPEOF '(' expr ')' { $$ = mk_node("TyTypeof", 1, $3); }
|
|||
|
| UNDERSCORE { $$ = mk_atom("TyInfer"); }
|
|||
|
| ty_bare_fn
|
|||
|
| ty_proc
|
|||
|
| for_in_type
|
|||
|
;
|
|||
|
|
|||
|
ty_bare_fn
|
|||
|
: FN ty_fn_decl { $$ = $2; }
|
|||
|
| UNSAFE FN ty_fn_decl { $$ = $3; }
|
|||
|
| EXTERN maybe_abi FN ty_fn_decl { $$ = $4; }
|
|||
|
| UNSAFE EXTERN maybe_abi FN ty_fn_decl { $$ = $5; }
|
|||
|
;
|
|||
|
|
|||
|
ty_fn_decl
|
|||
|
: generic_params fn_anon_params ret_ty { $$ = mk_node("TyFnDecl", 3, $1, $2, $3); }
|
|||
|
;
|
|||
|
|
|||
|
ty_closure
|
|||
|
: UNSAFE '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $3, $5, $6); }
|
|||
|
| '|' anon_params '|' maybe_bounds ret_ty { $$ = mk_node("TyClosure", 3, $2, $4, $5); }
|
|||
|
| UNSAFE OROR maybe_bounds ret_ty { $$ = mk_node("TyClosure", 2, $3, $4); }
|
|||
|
| OROR maybe_bounds ret_ty { $$ = mk_node("TyClosure", 2, $2, $3); }
|
|||
|
;
|
|||
|
|
|||
|
ty_proc
|
|||
|
: PROC generic_params fn_params maybe_bounds ret_ty { $$ = mk_node("TyProc", 4, $2, $3, $4, $5); }
|
|||
|
;
|
|||
|
|
|||
|
for_in_type
|
|||
|
: FOR '<' maybe_lifetimes '>' for_in_type_suffix { $$ = mk_node("ForInType", 2, $3, $5); }
|
|||
|
;
|
|||
|
|
|||
|
for_in_type_suffix
|
|||
|
: ty_proc
|
|||
|
| ty_bare_fn
|
|||
|
| trait_ref
|
|||
|
| ty_closure
|
|||
|
;
|
|||
|
|
|||
|
maybe_mut
|
|||
|
: MUT { $$ = mk_atom("MutMutable"); }
|
|||
|
| %prec MUT %empty { $$ = mk_atom("MutImmutable"); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_mut_or_const
|
|||
|
: MUT { $$ = mk_atom("MutMutable"); }
|
|||
|
| CONST { $$ = mk_atom("MutImmutable"); }
|
|||
|
| %empty { $$ = mk_atom("MutImmutable"); }
|
|||
|
;
|
|||
|
|
|||
|
ty_qualified_path_and_generic_values
|
|||
|
: ty_qualified_path maybe_bindings
|
|||
|
{
|
|||
|
$$ = mk_node("GenericValues", 3, mk_none(), mk_node("TySums", 1, mk_node("TySum", 1, $1)), $2);
|
|||
|
}
|
|||
|
| ty_qualified_path ',' ty_sums maybe_bindings
|
|||
|
{
|
|||
|
$$ = mk_node("GenericValues", 3, mk_none(), ext_node(mk_node("TySums", 1, $1), 1, $3), $4); }
|
|||
|
;
|
|||
|
|
|||
|
ty_qualified_path
|
|||
|
: ty_sum AS trait_ref '>' MOD_SEP ident { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); }
|
|||
|
| ty_sum AS trait_ref '>' MOD_SEP ident '+' ty_param_bounds { $$ = mk_node("TyQualifiedPath", 3, $1, $3, $6); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_ty_sums
|
|||
|
: ty_sums
|
|||
|
| ty_sums ','
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
ty_sums
|
|||
|
: ty_sum { $$ = mk_node("TySums", 1, $1); }
|
|||
|
| ty_sums ',' ty_sum { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
ty_sum
|
|||
|
: ty { $$ = mk_node("TySum", 1, $1); }
|
|||
|
| ty '+' ty_param_bounds { $$ = mk_node("TySum", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
ty_prim_sum
|
|||
|
: ty_prim { $$ = mk_node("TySum", 1, $1); }
|
|||
|
| ty_prim '+' ty_param_bounds { $$ = mk_node("TySum", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_ty_param_bounds
|
|||
|
: ':' ty_param_bounds { $$ = $2; }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
ty_param_bounds
|
|||
|
: boundseq
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
boundseq
|
|||
|
: polybound
|
|||
|
| boundseq '+' polybound { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
polybound
|
|||
|
: FOR '<' maybe_lifetimes '>' bound { $$ = mk_node("PolyBound", 2, $3, $5); }
|
|||
|
| bound
|
|||
|
| '?' bound { $$ = $2; }
|
|||
|
;
|
|||
|
|
|||
|
bindings
|
|||
|
: binding { $$ = mk_node("Bindings", 1, $1); }
|
|||
|
| bindings ',' binding { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
binding
|
|||
|
: ident '=' ty { mk_node("Binding", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
ty_param
|
|||
|
: ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node("TyParam", 3, $1, $2, $3); }
|
|||
|
| ident '?' ident maybe_ty_param_bounds maybe_ty_default { $$ = mk_node("TyParam", 4, $1, $3, $4, $5); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_bounds
|
|||
|
: %prec SHIFTPLUS
|
|||
|
':' bounds { $$ = $2; }
|
|||
|
| %prec SHIFTPLUS %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
bounds
|
|||
|
: bound { $$ = mk_node("bounds", 1, $1); }
|
|||
|
| bounds '+' bound { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
bound
|
|||
|
: lifetime
|
|||
|
| trait_ref
|
|||
|
;
|
|||
|
|
|||
|
maybe_ltbounds
|
|||
|
: %prec SHIFTPLUS
|
|||
|
':' ltbounds { $$ = $2; }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
ltbounds
|
|||
|
: lifetime { $$ = mk_node("ltbounds", 1, $1); }
|
|||
|
| ltbounds '+' lifetime { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_ty_default
|
|||
|
: '=' ty_sum { $$ = mk_node("TyDefault", 1, $2); }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_lifetimes
|
|||
|
: lifetimes
|
|||
|
| lifetimes ','
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
lifetimes
|
|||
|
: lifetime_and_bounds { $$ = mk_node("Lifetimes", 1, $1); }
|
|||
|
| lifetimes ',' lifetime_and_bounds { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
lifetime_and_bounds
|
|||
|
: LIFETIME maybe_ltbounds { $$ = mk_node("lifetime", 2, mk_atom(yytext), $2); }
|
|||
|
| STATIC_LIFETIME { $$ = mk_atom("static_lifetime"); }
|
|||
|
;
|
|||
|
|
|||
|
lifetime
|
|||
|
: LIFETIME { $$ = mk_node("lifetime", 1, mk_atom(yytext)); }
|
|||
|
| STATIC_LIFETIME { $$ = mk_atom("static_lifetime"); }
|
|||
|
;
|
|||
|
|
|||
|
trait_ref
|
|||
|
: %prec IDENT path_generic_args_without_colons
|
|||
|
| %prec IDENT MOD_SEP path_generic_args_without_colons { $$ = $2; }
|
|||
|
;
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////
|
|||
|
// Part 4: Blocks, statements, and expressions
|
|||
|
////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
inner_attrs_and_block
|
|||
|
: '{' maybe_inner_attrs maybe_stmts '}' { $$ = mk_node("ExprBlock", 2, $2, $3); }
|
|||
|
;
|
|||
|
|
|||
|
block
|
|||
|
: '{' maybe_stmts '}' { $$ = mk_node("ExprBlock", 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_stmts
|
|||
|
: stmts
|
|||
|
| stmts nonblock_expr { $$ = ext_node($1, 1, $2); }
|
|||
|
| nonblock_expr
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
// There are two sub-grammars within a "stmts: exprs" derivation
|
|||
|
// depending on whether each stmt-expr is a block-expr form; this is to
|
|||
|
// handle the "semicolon rule" for stmt sequencing that permits
|
|||
|
// writing
|
|||
|
//
|
|||
|
// if foo { bar } 10
|
|||
|
//
|
|||
|
// as a sequence of two stmts (one if-expr stmt, one lit-10-expr
|
|||
|
// stmt). Unfortunately by permitting juxtaposition of exprs in
|
|||
|
// sequence like that, the non-block expr grammar has to have a
|
|||
|
// second limited sub-grammar that excludes the prefix exprs that
|
|||
|
// are ambiguous with binops. That is to say:
|
|||
|
//
|
|||
|
// {10} - 1
|
|||
|
//
|
|||
|
// should parse as (progn (progn 10) (- 1)) not (- (progn 10) 1), that
|
|||
|
// is to say, two statements rather than one, at least according to
|
|||
|
// the mainline rust parser.
|
|||
|
//
|
|||
|
// So we wind up with a 3-way split in exprs that occur in stmt lists:
|
|||
|
// block, nonblock-prefix, and nonblock-nonprefix.
|
|||
|
//
|
|||
|
// In non-stmts contexts, expr can relax this trichotomy.
|
|||
|
//
|
|||
|
// There are also two other expr subtypes: first, nonparen_expr
|
|||
|
// disallows exprs surrounded by parens (including tuple expressions),
|
|||
|
// this is neccesary for BOX (place) expressions, so a parens expr
|
|||
|
// following the BOX is always parsed as the place. There is also
|
|||
|
// expr_norange used in index_expr, which disallows '..' in
|
|||
|
// expressions as that has special meaning inside of brackets.
|
|||
|
|
|||
|
stmts
|
|||
|
: stmt { $$ = mk_node("stmts", 1, $1); }
|
|||
|
| stmts stmt { $$ = ext_node($1, 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
stmt
|
|||
|
: let
|
|||
|
| stmt_item
|
|||
|
| PUB stmt_item { $$ = $2; }
|
|||
|
| outer_attrs stmt_item { $$ = $2; }
|
|||
|
| outer_attrs PUB stmt_item { $$ = $3; }
|
|||
|
| full_block_expr
|
|||
|
| block
|
|||
|
| nonblock_expr ';'
|
|||
|
| ';' { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_exprs
|
|||
|
: exprs
|
|||
|
| exprs ','
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_expr
|
|||
|
: expr
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
exprs
|
|||
|
: expr { $$ = mk_node("exprs", 1, $1); }
|
|||
|
| exprs ',' expr { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
path_expr
|
|||
|
: path_generic_args_with_colons
|
|||
|
| MOD_SEP path_generic_args_with_colons { $$ = $2; }
|
|||
|
| SELF MOD_SEP path_generic_args_with_colons { $$ = mk_node("SelfPath", 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
// A path with a lifetime and type parameters with double colons before
|
|||
|
// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>`
|
|||
|
//
|
|||
|
// These show up in expr context, in order to disambiguate from "less-than"
|
|||
|
// expressions.
|
|||
|
path_generic_args_with_colons
|
|||
|
: ident { $$ = mk_node("components", 1, $1); }
|
|||
|
| path_generic_args_with_colons MOD_SEP ident { $$ = ext_node($1, 1, $3); }
|
|||
|
| path_generic_args_with_colons MOD_SEP generic_args { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
// the braces-delimited macro is a block_expr so it doesn't appear here
|
|||
|
macro_expr
|
|||
|
: path_expr '!' maybe_ident parens_delimited_token_trees { $$ = mk_node("MacroExpr", 3, $1, $3, $4); }
|
|||
|
| path_expr '!' maybe_ident brackets_delimited_token_trees { $$ = mk_node("MacroExpr", 3, $1, $3, $4); }
|
|||
|
;
|
|||
|
|
|||
|
nonblock_expr
|
|||
|
: lit { $$ = mk_node("ExprLit", 1, $1); }
|
|||
|
| %prec IDENT
|
|||
|
path_expr { $$ = mk_node("ExprPath", 1, $1); }
|
|||
|
| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
|
|||
|
| macro_expr { $$ = mk_node("ExprMac", 1, $1); }
|
|||
|
| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); }
|
|||
|
| nonblock_expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); }
|
|||
|
| nonblock_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); }
|
|||
|
| nonblock_expr '[' index_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); }
|
|||
|
| nonblock_expr '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); }
|
|||
|
| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); }
|
|||
|
| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); }
|
|||
|
| CONTINUE { $$ = mk_node("ExprAgain", 0); }
|
|||
|
| CONTINUE lifetime { $$ = mk_node("ExprAgain", 1, $2); }
|
|||
|
| RETURN { $$ = mk_node("ExprRet", 0); }
|
|||
|
| RETURN expr { $$ = mk_node("ExprRet", 1, $2); }
|
|||
|
| BREAK { $$ = mk_node("ExprBreak", 0); }
|
|||
|
| BREAK lifetime { $$ = mk_node("ExprBreak", 1, $2); }
|
|||
|
| nonblock_expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); }
|
|||
|
| nonblock_expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
|
|||
|
| nonblock_expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
|
|||
|
| nonblock_expr MINUSEQ expr { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
|
|||
|
| nonblock_expr ANDEQ expr { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
|
|||
|
| nonblock_expr OREQ expr { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
|
|||
|
| nonblock_expr PLUSEQ expr { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
|
|||
|
| nonblock_expr STAREQ expr { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
|
|||
|
| nonblock_expr SLASHEQ expr { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
|
|||
|
| nonblock_expr CARETEQ expr { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
|
|||
|
| nonblock_expr PERCENTEQ expr { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
|
|||
|
| nonblock_expr OROR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
|
|||
|
| nonblock_expr ANDAND expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
|
|||
|
| nonblock_expr EQEQ expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
|
|||
|
| nonblock_expr NE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
|
|||
|
| nonblock_expr '<' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
|
|||
|
| nonblock_expr '>' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
|
|||
|
| nonblock_expr LE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
|
|||
|
| nonblock_expr GE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
|
|||
|
| nonblock_expr '|' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
|
|||
|
| nonblock_expr '^' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
|
|||
|
| nonblock_expr '&' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
|
|||
|
| nonblock_expr SHL expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
|
|||
|
| nonblock_expr SHR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
|
|||
|
| nonblock_expr '+' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
|
|||
|
| nonblock_expr '-' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
|
|||
|
| nonblock_expr '*' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
|
|||
|
| nonblock_expr '/' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
|
|||
|
| nonblock_expr '%' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
|
|||
|
| nonblock_expr DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
|
|||
|
| nonblock_expr DOTDOT expr { $$ = mk_node("ExprRange", 2, $1, $3); }
|
|||
|
| DOTDOT expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
|
|||
|
| nonblock_expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); }
|
|||
|
| BOX nonparen_expr { $$ = mk_node("ExprBox", 1, $2); }
|
|||
|
| %prec BOXPLACE BOX '(' maybe_expr ')' nonblock_expr { $$ = mk_node("ExprBox", 2, $3, $5); }
|
|||
|
| nonblock_prefix_expr
|
|||
|
;
|
|||
|
|
|||
|
expr
|
|||
|
: lit { $$ = mk_node("ExprLit", 1, $1); }
|
|||
|
| %prec IDENT
|
|||
|
path_expr { $$ = mk_node("ExprPath", 1, $1); }
|
|||
|
| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
|
|||
|
| macro_expr { $$ = mk_node("ExprMac", 1, $1); }
|
|||
|
| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); }
|
|||
|
| expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); }
|
|||
|
| expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); }
|
|||
|
| expr '[' index_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); }
|
|||
|
| expr '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); }
|
|||
|
| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); }
|
|||
|
| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); }
|
|||
|
| CONTINUE { $$ = mk_node("ExprAgain", 0); }
|
|||
|
| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); }
|
|||
|
| RETURN { $$ = mk_node("ExprRet", 0); }
|
|||
|
| RETURN expr { $$ = mk_node("ExprRet", 1, $2); }
|
|||
|
| BREAK { $$ = mk_node("ExprBreak", 0); }
|
|||
|
| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); }
|
|||
|
| expr '=' expr { $$ = mk_node("ExprAssign", 2, $1, $3); }
|
|||
|
| expr SHLEQ expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
|
|||
|
| expr SHREQ expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
|
|||
|
| expr MINUSEQ expr { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
|
|||
|
| expr ANDEQ expr { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
|
|||
|
| expr OREQ expr { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
|
|||
|
| expr PLUSEQ expr { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
|
|||
|
| expr STAREQ expr { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
|
|||
|
| expr SLASHEQ expr { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
|
|||
|
| expr CARETEQ expr { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
|
|||
|
| expr PERCENTEQ expr { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
|
|||
|
| expr OROR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
|
|||
|
| expr ANDAND expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
|
|||
|
| expr EQEQ expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
|
|||
|
| expr NE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
|
|||
|
| expr '<' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
|
|||
|
| expr '>' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
|
|||
|
| expr LE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
|
|||
|
| expr GE expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
|
|||
|
| expr '|' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
|
|||
|
| expr '^' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
|
|||
|
| expr '&' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
|
|||
|
| expr SHL expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
|
|||
|
| expr SHR expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
|
|||
|
| expr '+' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
|
|||
|
| expr '-' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
|
|||
|
| expr '*' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
|
|||
|
| expr '/' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
|
|||
|
| expr '%' expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
|
|||
|
| expr DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
|
|||
|
| expr DOTDOT expr { $$ = mk_node("ExprRange", 2, $1, $3); }
|
|||
|
| DOTDOT expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
|
|||
|
| expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); }
|
|||
|
| BOX nonparen_expr { $$ = mk_node("ExprBox", 1, $2); }
|
|||
|
| %prec BOXPLACE BOX '(' maybe_expr ')' expr { $$ = mk_node("ExprBox", 2, $3, $5); }
|
|||
|
| block_expr
|
|||
|
| block
|
|||
|
| nonblock_prefix_expr
|
|||
|
;
|
|||
|
|
|||
|
nonparen_expr
|
|||
|
: lit { $$ = mk_node("ExprLit", 1, $1); }
|
|||
|
| %prec IDENT
|
|||
|
path_expr { $$ = mk_node("ExprPath", 1, $1); }
|
|||
|
| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
|
|||
|
| macro_expr { $$ = mk_node("ExprMac", 1, $1); }
|
|||
|
| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); }
|
|||
|
| nonparen_expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); }
|
|||
|
| nonparen_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); }
|
|||
|
| nonparen_expr '[' index_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); }
|
|||
|
| nonparen_expr '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); }
|
|||
|
| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); }
|
|||
|
| CONTINUE { $$ = mk_node("ExprAgain", 0); }
|
|||
|
| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); }
|
|||
|
| RETURN { $$ = mk_node("ExprRet", 0); }
|
|||
|
| RETURN expr { $$ = mk_node("ExprRet", 1, $2); }
|
|||
|
| BREAK { $$ = mk_node("ExprBreak", 0); }
|
|||
|
| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); }
|
|||
|
| nonparen_expr '=' nonparen_expr { $$ = mk_node("ExprAssign", 2, $1, $3); }
|
|||
|
| nonparen_expr SHLEQ nonparen_expr { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
|
|||
|
| nonparen_expr SHREQ nonparen_expr { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
|
|||
|
| nonparen_expr MINUSEQ nonparen_expr { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
|
|||
|
| nonparen_expr ANDEQ nonparen_expr { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
|
|||
|
| nonparen_expr OREQ nonparen_expr { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
|
|||
|
| nonparen_expr PLUSEQ nonparen_expr { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
|
|||
|
| nonparen_expr STAREQ nonparen_expr { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
|
|||
|
| nonparen_expr SLASHEQ nonparen_expr { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
|
|||
|
| nonparen_expr CARETEQ nonparen_expr { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
|
|||
|
| nonparen_expr PERCENTEQ nonparen_expr { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
|
|||
|
| nonparen_expr OROR nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
|
|||
|
| nonparen_expr ANDAND nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
|
|||
|
| nonparen_expr EQEQ nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
|
|||
|
| nonparen_expr NE nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
|
|||
|
| nonparen_expr '<' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
|
|||
|
| nonparen_expr '>' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
|
|||
|
| nonparen_expr LE nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
|
|||
|
| nonparen_expr GE nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
|
|||
|
| nonparen_expr '|' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
|
|||
|
| nonparen_expr '^' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
|
|||
|
| nonparen_expr '&' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
|
|||
|
| nonparen_expr SHL nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
|
|||
|
| nonparen_expr SHR nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
|
|||
|
| nonparen_expr '+' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
|
|||
|
| nonparen_expr '-' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
|
|||
|
| nonparen_expr '*' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
|
|||
|
| nonparen_expr '/' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
|
|||
|
| nonparen_expr '%' nonparen_expr { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
|
|||
|
| nonparen_expr DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
|
|||
|
| nonparen_expr DOTDOT nonparen_expr { $$ = mk_node("ExprRange", 2, $1, $3); }
|
|||
|
| DOTDOT nonparen_expr { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
|
|||
|
| nonparen_expr AS ty { $$ = mk_node("ExprCast", 2, $1, $3); }
|
|||
|
| BOX nonparen_expr { $$ = mk_node("ExprBox", 1, $2); }
|
|||
|
| %prec BOXPLACE BOX '(' maybe_expr ')' expr { $$ = mk_node("ExprBox", 1, $3, $5); }
|
|||
|
| block_expr
|
|||
|
| block
|
|||
|
| nonblock_prefix_expr
|
|||
|
;
|
|||
|
|
|||
|
expr_norange
|
|||
|
: lit { $$ = mk_node("ExprLit", 1, $1); }
|
|||
|
| %prec IDENT
|
|||
|
path_expr { $$ = mk_node("ExprPath", 1, $1); }
|
|||
|
| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
|
|||
|
| macro_expr { $$ = mk_node("ExprMac", 1, $1); }
|
|||
|
| path_expr '{' struct_expr_fields '}' { $$ = mk_node("ExprStruct", 2, $1, $3); }
|
|||
|
| expr_norange '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); }
|
|||
|
| expr_norange '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); }
|
|||
|
| expr_norange '[' index_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); }
|
|||
|
| expr_norange '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); }
|
|||
|
| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); }
|
|||
|
| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); }
|
|||
|
| CONTINUE { $$ = mk_node("ExprAgain", 0); }
|
|||
|
| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); }
|
|||
|
| RETURN { $$ = mk_node("ExprRet", 0); }
|
|||
|
| RETURN expr { $$ = mk_node("ExprRet", 1, $2); }
|
|||
|
| BREAK { $$ = mk_node("ExprBreak", 0); }
|
|||
|
| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); }
|
|||
|
| expr_norange '=' expr_norange { $$ = mk_node("ExprAssign", 2, $1, $3); }
|
|||
|
| expr_norange SHLEQ expr_norange { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
|
|||
|
| expr_norange SHREQ expr_norange { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
|
|||
|
| expr_norange MINUSEQ expr_norange { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
|
|||
|
| expr_norange ANDEQ expr_norange { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
|
|||
|
| expr_norange OREQ expr_norange { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
|
|||
|
| expr_norange PLUSEQ expr_norange { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
|
|||
|
| expr_norange STAREQ expr_norange { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
|
|||
|
| expr_norange SLASHEQ expr_norange { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
|
|||
|
| expr_norange CARETEQ expr_norange { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
|
|||
|
| expr_norange PERCENTEQ expr_norange { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
|
|||
|
| expr_norange OROR expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
|
|||
|
| expr_norange ANDAND expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
|
|||
|
| expr_norange EQEQ expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
|
|||
|
| expr_norange NE expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
|
|||
|
| expr_norange '<' expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
|
|||
|
| expr_norange '>' expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
|
|||
|
| expr_norange LE expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
|
|||
|
| expr_norange GE expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
|
|||
|
| expr_norange '|' expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
|
|||
|
| expr_norange '^' expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
|
|||
|
| expr_norange '&' expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
|
|||
|
| expr_norange SHL expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
|
|||
|
| expr_norange SHR expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
|
|||
|
| expr_norange '+' expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
|
|||
|
| expr_norange '-' expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
|
|||
|
| expr_norange '*' expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
|
|||
|
| expr_norange '/' expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
|
|||
|
| expr_norange '%' expr_norange { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
|
|||
|
| expr_norange AS ty { $$ = mk_node("Expr_NorangeCast", 2, $1, $3); }
|
|||
|
| BOX nonparen_expr { $$ = mk_node("ExprBox", 1, $2); }
|
|||
|
| %prec BOXPLACE BOX '(' maybe_expr ')' expr_norange { $$ = mk_node("ExprBox", 2, $3, $5); }
|
|||
|
| block_expr
|
|||
|
| block
|
|||
|
| nonblock_prefix_expr
|
|||
|
;
|
|||
|
|
|||
|
expr_nostruct
|
|||
|
: lit { $$ = mk_node("ExprLit", 1, $1); }
|
|||
|
| %prec IDENT
|
|||
|
path_expr { $$ = mk_node("ExprPath", 1, $1); }
|
|||
|
| SELF { $$ = mk_node("ExprPath", 1, mk_node("ident", 1, mk_atom("self"))); }
|
|||
|
| macro_expr { $$ = mk_node("ExprMac", 1, $1); }
|
|||
|
| expr_nostruct '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); }
|
|||
|
| expr_nostruct '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); }
|
|||
|
| expr_nostruct '[' index_expr ']' { $$ = mk_node("ExprIndex", 2, $1, $3); }
|
|||
|
| expr_nostruct '(' maybe_exprs ')' { $$ = mk_node("ExprCall", 2, $1, $3); }
|
|||
|
| '[' vec_expr ']' { $$ = mk_node("ExprVec", 1, $2); }
|
|||
|
| '(' maybe_exprs ')' { $$ = mk_node("ExprParen", 1, $2); }
|
|||
|
| CONTINUE { $$ = mk_node("ExprAgain", 0); }
|
|||
|
| CONTINUE ident { $$ = mk_node("ExprAgain", 1, $2); }
|
|||
|
| RETURN { $$ = mk_node("ExprRet", 0); }
|
|||
|
| RETURN expr { $$ = mk_node("ExprRet", 1, $2); }
|
|||
|
| BREAK { $$ = mk_node("ExprBreak", 0); }
|
|||
|
| BREAK ident { $$ = mk_node("ExprBreak", 1, $2); }
|
|||
|
| expr_nostruct '=' expr_nostruct { $$ = mk_node("ExprAssign", 2, $1, $3); }
|
|||
|
| expr_nostruct SHLEQ expr_nostruct { $$ = mk_node("ExprAssignShl", 2, $1, $3); }
|
|||
|
| expr_nostruct SHREQ expr_nostruct { $$ = mk_node("ExprAssignShr", 2, $1, $3); }
|
|||
|
| expr_nostruct MINUSEQ expr_nostruct { $$ = mk_node("ExprAssignSub", 2, $1, $3); }
|
|||
|
| expr_nostruct ANDEQ expr_nostruct { $$ = mk_node("ExprAssignBitAnd", 2, $1, $3); }
|
|||
|
| expr_nostruct OREQ expr_nostruct { $$ = mk_node("ExprAssignBitOr", 2, $1, $3); }
|
|||
|
| expr_nostruct PLUSEQ expr_nostruct { $$ = mk_node("ExprAssignAdd", 2, $1, $3); }
|
|||
|
| expr_nostruct STAREQ expr_nostruct { $$ = mk_node("ExprAssignMul", 2, $1, $3); }
|
|||
|
| expr_nostruct SLASHEQ expr_nostruct { $$ = mk_node("ExprAssignDiv", 2, $1, $3); }
|
|||
|
| expr_nostruct CARETEQ expr_nostruct { $$ = mk_node("ExprAssignBitXor", 2, $1, $3); }
|
|||
|
| expr_nostruct PERCENTEQ expr_nostruct { $$ = mk_node("ExprAssignRem", 2, $1, $3); }
|
|||
|
| expr_nostruct OROR expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiOr"), $1, $3); }
|
|||
|
| expr_nostruct ANDAND expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiAnd"), $1, $3); }
|
|||
|
| expr_nostruct EQEQ expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiEq"), $1, $3); }
|
|||
|
| expr_nostruct NE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiNe"), $1, $3); }
|
|||
|
| expr_nostruct '<' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiLt"), $1, $3); }
|
|||
|
| expr_nostruct '>' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiGt"), $1, $3); }
|
|||
|
| expr_nostruct LE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiLe"), $1, $3); }
|
|||
|
| expr_nostruct GE expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiGe"), $1, $3); }
|
|||
|
| expr_nostruct '|' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitOr"), $1, $3); }
|
|||
|
| expr_nostruct '^' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitXor"), $1, $3); }
|
|||
|
| expr_nostruct '&' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiBitAnd"), $1, $3); }
|
|||
|
| expr_nostruct SHL expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiShl"), $1, $3); }
|
|||
|
| expr_nostruct SHR expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiShr"), $1, $3); }
|
|||
|
| expr_nostruct '+' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiAdd"), $1, $3); }
|
|||
|
| expr_nostruct '-' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiSub"), $1, $3); }
|
|||
|
| expr_nostruct '*' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiMul"), $1, $3); }
|
|||
|
| expr_nostruct '/' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiDiv"), $1, $3); }
|
|||
|
| expr_nostruct '%' expr_nostruct { $$ = mk_node("ExprBinary", 3, mk_atom("BiRem"), $1, $3); }
|
|||
|
| expr_nostruct DOTDOT { $$ = mk_node("ExprRange", 2, $1, mk_none()); }
|
|||
|
| expr_nostruct DOTDOT expr_nostruct { $$ = mk_node("ExprRange", 2, $1, $3); }
|
|||
|
| DOTDOT expr_nostruct { $$ = mk_node("ExprRange", 2, mk_none(), $2); }
|
|||
|
| expr_nostruct AS ty { $$ = mk_node("ExprCast", 2, $1, $3); }
|
|||
|
| BOX nonparen_expr { $$ = mk_node("ExprBox", 1, $2); }
|
|||
|
| %prec BOXPLACE BOX '(' maybe_expr ')' expr_nostruct { $$ = mk_node("ExprBox", 1, $3, $5); }
|
|||
|
| block_expr
|
|||
|
| block
|
|||
|
| nonblock_prefix_expr_nostruct
|
|||
|
;
|
|||
|
|
|||
|
nonblock_prefix_expr_nostruct
|
|||
|
: '-' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); }
|
|||
|
| '!' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); }
|
|||
|
| '*' expr_nostruct { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); }
|
|||
|
| '&' maybe_mut expr_nostruct { $$ = mk_node("ExprAddrOf", 2, $2, $3); }
|
|||
|
| ANDAND maybe_mut expr_nostruct { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); }
|
|||
|
| lambda_expr_nostruct
|
|||
|
| MOVE lambda_expr_nostruct { $$ = $2; }
|
|||
|
| proc_expr_nostruct
|
|||
|
;
|
|||
|
|
|||
|
nonblock_prefix_expr
|
|||
|
: '-' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnNeg"), $2); }
|
|||
|
| '!' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnNot"), $2); }
|
|||
|
| '*' expr { $$ = mk_node("ExprUnary", 2, mk_atom("UnDeref"), $2); }
|
|||
|
| '&' maybe_mut expr { $$ = mk_node("ExprAddrOf", 2, $2, $3); }
|
|||
|
| ANDAND maybe_mut expr { $$ = mk_node("ExprAddrOf", 1, mk_node("ExprAddrOf", 2, $2, $3)); }
|
|||
|
| lambda_expr
|
|||
|
| MOVE lambda_expr { $$ = $2; }
|
|||
|
| proc_expr
|
|||
|
;
|
|||
|
|
|||
|
lambda_expr
|
|||
|
: %prec LAMBDA
|
|||
|
OROR ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $2, $3); }
|
|||
|
| %prec LAMBDA
|
|||
|
'|' maybe_unboxed_closure_kind '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, mk_none(), $4, $5); }
|
|||
|
| %prec LAMBDA
|
|||
|
'|' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $2, $4, $5); }
|
|||
|
| %prec LAMBDA
|
|||
|
'|' '&' maybe_mut ':' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $5, $7, $8); }
|
|||
|
| %prec LAMBDA
|
|||
|
'|' ':' inferrable_params '|' ret_ty expr { $$ = mk_node("ExprFnBlock", 3, $3, $5, $6); }
|
|||
|
;
|
|||
|
|
|||
|
lambda_expr_nostruct
|
|||
|
: %prec LAMBDA
|
|||
|
OROR expr_nostruct { $$ = mk_node("ExprFnBlock", 2, mk_none(), $2); }
|
|||
|
| %prec LAMBDA
|
|||
|
'|' maybe_unboxed_closure_kind '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, mk_none(), $4); }
|
|||
|
| %prec LAMBDA
|
|||
|
'|' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $2, $4); }
|
|||
|
| %prec LAMBDA
|
|||
|
'|' '&' maybe_mut ':' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $5, $7); }
|
|||
|
| %prec LAMBDA
|
|||
|
'|' ':' inferrable_params '|' expr_nostruct { $$ = mk_node("ExprFnBlock", 2, $3, $5); }
|
|||
|
|
|||
|
;
|
|||
|
|
|||
|
proc_expr
|
|||
|
: %prec LAMBDA
|
|||
|
PROC '(' ')' expr { $$ = mk_node("ExprProc", 2, mk_none(), $4); }
|
|||
|
| %prec LAMBDA
|
|||
|
PROC '(' inferrable_params ')' expr { $$ = mk_node("ExprProc", 2, $3, $5); }
|
|||
|
;
|
|||
|
|
|||
|
proc_expr_nostruct
|
|||
|
: %prec LAMBDA
|
|||
|
PROC '(' ')' expr_nostruct { $$ = mk_node("ExprProc", 2, mk_none(), $4); }
|
|||
|
| %prec LAMBDA
|
|||
|
PROC '(' inferrable_params ')' expr_nostruct { $$ = mk_node("ExprProc", 2, $3, $5); }
|
|||
|
;
|
|||
|
|
|||
|
vec_expr
|
|||
|
: maybe_exprs
|
|||
|
| exprs ';' expr { $$ = mk_node("VecRepeat", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
index_expr
|
|||
|
: expr_norange { $$ = mk_node("Index", 1, $1); }
|
|||
|
| expr_norange DOTDOT { $$ = mk_node("SliceToEnd", 1, $1); }
|
|||
|
| DOTDOT expr_norange { $$ = mk_node("SliceFromBeginning", 1, $2); }
|
|||
|
| expr_norange DOTDOT expr_norange { $$ = mk_node("Slice", 2, $1, $3); }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
struct_expr_fields
|
|||
|
: field_inits
|
|||
|
| field_inits ','
|
|||
|
| maybe_field_inits default_field_init { $$ = ext_node($1, 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_field_inits
|
|||
|
: field_inits
|
|||
|
| field_inits ','
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
field_inits
|
|||
|
: field_init { $$ = mk_node("FieldInits", 1, $1); }
|
|||
|
| field_inits ',' field_init { $$ = ext_node($1, 1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
field_init
|
|||
|
: ident ':' expr { $$ = mk_node("FieldInit", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
default_field_init
|
|||
|
: DOTDOT expr { $$ = mk_node("DefaultFieldInit", 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
block_expr
|
|||
|
: expr_match
|
|||
|
| expr_if
|
|||
|
| expr_if_let
|
|||
|
| expr_while
|
|||
|
| expr_while_let
|
|||
|
| expr_loop
|
|||
|
| expr_for
|
|||
|
| UNSAFE block { $$ = mk_node("UnsafeBlock", 1, $2); }
|
|||
|
| path_expr '!' maybe_ident braces_delimited_token_trees { $$ = mk_node("Macro", 3, $1, $3, $4); }
|
|||
|
;
|
|||
|
|
|||
|
full_block_expr
|
|||
|
: block_expr
|
|||
|
| full_block_expr '.' path_generic_args_with_colons { $$ = mk_node("ExprField", 2, $1, $3); }
|
|||
|
| full_block_expr '.' LIT_INTEGER { $$ = mk_node("ExprTupleIndex", 1, $1); }
|
|||
|
;
|
|||
|
|
|||
|
expr_match
|
|||
|
: MATCH expr_nostruct '{' '}' { $$ = mk_node("ExprMatch", 1, $2); }
|
|||
|
| MATCH expr_nostruct '{' match_clauses '}' { $$ = mk_node("ExprMatch", 2, $2, $4); }
|
|||
|
| MATCH expr_nostruct '{' match_clauses nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, ext_node($4, 1, $5)); }
|
|||
|
| MATCH expr_nostruct '{' nonblock_match_clause '}' { $$ = mk_node("ExprMatch", 2, $2, mk_node("Arms", 1, $4)); }
|
|||
|
;
|
|||
|
|
|||
|
match_clauses
|
|||
|
: match_clause { $$ = mk_node("Arms", 1, $1); }
|
|||
|
| match_clauses match_clause { $$ = ext_node($1, 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
match_clause
|
|||
|
: nonblock_match_clause ','
|
|||
|
| block_match_clause
|
|||
|
| block_match_clause ','
|
|||
|
;
|
|||
|
|
|||
|
nonblock_match_clause
|
|||
|
: maybe_outer_attrs pats_or maybe_guard FAT_ARROW nonblock_expr { $$ = mk_node("Arm", 4, $1, $2, $3, $5); }
|
|||
|
| maybe_outer_attrs pats_or maybe_guard FAT_ARROW full_block_expr { $$ = mk_node("Arm", 4, $1, $2, $3, $5); }
|
|||
|
;
|
|||
|
|
|||
|
block_match_clause
|
|||
|
: maybe_outer_attrs pats_or maybe_guard FAT_ARROW block { $$ = mk_node("Arm", 4, $1, $2, $3, $5); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_guard
|
|||
|
: IF expr_nostruct { $$ = $2; }
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
expr_if
|
|||
|
: IF expr_nostruct block { $$ = mk_node("ExprIf", 2, $2, $3); }
|
|||
|
| IF expr_nostruct block ELSE block_or_if { $$ = mk_node("ExprIf", 3, $2, $3, $5); }
|
|||
|
;
|
|||
|
|
|||
|
expr_if_let
|
|||
|
: IF LET pat '=' expr_nostruct block { $$ = mk_node("ExprIfLet", 3, $3, $5, $6); }
|
|||
|
| IF LET pat '=' expr_nostruct block ELSE block_or_if { $$ = mk_node("ExprIfLet", 4, $3, $5, $6, $8); }
|
|||
|
;
|
|||
|
|
|||
|
block_or_if
|
|||
|
: block
|
|||
|
| expr_if
|
|||
|
| expr_if_let
|
|||
|
;
|
|||
|
|
|||
|
expr_while
|
|||
|
: maybe_label WHILE expr_nostruct block { $$ = mk_node("ExprWhile", 3, $1, $3, $4); }
|
|||
|
;
|
|||
|
|
|||
|
expr_while_let
|
|||
|
: maybe_label WHILE LET pat '=' expr_nostruct block { $$ = mk_node("ExprWhileLet", 4, $1, $4, $6, $7); }
|
|||
|
;
|
|||
|
|
|||
|
expr_loop
|
|||
|
: maybe_label LOOP block { $$ = mk_node("ExprLoop", 2, $1, $3); }
|
|||
|
;
|
|||
|
|
|||
|
expr_for
|
|||
|
: maybe_label FOR pat IN expr_nostruct block { $$ = mk_node("ExprForLoop", 4, $1, $3, $5, $6); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_label
|
|||
|
: lifetime ':'
|
|||
|
| %empty { $$ = mk_none(); }
|
|||
|
;
|
|||
|
|
|||
|
let
|
|||
|
: LET pat maybe_ty_ascription maybe_init_expr ';' { $$ = mk_node("DeclLocal", 3, $2, $3, $4); }
|
|||
|
;
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////
|
|||
|
// Part 5: Macros and misc. rules
|
|||
|
////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
lit
|
|||
|
: LIT_BYTE { $$ = mk_node("LitByte", 1, mk_atom(yytext)); }
|
|||
|
| LIT_CHAR { $$ = mk_node("LitChar", 1, mk_atom(yytext)); }
|
|||
|
| LIT_INTEGER { $$ = mk_node("LitInteger", 1, mk_atom(yytext)); }
|
|||
|
| LIT_FLOAT { $$ = mk_node("LitFloat", 1, mk_atom(yytext)); }
|
|||
|
| TRUE { $$ = mk_node("LitBool", 1, mk_atom(yytext)); }
|
|||
|
| FALSE { $$ = mk_node("LitBool", 1, mk_atom(yytext)); }
|
|||
|
| str
|
|||
|
;
|
|||
|
|
|||
|
str
|
|||
|
: LIT_STR { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("CookedStr")); }
|
|||
|
| LIT_STR_RAW { $$ = mk_node("LitStr", 1, mk_atom(yytext), mk_atom("RawStr")); }
|
|||
|
| LIT_BINARY { $$ = mk_node("LitBinary", 1, mk_atom(yytext), mk_atom("BinaryStr")); }
|
|||
|
| LIT_BINARY_RAW { $$ = mk_node("LitBinary", 1, mk_atom(yytext), mk_atom("RawBinaryStr")); }
|
|||
|
;
|
|||
|
|
|||
|
maybe_ident
|
|||
|
: %empty { $$ = mk_none(); }
|
|||
|
| ident
|
|||
|
;
|
|||
|
|
|||
|
ident
|
|||
|
: IDENT { $$ = mk_node("ident", 1, mk_atom(yytext)); }
|
|||
|
;
|
|||
|
|
|||
|
unpaired_token
|
|||
|
: SHL { $$ = mk_atom(yytext); }
|
|||
|
| SHR { $$ = mk_atom(yytext); }
|
|||
|
| LE { $$ = mk_atom(yytext); }
|
|||
|
| EQEQ { $$ = mk_atom(yytext); }
|
|||
|
| NE { $$ = mk_atom(yytext); }
|
|||
|
| GE { $$ = mk_atom(yytext); }
|
|||
|
| ANDAND { $$ = mk_atom(yytext); }
|
|||
|
| OROR { $$ = mk_atom(yytext); }
|
|||
|
| SHLEQ { $$ = mk_atom(yytext); }
|
|||
|
| SHREQ { $$ = mk_atom(yytext); }
|
|||
|
| MINUSEQ { $$ = mk_atom(yytext); }
|
|||
|
| ANDEQ { $$ = mk_atom(yytext); }
|
|||
|
| OREQ { $$ = mk_atom(yytext); }
|
|||
|
| PLUSEQ { $$ = mk_atom(yytext); }
|
|||
|
| STAREQ { $$ = mk_atom(yytext); }
|
|||
|
| SLASHEQ { $$ = mk_atom(yytext); }
|
|||
|
| CARETEQ { $$ = mk_atom(yytext); }
|
|||
|
| PERCENTEQ { $$ = mk_atom(yytext); }
|
|||
|
| DOTDOT { $$ = mk_atom(yytext); }
|
|||
|
| DOTDOTDOT { $$ = mk_atom(yytext); }
|
|||
|
| MOD_SEP { $$ = mk_atom(yytext); }
|
|||
|
| RARROW { $$ = mk_atom(yytext); }
|
|||
|
| FAT_ARROW { $$ = mk_atom(yytext); }
|
|||
|
| LIT_BYTE { $$ = mk_atom(yytext); }
|
|||
|
| LIT_CHAR { $$ = mk_atom(yytext); }
|
|||
|
| LIT_INTEGER { $$ = mk_atom(yytext); }
|
|||
|
| LIT_FLOAT { $$ = mk_atom(yytext); }
|
|||
|
| LIT_STR { $$ = mk_atom(yytext); }
|
|||
|
| LIT_STR_RAW { $$ = mk_atom(yytext); }
|
|||
|
| LIT_BINARY { $$ = mk_atom(yytext); }
|
|||
|
| LIT_BINARY_RAW { $$ = mk_atom(yytext); }
|
|||
|
| IDENT { $$ = mk_atom(yytext); }
|
|||
|
| UNDERSCORE { $$ = mk_atom(yytext); }
|
|||
|
| LIFETIME { $$ = mk_atom(yytext); }
|
|||
|
| SELF { $$ = mk_atom(yytext); }
|
|||
|
| STATIC { $$ = mk_atom(yytext); }
|
|||
|
| AS { $$ = mk_atom(yytext); }
|
|||
|
| BREAK { $$ = mk_atom(yytext); }
|
|||
|
| CRATE { $$ = mk_atom(yytext); }
|
|||
|
| ELSE { $$ = mk_atom(yytext); }
|
|||
|
| ENUM { $$ = mk_atom(yytext); }
|
|||
|
| EXTERN { $$ = mk_atom(yytext); }
|
|||
|
| FALSE { $$ = mk_atom(yytext); }
|
|||
|
| FN { $$ = mk_atom(yytext); }
|
|||
|
| FOR { $$ = mk_atom(yytext); }
|
|||
|
| IF { $$ = mk_atom(yytext); }
|
|||
|
| IMPL { $$ = mk_atom(yytext); }
|
|||
|
| IN { $$ = mk_atom(yytext); }
|
|||
|
| LET { $$ = mk_atom(yytext); }
|
|||
|
| LOOP { $$ = mk_atom(yytext); }
|
|||
|
| MATCH { $$ = mk_atom(yytext); }
|
|||
|
| MOD { $$ = mk_atom(yytext); }
|
|||
|
| MOVE { $$ = mk_atom(yytext); }
|
|||
|
| MUT { $$ = mk_atom(yytext); }
|
|||
|
| PRIV { $$ = mk_atom(yytext); }
|
|||
|
| PUB { $$ = mk_atom(yytext); }
|
|||
|
| REF { $$ = mk_atom(yytext); }
|
|||
|
| RETURN { $$ = mk_atom(yytext); }
|
|||
|
| STRUCT { $$ = mk_atom(yytext); }
|
|||
|
| TRUE { $$ = mk_atom(yytext); }
|
|||
|
| TRAIT { $$ = mk_atom(yytext); }
|
|||
|
| TYPE { $$ = mk_atom(yytext); }
|
|||
|
| UNSAFE { $$ = mk_atom(yytext); }
|
|||
|
| USE { $$ = mk_atom(yytext); }
|
|||
|
| WHILE { $$ = mk_atom(yytext); }
|
|||
|
| CONTINUE { $$ = mk_atom(yytext); }
|
|||
|
| PROC { $$ = mk_atom(yytext); }
|
|||
|
| BOX { $$ = mk_atom(yytext); }
|
|||
|
| CONST { $$ = mk_atom(yytext); }
|
|||
|
| WHERE { $$ = mk_atom(yytext); }
|
|||
|
| TYPEOF { $$ = mk_atom(yytext); }
|
|||
|
| INNER_DOC_COMMENT { $$ = mk_atom(yytext); }
|
|||
|
| OUTER_DOC_COMMENT { $$ = mk_atom(yytext); }
|
|||
|
| SHEBANG { $$ = mk_atom(yytext); }
|
|||
|
| STATIC_LIFETIME { $$ = mk_atom(yytext); }
|
|||
|
| ';' { $$ = mk_atom(yytext); }
|
|||
|
| ',' { $$ = mk_atom(yytext); }
|
|||
|
| '.' { $$ = mk_atom(yytext); }
|
|||
|
| '@' { $$ = mk_atom(yytext); }
|
|||
|
| '#' { $$ = mk_atom(yytext); }
|
|||
|
| '~' { $$ = mk_atom(yytext); }
|
|||
|
| ':' { $$ = mk_atom(yytext); }
|
|||
|
| '$' { $$ = mk_atom(yytext); }
|
|||
|
| '=' { $$ = mk_atom(yytext); }
|
|||
|
| '?' { $$ = mk_atom(yytext); }
|
|||
|
| '!' { $$ = mk_atom(yytext); }
|
|||
|
| '<' { $$ = mk_atom(yytext); }
|
|||
|
| '>' { $$ = mk_atom(yytext); }
|
|||
|
| '-' { $$ = mk_atom(yytext); }
|
|||
|
| '&' { $$ = mk_atom(yytext); }
|
|||
|
| '|' { $$ = mk_atom(yytext); }
|
|||
|
| '+' { $$ = mk_atom(yytext); }
|
|||
|
| '*' { $$ = mk_atom(yytext); }
|
|||
|
| '/' { $$ = mk_atom(yytext); }
|
|||
|
| '^' { $$ = mk_atom(yytext); }
|
|||
|
| '%' { $$ = mk_atom(yytext); }
|
|||
|
;
|
|||
|
|
|||
|
token_trees
|
|||
|
: %empty { $$ = mk_node("TokenTrees", 0); }
|
|||
|
| token_trees token_tree { $$ = ext_node($1, 1, $2); }
|
|||
|
;
|
|||
|
|
|||
|
token_tree
|
|||
|
: delimited_token_trees
|
|||
|
| unpaired_token { $$ = mk_node("TTTok", 1, $1); }
|
|||
|
;
|
|||
|
|
|||
|
delimited_token_trees
|
|||
|
: parens_delimited_token_trees
|
|||
|
| braces_delimited_token_trees
|
|||
|
| brackets_delimited_token_trees
|
|||
|
;
|
|||
|
|
|||
|
parens_delimited_token_trees
|
|||
|
: '(' token_trees ')'
|
|||
|
{
|
|||
|
$$ = mk_node("TTDelim", 3,
|
|||
|
mk_node("TTTok", 1, mk_atom("(")),
|
|||
|
$2,
|
|||
|
mk_node("TTTok", 1, mk_atom(")")));
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
braces_delimited_token_trees
|
|||
|
: '{' token_trees '}'
|
|||
|
{
|
|||
|
$$ = mk_node("TTDelim", 3,
|
|||
|
mk_node("TTTok", 1, mk_atom("{")),
|
|||
|
$2,
|
|||
|
mk_node("TTTok", 1, mk_atom("}")));
|
|||
|
}
|
|||
|
;
|
|||
|
|
|||
|
brackets_delimited_token_trees
|
|||
|
: '[' token_trees ']'
|
|||
|
{
|
|||
|
$$ = mk_node("TTDelim", 3,
|
|||
|
mk_node("TTTok", 1, mk_atom("[")),
|
|||
|
$2,
|
|||
|
mk_node("TTTok", 1, mk_atom("]")));
|
|||
|
}
|
|||
|
;
|