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