Home | History | Annotate | Download | only in gc
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 /*
      6  * Go language grammar.
      7  *
      8  * The Go semicolon rules are:
      9  *
     10  *  1. all statements and declarations are terminated by semicolons.
     11  *  2. semicolons can be omitted before a closing ) or }.
     12  *  3. semicolons are inserted by the lexer before a newline
     13  *      following a specific list of tokens.
     14  *
     15  * Rules #1 and #2 are accomplished by writing the lists as
     16  * semicolon-separated lists with an optional trailing semicolon.
     17  * Rule #3 is implemented in yylex.
     18  */
     19 
     20 %{
     21 package gc
     22 
     23 import (
     24 	"fmt"
     25 	"strings"
     26 )
     27 %}
     28 %union	{
     29 	node *Node
     30 	list *NodeList
     31 	typ *Type
     32 	sym *Sym
     33 	val Val
     34 	i int
     35 }
     36 
     37 // |sed 's/.*	//' |9 fmt -l1 |sort |9 fmt -l50 | sed 's/^/%xxx		/'
     38 
     39 %token	<val>	LLITERAL
     40 %token	<i>	LASOP LCOLAS
     41 %token	<sym>	LBREAK LCASE LCHAN LCONST LCONTINUE LDDD
     42 %token	<sym>	LDEFAULT LDEFER LELSE LFALL LFOR LFUNC LGO LGOTO
     43 %token	<sym>	LIF LIMPORT LINTERFACE LMAP LNAME
     44 %token	<sym>	LPACKAGE LRANGE LRETURN LSELECT LSTRUCT LSWITCH
     45 %token	<sym>	LTYPE LVAR
     46 
     47 %token		LANDAND LANDNOT LBODY LCOMM LDEC LEQ LGE LGT
     48 %token		LIGNORE LINC LLE LLSH LLT LNE LOROR LRSH
     49 
     50 %type	<i>	lbrace import_here
     51 %type	<sym>	sym packname
     52 %type	<val>	oliteral
     53 
     54 %type	<node>	stmt ntype
     55 %type	<node>	arg_type
     56 %type	<node>	case caseblock
     57 %type	<node>	compound_stmt dotname embed expr complitexpr bare_complitexpr
     58 %type	<node>	expr_or_type
     59 %type	<node>	fndcl hidden_fndcl fnliteral
     60 %type	<node>	for_body for_header for_stmt if_header if_stmt non_dcl_stmt
     61 %type	<node>	interfacedcl keyval labelname name
     62 %type	<node>	name_or_type non_expr_type
     63 %type	<node>	new_name dcl_name oexpr typedclname
     64 %type	<node>	onew_name
     65 %type	<node>	osimple_stmt pexpr pexpr_no_paren
     66 %type	<node>	pseudocall range_stmt select_stmt
     67 %type	<node>	simple_stmt
     68 %type	<node>	switch_stmt uexpr
     69 %type	<node>	xfndcl typedcl start_complit
     70 
     71 %type	<list>	xdcl fnbody fnres loop_body dcl_name_list
     72 %type	<list>	new_name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list
     73 %type	<list>	oexpr_list caseblock_list elseif elseif_list else stmt_list oarg_type_list_ocomma arg_type_list
     74 %type	<list>	interfacedcl_list vardcl vardcl_list structdcl structdcl_list
     75 %type	<list>	common_dcl constdcl constdcl1 constdcl_list typedcl_list
     76 
     77 %type	<node>	convtype comptype dotdotdot
     78 %type	<node>	indcl interfacetype structtype ptrtype
     79 %type	<node>	recvchantype non_recvchantype othertype fnret_type fntype
     80 
     81 %type	<sym>	hidden_importsym hidden_pkg_importsym
     82 
     83 %type	<node>	hidden_constant hidden_literal hidden_funarg
     84 %type	<node>	hidden_interfacedcl hidden_structdcl
     85 
     86 %type	<list>	hidden_funres
     87 %type	<list>	ohidden_funres
     88 %type	<list>	hidden_funarg_list ohidden_funarg_list
     89 %type	<list>	hidden_interfacedcl_list ohidden_interfacedcl_list
     90 %type	<list>	hidden_structdcl_list ohidden_structdcl_list
     91 
     92 %type	<typ>	hidden_type hidden_type_misc hidden_pkgtype
     93 %type	<typ>	hidden_type_func
     94 %type	<typ>	hidden_type_recv_chan hidden_type_non_recv_chan
     95 
     96 %left		LCOMM	/* outside the usual hierarchy; here for good error messages */
     97 
     98 %left		LOROR
     99 %left		LANDAND
    100 %left		LEQ LNE LLE LGE LLT LGT
    101 %left		'+' '-' '|' '^'
    102 %left		'*' '/' '%' '&' LLSH LRSH LANDNOT
    103 
    104 /*
    105  * manual override of shift/reduce conflicts.
    106  * the general form is that we assign a precedence
    107  * to the token being shifted and then introduce
    108  * NotToken with lower precedence or PreferToToken with higher
    109  * and annotate the reducing rule accordingly.
    110  */
    111 %left		NotPackage
    112 %left		LPACKAGE
    113 
    114 %left		NotParen
    115 %left		'('
    116 
    117 %left		')'
    118 %left		PreferToRightParen
    119 
    120 %error loadsys package LIMPORT '(' LLITERAL import_package import_there ',':
    121 	"unexpected comma during import block"
    122 
    123 %error loadsys package LIMPORT LNAME ';':
    124 	"missing import path; require quoted string"
    125 
    126 %error loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header ';':
    127 	"missing { after if clause"
    128 
    129 %error loadsys package imports LFUNC LNAME '(' ')' '{' LSWITCH if_header ';':
    130 	"missing { after switch clause"
    131 
    132 %error loadsys package imports LFUNC LNAME '(' ')' '{' LFOR for_header ';':
    133 	"missing { after for clause"
    134 
    135 %error loadsys package imports LFUNC LNAME '(' ')' '{' LFOR ';' LBODY:
    136 	"missing { after for clause"
    137 
    138 %error loadsys package imports LFUNC LNAME '(' ')' ';' '{':
    139 	"unexpected semicolon or newline before {"
    140 
    141 %error loadsys package imports LTYPE LNAME ';':
    142 	"unexpected semicolon or newline in type declaration"
    143 
    144 %error loadsys package imports LCHAN '}':
    145 	"unexpected } in channel type"
    146 
    147 %error loadsys package imports LCHAN ')':
    148 	"unexpected ) in channel type"
    149 
    150 %error loadsys package imports LCHAN ',':
    151 	"unexpected comma in channel type"
    152 
    153 %error loadsys package imports LFUNC LNAME '(' ')' '{' if_stmt ';' LELSE:
    154 	"unexpected semicolon or newline before else"
    155 
    156 %error loadsys package imports LTYPE LNAME LINTERFACE '{' LNAME ',' LNAME:
    157 	"name list not allowed in interface type"
    158 
    159 %error loadsys package imports LFUNC LNAME '(' ')' '{' LFOR LVAR LNAME '=' LNAME:
    160 	"var declaration not allowed in for initializer"
    161 
    162 %error loadsys package imports LVAR LNAME '[' ']' LNAME '{':
    163 	"unexpected { at end of statement"
    164 
    165 %error loadsys package imports LFUNC LNAME '(' ')' '{' LVAR LNAME '[' ']' LNAME '{':
    166 	"unexpected { at end of statement"
    167 
    168 %error loadsys package imports LFUNC LNAME '(' ')' '{' LDEFER LNAME ';':
    169 	"argument to go/defer must be function call"
    170 
    171 %error loadsys package imports LVAR LNAME '=' LNAME '{' LNAME ';':
    172 	"need trailing comma before newline in composite literal"
    173 
    174 %error loadsys package imports LVAR LNAME '=' comptype '{' LNAME ';':
    175 	"need trailing comma before newline in composite literal"
    176 
    177 %error loadsys package imports LFUNC LNAME '(' ')' '{' LFUNC LNAME:
    178 	"nested func not allowed"
    179 
    180 %error loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header loop_body LELSE ';':
    181 	"else must be followed by if or statement block"
    182 
    183 %%
    184 file:
    185 	loadsys
    186 	package
    187 	imports
    188 	xdcl_list
    189 	{
    190 		xtop = concat(xtop, $4);
    191 	}
    192 
    193 package:
    194 	%prec NotPackage
    195 	{
    196 		prevlineno = lineno;
    197 		Yyerror("package statement must be first");
    198 		errorexit();
    199 	}
    200 |	LPACKAGE sym ';'
    201 	{
    202 		mkpackage($2.Name);
    203 	}
    204 
    205 /*
    206  * this loads the definitions for the low-level runtime functions,
    207  * so that the compiler can generate calls to them,
    208  * but does not make the name "runtime" visible as a package.
    209  */
    210 loadsys:
    211 	{
    212 		importpkg = Runtimepkg;
    213 
    214 		if Debug['A'] != 0 {
    215 			cannedimports("runtime.Builtin", "package runtime\n\n$$\n\n");
    216 		} else {
    217 			cannedimports("runtime.Builtin", runtimeimport);
    218 		}
    219 		curio.importsafe = true
    220 	}
    221 	import_package
    222 	import_there
    223 	{
    224 		importpkg = nil;
    225 	}
    226 
    227 imports:
    228 |	imports import ';'
    229 
    230 import:
    231 	LIMPORT import_stmt
    232 |	LIMPORT '(' import_stmt_list osemi ')'
    233 |	LIMPORT '(' ')'
    234 
    235 import_stmt:
    236 	import_here import_package import_there
    237 	{
    238 		ipkg := importpkg;
    239 		my := importmyname;
    240 		importpkg = nil;
    241 		importmyname = nil;
    242 
    243 		if my == nil {
    244 			my = Lookup(ipkg.Name);
    245 		}
    246 
    247 		pack := Nod(OPACK, nil, nil);
    248 		pack.Sym = my;
    249 		pack.Name.Pkg = ipkg;
    250 		pack.Lineno = int32($1);
    251 
    252 		if strings.HasPrefix(my.Name, ".") {
    253 			importdot(ipkg, pack);
    254 			break;
    255 		}
    256 		if my.Name == "init" {
    257 			Yyerror("cannot import package as init - init must be a func");
    258 			break;
    259 		}
    260 		if my.Name == "_" {
    261 			break;
    262 		}
    263 		if my.Def != nil {
    264 			lineno = int32($1);
    265 			redeclare(my, "as imported package name");
    266 		}
    267 		my.Def = pack;
    268 		my.Lastlineno = int32($1);
    269 		my.Block = 1;	// at top level
    270 	}
    271 |	import_here import_there
    272 	{
    273 		// When an invalid import path is passed to importfile,
    274 		// it calls Yyerror and then sets up a fake import with
    275 		// no package statement. This allows us to test more
    276 		// than one invalid import statement in a single file.
    277 		if nerrors == 0 {
    278 			Fatal("phase error in import");
    279 		}
    280 	}
    281 
    282 import_stmt_list:
    283 	import_stmt
    284 |	import_stmt_list ';' import_stmt
    285 
    286 import_here:
    287 	LLITERAL
    288 	{
    289 		// import with original name
    290 		$$ = parserline();
    291 		importmyname = nil;
    292 		importfile(&$1, $$);
    293 	}
    294 |	sym LLITERAL
    295 	{
    296 		// import with given name
    297 		$$ = parserline();
    298 		importmyname = $1;
    299 		importfile(&$2, $$);
    300 	}
    301 |	'.' LLITERAL
    302 	{
    303 		// import into my name space
    304 		$$ = parserline();
    305 		importmyname = Lookup(".");
    306 		importfile(&$2, $$);
    307 	}
    308 
    309 import_package:
    310 	LPACKAGE LNAME import_safety ';'
    311 	{
    312 		if importpkg.Name == "" {
    313 			importpkg.Name = $2.Name;
    314 			numImport[$2.Name]++
    315 		} else if importpkg.Name != $2.Name {
    316 			Yyerror("conflicting names %s and %s for package %q", importpkg.Name, $2.Name, importpkg.Path);
    317 		}
    318 		importpkg.Direct = 1;
    319 		importpkg.Safe = curio.importsafe
    320 
    321 		if safemode != 0 && !curio.importsafe {
    322 			Yyerror("cannot import unsafe package %q", importpkg.Path);
    323 		}
    324 	}
    325 
    326 import_safety:
    327 |	LNAME
    328 	{
    329 		if $1.Name == "safe" {
    330 			curio.importsafe = true
    331 		}
    332 	}
    333 
    334 import_there:
    335 	{
    336 		defercheckwidth();
    337 	}
    338 	hidden_import_list '$' '$'
    339 	{
    340 		resumecheckwidth();
    341 		unimportfile();
    342 	}
    343 
    344 /*
    345  * declarations
    346  */
    347 xdcl:
    348 	{
    349 		Yyerror("empty top-level declaration");
    350 		$$ = nil;
    351 	}
    352 |	common_dcl
    353 |	xfndcl
    354 	{
    355 		$$ = list1($1);
    356 	}
    357 |	non_dcl_stmt
    358 	{
    359 		Yyerror("non-declaration statement outside function body");
    360 		$$ = nil;
    361 	}
    362 |	error
    363 	{
    364 		$$ = nil;
    365 	}
    366 
    367 common_dcl:
    368 	LVAR vardcl
    369 	{
    370 		$$ = $2;
    371 	}
    372 |	LVAR '(' vardcl_list osemi ')'
    373 	{
    374 		$$ = $3;
    375 	}
    376 |	LVAR '(' ')'
    377 	{
    378 		$$ = nil;
    379 	}
    380 |	lconst constdcl
    381 	{
    382 		$$ = $2;
    383 		iota_ = -100000;
    384 		lastconst = nil;
    385 	}
    386 |	lconst '(' constdcl osemi ')'
    387 	{
    388 		$$ = $3;
    389 		iota_ = -100000;
    390 		lastconst = nil;
    391 	}
    392 |	lconst '(' constdcl ';' constdcl_list osemi ')'
    393 	{
    394 		$$ = concat($3, $5);
    395 		iota_ = -100000;
    396 		lastconst = nil;
    397 	}
    398 |	lconst '(' ')'
    399 	{
    400 		$$ = nil;
    401 		iota_ = -100000;
    402 	}
    403 |	LTYPE typedcl
    404 	{
    405 		$$ = list1($2);
    406 	}
    407 |	LTYPE '(' typedcl_list osemi ')'
    408 	{
    409 		$$ = $3;
    410 	}
    411 |	LTYPE '(' ')'
    412 	{
    413 		$$ = nil;
    414 	}
    415 
    416 lconst:
    417 	LCONST
    418 	{
    419 		iota_ = 0;
    420 	}
    421 
    422 vardcl:
    423 	dcl_name_list ntype
    424 	{
    425 		$$ = variter($1, $2, nil);
    426 	}
    427 |	dcl_name_list ntype '=' expr_list
    428 	{
    429 		$$ = variter($1, $2, $4);
    430 	}
    431 |	dcl_name_list '=' expr_list
    432 	{
    433 		$$ = variter($1, nil, $3);
    434 	}
    435 
    436 constdcl:
    437 	dcl_name_list ntype '=' expr_list
    438 	{
    439 		$$ = constiter($1, $2, $4);
    440 	}
    441 |	dcl_name_list '=' expr_list
    442 	{
    443 		$$ = constiter($1, nil, $3);
    444 	}
    445 
    446 constdcl1:
    447 	constdcl
    448 |	dcl_name_list ntype
    449 	{
    450 		$$ = constiter($1, $2, nil);
    451 	}
    452 |	dcl_name_list
    453 	{
    454 		$$ = constiter($1, nil, nil);
    455 	}
    456 
    457 typedclname:
    458 	sym
    459 	{
    460 		// different from dclname because the name
    461 		// becomes visible right here, not at the end
    462 		// of the declaration.
    463 		$$ = typedcl0($1);
    464 	}
    465 
    466 typedcl:
    467 	typedclname ntype
    468 	{
    469 		$$ = typedcl1($1, $2, true);
    470 	}
    471 
    472 simple_stmt:
    473 	expr
    474 	{
    475 		$$ = $1;
    476 
    477 		// These nodes do not carry line numbers.
    478 		// Since a bare name used as an expression is an error,
    479 		// introduce a wrapper node to give the correct line.
    480 		switch($$.Op) {
    481 		case ONAME, ONONAME, OTYPE, OPACK, OLITERAL:
    482 			$$ = Nod(OPAREN, $$, nil);
    483 			$$.Implicit = true;
    484 			break;
    485 		}
    486 	}
    487 |	expr LASOP expr
    488 	{
    489 		$$ = Nod(OASOP, $1, $3);
    490 		$$.Etype = uint8($2);			// rathole to pass opcode
    491 	}
    492 |	expr_list '=' expr_list
    493 	{
    494 		if $1.Next == nil && $3.Next == nil {
    495 			// simple
    496 			$$ = Nod(OAS, $1.N, $3.N);
    497 			break;
    498 		}
    499 		// multiple
    500 		$$ = Nod(OAS2, nil, nil);
    501 		$$.List = $1;
    502 		$$.Rlist = $3;
    503 	}
    504 |	expr_list LCOLAS expr_list
    505 	{
    506 		if $3.N.Op == OTYPESW {
    507 			$$ = Nod(OTYPESW, nil, $3.N.Right);
    508 			if $3.Next != nil {
    509 				Yyerror("expr.(type) must be alone in list");
    510 			}
    511 			if $1.Next != nil {
    512 				Yyerror("argument count mismatch: %d = %d", count($1), 1);
    513 			} else if ($1.N.Op != ONAME && $1.N.Op != OTYPE && $1.N.Op != ONONAME) || isblank($1.N) {
    514 				Yyerror("invalid variable name %s in type switch", $1.N);
    515 			} else {
    516 				$$.Left = dclname($1.N.Sym);
    517 			}  // it's a colas, so must not re-use an oldname.
    518 			break;
    519 		}
    520 		$$ = colas($1, $3, int32($2));
    521 	}
    522 |	expr LINC
    523 	{
    524 		$$ = Nod(OASOP, $1, Nodintconst(1));
    525 		$$.Implicit = true;
    526 		$$.Etype = OADD;
    527 	}
    528 |	expr LDEC
    529 	{
    530 		$$ = Nod(OASOP, $1, Nodintconst(1));
    531 		$$.Implicit = true;
    532 		$$.Etype = OSUB;
    533 	}
    534 
    535 case:
    536 	LCASE expr_or_type_list ':'
    537 	{
    538 		var n, nn *Node
    539 
    540 		// will be converted to OCASE
    541 		// right will point to next case
    542 		// done in casebody()
    543 		markdcl();
    544 		$$ = Nod(OXCASE, nil, nil);
    545 		$$.List = $2;
    546 		if typesw != nil && typesw.Right != nil {
    547 			n = typesw.Right.Left
    548 			if n != nil {
    549 				// type switch - declare variable
    550 				nn = newname(n.Sym);
    551 				declare(nn, dclcontext);
    552 				$$.Rlist = list1(nn);
    553 
    554 				// keep track of the instances for reporting unused
    555 				nn.Name.Defn = typesw.Right;
    556 			}
    557 		}
    558 	}
    559 |	LCASE expr_or_type_list '=' expr ':'
    560 	{
    561 		var n *Node
    562 
    563 		// will be converted to OCASE
    564 		// right will point to next case
    565 		// done in casebody()
    566 		markdcl();
    567 		$$ = Nod(OXCASE, nil, nil);
    568 		if $2.Next == nil {
    569 			n = Nod(OAS, $2.N, $4);
    570 		} else {
    571 			n = Nod(OAS2, nil, nil);
    572 			n.List = $2;
    573 			n.Rlist = list1($4);
    574 		}
    575 		$$.List = list1(n);
    576 	}
    577 |	LCASE expr_or_type_list LCOLAS expr ':'
    578 	{
    579 		// will be converted to OCASE
    580 		// right will point to next case
    581 		// done in casebody()
    582 		markdcl();
    583 		$$ = Nod(OXCASE, nil, nil);
    584 		$$.List = list1(colas($2, list1($4), int32($3)));
    585 	}
    586 |	LDEFAULT ':'
    587 	{
    588 		var n, nn *Node
    589 
    590 		markdcl();
    591 		$$ = Nod(OXCASE, nil, nil);
    592 		if typesw != nil && typesw.Right != nil {
    593 			n = typesw.Right.Left
    594 			if n != nil {
    595 				// type switch - declare variable
    596 				nn = newname(n.Sym);
    597 				declare(nn, dclcontext);
    598 				$$.Rlist = list1(nn);
    599 
    600 				// keep track of the instances for reporting unused
    601 				nn.Name.Defn = typesw.Right;
    602 			}
    603 		}
    604 	}
    605 
    606 compound_stmt:
    607 	'{'
    608 	{
    609 		markdcl();
    610 	}
    611 	stmt_list '}'
    612 	{
    613 		if $3 == nil {
    614 			$$ = Nod(OEMPTY, nil, nil);
    615 		} else {
    616 			$$ = liststmt($3);
    617 		}
    618 		popdcl();
    619 	}
    620 
    621 caseblock:
    622 	case
    623 	{
    624 		// If the last token read by the lexer was consumed
    625 		// as part of the case, clear it (parser has cleared yychar).
    626 		// If the last token read by the lexer was the lookahead
    627 		// leave it alone (parser has it cached in yychar).
    628 		// This is so that the stmt_list action doesn't look at
    629 		// the case tokens if the stmt_list is empty.
    630 		yylast = yychar;
    631 		$1.Xoffset = int64(block);
    632 	}
    633 	stmt_list
    634 	{
    635 		// This is the only place in the language where a statement
    636 		// list is not allowed to drop the final semicolon, because
    637 		// it's the only place where a statement list is not followed
    638 		// by a closing brace.  Handle the error for pedantry.
    639 
    640 		// Find the final token of the statement list.
    641 		// yylast is lookahead; yyprev is last of stmt_list
    642 		last := yyprev;
    643 
    644 		if last > 0 && last != ';' && yychar != '}' {
    645 			Yyerror("missing statement after label");
    646 		}
    647 		$$ = $1;
    648 		$$.Nbody = $3;
    649 		popdcl();
    650 	}
    651 
    652 caseblock_list:
    653 	{
    654 		$$ = nil;
    655 	}
    656 |	caseblock_list caseblock
    657 	{
    658 		$$ = list($1, $2);
    659 	}
    660 
    661 loop_body:
    662 	LBODY
    663 	{
    664 		markdcl();
    665 	}
    666 	stmt_list '}'
    667 	{
    668 		$$ = $3;
    669 		popdcl();
    670 	}
    671 
    672 range_stmt:
    673 	expr_list '=' LRANGE expr
    674 	{
    675 		$$ = Nod(ORANGE, nil, $4);
    676 		$$.List = $1;
    677 		$$.Etype = 0;	// := flag
    678 	}
    679 |	expr_list LCOLAS LRANGE expr
    680 	{
    681 		$$ = Nod(ORANGE, nil, $4);
    682 		$$.List = $1;
    683 		$$.Colas = true;
    684 		colasdefn($1, $$);
    685 	}
    686 |	LRANGE expr
    687 	{
    688 		$$ = Nod(ORANGE, nil, $2);
    689 		$$.Etype = 0; // := flag
    690 	}
    691 
    692 for_header:
    693 	osimple_stmt ';' osimple_stmt ';' osimple_stmt
    694 	{
    695 		// init ; test ; incr
    696 		if $5 != nil && $5.Colas {
    697 			Yyerror("cannot declare in the for-increment");
    698 		}
    699 		$$ = Nod(OFOR, nil, nil);
    700 		if $1 != nil {
    701 			$$.Ninit = list1($1);
    702 		}
    703 		$$.Left = $3;
    704 		$$.Right = $5;
    705 	}
    706 |	osimple_stmt
    707 	{
    708 		// normal test
    709 		$$ = Nod(OFOR, nil, nil);
    710 		$$.Left = $1;
    711 	}
    712 |	range_stmt
    713 
    714 for_body:
    715 	for_header loop_body
    716 	{
    717 		$$ = $1;
    718 		$$.Nbody = concat($$.Nbody, $2);
    719 	}
    720 
    721 for_stmt:
    722 	LFOR
    723 	{
    724 		markdcl();
    725 	}
    726 	for_body
    727 	{
    728 		$$ = $3;
    729 		popdcl();
    730 	}
    731 
    732 if_header:
    733 	osimple_stmt
    734 	{
    735 		// test
    736 		$$ = Nod(OIF, nil, nil);
    737 		$$.Left = $1;
    738 	}
    739 |	osimple_stmt ';' osimple_stmt
    740 	{
    741 		// init ; test
    742 		$$ = Nod(OIF, nil, nil);
    743 		if $1 != nil {
    744 			$$.Ninit = list1($1);
    745 		}
    746 		$$.Left = $3;
    747 	}
    748 
    749 /* IF cond body (ELSE IF cond body)* (ELSE block)? */
    750 if_stmt:
    751 	LIF
    752 	{
    753 		markdcl();
    754 	}
    755 	if_header
    756 	{
    757 		if $3.Left == nil {
    758 			Yyerror("missing condition in if statement");
    759 		}
    760 	}
    761 	loop_body
    762 	{
    763 		$3.Nbody = $5;
    764 	}
    765 	elseif_list else
    766 	{
    767 		var n *Node
    768 		var nn *NodeList
    769 
    770 		$$ = $3;
    771 		n = $3;
    772 		popdcl();
    773 		for nn = concat($7, $8); nn != nil; nn = nn.Next {
    774 			if nn.N.Op == OIF {
    775 				popdcl();
    776 			}
    777 			n.Rlist = list1(nn.N);
    778 			n = nn.N;
    779 		}
    780 	}
    781 
    782 elseif:
    783 	LELSE LIF
    784 	{
    785 		markdcl();
    786 	}
    787 	if_header loop_body
    788 	{
    789 		if $4.Left == nil {
    790 			Yyerror("missing condition in if statement");
    791 		}
    792 		$4.Nbody = $5;
    793 		$$ = list1($4);
    794 	}
    795 
    796 elseif_list:
    797 	{
    798 		$$ = nil;
    799 	}
    800 |	elseif_list elseif
    801 	{
    802 		$$ = concat($1, $2);
    803 	}
    804 
    805 else:
    806 	{
    807 		$$ = nil;
    808 	}
    809 |	LELSE compound_stmt
    810 	{
    811 		l := &NodeList{N: $2}
    812 		l.End = l
    813 		$$ = l;
    814 	}
    815 
    816 switch_stmt:
    817 	LSWITCH
    818 	{
    819 		markdcl();
    820 	}
    821 	if_header
    822 	{
    823 		var n *Node
    824 		n = $3.Left;
    825 		if n != nil && n.Op != OTYPESW {
    826 			n = nil;
    827 		}
    828 		typesw = Nod(OXXX, typesw, n);
    829 	}
    830 	LBODY caseblock_list '}'
    831 	{
    832 		$$ = $3;
    833 		$$.Op = OSWITCH;
    834 		$$.List = $6;
    835 		typesw = typesw.Left;
    836 		popdcl();
    837 	}
    838 
    839 select_stmt:
    840 	LSELECT
    841 	{
    842 		typesw = Nod(OXXX, typesw, nil);
    843 	}
    844 	LBODY caseblock_list '}'
    845 	{
    846 		$$ = Nod(OSELECT, nil, nil);
    847 		$$.Lineno = typesw.Lineno;
    848 		$$.List = $4;
    849 		typesw = typesw.Left;
    850 	}
    851 
    852 /*
    853  * expressions
    854  */
    855 expr:
    856 	uexpr
    857 |	expr LOROR expr
    858 	{
    859 		$$ = Nod(OOROR, $1, $3);
    860 	}
    861 |	expr LANDAND expr
    862 	{
    863 		$$ = Nod(OANDAND, $1, $3);
    864 	}
    865 |	expr LEQ expr
    866 	{
    867 		$$ = Nod(OEQ, $1, $3);
    868 	}
    869 |	expr LNE expr
    870 	{
    871 		$$ = Nod(ONE, $1, $3);
    872 	}
    873 |	expr LLT expr
    874 	{
    875 		$$ = Nod(OLT, $1, $3);
    876 	}
    877 |	expr LLE expr
    878 	{
    879 		$$ = Nod(OLE, $1, $3);
    880 	}
    881 |	expr LGE expr
    882 	{
    883 		$$ = Nod(OGE, $1, $3);
    884 	}
    885 |	expr LGT expr
    886 	{
    887 		$$ = Nod(OGT, $1, $3);
    888 	}
    889 |	expr '+' expr
    890 	{
    891 		$$ = Nod(OADD, $1, $3);
    892 	}
    893 |	expr '-' expr
    894 	{
    895 		$$ = Nod(OSUB, $1, $3);
    896 	}
    897 |	expr '|' expr
    898 	{
    899 		$$ = Nod(OOR, $1, $3);
    900 	}
    901 |	expr '^' expr
    902 	{
    903 		$$ = Nod(OXOR, $1, $3);
    904 	}
    905 |	expr '*' expr
    906 	{
    907 		$$ = Nod(OMUL, $1, $3);
    908 	}
    909 |	expr '/' expr
    910 	{
    911 		$$ = Nod(ODIV, $1, $3);
    912 	}
    913 |	expr '%' expr
    914 	{
    915 		$$ = Nod(OMOD, $1, $3);
    916 	}
    917 |	expr '&' expr
    918 	{
    919 		$$ = Nod(OAND, $1, $3);
    920 	}
    921 |	expr LANDNOT expr
    922 	{
    923 		$$ = Nod(OANDNOT, $1, $3);
    924 	}
    925 |	expr LLSH expr
    926 	{
    927 		$$ = Nod(OLSH, $1, $3);
    928 	}
    929 |	expr LRSH expr
    930 	{
    931 		$$ = Nod(ORSH, $1, $3);
    932 	}
    933 	/* not an expression anymore, but left in so we can give a good error */
    934 |	expr LCOMM expr
    935 	{
    936 		$$ = Nod(OSEND, $1, $3);
    937 	}
    938 
    939 uexpr:
    940 	pexpr
    941 |	'*' uexpr
    942 	{
    943 		$$ = Nod(OIND, $2, nil);
    944 	}
    945 |	'&' uexpr
    946 	{
    947 		if $2.Op == OCOMPLIT {
    948 			// Special case for &T{...}: turn into (*T){...}.
    949 			$$ = $2;
    950 			$$.Right = Nod(OIND, $$.Right, nil);
    951 			$$.Right.Implicit = true;
    952 		} else {
    953 			$$ = Nod(OADDR, $2, nil);
    954 		}
    955 	}
    956 |	'+' uexpr
    957 	{
    958 		$$ = Nod(OPLUS, $2, nil);
    959 	}
    960 |	'-' uexpr
    961 	{
    962 		$$ = Nod(OMINUS, $2, nil);
    963 	}
    964 |	'!' uexpr
    965 	{
    966 		$$ = Nod(ONOT, $2, nil);
    967 	}
    968 |	'~' uexpr
    969 	{
    970 		Yyerror("the bitwise complement operator is ^");
    971 		$$ = Nod(OCOM, $2, nil);
    972 	}
    973 |	'^' uexpr
    974 	{
    975 		$$ = Nod(OCOM, $2, nil);
    976 	}
    977 |	LCOMM uexpr
    978 	{
    979 		$$ = Nod(ORECV, $2, nil);
    980 	}
    981 
    982 /*
    983  * call-like statements that
    984  * can be preceded by 'defer' and 'go'
    985  */
    986 pseudocall:
    987 	pexpr '(' ')'
    988 	{
    989 		$$ = Nod(OCALL, $1, nil);
    990 	}
    991 |	pexpr '(' expr_or_type_list ocomma ')'
    992 	{
    993 		$$ = Nod(OCALL, $1, nil);
    994 		$$.List = $3;
    995 	}
    996 |	pexpr '(' expr_or_type_list LDDD ocomma ')'
    997 	{
    998 		$$ = Nod(OCALL, $1, nil);
    999 		$$.List = $3;
   1000 		$$.Isddd = true;
   1001 	}
   1002 
   1003 pexpr_no_paren:
   1004 	LLITERAL
   1005 	{
   1006 		$$ = nodlit($1);
   1007 	}
   1008 |	name
   1009 |	pexpr '.' sym
   1010 	{
   1011 		if $1.Op == OPACK {
   1012 			var s *Sym
   1013 			s = restrictlookup($3.Name, $1.Name.Pkg);
   1014 			$1.Used = true;
   1015 			$$ = oldname(s);
   1016 			break;
   1017 		}
   1018 		$$ = Nod(OXDOT, $1, newname($3));
   1019 	}
   1020 |	pexpr '.' '(' expr_or_type ')'
   1021 	{
   1022 		$$ = Nod(ODOTTYPE, $1, $4);
   1023 	}
   1024 |	pexpr '.' '(' LTYPE ')'
   1025 	{
   1026 		$$ = Nod(OTYPESW, nil, $1);
   1027 	}
   1028 |	pexpr '[' expr ']'
   1029 	{
   1030 		$$ = Nod(OINDEX, $1, $3);
   1031 	}
   1032 |	pexpr '[' oexpr ':' oexpr ']'
   1033 	{
   1034 		$$ = Nod(OSLICE, $1, Nod(OKEY, $3, $5));
   1035 	}
   1036 |	pexpr '[' oexpr ':' oexpr ':' oexpr ']'
   1037 	{
   1038 		if $5 == nil {
   1039 			Yyerror("middle index required in 3-index slice");
   1040 		}
   1041 		if $7 == nil {
   1042 			Yyerror("final index required in 3-index slice");
   1043 		}
   1044 		$$ = Nod(OSLICE3, $1, Nod(OKEY, $3, Nod(OKEY, $5, $7)));
   1045 	}
   1046 |	pseudocall
   1047 |	convtype '(' expr ocomma ')'
   1048 	{
   1049 		// conversion
   1050 		$$ = Nod(OCALL, $1, nil);
   1051 		$$.List = list1($3);
   1052 	}
   1053 |	comptype lbrace start_complit braced_keyval_list '}'
   1054 	{
   1055 		$$ = $3;
   1056 		$$.Right = $1;
   1057 		$$.List = $4;
   1058 		fixlbrace($2);
   1059 	}
   1060 |	pexpr_no_paren '{' start_complit braced_keyval_list '}'
   1061 	{
   1062 		$$ = $3;
   1063 		$$.Right = $1;
   1064 		$$.List = $4;
   1065 	}
   1066 |	'(' expr_or_type ')' '{' start_complit braced_keyval_list '}'
   1067 	{
   1068 		Yyerror("cannot parenthesize type in composite literal");
   1069 		$$ = $5;
   1070 		$$.Right = $2;
   1071 		$$.List = $6;
   1072 	}
   1073 |	fnliteral
   1074 
   1075 start_complit:
   1076 	{
   1077 		// composite expression.
   1078 		// make node early so we get the right line number.
   1079 		$$ = Nod(OCOMPLIT, nil, nil);
   1080 	}
   1081 
   1082 keyval:
   1083 	complitexpr ':' complitexpr
   1084 	{
   1085 		$$ = Nod(OKEY, $1, $3);
   1086 	}
   1087 
   1088 bare_complitexpr:
   1089 	expr
   1090 	{
   1091 		// These nodes do not carry line numbers.
   1092 		// Since a composite literal commonly spans several lines,
   1093 		// the line number on errors may be misleading.
   1094 		// Introduce a wrapper node to give the correct line.
   1095 		$$ = $1;
   1096 		switch($$.Op) {
   1097 		case ONAME, ONONAME, OTYPE, OPACK, OLITERAL:
   1098 			$$ = Nod(OPAREN, $$, nil);
   1099 			$$.Implicit = true;
   1100 		}
   1101 	}
   1102 |	'{' start_complit braced_keyval_list '}'
   1103 	{
   1104 		$$ = $2;
   1105 		$$.List = $3;
   1106 	}
   1107 
   1108 complitexpr:
   1109 	expr
   1110 |	'{' start_complit braced_keyval_list '}'
   1111 	{
   1112 		$$ = $2;
   1113 		$$.List = $3;
   1114 	}
   1115 
   1116 pexpr:
   1117 	pexpr_no_paren
   1118 |	'(' expr_or_type ')'
   1119 	{
   1120 		$$ = $2;
   1121 
   1122 		// Need to know on lhs of := whether there are ( ).
   1123 		// Don't bother with the OPAREN in other cases:
   1124 		// it's just a waste of memory and time.
   1125 		switch($$.Op) {
   1126 		case ONAME, ONONAME, OPACK, OTYPE, OLITERAL, OTYPESW:
   1127 			$$ = Nod(OPAREN, $$, nil);
   1128 		}
   1129 	}
   1130 
   1131 expr_or_type:
   1132 	expr
   1133 |	non_expr_type	%prec PreferToRightParen
   1134 
   1135 name_or_type:
   1136 	ntype
   1137 
   1138 lbrace:
   1139 	LBODY
   1140 	{
   1141 		$$ = LBODY;
   1142 	}
   1143 |	'{'
   1144 	{
   1145 		$$ = '{';
   1146 	}
   1147 
   1148 /*
   1149  * names and types
   1150  *	newname is used before declared
   1151  *	oldname is used after declared
   1152  */
   1153 new_name:
   1154 	sym
   1155 	{
   1156 		if $1 == nil {
   1157 			$$ = nil;
   1158 		} else {
   1159 			$$ = newname($1);
   1160 		}
   1161 	}
   1162 
   1163 dcl_name:
   1164 	sym
   1165 	{
   1166 		$$ = dclname($1);
   1167 	}
   1168 
   1169 onew_name:
   1170 	{
   1171 		$$ = nil;
   1172 	}
   1173 |	new_name
   1174 
   1175 sym:
   1176 	LNAME
   1177 	{
   1178 		$$ = $1;
   1179 		// during imports, unqualified non-exported identifiers are from builtinpkg
   1180 		if importpkg != nil && !exportname($1.Name) {
   1181 			$$ = Pkglookup($1.Name, builtinpkg);
   1182 		}
   1183 	}
   1184 |	hidden_importsym
   1185 |	'?'
   1186 	{
   1187 		$$ = nil;
   1188 	}
   1189 
   1190 hidden_importsym:
   1191 	'@' LLITERAL '.' LNAME
   1192 	{
   1193 		var p *Pkg
   1194 
   1195 		if $2.U.(string) == "" {
   1196 			p = importpkg;
   1197 		} else {
   1198 			if isbadimport($2.U.(string)) {
   1199 				errorexit();
   1200 			}
   1201 			p = mkpkg($2.U.(string));
   1202 		}
   1203 		$$ = Pkglookup($4.Name, p);
   1204 	}
   1205 |	'@' LLITERAL '.' '?'
   1206 	{
   1207 		var p *Pkg
   1208 
   1209 		if $2.U.(string) == "" {
   1210 			p = importpkg;
   1211 		} else {
   1212 			if isbadimport($2.U.(string)) {
   1213 				errorexit();
   1214 			}
   1215 			p = mkpkg($2.U.(string));
   1216 		}
   1217 		$$ = Pkglookup("?", p);
   1218 	}
   1219 
   1220 name:
   1221 	sym	%prec NotParen
   1222 	{
   1223 		$$ = oldname($1);
   1224 		if $$.Name != nil && $$.Name.Pack != nil {
   1225 			$$.Name.Pack.Used = true;
   1226 		}
   1227 	}
   1228 
   1229 labelname:
   1230 	new_name
   1231 
   1232 /*
   1233  * to avoid parsing conflicts, type is split into
   1234  *	channel types
   1235  *	function types
   1236  *	parenthesized types
   1237  *	any other type
   1238  * the type system makes additional restrictions,
   1239  * but those are not implemented in the grammar.
   1240  */
   1241 dotdotdot:
   1242 	LDDD
   1243 	{
   1244 		Yyerror("final argument in variadic function missing type");
   1245 		$$ = Nod(ODDD, typenod(typ(TINTER)), nil);
   1246 	}
   1247 |	LDDD ntype
   1248 	{
   1249 		$$ = Nod(ODDD, $2, nil);
   1250 	}
   1251 
   1252 ntype:
   1253 	recvchantype
   1254 |	fntype
   1255 |	othertype
   1256 |	ptrtype
   1257 |	dotname
   1258 |	'(' ntype ')'
   1259 	{
   1260 		$$ = $2;
   1261 	}
   1262 
   1263 non_expr_type:
   1264 	recvchantype
   1265 |	fntype
   1266 |	othertype
   1267 |	'*' non_expr_type
   1268 	{
   1269 		$$ = Nod(OIND, $2, nil);
   1270 	}
   1271 
   1272 non_recvchantype:
   1273 	fntype
   1274 |	othertype
   1275 |	ptrtype
   1276 |	dotname
   1277 |	'(' ntype ')'
   1278 	{
   1279 		$$ = $2;
   1280 	}
   1281 
   1282 convtype:
   1283 	fntype
   1284 |	othertype
   1285 
   1286 comptype:
   1287 	othertype
   1288 
   1289 fnret_type:
   1290 	recvchantype
   1291 |	fntype
   1292 |	othertype
   1293 |	ptrtype
   1294 |	dotname
   1295 
   1296 dotname:
   1297 	name
   1298 |	name '.' sym
   1299 	{
   1300 		if $1.Op == OPACK {
   1301 			var s *Sym
   1302 			s = restrictlookup($3.Name, $1.Name.Pkg);
   1303 			$1.Used = true;
   1304 			$$ = oldname(s);
   1305 			break;
   1306 		}
   1307 		$$ = Nod(OXDOT, $1, newname($3));
   1308 	}
   1309 
   1310 othertype:
   1311 	'[' oexpr ']' ntype
   1312 	{
   1313 		$$ = Nod(OTARRAY, $2, $4);
   1314 	}
   1315 |	'[' LDDD ']' ntype
   1316 	{
   1317 		// array literal of nelem
   1318 		$$ = Nod(OTARRAY, Nod(ODDD, nil, nil), $4);
   1319 	}
   1320 |	LCHAN non_recvchantype
   1321 	{
   1322 		$$ = Nod(OTCHAN, $2, nil);
   1323 		$$.Etype = Cboth;
   1324 	}
   1325 |	LCHAN LCOMM ntype
   1326 	{
   1327 		$$ = Nod(OTCHAN, $3, nil);
   1328 		$$.Etype = Csend;
   1329 	}
   1330 |	LMAP '[' ntype ']' ntype
   1331 	{
   1332 		$$ = Nod(OTMAP, $3, $5);
   1333 	}
   1334 |	structtype
   1335 |	interfacetype
   1336 
   1337 ptrtype:
   1338 	'*' ntype
   1339 	{
   1340 		$$ = Nod(OIND, $2, nil);
   1341 	}
   1342 
   1343 recvchantype:
   1344 	LCOMM LCHAN ntype
   1345 	{
   1346 		$$ = Nod(OTCHAN, $3, nil);
   1347 		$$.Etype = Crecv;
   1348 	}
   1349 
   1350 structtype:
   1351 	LSTRUCT lbrace structdcl_list osemi '}'
   1352 	{
   1353 		$$ = Nod(OTSTRUCT, nil, nil);
   1354 		$$.List = $3;
   1355 		fixlbrace($2);
   1356 	}
   1357 |	LSTRUCT lbrace '}'
   1358 	{
   1359 		$$ = Nod(OTSTRUCT, nil, nil);
   1360 		fixlbrace($2);
   1361 	}
   1362 
   1363 interfacetype:
   1364 	LINTERFACE lbrace interfacedcl_list osemi '}'
   1365 	{
   1366 		$$ = Nod(OTINTER, nil, nil);
   1367 		$$.List = $3;
   1368 		fixlbrace($2);
   1369 	}
   1370 |	LINTERFACE lbrace '}'
   1371 	{
   1372 		$$ = Nod(OTINTER, nil, nil);
   1373 		fixlbrace($2);
   1374 	}
   1375 
   1376 /*
   1377  * function stuff
   1378  * all in one place to show how crappy it all is
   1379  */
   1380 xfndcl:
   1381 	LFUNC fndcl fnbody
   1382 	{
   1383 		$$ = $2;
   1384 		if $$ == nil {
   1385 			break;
   1386 		}
   1387 		if noescape && $3 != nil {
   1388 			Yyerror("can only use //go:noescape with external func implementations");
   1389 		}
   1390 		$$.Nbody = $3;
   1391 		$$.Func.Endlineno = lineno;
   1392 		$$.Noescape = noescape;
   1393 		$$.Func.Norace = norace;
   1394 		$$.Func.Nosplit = nosplit;
   1395 		$$.Func.Nowritebarrier = nowritebarrier;
   1396 		$$.Func.Systemstack = systemstack;
   1397 		funcbody($$);
   1398 	}
   1399 
   1400 fndcl:
   1401 	sym '(' oarg_type_list_ocomma ')' fnres
   1402 	{
   1403 		var t *Node
   1404 
   1405 		$$ = nil;
   1406 		$3 = checkarglist($3, 1);
   1407 
   1408 		if $1.Name == "init" {
   1409 			$1 = renameinit();
   1410 			if $3 != nil || $5 != nil {
   1411 				Yyerror("func init must have no arguments and no return values");
   1412 			}
   1413 		}
   1414 		if localpkg.Name == "main" && $1.Name == "main" {
   1415 			if $3 != nil || $5 != nil {
   1416 				Yyerror("func main must have no arguments and no return values");
   1417 			}
   1418 		}
   1419 
   1420 		t = Nod(OTFUNC, nil, nil);
   1421 		t.List = $3;
   1422 		t.Rlist = $5;
   1423 
   1424 		$$ = Nod(ODCLFUNC, nil, nil);
   1425 		$$.Func.Nname = newfuncname($1);
   1426 		$$.Func.Nname.Name.Defn = $$;
   1427 		$$.Func.Nname.Name.Param.Ntype = t;		// TODO: check if nname already has an ntype
   1428 		declare($$.Func.Nname, PFUNC);
   1429 
   1430 		funchdr($$);
   1431 	}
   1432 |	'(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres
   1433 	{
   1434 		var rcvr, t *Node
   1435 
   1436 		$$ = nil;
   1437 		$2 = checkarglist($2, 0);
   1438 		$6 = checkarglist($6, 1);
   1439 
   1440 		if $2 == nil {
   1441 			Yyerror("method has no receiver");
   1442 			break;
   1443 		}
   1444 		if $2.Next != nil {
   1445 			Yyerror("method has multiple receivers");
   1446 			break;
   1447 		}
   1448 		rcvr = $2.N;
   1449 		if rcvr.Op != ODCLFIELD {
   1450 			Yyerror("bad receiver in method");
   1451 			break;
   1452 		}
   1453 
   1454 		t = Nod(OTFUNC, rcvr, nil);
   1455 		t.List = $6;
   1456 		t.Rlist = $8;
   1457 
   1458 		$$ = Nod(ODCLFUNC, nil, nil);
   1459 		$$.Func.Shortname = newfuncname($4);
   1460 		$$.Func.Nname = methodname1($$.Func.Shortname, rcvr.Right);
   1461 		$$.Func.Nname.Name.Defn = $$;
   1462 		$$.Func.Nname.Name.Param.Ntype = t;
   1463 		$$.Func.Nname.Nointerface = nointerface;
   1464 		declare($$.Func.Nname, PFUNC);
   1465 
   1466 		funchdr($$);
   1467 	}
   1468 
   1469 hidden_fndcl:
   1470 	hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres
   1471 	{
   1472 		var s *Sym
   1473 		var t *Type
   1474 
   1475 		$$ = nil;
   1476 
   1477 		s = $1;
   1478 		t = functype(nil, $3, $5);
   1479 
   1480 		importsym(s, ONAME);
   1481 		if s.Def != nil && s.Def.Op == ONAME {
   1482 			if Eqtype(t, s.Def.Type) {
   1483 				dclcontext = PDISCARD;  // since we skip funchdr below
   1484 				break;
   1485 			}
   1486 			Yyerror("inconsistent definition for func %v during import\n\t%v\n\t%v", s, s.Def.Type, t);
   1487 		}
   1488 
   1489 		$$ = newfuncname(s);
   1490 		$$.Type = t;
   1491 		declare($$, PFUNC);
   1492 
   1493 		funchdr($$);
   1494 	}
   1495 |	'(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres
   1496 	{
   1497 		$$ = methodname1(newname($4), $2.N.Right);
   1498 		$$.Type = functype($2.N, $6, $8);
   1499 
   1500 		checkwidth($$.Type);
   1501 		addmethod($4, $$.Type, false, nointerface);
   1502 		nointerface = false
   1503 		funchdr($$);
   1504 
   1505 		// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
   1506 		// (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
   1507 		// out by typecheck's lookdot as this $$.ttype.  So by providing
   1508 		// this back link here we avoid special casing there.
   1509 		$$.Type.Nname = $$;
   1510 	}
   1511 
   1512 fntype:
   1513 	LFUNC '(' oarg_type_list_ocomma ')' fnres
   1514 	{
   1515 		$3 = checkarglist($3, 1);
   1516 		$$ = Nod(OTFUNC, nil, nil);
   1517 		$$.List = $3;
   1518 		$$.Rlist = $5;
   1519 	}
   1520 
   1521 fnbody:
   1522 	{
   1523 		$$ = nil;
   1524 	}
   1525 |	'{' stmt_list '}'
   1526 	{
   1527 		$$ = $2;
   1528 		if $$ == nil {
   1529 			$$ = list1(Nod(OEMPTY, nil, nil));
   1530 		}
   1531 	}
   1532 
   1533 fnres:
   1534 	%prec NotParen
   1535 	{
   1536 		$$ = nil;
   1537 	}
   1538 |	fnret_type
   1539 	{
   1540 		$$ = list1(Nod(ODCLFIELD, nil, $1));
   1541 	}
   1542 |	'(' oarg_type_list_ocomma ')'
   1543 	{
   1544 		$2 = checkarglist($2, 0);
   1545 		$$ = $2;
   1546 	}
   1547 
   1548 fnlitdcl:
   1549 	fntype
   1550 	{
   1551 		closurehdr($1);
   1552 	}
   1553 
   1554 fnliteral:
   1555 	fnlitdcl lbrace stmt_list '}'
   1556 	{
   1557 		$$ = closurebody($3);
   1558 		fixlbrace($2);
   1559 	}
   1560 |	fnlitdcl error
   1561 	{
   1562 		$$ = closurebody(nil);
   1563 	}
   1564 
   1565 /*
   1566  * lists of things
   1567  * note that they are left recursive
   1568  * to conserve yacc stack. they need to
   1569  * be reversed to interpret correctly
   1570  */
   1571 xdcl_list:
   1572 	{
   1573 		$$ = nil;
   1574 	}
   1575 |	xdcl_list xdcl ';'
   1576 	{
   1577 		$$ = concat($1, $2);
   1578 		if nsyntaxerrors == 0 {
   1579 			testdclstack();
   1580 		}
   1581 		nointerface = false
   1582 		noescape = false
   1583 		norace = false
   1584 		nosplit = false
   1585 		nowritebarrier = false
   1586 		systemstack = false
   1587 	}
   1588 
   1589 vardcl_list:
   1590 	vardcl
   1591 |	vardcl_list ';' vardcl
   1592 	{
   1593 		$$ = concat($1, $3);
   1594 	}
   1595 
   1596 constdcl_list:
   1597 	constdcl1
   1598 |	constdcl_list ';' constdcl1
   1599 	{
   1600 		$$ = concat($1, $3);
   1601 	}
   1602 
   1603 typedcl_list:
   1604 	typedcl
   1605 	{
   1606 		$$ = list1($1);
   1607 	}
   1608 |	typedcl_list ';' typedcl
   1609 	{
   1610 		$$ = list($1, $3);
   1611 	}
   1612 
   1613 structdcl_list:
   1614 	structdcl
   1615 |	structdcl_list ';' structdcl
   1616 	{
   1617 		$$ = concat($1, $3);
   1618 	}
   1619 
   1620 interfacedcl_list:
   1621 	interfacedcl
   1622 	{
   1623 		$$ = list1($1);
   1624 	}
   1625 |	interfacedcl_list ';' interfacedcl
   1626 	{
   1627 		$$ = list($1, $3);
   1628 	}
   1629 
   1630 structdcl:
   1631 	new_name_list ntype oliteral
   1632 	{
   1633 		var l *NodeList
   1634 
   1635 		var n *Node
   1636 		l = $1;
   1637 		if l == nil || l.N.Sym.Name == "?" {
   1638 			// ? symbol, during import (list1(nil) == nil)
   1639 			n = $2;
   1640 			if n.Op == OIND {
   1641 				n = n.Left;
   1642 			}
   1643 			n = embedded(n.Sym, importpkg);
   1644 			n.Right = $2;
   1645 			n.SetVal($3)
   1646 			$$ = list1(n);
   1647 			break;
   1648 		}
   1649 
   1650 		for l=$1; l != nil; l=l.Next {
   1651 			l.N = Nod(ODCLFIELD, l.N, $2);
   1652 			l.N.SetVal($3)
   1653 		}
   1654 	}
   1655 |	embed oliteral
   1656 	{
   1657 		$1.SetVal($2)
   1658 		$$ = list1($1);
   1659 	}
   1660 |	'(' embed ')' oliteral
   1661 	{
   1662 		$2.SetVal($4)
   1663 		$$ = list1($2);
   1664 		Yyerror("cannot parenthesize embedded type");
   1665 	}
   1666 |	'*' embed oliteral
   1667 	{
   1668 		$2.Right = Nod(OIND, $2.Right, nil);
   1669 		$2.SetVal($3)
   1670 		$$ = list1($2);
   1671 	}
   1672 |	'(' '*' embed ')' oliteral
   1673 	{
   1674 		$3.Right = Nod(OIND, $3.Right, nil);
   1675 		$3.SetVal($5)
   1676 		$$ = list1($3);
   1677 		Yyerror("cannot parenthesize embedded type");
   1678 	}
   1679 |	'*' '(' embed ')' oliteral
   1680 	{
   1681 		$3.Right = Nod(OIND, $3.Right, nil);
   1682 		$3.SetVal($5)
   1683 		$$ = list1($3);
   1684 		Yyerror("cannot parenthesize embedded type");
   1685 	}
   1686 
   1687 packname:
   1688 	LNAME
   1689 	{
   1690 		var n *Node
   1691 
   1692 		$$ = $1;
   1693 		n = oldname($1);
   1694 		if n.Name != nil && n.Name.Pack != nil {
   1695 			n.Name.Pack.Used = true;
   1696 		}
   1697 	}
   1698 |	LNAME '.' sym
   1699 	{
   1700 		var pkg *Pkg
   1701 
   1702 		if $1.Def == nil || $1.Def.Op != OPACK {
   1703 			Yyerror("%v is not a package", $1);
   1704 			pkg = localpkg;
   1705 		} else {
   1706 			$1.Def.Used = true;
   1707 			pkg = $1.Def.Name.Pkg;
   1708 		}
   1709 		$$ = restrictlookup($3.Name, pkg);
   1710 	}
   1711 
   1712 embed:
   1713 	packname
   1714 	{
   1715 		$$ = embedded($1, localpkg);
   1716 	}
   1717 
   1718 interfacedcl:
   1719 	new_name indcl
   1720 	{
   1721 		$$ = Nod(ODCLFIELD, $1, $2);
   1722 		ifacedcl($$);
   1723 	}
   1724 |	packname
   1725 	{
   1726 		$$ = Nod(ODCLFIELD, nil, oldname($1));
   1727 	}
   1728 |	'(' packname ')'
   1729 	{
   1730 		$$ = Nod(ODCLFIELD, nil, oldname($2));
   1731 		Yyerror("cannot parenthesize embedded type");
   1732 	}
   1733 
   1734 indcl:
   1735 	'(' oarg_type_list_ocomma ')' fnres
   1736 	{
   1737 		// without func keyword
   1738 		$2 = checkarglist($2, 1);
   1739 		$$ = Nod(OTFUNC, fakethis(), nil);
   1740 		$$.List = $2;
   1741 		$$.Rlist = $4;
   1742 	}
   1743 
   1744 /*
   1745  * function arguments.
   1746  */
   1747 arg_type:
   1748 	name_or_type
   1749 |	sym name_or_type
   1750 	{
   1751 		$$ = Nod(ONONAME, nil, nil);
   1752 		$$.Sym = $1;
   1753 		$$ = Nod(OKEY, $$, $2);
   1754 	}
   1755 |	sym dotdotdot
   1756 	{
   1757 		$$ = Nod(ONONAME, nil, nil);
   1758 		$$.Sym = $1;
   1759 		$$ = Nod(OKEY, $$, $2);
   1760 	}
   1761 |	dotdotdot
   1762 
   1763 arg_type_list:
   1764 	arg_type
   1765 	{
   1766 		$$ = list1($1);
   1767 	}
   1768 |	arg_type_list ',' arg_type
   1769 	{
   1770 		$$ = list($1, $3);
   1771 	}
   1772 
   1773 oarg_type_list_ocomma:
   1774 	{
   1775 		$$ = nil;
   1776 	}
   1777 |	arg_type_list ocomma
   1778 	{
   1779 		$$ = $1;
   1780 	}
   1781 
   1782 /*
   1783  * statement
   1784  */
   1785 stmt:
   1786 	{
   1787 		$$ = nil;
   1788 	}
   1789 |	compound_stmt
   1790 |	common_dcl
   1791 	{
   1792 		$$ = liststmt($1);
   1793 	}
   1794 |	non_dcl_stmt
   1795 |	error
   1796 	{
   1797 		$$ = nil;
   1798 	}
   1799 
   1800 non_dcl_stmt:
   1801 	simple_stmt
   1802 |	for_stmt
   1803 |	switch_stmt
   1804 |	select_stmt
   1805 |	if_stmt
   1806 |	labelname ':'
   1807 	{
   1808 		$1 = Nod(OLABEL, $1, nil);
   1809 		$1.Sym = dclstack;  // context, for goto restrictions
   1810 	}
   1811 	stmt
   1812 	{
   1813 		var l *NodeList
   1814 
   1815 		$1.Name.Defn = $4;
   1816 		l = list1($1);
   1817 		if $4 != nil {
   1818 			l = list(l, $4);
   1819 		}
   1820 		$$ = liststmt(l);
   1821 	}
   1822 |	LFALL
   1823 	{
   1824 		// will be converted to OFALL
   1825 		$$ = Nod(OXFALL, nil, nil);
   1826 		$$.Xoffset = int64(block);
   1827 	}
   1828 |	LBREAK onew_name
   1829 	{
   1830 		$$ = Nod(OBREAK, $2, nil);
   1831 	}
   1832 |	LCONTINUE onew_name
   1833 	{
   1834 		$$ = Nod(OCONTINUE, $2, nil);
   1835 	}
   1836 |	LGO pseudocall
   1837 	{
   1838 		$$ = Nod(OPROC, $2, nil);
   1839 	}
   1840 |	LDEFER pseudocall
   1841 	{
   1842 		$$ = Nod(ODEFER, $2, nil);
   1843 	}
   1844 |	LGOTO new_name
   1845 	{
   1846 		$$ = Nod(OGOTO, $2, nil);
   1847 		$$.Sym = dclstack;  // context, for goto restrictions
   1848 	}
   1849 |	LRETURN oexpr_list
   1850 	{
   1851 		$$ = Nod(ORETURN, nil, nil);
   1852 		$$.List = $2;
   1853 		if $$.List == nil && Curfn != nil {
   1854 			var l *NodeList
   1855 
   1856 			for l=Curfn.Func.Dcl; l != nil; l=l.Next {
   1857 				if l.N.Class == PPARAM {
   1858 					continue;
   1859 				}
   1860 				if l.N.Class != PPARAMOUT {
   1861 					break;
   1862 				}
   1863 				if l.N.Sym.Def != l.N {
   1864 					Yyerror("%s is shadowed during return", l.N.Sym.Name);
   1865 				}
   1866 			}
   1867 		}
   1868 	}
   1869 
   1870 stmt_list:
   1871 	stmt
   1872 	{
   1873 		$$ = nil;
   1874 		if $1 != nil {
   1875 			$$ = list1($1);
   1876 		}
   1877 	}
   1878 |	stmt_list ';' stmt
   1879 	{
   1880 		$$ = $1;
   1881 		if $3 != nil {
   1882 			$$ = list($$, $3);
   1883 		}
   1884 	}
   1885 
   1886 new_name_list:
   1887 	new_name
   1888 	{
   1889 		$$ = list1($1);
   1890 	}
   1891 |	new_name_list ',' new_name
   1892 	{
   1893 		$$ = list($1, $3);
   1894 	}
   1895 
   1896 dcl_name_list:
   1897 	dcl_name
   1898 	{
   1899 		$$ = list1($1);
   1900 	}
   1901 |	dcl_name_list ',' dcl_name
   1902 	{
   1903 		$$ = list($1, $3);
   1904 	}
   1905 
   1906 expr_list:
   1907 	expr
   1908 	{
   1909 		$$ = list1($1);
   1910 	}
   1911 |	expr_list ',' expr
   1912 	{
   1913 		$$ = list($1, $3);
   1914 	}
   1915 
   1916 expr_or_type_list:
   1917 	expr_or_type
   1918 	{
   1919 		$$ = list1($1);
   1920 	}
   1921 |	expr_or_type_list ',' expr_or_type
   1922 	{
   1923 		$$ = list($1, $3);
   1924 	}
   1925 
   1926 /*
   1927  * list of combo of keyval and val
   1928  */
   1929 keyval_list:
   1930 	keyval
   1931 	{
   1932 		$$ = list1($1);
   1933 	}
   1934 |	bare_complitexpr
   1935 	{
   1936 		$$ = list1($1);
   1937 	}
   1938 |	keyval_list ',' keyval
   1939 	{
   1940 		$$ = list($1, $3);
   1941 	}
   1942 |	keyval_list ',' bare_complitexpr
   1943 	{
   1944 		$$ = list($1, $3);
   1945 	}
   1946 
   1947 braced_keyval_list:
   1948 	{
   1949 		$$ = nil;
   1950 	}
   1951 |	keyval_list ocomma
   1952 	{
   1953 		$$ = $1;
   1954 	}
   1955 
   1956 /*
   1957  * optional things
   1958  */
   1959 osemi:
   1960 |	';'
   1961 
   1962 ocomma:
   1963 |	','
   1964 
   1965 oexpr:
   1966 	{
   1967 		$$ = nil;
   1968 	}
   1969 |	expr
   1970 
   1971 oexpr_list:
   1972 	{
   1973 		$$ = nil;
   1974 	}
   1975 |	expr_list
   1976 
   1977 osimple_stmt:
   1978 	{
   1979 		$$ = nil;
   1980 	}
   1981 |	simple_stmt
   1982 
   1983 ohidden_funarg_list:
   1984 	{
   1985 		$$ = nil;
   1986 	}
   1987 |	hidden_funarg_list
   1988 
   1989 ohidden_structdcl_list:
   1990 	{
   1991 		$$ = nil;
   1992 	}
   1993 |	hidden_structdcl_list
   1994 
   1995 ohidden_interfacedcl_list:
   1996 	{
   1997 		$$ = nil;
   1998 	}
   1999 |	hidden_interfacedcl_list
   2000 
   2001 oliteral:
   2002 	{
   2003 		$$.U = nil
   2004 	}
   2005 |	LLITERAL
   2006 
   2007 /*
   2008  * import syntax from package header
   2009  */
   2010 hidden_import:
   2011 	LIMPORT LNAME LLITERAL ';'
   2012 	{
   2013 		importimport($2, $3.U.(string));
   2014 	}
   2015 |	LVAR hidden_pkg_importsym hidden_type ';'
   2016 	{
   2017 		importvar($2, $3);
   2018 	}
   2019 |	LCONST hidden_pkg_importsym '=' hidden_constant ';'
   2020 	{
   2021 		importconst($2, Types[TIDEAL], $4);
   2022 	}
   2023 |	LCONST hidden_pkg_importsym hidden_type '=' hidden_constant ';'
   2024 	{
   2025 		importconst($2, $3, $5);
   2026 	}
   2027 |	LTYPE hidden_pkgtype hidden_type ';'
   2028 	{
   2029 		importtype($2, $3);
   2030 	}
   2031 |	LFUNC hidden_fndcl fnbody ';'
   2032 	{
   2033 		if $2 == nil {
   2034 			dclcontext = PEXTERN;  // since we skip the funcbody below
   2035 			break;
   2036 		}
   2037 
   2038 		$2.Func.Inl = $3;
   2039 
   2040 		funcbody($2);
   2041 		importlist = list(importlist, $2);
   2042 
   2043 		if Debug['E'] > 0 {
   2044 			fmt.Printf("import [%q] func %v \n", importpkg.Path, $2)
   2045 			if Debug['m'] > 2 && $2.Func.Inl != nil {
   2046 				fmt.Printf("inl body:%v\n", $2.Func.Inl)
   2047 			}
   2048 		}
   2049 	}
   2050 
   2051 hidden_pkg_importsym:
   2052 	hidden_importsym
   2053 	{
   2054 		$$ = $1;
   2055 		structpkg = $$.Pkg;
   2056 	}
   2057 
   2058 hidden_pkgtype:
   2059 	hidden_pkg_importsym
   2060 	{
   2061 		$$ = pkgtype($1);
   2062 		importsym($1, OTYPE);
   2063 	}
   2064 
   2065 /*
   2066  *  importing types
   2067  */
   2068 
   2069 hidden_type:
   2070 	hidden_type_misc
   2071 |	hidden_type_recv_chan
   2072 |	hidden_type_func
   2073 
   2074 hidden_type_non_recv_chan:
   2075 	hidden_type_misc
   2076 |	hidden_type_func
   2077 
   2078 hidden_type_misc:
   2079 	hidden_importsym
   2080 	{
   2081 		$$ = pkgtype($1);
   2082 	}
   2083 |	LNAME
   2084 	{
   2085 		// predefined name like uint8
   2086 		$1 = Pkglookup($1.Name, builtinpkg);
   2087 		if $1.Def == nil || $1.Def.Op != OTYPE {
   2088 			Yyerror("%s is not a type", $1.Name);
   2089 			$$ = nil;
   2090 		} else {
   2091 			$$ = $1.Def.Type;
   2092 		}
   2093 	}
   2094 |	'[' ']' hidden_type
   2095 	{
   2096 		$$ = aindex(nil, $3);
   2097 	}
   2098 |	'[' LLITERAL ']' hidden_type
   2099 	{
   2100 		$$ = aindex(nodlit($2), $4);
   2101 	}
   2102 |	LMAP '[' hidden_type ']' hidden_type
   2103 	{
   2104 		$$ = maptype($3, $5);
   2105 	}
   2106 |	LSTRUCT '{' ohidden_structdcl_list '}'
   2107 	{
   2108 		$$ = tostruct($3);
   2109 	}
   2110 |	LINTERFACE '{' ohidden_interfacedcl_list '}'
   2111 	{
   2112 		$$ = tointerface($3);
   2113 	}
   2114 |	'*' hidden_type
   2115 	{
   2116 		$$ = Ptrto($2);
   2117 	}
   2118 |	LCHAN hidden_type_non_recv_chan
   2119 	{
   2120 		$$ = typ(TCHAN);
   2121 		$$.Type = $2;
   2122 		$$.Chan = Cboth;
   2123 	}
   2124 |	LCHAN '(' hidden_type_recv_chan ')'
   2125 	{
   2126 		$$ = typ(TCHAN);
   2127 		$$.Type = $3;
   2128 		$$.Chan = Cboth;
   2129 	}
   2130 |	LCHAN LCOMM hidden_type
   2131 	{
   2132 		$$ = typ(TCHAN);
   2133 		$$.Type = $3;
   2134 		$$.Chan = Csend;
   2135 	}
   2136 
   2137 hidden_type_recv_chan:
   2138 	LCOMM LCHAN hidden_type
   2139 	{
   2140 		$$ = typ(TCHAN);
   2141 		$$.Type = $3;
   2142 		$$.Chan = Crecv;
   2143 	}
   2144 
   2145 hidden_type_func:
   2146 	LFUNC '(' ohidden_funarg_list ')' ohidden_funres
   2147 	{
   2148 		$$ = functype(nil, $3, $5);
   2149 	}
   2150 
   2151 hidden_funarg:
   2152 	sym hidden_type oliteral
   2153 	{
   2154 		$$ = Nod(ODCLFIELD, nil, typenod($2));
   2155 		if $1 != nil {
   2156 			$$.Left = newname($1);
   2157 		}
   2158 		$$.SetVal($3)
   2159 	}
   2160 |	sym LDDD hidden_type oliteral
   2161 	{
   2162 		var t *Type
   2163 
   2164 		t = typ(TARRAY);
   2165 		t.Bound = -1;
   2166 		t.Type = $3;
   2167 
   2168 		$$ = Nod(ODCLFIELD, nil, typenod(t));
   2169 		if $1 != nil {
   2170 			$$.Left = newname($1);
   2171 		}
   2172 		$$.Isddd = true;
   2173 		$$.SetVal($4)
   2174 	}
   2175 
   2176 hidden_structdcl:
   2177 	sym hidden_type oliteral
   2178 	{
   2179 		var s *Sym
   2180 		var p *Pkg
   2181 
   2182 		if $1 != nil && $1.Name != "?" {
   2183 			$$ = Nod(ODCLFIELD, newname($1), typenod($2));
   2184 			$$.SetVal($3)
   2185 		} else {
   2186 			s = $2.Sym;
   2187 			if s == nil && Isptr[$2.Etype] {
   2188 				s = $2.Type.Sym;
   2189 			}
   2190 			p = importpkg;
   2191 			if $1 != nil {
   2192 				p = $1.Pkg;
   2193 			}
   2194 			$$ = embedded(s, p);
   2195 			$$.Right = typenod($2);
   2196 			$$.SetVal($3)
   2197 		}
   2198 	}
   2199 
   2200 hidden_interfacedcl:
   2201 	sym '(' ohidden_funarg_list ')' ohidden_funres
   2202 	{
   2203 		$$ = Nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
   2204 	}
   2205 |	hidden_type
   2206 	{
   2207 		$$ = Nod(ODCLFIELD, nil, typenod($1));
   2208 	}
   2209 
   2210 ohidden_funres:
   2211 	{
   2212 		$$ = nil;
   2213 	}
   2214 |	hidden_funres
   2215 
   2216 hidden_funres:
   2217 	'(' ohidden_funarg_list ')'
   2218 	{
   2219 		$$ = $2;
   2220 	}
   2221 |	hidden_type
   2222 	{
   2223 		$$ = list1(Nod(ODCLFIELD, nil, typenod($1)));
   2224 	}
   2225 
   2226 /*
   2227  *  importing constants
   2228  */
   2229 
   2230 hidden_literal:
   2231 	LLITERAL
   2232 	{
   2233 		$$ = nodlit($1);
   2234 	}
   2235 |	'-' LLITERAL
   2236 	{
   2237 		$$ = nodlit($2);
   2238 		switch($$.Val().Ctype()){
   2239 		case CTINT, CTRUNE:
   2240 			mpnegfix($$.Val().U.(*Mpint));
   2241 			break;
   2242 		case CTFLT:
   2243 			mpnegflt($$.Val().U.(*Mpflt));
   2244 			break;
   2245 		case CTCPLX:
   2246 			mpnegflt(&$$.Val().U.(*Mpcplx).Real);
   2247 			mpnegflt(&$$.Val().U.(*Mpcplx).Imag);
   2248 			break;
   2249 		default:
   2250 			Yyerror("bad negated constant");
   2251 		}
   2252 	}
   2253 |	sym
   2254 	{
   2255 		$$ = oldname(Pkglookup($1.Name, builtinpkg));
   2256 		if $$.Op != OLITERAL {
   2257 			Yyerror("bad constant %v", $$.Sym);
   2258 		}
   2259 	}
   2260 
   2261 hidden_constant:
   2262 	hidden_literal
   2263 |	'(' hidden_literal '+' hidden_literal ')'
   2264 	{
   2265 		if $2.Val().Ctype() == CTRUNE && $4.Val().Ctype() == CTINT {
   2266 			$$ = $2;
   2267 			mpaddfixfix($2.Val().U.(*Mpint), $4.Val().U.(*Mpint), 0);
   2268 			break;
   2269 		}
   2270 		$4.Val().U.(*Mpcplx).Real = $4.Val().U.(*Mpcplx).Imag;
   2271 		Mpmovecflt(&$4.Val().U.(*Mpcplx).Imag, 0.0);
   2272 		$$ = nodcplxlit($2.Val(), $4.Val());
   2273 	}
   2274 
   2275 hidden_import_list:
   2276 |	hidden_import_list hidden_import
   2277 
   2278 hidden_funarg_list:
   2279 	hidden_funarg
   2280 	{
   2281 		$$ = list1($1);
   2282 	}
   2283 |	hidden_funarg_list ',' hidden_funarg
   2284 	{
   2285 		$$ = list($1, $3);
   2286 	}
   2287 
   2288 hidden_structdcl_list:
   2289 	hidden_structdcl
   2290 	{
   2291 		$$ = list1($1);
   2292 	}
   2293 |	hidden_structdcl_list ';' hidden_structdcl
   2294 	{
   2295 		$$ = list($1, $3);
   2296 	}
   2297 
   2298 hidden_interfacedcl_list:
   2299 	hidden_interfacedcl
   2300 	{
   2301 		$$ = list1($1);
   2302 	}
   2303 |	hidden_interfacedcl_list ';' hidden_interfacedcl
   2304 	{
   2305 		$$ = list($1, $3);
   2306 	}
   2307 
   2308 %%
   2309 func fixlbrace(lbr int) {
   2310 	// If the opening brace was an LBODY,
   2311 	// set up for another one now that we're done.
   2312 	// See comment in lex.C about loophack.
   2313 	if lbr == LBODY {
   2314 		loophack = 1
   2315 	}
   2316 }
   2317