/parser/parser.y
Happy | 3233 lines | 2814 code | 419 blank | 0 comment | 0 complexity | 51b75304e15e25bcbee69e801de89474 MD5 | raw file
Possible License(s): BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- %{
- // Copyright 2012 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- // CAUTION: If this file is 'parser.go', it was generated
- // automatically from 'parser.y' - DO NOT EDIT in that case!
- /*
- Tracks:
- -----------------------------------------------
- Revision: f1deaf35e1d1
- Author: Luuk van Dijk <l...@golang.org>
- Date: Jan 17 2012
- Branch: default
- */
- /*TODO
- OPACK handling
- "release":
- - i_, val_, sym_, node_ list_ prefixes?
- */
- package parser
- import (
- "fmt"
- "go/token"
- )
- %}
- %union{
- pos token.Pos
- list []*Node
- node *Node
- sym *Sym
- val *Val
- closure func()
- i int
- }
- %token <val> val_LLITERAL
- %token <i> i_LASOP
- %token LBREAK LCASE LCHAN LCOLAS LCONST LCONTINUE LDDD
- %token LDEFAULT LDEFER LELSE LFALL LFOR LFUNC LGO LGOTO
- %token LIF LIMPORT LINTERFACE LMAP
- %token <sym> sym_LNAME
- %token LPACKAGE LRANGE LRETURN LSELECT LSTRUCT LSWITCH
- %token LTYPE LVAR
- %token LANDAND LANDNOT LBODY LCOMM LDEC LEQ LGE LGT
- %token LIGNORE LINC LLE LLSH LLT LNE LOROR LRSH
- %type <i> i_lbrace i_import_here
- %type <sym> sym_sym sym_packname
- %type <val> val_oliteral
- %type <node> node_stmt node_ntype
- %type <node> node_arg_type
- %type <node> node_case node_caseblock
- %type <node> node_compound_stmt node_dotname node_embed node_expr node_complitexpr
- %type <node> node_expr_or_type
- %type <node> node_fndcl /*node_hidden_fndcl*/ node_fnliteral
- %type <node> node_for_body node_for_header node_for_stmt node_if_header node_if_stmt node_else node_non_dcl_stmt
- %type <node> node_interfacedcl node_keyval node_labelname node_name
- %type <node> node_name_or_type node_non_expr_type
- %type <node> node_new_name node_dcl_name node_oexpr node_typedclname
- %type <node> node_onew_name
- %type <node> node_osimple_stmt node_pexpr node_pexpr_no_paren
- %type <node> node_pseudocall node_range_stmt node_select_stmt
- %type <node> node_simple_stmt
- %type <node> node_switch_stmt node_uexpr
- %type <node> node_xfndcl node_typedcl node_start_complit
- %type <node> node_fnlitdcl
- %type <list> list_xdcl list_fnbody list_fnres list_loop_body list_dcl_name_list
- %type <list> list_new_name_list list_expr_list list_keyval_list list_braced_keyval_list list_expr_or_type_list list_xdcl_list
- %type <list> list_oexpr_list list_caseblock_list list_stmt_list list_oarg_type_list_ocomma list_arg_type_list
- %type <list> list_interfacedcl_list list_vardcl list_vardcl_list list_structdcl list_structdcl_list
- %type <list> list_common_dcl list_constdcl list_constdcl1 list_constdcl_list list_typedcl_list
- %type <node> node_convtype node_comptype node_dotdotdot
- %type <node> node_indcl node_interfacetype node_structtype node_ptrtype
- %type <node> node_recvchantype node_non_recvchantype node_othertype node_fnret_type node_fntype
- /*
- %type <sym> sym_hidden_importsym sym_hidden_pkg_importsym
- %type <node> node_hidden_constant node_hidden_literal node_hidden_funarg
- %type <node> node_hidden_interfacedcl node_hidden_structdcl
- %type <list> list_hidden_funres
- %type <list> list_ohidden_funres
- %type <list> list_hidden_funarg_list list_ohidden_funarg_list
- %type <list> list_hidden_interfacedcl_list list_ohidden_interfacedcl_list
- %type <list> list_hidden_structdcl_list list_ohidden_structdcl_list
- %type <type> type_hidden_type type_hidden_type_misc type_hidden_pkgtype
- %type <type> type_hidden_type_func
- %type <type> type_hidden_type_recv_chan type_hidden_type_non_recv_chan
- */
- %left LCOMM /* outside the usual hierarchy; here for good error messages */
- %left LOROR
- %left LANDAND
- %left LEQ LNE LLE LGE LLT LGT
- %left '+' '-' '|' '^'
- %left '*' '/' '%' '&' LLSH LRSH LANDNOT
- /*
- * manual override of shift/reduce conflicts.
- * the general form is that we assign a precedence
- * to the token being shifted and then introduce
- * NotToken with lower precedence or PreferToToken with higher
- * and annotate the reducing rule accordingly.
- */
- %left NotPackage
- %left LPACKAGE
- %left NotParen
- %left '('
- %left ')'
- %left PreferToRightParen
- %%
- file:
- /*
- loadsys
- */
- package
- imports
- list_xdcl_list
- {
- /*
- xtop = concat(xtop, $4);
- */
- yylex.top = append(yylex.top, $3...)
- if !yylex.errored {
- s := yylex.scope
- if s == nil || s.Tag != FileScope {
- internalError("!= FileScope")
- }
- s = s.Outer
- if s == nil || s.Tag != PackageScope {
- internalError("!= PackageScope")
- }
- s = s.Outer
- if s == nil || s.Tag != UniverseScope {
- internalError("!= UniverseScope")
- }
- }
- for yylex.scope != nil && yylex.scope.Tag != PackageScope {
- yylex.scope = yylex.scope.Outer
- }
- }
- package:
- %prec NotPackage
- {
- /*
- prevlineno = lineno;
- yyerror("package statement must be first");
- flusherrors();
- mkpackage("main");
- */
- yylex.Error("package statement must be first")
- }
- | LPACKAGE sym_sym ';'
- {
- //mkpackage($2->node_name);
- new := string($2.Name)
- if new == "_" {
- yylex.error($<pos>2, "invalid package name _")
- }
- if old := yylex.pkg; old != "" && old != new {
- yylex.error($<pos>2, "expected package %q got %q", old, new)
- }
- yylex.pkg = new
- }
- /*
- * this loads the definitions for the low-level runtime functions,
- * so that the compiler can generate calls to them,
- * but does not make the node_name "runtime" visible as a package.
- */
- /*
- loadsys:
- {
- importpkg = runtimepkg;
- if(debug['A'])
- cannedimports("runtime.builtin", "package runtime\n\n$$\n\n");
- else
- cannedimports("runtime.builtin", runtimeimport);
- curio.importsafe = 1;
- }
- import_package
- import_there
- {
- importpkg = nil;
- }
- */
- imports:
- | imports import ';'
- import:
- LIMPORT import_stmt
- | LIMPORT '(' import_stmt_list osemi ')'
- | LIMPORT '(' ')'
- import_stmt:
- i_import_here /*import_package import_there*/
- {
- /*
- Pkg *ipkg;
- Sym *my;
- Node *pack;
-
- ipkg = importpkg;
- my = importmyname;
- importpkg = nil;
- importmyname = S;
- if(my == nil)
- my = lookup(ipkg->node_name);
- pack = nod(OPACK, N, N);
- pack->sym_sym = my;
- pack->pkg = ipkg;
- pack->lineno = $1;
- if(my->node_name[0] == '.') {
- importdot(ipkg, pack);
- break;
- }
- if(my->node_name[0] == '_' && my->node_name[1] == '\0')
- break;
- if(my->def) {
- lineno = $1;
- redeclare(my, "as imported package node_name");
- }
- my->def = pack;
- my->lastlineno = $1;
- my->block = 1; // at top level
- */
- }
- import_stmt_list:
- import_stmt
- | import_stmt_list ';' import_stmt
- i_import_here:
- val_LLITERAL
- {
- /*
- // import with original name
- $$ = parserline();
- importmyname = S;
- importfile(&$1, $$);
- */
-
- $$ = -1
- /*internalError(243)*/ //TODO
- }
- | sym_sym val_LLITERAL
- {
- /*
- // import with given name
- $$ = parserline();
- importmyname = $1;
- importfile(&$2, $$);
- */
-
- $$ = -1
- /*internalError(255)*/ //TODO
- }
- | '.' val_LLITERAL
- {
- /*
- // import into my name space
- $$ = parserline();
- importmyname = lookup(".");
- importfile(&$2, $$);
- */
-
- $$ = -1
- /*internalError(267)*/ //TODO
- }
- /*
- import_package:
- LPACKAGE sym_LNAME import_safety ';'
- {
- if(importpkg->node_name == nil) {
- importpkg->node_name = $2->node_name;
- pkglookup($2->node_name, nil)->npkg++;
- } else if(strcmp(importpkg->node_name, $2->node_name) != 0)
- yyerror("conflicting names %s and %s for package \"%Z\"", importpkg->node_name, $2->node_name, importpkg->path);
- importpkg->direct = 1;
-
- if(safemode && !curio.importsafe)
- yyerror("cannot import unsafe package \"%Z\"", importpkg->path);
- }
- import_safety:
- | sym_LNAME
- {
- if(strcmp($1->node_name, "safe") == 0)
- curio.importsafe = 1;
- }
- import_there:
- {
- defercheckwidth();
- }
- hidden_import_list '$' '$'
- {
- resumecheckwidth();
- unimportfile();
- }
- */
- /*
- * declarations
- */
- list_xdcl:
- {
- /*
- yyerror("empty top-level declaration");
- $$ = nil;
- */
- $$ = nil
- yylex.Error("empty top-level declaration")
- }
- | list_common_dcl
- | node_xfndcl
- {
- /*
- $$ = list1($1);
- */
- $$ = $1.list()
- }
- | node_non_dcl_stmt
- {
- /*
- yyerror("non-declaration statement outside function body");
- $$ = nil;
- */
- yylex.error($<pos>1, "non-declaration statement outside function body")
- $$ = nil
- }
- | error
- {
- /*
- $$ = nil;
- */
-
- $$ = nil
- //TODO yylex.error()?
- }
- list_common_dcl:
- LVAR list_vardcl
- {
- /*
- $$ = $2;
- */
- $$ = $2
- }
- | LVAR '(' list_vardcl_list osemi ')'
- {
- /*
- $$ = $3;
- */
-
- $$ = $3
- }
- | LVAR '(' ')'
- {
- /*
- $$ = nil;
- */
- $$ = nil
- }
- | lconst list_constdcl
- {
- /*
- $$ = $2;
- iota = -100000;
- lastconst = nil;
- */
- $$ = $2
- }
- | lconst '(' list_constdcl osemi ')'
- {
- /*
- $$ = $3;
- iota = -100000;
- lastconst = nil;
- */
- $$ = $3
- }
- | lconst '(' list_constdcl ';' list_constdcl_list osemi ')'
- {
- /*
- $$ = concat($3, $5);
- iota = -100000;
- lastconst = nil;
- */
- $$ = append($3, $5...)
- }
- | lconst '(' ')'
- {
- /*
- $$ = nil;
- iota = -100000;
- */
- $$ = nil
- }
- | LTYPE node_typedcl
- {
- /*
- $$ = list1($2);
- */
- $$ = $2.list()
- }
- | LTYPE '(' list_typedcl_list osemi ')'
- {
- /*
- $$ = $3;
- */
- $$ = $3
- }
- | LTYPE '(' ')'
- {
- /*
- $$ = nil;
- */
- $$ = nil
- }
- lconst:
- LCONST
- {
- /*
- iota = 0;
- */
- yylex.iota = 0
- }
- list_vardcl: //TODO -> <node>?
- list_dcl_name_list node_ntype
- {
- /*
- $$ = variter($1, $2, nil);
- */
- $$ = (&Node{Pos: $<pos>1, Op: ODCL, LL: $1, NL: $2}).list()
- }
- | list_dcl_name_list node_ntype '=' list_expr_list
- {
- /*
- $$ = variter($1, $2, $4);
- */
- $$ = (&Node{Pos: $<pos>1, Op: ODCL, LL: $1, NL: $2, LR: $4}).list()
- }
- | list_dcl_name_list '=' list_expr_list
- {
- /*
- $$ = variter($1, nil, $3);
- */
- $$ = (&Node{Pos: $<pos>1, Op: ODCL, LL: $1, LR: $3}).list()
- }
- list_constdcl: //TODO -> <node>?
- list_dcl_name_list node_ntype '=' list_expr_list
- {
- /*
- $$ = constiter($1, $2, $4);
- */
- for _, v := range $1 { //TODO -DRY
- v.Iota = yylex.iota
- }
- yylex.iota++
- $$ = (&Node{Pos: $<pos>1, Op: ODCLCONST, LL: $1, NL: $2, LR: $4}).list()
- }
- | list_dcl_name_list '=' list_expr_list
- {
- /*
- $$ = constiter($1, N, $3);
- */
- for _, v := range $1 { //TODO -DRY
- v.Iota = yylex.iota
- }
- yylex.iota++
- $$ = (&Node{Pos: $<pos>1, Op: ODCLCONST, LL: $1, LR: $3}).list()
- }
- list_constdcl1:
- list_constdcl
- | list_dcl_name_list node_ntype
- {
- /*
- $$ = constiter($1, $2, nil);
- */
- for _, v := range $1 { //TODO -DRY
- v.Iota = yylex.iota
- }
- yylex.iota++
- $$ = (&Node{Pos: $<pos>1, Op: ODCLCONST, LL: $1, NL: $2}).list()
- yylex.error($<pos>2, "constdcl cannot have type without expr")
- }
- | list_dcl_name_list
- {
- /*
- $$ = constiter($1, N, nil);
- */
- for _, v := range $1 { //TODO -DRY
- v.Iota = yylex.iota
- }
- yylex.iota++
- $$ = (&Node{Pos: $<pos>1, Op: ODCLCONST, LL: $1}).list()
- }
- node_typedclname:
- sym_sym
- {
- /*
- // different from dclname because the node_name
- // becomes visible right here, not at the end
- // of the declaration.
- $$ = typedcl0($1);
- */
- $$ = &Node{Pos: $<pos>1, Op: ONAME, Name: $1}
- }
- node_typedcl:
- node_typedclname node_ntype
- {
- /*
- $$ = typedcl1($1, $2, 1);
- */
- if $2.Op == OTARRAY && $2.NL != nil && $2.NL.Op == ODDD {
- yylex.error($2.NL.Pos, "use of [...] array outside of array literal")
- }
- $$ = &Node{Pos: $<pos>1, Op: ODCLTYPE, NL: $1, NR: $2}
- }
- node_simple_stmt:
- node_expr
- /*
- {
- $$ = $1;
- }
- */
- | node_expr i_LASOP node_expr
- {
- /*
- $$ = nod(OASOP, $1, $3);
- $$->etype = $2; // rathole to pass opcode
- */
- $$ = &Node{Pos: $<pos>1, Op: OASOP, NL: $1, AsOpTok: $2, NR: $3}
- }
- | list_expr_list '=' list_expr_list
- {
- /*
- if($1->next == nil && $3->next == nil) {
- // simple
- $$ = nod(OAS, $1->n, $3->n);
- break;
- }
- // multiple
- $$ = nod(OAS2, N, N);
- $$->list = $1;
- $$->rlist = $3;
- */
- if len($1) == 1 && len($3) == 1 {
- $$ = &Node{Pos: $<pos>1, Op: OAS, NL: $1[0], NR: $3[0]}
- break
- }
- $$ = &Node{Pos: $<pos>1, Op: OAS2, LL: $1, LR: $3}
- }
- | list_expr_list LCOLAS list_expr_list
- {
- /*
- if($3->n->op == OTYPESW) {
- $$ = nod(OTYPESW, N, $3->n->right);
- if($3->next != nil)
- yyerror("node_expr.(type) must be alone in list");
- if($1->next != nil)
- yyerror("argument count mismatch: %d = %d", count($1), 1);
- else if($1->n->op != ONAME && $1->n->op != OTYPE && $1->n->op != ONONAME)
- yyerror("invalid variable name %N in type switch", $1->n);
- else
- $$->left = dclname($1->n->sym_sym); // it's a colas, so must not re-use an oldname.
- break;
- }
- $$ = colas($1, $3);
- */
- //TODO above!
- if n := $3[0]; n.Op == OTYPESW {
- $$ = n
- if len($3) != 1 {
- yylex.error($3[1].Pos, "node_expr.(type) must be alone in list")
- }
- if n := len($1); n > 1 {
- yylex.error($<pos>1, "argument count mismatch: %d = %d", n, 1)
- }
- if n := $1[0]; n.Op != ONAME {
- yylex.error($<pos>1, "invalid variable name %s in type switch", n);
- }
- break
- }
- $$ = yylex.colas($1, $3)
- }
- | node_expr LINC
- {
- /*
- $$ = nod(OASOP, $1, nodintconst(1));
- $$->etype = OADD;
- */
- $$ = &Node{Pos: $<pos>1, Op: OINC, NL: $1}
- }
- | node_expr LDEC
- {
- /*
- $$ = nod(OASOP, $1, nodintconst(1));
- $$->etype = OSUB;
- */
- $$ = &Node{Pos: $<pos>1, Op: ODEC, NL: $1}
- }
- node_case:
- LCASE list_expr_or_type_list ':'
- {
- /*
- Node *n, *nn;
- // will be converted to OCASE
- // right will point to next node_case
- // done in casebody()
- markdcl();
- $$ = nod(OXCASE, N, N);
- $$->list = $2;
- if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
- // type switch - declare variable
- nn = newname(n->sym_sym);
- declare(nn, dclcontext);
- $$->nname = nn;
- // keep track of the instances for reporting unused
- nn->defn = typesw->right;
- }
- */
- yylex.newScope(OtherScope)
- $$ = &Node{Pos: $<pos>1, Op: OCASE, LL: $2}
- }
- | LCASE list_expr_or_type_list '=' node_expr ':'
- {
- /*
- Node *n;
- // will be converted to OCASE
- // right will point to next node_case
- // done in casebody()
- markdcl();
- $$ = nod(OXCASE, N, N);
- if($2->next == nil)
- n = nod(OAS, $2->n, $4);
- else {
- n = nod(OAS2, N, N);
- n->list = $2;
- n->rlist = list1($4);
- }
- $$->list = list1(n);
- */
- yylex.newScope(OtherScope)
- $$ = &Node{Pos: $<pos>1, Op: OCASE, LL: $2, NL: $4}
- if len($2) == 1 {
- $$.NL = &Node{Pos: $<pos>2, Op: OAS, NL: $2[0], NR: $4}
- break
- }
- $$.NL = &Node{Pos: $<pos>2, Op: OAS, LL: $2, LR: $4.list()}
- }
- | LCASE list_expr_or_type_list LCOLAS node_expr ':'
- {
- /*
- // will be converted to OCASE
- // right will point to next node_case
- // done in casebody()
- markdcl();
- $$ = nod(OXCASE, N, N);
- $$->list = list1(colas($2, list1($4)));
- */
- yylex.newScope(OtherScope)
- $$ = &Node{Pos: $<pos>1, Op: OCASE}
- $$.NL = yylex.colas($2, $4.list())
- }
- | LDEFAULT ':'
- {
- /*
- Node *n, *nn;
- markdcl();
- $$ = nod(OXCASE, N, N);
- if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
- // type switch - declare variable
- nn = newname(n->sym_sym);
- declare(nn, dclcontext);
- $$->nname = nn;
- // keep track of the instances for reporting unused
- nn->defn = typesw->right;
- }
- */
- yylex.newScope(OtherScope)
- $$ = &Node{Pos: $<pos>1, Op: OCASE}
- }
- node_compound_stmt:
- '{'
- {
- /*
- markdcl();
- */
- yylex.newScope(OtherScope)
- }
- list_stmt_list '}'
- {
- /*
- $$ = liststmt($3);
- popdcl();
- */
- $$ = &Node{Pos: $<pos>1, Op: OBLOCK, LL: $3}
- yylex.popScope()
- }
- node_caseblock:
- node_case
- {
- /*
- // If the last token read by the lexer was consumed
- // as part of the node_case, clear it (parser has cleared yychar).
- // If the last token read by the lexer was the lookahead
- // leave it alone (parser has it cached in yychar).
- // This is so that the list_stmt_list action doesn't look at
- // the node_case tokens if the list_stmt_list is empty.
- yylast = yychar;
- */
- yylex.last = yychar
- }
- list_stmt_list
- {
- /*
- int last;
- // This is the only place in the language where a statement
- // list is not allowed to drop the final semicolon, because
- // it's the only place where a statement list is not followed
- // by a closing brace. Handle the error for pedantry.
- // Find the final token of the statement list.
- // yylast is lookahead; yyprev is last of list_stmt_list
- last = yyprev;
- if(last > 0 && last != ';' && yychar != '}')
- yyerror("missing statement after label");
- $$ = $1;
- $$->nbody = $3;
- popdcl();
- */
- if yylex.prev > 0 && yylex.prev != ';' && yylex.last != '}' { //e.g. test/fixedbugs/bug274.go
- yylex.error($<pos>3, "missing statement after label")
- }
- $$ = $1
- $$.LR = $3
- yylex.popScope()
- }
- list_caseblock_list:
- {
- /*
- $$ = nil;
- */
- $$ = nil
- }
- | list_caseblock_list node_caseblock
- {
- /*
- $$ = list($1, $2);
- */
- $$ = append($1, $2)
- }
- list_loop_body:
- LBODY
- {
- /*
- markdcl();
- */
- yylex.newScope(OtherScope)
- }
- list_stmt_list '}'
- {
- /*
- $$ = $3;
- popdcl();
- */
- $$ = $3
- yylex.popScope()
- }
- node_range_stmt:
- list_expr_list '=' LRANGE node_expr
- {
- /*
- $$ = nod(ORANGE, N, $4);
- $$->list = $1;
- $$->etype = 0; // := flag
- */
- $$ = &Node{Pos: $<pos>1, Op: ORANGE, LL: $1, NL: $4}
- }
- | list_expr_list LCOLAS LRANGE node_expr
- {
- /*
- $$ = nod(ORANGE, N, $4);
- $$->list = $1;
- $$->colas = 1;
- colasdefn($1, $$);
- */
- $$ = &Node{Pos: $<pos>1, Op: ORANGE, LL: $1, NL: $4, IsColas: true}
- yylex.colasdefn($1)
- }
- node_for_header:
- node_osimple_stmt ';' node_osimple_stmt ';' node_osimple_stmt
- {
- /*
- // init ; test ; incr
- if($5 != N && $5->colas != 0)
- yyerror("cannot declare in the for-increment");
- $$ = nod(OFOR, N, N);
- if($1 != N)
- $$->ninit = list1($1);
- $$->ntest = $3;
- $$->nincr = $5;
- */
- //TODO err check above
- $$ = &Node{Pos: $<pos>1, Op: OFOR, NL: $1, NR: $3, N3: $5}
- }
- | node_osimple_stmt
- {
- /*
- // normal test
- $$ = nod(OFOR, N, N);
- $$->ntest = $1;
- */
- $$ = &Node{Pos: $<pos>1, Op: OFOR, NR: $1} // <pos> invalid if $1 == nil
- }
- | node_range_stmt
- | LVAR node_osimple_stmt ';' node_osimple_stmt ';' node_osimple_stmt
- {
- yylex.error($<pos>1, "syntax error: var declaration not allowed in for initializer")
- $$ = &Node{Pos: $<pos>1, Op: OFOR, NL: $2, NR: $4, N3: $6}
- }
- node_for_body:
- node_for_header list_loop_body
- {
- /*
- $$ = $1;
- $$->nbody = concat($$->nbody, $2);
- */
- $$ = $1
- $$.LR = $2
- }
- node_for_stmt:
- LFOR
- {
- /*
- markdcl();
- */
- yylex.newScope(OtherScope)
- }
- node_for_body
- {
- /*
- $$ = $3;
- popdcl();
- */
- $$ = $3
- if $$.NR == nil {
- $$.Pos = $<pos>1 // correct Pos, see node_for_header
- }
- yylex.popScope()
- }
- node_if_header:
- node_osimple_stmt
- {
- /*
- // test
- $$ = nod(OIF, N, N);
- $$->ntest = $1;
- */
- $$ = &Node{Pos: $<pos>1, Op: OIF, NR: $1} // <pos> invalid if $1 == nil
- }
- | node_osimple_stmt ';' node_osimple_stmt
- {
- /*
- // init ; test
- $$ = nod(OIF, N, N);
- if($1 != N)
- $$->ninit = list1($1);
- $$->ntest = $3;
- */
- $$ = &Node{Pos: $<pos>1, Op: OIF, NL: $1, NR: $3}
- }
- /* IF cond body (ELSE IF cond body)* (ELSE block)? */
- node_if_stmt:
- LIF
- {
- /*
- markdcl();
- */
- yylex.newScope(OtherScope)
- }
- node_if_header
- {
- /*
- if($3->ntest == N)
- yyerror("missing condition in if statement");
- */
- if $3.NR == nil {
- yylex.error($<pos>1, "missing condition in if statement")
- }
- }
- list_loop_body
- {
- /*
- $3->nbody = $5;
- */
- $3.LL = $5
- }
- node_else
- {
- /*
- popdcl();
- $$ = $3;
- if($7 != N)
- $$->nelse = list1($7);
- */
- yylex.popScope()
- $$ = $3
- if $$.NR == nil { // see node_if_header
- $$.Pos = $<pos>1
- }
- $$.N3 = $7
- }
- node_else:
- {
- /*
- $$ = N;
- */
- $$ = nil
- }
- | LELSE node_if_stmt
- {
- /*
- $$ = $2;
- */
- $$ = $2
- }
- | LELSE node_compound_stmt
- {
- /*
- $$ = $2;
- */
- $$ = $2
- }
- node_switch_stmt:
- LSWITCH
- {
- /*
- markdcl();
- */
- yylex.newScope(OtherScope)
- }
- node_if_header
- {
- /*
- Node *n;
- n = $3->ntest;
- if(n != N && n->op != OTYPESW)
- n = N;
- typesw = nod(OXXX, typesw, n);
- */
- //TODO above?
- }
- LBODY list_caseblock_list '}'
- {
- /*
- $$ = $3;
- $$->op = OSWITCH;
- $$->list = $6;
- typesw = typesw->left;
- popdcl();
- */
- $$ = $3
- $$.Op = OSWITCH
- $$.LL = $6
- if $$.NR == nil { // see node_if_header
- $$.Pos = $<pos>1
- }
- yylex.popScope()
- }
- node_select_stmt:
- LSELECT
- {
- /*
- typesw = nod(OXXX, typesw, N);
- */
- //TODO OXXX?
- }
- LBODY list_caseblock_list '}'
- {
- /*
- $$ = nod(OSELECT, N, N);
- $$->lineno = typesw->lineno;
- $$->list = $4;
- typesw = typesw->left;
- */
- //TODO
- /*
- for _, item := range $4 {
- switch {
- case item.Op != OCASE:
- internalError()
- case len(item.LL) > 1:
- yylex.error(item.LL[0].Pos, "select case must be receive, send or assign recv")
- }
- }
- */
- $$ = &Node{Pos: $<pos>1, Op: OSELECT, LL: $4}
- }
- /*
- * expressions
- */
- node_expr:
- node_uexpr
- | node_expr LOROR node_expr
- {
- /*
- $$ = nod(OOROR, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OOROR, NL: $1, NR: $3}
- }
- | node_expr LANDAND node_expr
- {
- /*
- $$ = nod(OANDAND, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OANDAND, NL: $1, NR: $3}
- }
- | node_expr LEQ node_expr
- {
- /*
- $$ = nod(OEQ, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OEQ, NL: $1, NR: $3}
- }
- | node_expr LNE node_expr
- {
- /*
- $$ = nod(ONE, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: ONE, NL: $1, NR: $3}
- }
- | node_expr LLT node_expr
- {
- /*
- $$ = nod(OLT, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OLT, NL: $1, NR: $3}
- }
- | node_expr LLE node_expr
- {
- /*
- $$ = nod(OLE, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OLE, NL: $1, NR: $3}
- }
- | node_expr LGE node_expr
- {
- /*
- $$ = nod(OGE, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OGE, NL: $1, NR: $3}
- }
- | node_expr LGT node_expr
- {
- /*
- $$ = nod(OGT, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OGT, NL: $1, NR: $3}
- }
- | node_expr '+' node_expr
- {
- /*
- $$ = nod(OADD, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OADD, NL: $1, NR: $3}
- }
- | node_expr '-' node_expr
- {
- /*
- $$ = nod(OSUB, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OSUB, NL: $1, NR: $3}
- }
- | node_expr '|' node_expr
- {
- /*
- $$ = nod(OOR, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OOR, NL: $1, NR: $3}
- }
- | node_expr '^' node_expr
- {
- /*
- $$ = nod(OXOR, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OXOR, NL: $1, NR: $3}
- }
- | node_expr '*' node_expr
- {
- /*
- $$ = nod(OMUL, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OMUL, NL: $1, NR: $3}
- }
- | node_expr '/' node_expr
- {
- /*
- $$ = nod(ODIV, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: ODIV, NL: $1, NR: $3}
- }
- | node_expr '%' node_expr
- {
- /*
- $$ = nod(OMOD, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OMOD, NL: $1, NR: $3}
- }
- | node_expr '&' node_expr
- {
- /*
- $$ = nod(OAND, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OAND, NL: $1, NR: $3}
- }
- | node_expr LANDNOT node_expr
- {
- /*
- $$ = nod(OANDNOT, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OANDNOT, NL: $1, NR: $3}
- }
- | node_expr LLSH node_expr
- {
- /*
- $$ = nod(OLSH, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OLSH, NL: $1, NR: $3}
- }
- | node_expr LRSH node_expr
- {
- /*
- $$ = nod(ORSH, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: ORSH, NL: $1, NR: $3}
- }
- /* not an expression anymore, but left in so we can give a good error */
- | node_expr LCOMM node_expr
- {
- /*
- $$ = nod(OSEND, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OSEND, NL: $1, NR: $3}
- }
- node_uexpr:
- node_pexpr
- | '*' node_uexpr
- {
- /*
- $$ = nod(OIND, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OIND, NL: $2}
- }
- | '&' node_uexpr
- {
- /*
- if($2->op == OCOMPLIT) {
- // Special case for &T{...}: turn into (*T){...}.
- $$ = $2;
- $$->right = nod(OIND, $$->right, N);
- $$->right->implicit = 1;
- } else {
- $$ = nod(OADDR, $2, N);
- }
- */
- switch {
- case $2.Op == OCOMPLIT:
- // Special case for &T{...}: turn into (*T){...}.
- $$ = $2
- $$.NL = &Node{Pos: $$.NL.Pos, Op: OIND, NL: $$.NL}
- default:
- $$ = &Node{Pos: $<pos>1, Op: OADDR, NL: $2}
- }
- }
- | '+' node_uexpr
- {
- /*
- $$ = nod(OPLUS, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OPLUS, NL: $2}
- }
- | '-' node_uexpr
- {
- /**
- $$ = nod(OMINUS, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OMINUS, NL: $2}
- }
- | '!' node_uexpr
- {
- /*
- $$ = nod(ONOT, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: ONOT, NL: $2}
- }
- | '~' node_uexpr
- {
- /*
- yyerror("the bitwise complement operator is ^");
- $$ = nod(OCOM, $2, N);
- */
- yylex.error($<pos>1, "the bitwise complement operator is ^")
- $$ = &Node{Pos: $<pos>1, Op: OCOM, NL: $2}
- }
- | '^' node_uexpr
- {
- /*
- $$ = nod(OCOM, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OCOM, NL: $2}
- }
- | LCOMM node_uexpr
- {
- /*
- $$ = nod(ORECV, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: ORECV, NL: $2}
- }
- /*
- * call-like statements that
- * can be preceded by 'defer' and 'go'
- */
- node_pseudocall:
- node_pexpr '(' ')'
- {
- /*
- $$ = nod(OCALL, $1, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OCALL, NL: $1}
- }
- | node_pexpr '(' list_expr_or_type_list ocomma ')'
- {
- /*
- $$ = nod(OCALL, $1, N);
- $$->list = $3;
- */
- $$ = &Node{Pos: $<pos>1, Op: OCALL, NL: $1, LL: $3}
- }
- | node_pexpr '(' list_expr_or_type_list LDDD ocomma ')'
- {
- /*
- $$ = nod(OCALL, $1, N);
- $$->list = $3;
- $$->isddd = 1;
- */
- $$ = &Node{Pos: $<pos>1, Op: OCALL, NL: $1, LL: $3, IsDDD: true}
- }
- node_pexpr_no_paren:
- val_LLITERAL
- {
- /*
- $$ = nodlit($1);
- */
- $$ = &Node{Pos: $1.Pos, Op: OLITERAL, Literal: $1}
- }
- | node_name
- | node_pexpr '.' sym_sym
- {
- /*
- if($1->op == OPACK) {
- Sym *s;
- s = restrictlookup($3->node_name, $1->pkg);
- $1->used = 1;
- $$ = oldname(s);
- break;
- }
- $$ = nod(OXDOT, $1, newname($3));
- */
- //TODO above
- $$ = &Node{Pos: $<pos>1, Op: OXDOT, NL: $1}
- $$.NR = &Node{Pos: $<pos>3, Op: ONAME, Name: $3}
- }
- | node_pexpr '.' '(' node_expr_or_type ')'
- {
- /*
- $$ = nod(ODOTTYPE, $1, $4);
- */
- $$ = &Node{Pos: $<pos>1, Op: ODOTTYPE, NL: $1, NR: $4}
- }
- | node_pexpr '.' '(' LTYPE ')'
- {
- /*
- $$ = nod(OTYPESW, N, $1);
- */
- $$ = &Node{Pos: $<pos>1, Op: OTYPESW, NL: $1}
- }
- | node_pexpr '[' node_expr ']'
- {
- /*
- $$ = nod(OINDEX, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OINDEX, NL: $1, NR: $3}
- }
- | node_pexpr '[' node_oexpr ':' node_oexpr ']'
- {
- /*
- $$ = nod(OSLICE, $1, nod(OKEY, $3, $5));
- */
- $$ = &Node{Pos: $<pos>1, Op: OSLICE, NL: $1}
- $$.NR = &Node{Pos: $<pos>3, Op: OKEY, NL: $3, NR: $5}
- }
- | node_pseudocall
- | node_convtype '(' node_expr ')'
- {
- /*
- // conversion
- $$ = nod(OCALL, $1, N);
- $$->list = list1($3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OCALL, NL: $1, LL: $3.list()}
- }
- | node_comptype i_lbrace node_start_complit list_braced_keyval_list '}'
- {
- /*
- $$ = $3;
- $$->right = $1;
- $$->list = $4;
- fixlbrace($2);
- */
- $$ = $3
- $$.NL, $$.LL = $1, $4
- yylex.fixlbrace($2)
- }
- | node_pexpr_no_paren '{' node_start_complit list_braced_keyval_list '}'
- {
- /*
- $$ = $3;
- $$->right = $1;
- $$->list = $4;
- */
- $$ = $3
- $$.NL, $$.LL = $1, $4
- }
- | '(' node_expr_or_type ')' '{' node_start_complit list_braced_keyval_list '}'
- {
- /*
- yyerror("cannot parenthesize type in composite literal");
- $$ = $5;
- $$->right = $2;
- $$->list = $6;
- */
- $$ = $5
- $$.NL, $$.LL = $2, $6
- yylex.error($<pos>1, "cannot parenthesize type in composite literal")
- }
- | node_fnliteral
- node_start_complit: //TODO -?
- {
- /*
- // composite expression.
- // make node early so we get the right line number.
- $$ = nod(OCOMPLIT, N, N);
- */
- $$ = &Node{Pos: yylex.lbrpos, Op: OCOMPLIT} //TODO check pos!
- }
- node_keyval:
- node_expr ':' node_complitexpr
- {
- /*
- $$ = nod(OKEY, $1, $3);
- */
- $$ = &Node{Pos: $<pos>1, Op: OKEY, NL: $1, NR: $3}
- }
- node_complitexpr:
- node_expr
- | '{' node_start_complit list_braced_keyval_list '}'
- {
- /*
- $$ = $2;
- $$->list = $3;
- */
- $$ = $2
- $$.LL = $3
- }
- node_pexpr:
- node_pexpr_no_paren
- | '(' node_expr_or_type ')'
- {
- /*
- $$ = $2;
-
- // Need to know on lhs of := whether there are ( ).
- // Don't bother with the OPAREN in other cases:
- // it's just a waste of memory and time.
- switch($$->op) {
- case ONAME:
- case ONONAME:
- case OPACK:
- case OTYPE:
- case OLITERAL:
- $$ = nod(OPAREN, $$, N);
- }
- */
- switch $2.Op {
- case ONAME, /*TODO ONONAME,*/ /*TODO OPACK,*/ /*TODO OTYPE,*/ OLITERAL:
- $$ = &Node{Pos: $<pos>1, Op: OPAREN, NL: $2}
- default:
- $$ = $2
- }
- }
- node_expr_or_type:
- node_expr
- | node_non_expr_type %prec PreferToRightParen
- node_name_or_type:
- node_ntype
- i_lbrace:
- LBODY
- {
- /*
- $$ = LBODY;
- */
- $$ = LBODY
- }
- | '{'
- {
- /*
- $$ = '{';
- */
- $$ = '{'
- }
- /*
- * names and types
- * newname is used before declared
- * oldname is used after declared
- */
- node_new_name:
- sym_sym
- {
- /*
- $$ = newname($1);
- */
- $$ = &Node{Pos: $<pos>1, Op: ONAME, Name: $1}
- }
- node_dcl_name:
- sym_sym
- {
- /*
- $$ = dclname($1);
- */
- $$ = yylex.declare($1, SymTag(0)) // not known here
- }
- node_onew_name:
- {
- /*
- $$ = N;
- */
- $$ = nil
- }
- | node_new_name
- sym_sym:
- sym_LNAME
- /*
- {
- $$ = $1;
- // during imports, unqualified non-exported identifiers are from builtinpkg
- if(importpkg != nil && !exportname($1->node_name))
- $$ = pkglookup($1->node_name, builtinpkg);
- }
- */
- /*
- | sym_hidden_importsym
- */
- /*
- | '?'
- {
- $$ = S;
- }
- */
- /*
- sym_hidden_importsym:
- '@' val_LLITERAL '.' sym_LNAME
- {
- if($2.u.sval->len == 0)
- $$ = pkglookup($4->node_name, importpkg);
- else
- $$ = pkglookup($4->node_name, mkpkg($2.u.sval));
- }
- */
- node_name:
- sym_sym %prec NotParen
- {
- /*
- $$ = oldname($1);
- if($$->pack != N)
- $$->pack->used = 1;
- */
- $$ = &Node{Pos: $<pos>1, Op: ONAME, Name: $1}
- }
- node_labelname:
- node_new_name
- /*
- * to avoid parsing conflicts, type is split into
- * channel types
- * function types
- * parenthesized types
- * any other type
- * the type system makes additional restrictions,
- * but those are not implemented in the grammar.
- */
- node_dotdotdot:
- LDDD
- {
- /*
- yyerror("final argument in variadic function missing type");
- $$ = nod(ODDD, typenod(typ(TINTER)), N);
- */
- yylex.error($<pos>1, "final argument in variadic function missing type")
- $$ = &Node{Pos: $<pos>1, Op: ODDD}
- $$.NL = &Node{Pos: $<pos>1, Op: OTYPE}
- $$.NL.Type = &Type{Tag: TINTER}
- }
- | LDDD node_ntype
- {
- /*
- $$ = nod(ODDD, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: ODDD, NL: $2}
- }
- node_ntype:
- node_recvchantype
- | node_fntype
- | node_othertype
- | node_ptrtype
- | node_dotname
- | '(' node_ntype ')'
- {
- /*
- $$ = nod(OTPAREN, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OTPAREN, NL: $2}
- }
- node_non_expr_type:
- node_recvchantype
- | node_fntype
- | node_othertype
- | '*' node_non_expr_type
- {
- /*
- $$ = nod(OIND, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OIND, NL: $2}
- }
- node_non_recvchantype:
- node_fntype
- | node_othertype
- | node_ptrtype
- | node_dotname
- | '(' node_ntype ')'
- {
- /*
- $$ = nod(OTPAREN, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OTPAREN, NL: $2}
- }
- node_convtype:
- node_fntype
- | node_othertype
- node_comptype:
- node_othertype
- node_fnret_type:
- node_recvchantype
- | node_fntype
- | node_othertype
- | node_ptrtype
- | node_dotname
- node_dotname:
- node_name
- | node_name '.' sym_sym
- {
- /*
- if($1->op == OPACK) {
- Sym *s;
- s = restrictlookup($3->node_name, $1->pkg);
- $1->used = 1;
- $$ = oldname(s);
- break;
- }
- $$ = nod(OXDOT, $1, newname($3));
- */
- $$ = &Node{Pos: $<pos>1, Op: OXDOT, NL: $1}
- $$.NR = &Node{Pos: $<pos>3, Op: ONAME, Name: $3}
- }
- node_othertype:
- '[' node_oexpr ']' node_ntype
- {
- /*
- $$ = nod(OTARRAY, $2, $4);
- */
- $$ = &Node{Pos: $<pos>1, Op: OTARRAY, NL: $2, NR: $4}
- }
- | '[' LDDD ']' node_ntype
- {
- /*
- // array literal of nelem
- $$ = nod(OTARRAY, nod(ODDD, N, N), $4);
- */
- $$ = &Node{Pos: $<pos>1, Op: OTARRAY, NR: $4}
- $$.NL = &Node{Pos: $<pos>2, Op: ODDD}
- }
- | LCHAN node_non_recvchantype
- {
- /*
- $$ = nod(OTCHAN, $2, N);
- $$->etype = Cboth;
- */
- $$ = &Node{Pos: $<pos>1, Op: OTCHAN, NL: $2, CType: Cboth}
- }
- | LCHAN LCOMM node_ntype
- {
- /*
- $$ = nod(OTCHAN, $3, N);
- $$->etype = Csend;
- */
- $$ = &Node{Pos: $<pos>1, Op: OTCHAN, NL: $3, CType: Csend}
- }
- | LMAP '[' node_ntype ']' node_ntype
- {
- /*
- $$ = nod(OTMAP, $3, $5);
- */
- $$ = &Node{Pos: $<pos>1, Op: OTMAP, NL: $3, NR: $5}
- }
- | node_structtype
- | node_interfacetype
- node_ptrtype:
- '*' node_ntype
- {
- /*
- $$ = nod(OIND, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OIND, NL: $2}
- }
- node_recvchantype:
- LCOMM LCHAN node_ntype
- {
- /*
- $$ = nod(OTCHAN, $3, N);
- $$->etype = Crecv;
- */
- $$ = &Node{Pos: $<pos>1, Op: OTCHAN, NL: $3, CType: Crecv}
- }
- node_structtype:
- LSTRUCT i_lbrace list_structdcl_list osemi '}'
- {
- /*
- $$ = nod(OTSTRUCT, N, N);
- $$->list = $3;
- fixlbrace($2);
- */
- $$ = &Node{Pos: $<pos>1, Op: OTSTRUCT, LL: $3}
- yylex.fixlbrace($2)
- }
- | LSTRUCT i_lbrace '}'
- {
- /*
- $$ = nod(OTSTRUCT, N, N);
- fixlbrace($2);
- */
- $$ = &Node{Pos: $<pos>1, Op: OTSTRUCT}
- yylex.fixlbrace($2)
- }
- node_interfacetype:
- LINTERFACE i_lbrace list_interfacedcl_list osemi '}'
- {
- /*
- $$ = nod(OTINTER, N, N);
- $$->list = $3;
- fixlbrace($2);
- */
- $$ = &Node{Pos: $<pos>1, Op: OTINTER, LL: $3}
- yylex.fixlbrace($2)
- }
- | LINTERFACE i_lbrace '}'
- {
- /*
- $$ = nod(OTINTER, N, N);
- fixlbrace($2);
- */
- $$ = &Node{Pos: $<pos>1, Op: OTINTER}
- yylex.fixlbrace($2)
- }
- /*
- * function stuff
- * all in one place to show how crappy it all is
- */
- node_xfndcl:
- LFUNC node_fndcl list_fnbody
- {
- /*
- $$ = $2;
- if($$ == N)
- break;
- $$->nbody = $3;
- $$->endlineno = lineno;
- funcbody($$);
- */
- $$ = $2
- if $$ == nil {
- break
- }
- $$.LL = $3
- $$.Pos = $<pos>1
- yylex.funcbody($$)
- }
- node_fndcl:
- sym_sym '(' list_oarg_type_list_ocomma ')' list_fnres
- {
- /*
- Node *t;
- $$ = N;
- $3 = checkarglist($3, 1);
- if(strcmp($1->node_name, "init") == 0) {
- $1 = renameinit();
- if($3 != nil || $5 != nil)
- yyerror("func init must have no arguments and no return values");
- }
- if(strcmp(localpkg->node_name, "main") == 0 && strcmp($1->node_name, "main") == 0) {
- if($3 != nil || $5 != nil)
- yyerror("func main must have no arguments and no return values");
- }
- t = nod(OTFUNC, N, N);
- t->list = $3;
- t->rlist = $5;
- $$ = nod(ODCLFUNC, N, N);
- $$->nname = newname($1);
- $$->nname->defn = $$;
- $$->nname->node_ntype = t; // TODO: check if nname already has an node_ntype
- declare($$->nname, PFUNC);
- funchdr($$);
- */
- $3, $<closure>3 = yylex.checkarglist($3, true)
- //TODO above
- $$ = &Node{Pos: $<pos>1, Op: ODCLFUNC}
- $$.NL = yylex.declare($1, SymFunc)
- $$.NR = &Node{Pos: $<pos>2, Op: OTFUNC, LR: $3, L3: $5}
- yylex.funchdr($$)
- $<closure>3()
- $<closure>5()
- }
- | '(' list_oarg_type_list_ocomma ')' sym_sym '(' list_oarg_type_list_ocomma ')' list_fnres
- {
- /*
- Node *rcvr, *t;
- $$ = N;
- $2 = checkarglist($2, 0);
- $6 = checkarglist($6, 1);
- if($2 == nil) {
- yyerror("method has no receiver");
- break;
- }
- if($2->next != nil) {
- yyerror("method has multiple receivers");
- break;
- }
- rcvr = $2->n;
- if(rcvr->op != ODCLFIELD) {
- yyerror("bad receiver in method");
- break;
- }
- if(rcvr->right->op == OTPAREN || (rcvr->right->op == OIND && rcvr->right->left->op == OTPAREN))
- yyerror("cannot parenthesize receiver type");
- t = nod(OTFUNC, rcvr, N);
- t->list = $6;
- t->rlist = $8;
- $$ = nod(ODCLFUNC, N, N);
- $$->shortname = newname($4);
- $$->nname = methodname1($$->shortname, rcvr->right);
- $$->nname->defn = $$;
- $$->nname->node_ntype = t;
- declare($$->nname, PFUNC);
- funchdr($$);
- */
- $$ = nil
- $2, $<closure>2 = yylex.checkarglist($2, false)
- $6, $<closure>6 = yylex.checkarglist($6, true)
- //TODO above
- if $2 == nil {
- yylex.error($<pos>1, "method has no receiver")
- break
- } else if len($2) > 1 {
- yylex.error($2[1].Pos, "method has multiple receivers")
- break
- }
- var rcvr, t *Node
- n := $2[0]
- switch n.Op {
- case OKEY:
- rcvr, t = n.NL, n.NR
- case ONAME, OIND:
- t = n
- default:
- internalError(NodeOps[n.Op])
- }
- if rcvr == nil && t == nil {
- yylex.error(n.Pos, "bad receiver in method")
- break
- }
- if t != nil {
- if t.Op == OTPAREN || t.Op == OIND && t.NL.Op == OTPAREN {
- yylex.error(t.Pos, "cannot parenthesize receiver type")
- }
- }
- $$ = &Node{Pos: $<pos>1, Op: ODCLFUNC}
- $$.NL = yylex.declare(yylex.methodname($4, t), SymMeth)
- $$.NR = &Node{Pos: $<pos>5, Op: OTFUNC, LL: $2, LR: $6, L3: $8}
- yylex.funchdr($$)
- $<closure>2()
- $<closure>6()
- $<closure>8()
- }
- /*
- node_hidden_fndcl:
- sym_hidden_pkg_importsym '(' list_ohidden_funarg_list ')' list_ohidden_funres
- {
- Sym *s;
- Type *t;
- $$ = N;
- s = $1;
- t = functype(N, $3, $5);
- importsym(s, ONAME);
- if(s->def != N && s->def->op == ONAME) {
- if(eqtype(t, s->def->type))
- break;
- yyerror("inconsistent definition for func %S during import\n\t%T\n\t%T", s, s->def->type, t);
- }
- $$ = newname(s);
- $$->type = t;
- declare($$, PFUNC);
- funchdr($$);
- }
- | '(' list_hidden_funarg_list ')' sym_sym '(' list_ohidden_funarg_list ')' list_ohidden_funres
- {
- $$ = methodname1(newname($4), $2->n->right);
- $$->type = functype($2->n, $6, $8);
- checkwidth($$->type);
- addmethod($4, $$->type, 0);
- funchdr($$);
-
- // inl.c's inlnode in on a dotmeth node expects to find the inlineable body as
- // (dotmeth's type)->nname->inl, and dotmeth's type has been pulled
- // out by typecheck's lookdot as this $$->ttype. So by providing
- // this back link here we avoid special casing there.
- $$->type->nname = $$;
- }
- */
- node_fntype:
- LFUNC '(' list_oarg_type_list_ocomma ')' list_fnres
- {
- /*
- $3 = checkarglist($3, 1);
- $$ = nod(OTFUNC, N, N);
- $$->list = $3;
- $$->rlist = $5;
- */
- $3, $<closure>$ = yylex.checkarglist($3, true)
- $$ = &Node{Pos: $<pos>1, Op: OTFUNC, LR: $3, L3: $5}
- }
- list_fnbody:
- {
- /*
- $$ = nil;
- */
- $$ = nil
- }
- | '{' list_stmt_list '}'
- {
- /*
- $$ = $2;
- if($$ == nil)
- $$ = list1(nod(OEMPTY, N, N));
- */
- $$ = $2
- }
- list_fnres:
- %prec NotParen
- {
- /*
- $$ = nil;
- */
- $$ = nil
- $<closure>$ = nop
- }
- | node_fnret_type
- {
- /*
- $$ = list1(nod(ODCLFIELD, N, $1));
- */
- $$ = (&Node{Pos: $<pos>1, Op: ODCLFIELD, NR: $1}).list()
- $<closure>$ = nop
- }
- | '(' list_oarg_type_list_ocomma ')'
- {
- /*
- $2 = checkarglist($2, 0);
- $$ = $2;
- */
- $$, $<closure>$ = yylex.checkarglist($2, false)
- }
- /*
- fnlitdcl:
- node_fntype
- {
- closurehdr($1);
- }
- */
- node_fnlitdcl:
- node_fntype
- {
- /*
- closurehdr($1);
- */
- $$ = &Node{Pos: $1.Pos, Op: OCLOSURE, NL: $1}
- yylex.closurehdr($$)
- }
- /*
- node_fnliteral:
- fnlitdcl i_lbrace list_stmt_list '}'
- {
- $$ = closurebody($3);
- fixlbrace($2);
- }
- | fnlitdcl error
- {
- $$ = closurebody(nil);
- }
- */
- node_fnliteral:
- node_fnlitdcl i_lbrace list_stmt_list '}'
- {
- /*
- $$ = closurebody($3);
- fixlbrace($2);
- */
- $$ = yylex.closurebody($3)
- yylex.fixlbrace($2)
- }
- | node_fnlitdcl error
- {
- /*
- $$ = closurebody(nil);
- */
- $$ = yylex.closurebody(nil)
- //TODO yylex.error()?
- }
- /*
- * lists of things
- * note that they are left recursive
- * to conserve yacc stack. they need to
- * be reversed to interpret correctly
- */
- list_xdcl_list:
- {
- /*
- $$ = nil;
- */
- $$ = nil
- }
- | list_xdcl_list list_xdcl ';'
- {
- /*
- $$ = concat($1, $2);
- if(nsyntaxerrors == 0)
- testdclstack();
- */
- $$ = append($1, $2...)
- }
- list_vardcl_list:
- list_vardcl
- | list_vardcl_list ';' list_vardcl
- {
- /*
- $$ = concat($1, $3);
- */
- $$ = append($1, $3...)
- }
- list_constdcl_list:
- list_constdcl1
- | list_constdcl_list ';' list_constdcl1
- {
- /*
- $$ = concat($1, $3);
- */
- $$ = append($1, $3...)
- }
- list_typedcl_list:
- node_typedcl
- {
- /*
- $$ = list1($1);
- */
- $$ = $1.list()
- }
- | list_typedcl_list ';' node_typedcl
- {
- /*
- $$ = list($1, $3);
- */
- $$ = append($1, $3)
- }
- list_structdcl_list:
- list_structdcl
- | list_structdcl_list ';' list_structdcl
- {
- /*
- $$ = concat($1, $3);
- */
- $$ = append($1, $3...)
- }
- list_interfacedcl_list:
- node_interfacedcl
- {
- /*
- $$ = list1($1);
- */
- $$ = $1.list()
- }
- | list_interfacedcl_list ';' node_interfacedcl
- {
- /*
- $$ = list($1, $3);
- */
- $$ = append($1, $3)
- }
- list_structdcl:
- list_new_name_list node_ntype val_oliteral
- {
- /*
- NodeList *l;
- for(l=$1; l; l=l->next) {
- l->n = nod(ODCLFIELD, l->n, $2);
- l->n->val = $3;
- }
- */
- $$ = (&Node{Pos: $<pos>1, Op: ODCLFIELD, LL: $1, NL: $2, Literal: $3}).list()
- }
- | node_embed val_oliteral
- {
- /*
- $1->val = $2;
- $$ = list1($1);
- */
- $1.Literal = $2
- $$ = $1.list()
- }
- | '(' node_embed ')' val_oliteral
- {
- /*
- $2->val = $4;
- $$ = list1($2);
- yyerror("cannot parenthesize embedded type");
- */
- $2.Literal = $4
- $$ = $2.list()
- yylex.error($<pos>1, "cannot parenthesize embedded type")
- }
- | '*' node_embed val_oliteral
- {
- /*
- $2->right = nod(OIND, $2->right, N);
- $2->val = $3;
- $$ = list1($2);
- */
- $2.Literal = $3
- $$ = (&Node{Pos: $<pos>1, Op: OIND, NL: $2}).list()
- }
- | '(' '*' node_embed ')' val_oliteral
- {
- /*
- $3->right = nod(OIND, $3->right, N);
- $3->val = $5;
- $$ = list1($3);
- yyerror("cannot parenthesize embedded type");
- */
- $3.Literal = $5
- $$ = (&Node{Pos: $<pos>1, Op: OIND, NL: $3}).list()
- yylex.error($<pos>1, "cannot parenthesize embedded type")
- }
- | '*' '(' node_embed ')' val_oliteral
- {
- /*
- $3->right = nod(OIND, $3->right, N);
- $3->val = $5;
- $$ = list1($3);
- yyerror("cannot parenthesize embedded type");
- */
- $3.Literal = $5
- $$ = (&Node{Pos: $<pos>1, Op: OIND, NL: $3}).list()
- yylex.error($<pos>2, "cannot parenthesize embedded type")
- }
- sym_packname:
- sym_LNAME
- {
- /*
- Node *n;
- $$ = $1;
- n = oldname($1);
- if(n->pack != N)
- n->pack->used = 1;
- */
- $$ = $1
- }
- | sym_LNAME '.' sym_sym
- {
- /*
- Pkg *pkg;
- if($1->def == N || $1->def->op != OPACK) {
- yyerror("%S is not a package", $1);
- pkg = localpkg;
- } else {
- $1->def->used = 1;
- pkg = $1->def->pkg;
- }
- $$ = restrictlookup($3->node_name, pkg);
- */
- $$ = $3
- $$.Pos = $1.Pos
- $$.Packname = $1.Name
- }
- node_embed:
- sym_packname
- {
- /*
- $$ = embedded($1);
- */
- $$ = &Node{Pos: $<pos>1, Op: ODCLFIELD}
- $$.NR = &Node{Pos: $$.Pos, Op: ONAME, Name: $1}
- }
- node_interfacedcl:
- node_new_name node_indcl
- {
- /*
- $$ = nod(ODCLFIELD, $1, $2);
- ifacedcl($$);
- */
- $$ = &Node{Pos: $<pos>1, Op: ODCLFIELD, NL: $1, NR: $2}
- }
- | sym_packname
- {
- /*
- $$ = nod(ODCLFIELD, N, oldname($1));
- */
- $$ = &Node{Pos: $<pos>1, Op: ODCLFIELD}
- $$.NR = &Node{Pos: $<pos>1, Op: ONAME, Name: $1}
- }
- | '(' sym_packname ')'
- {
- /*
- $$ = nod(ODCLFIELD, N, oldname($2));
- yyerror("cannot parenthesize embedded type");
- */
- $$ = &Node{Pos: $<pos>1, Op: ODCLFIELD}
- $$.NR = &Node{Pos: $<pos>2, Op: ONAME, Name: $2}
- yylex.error($<pos>1, "cannot parenthesize embedded type")
- }
- node_indcl:
- '(' list_oarg_type_list_ocomma ')' list_fnres
- {
- /*
- // without func keyword
- $2 = checkarglist($2, 1);
- $$ = nod(OTFUNC, fakethis(), N);
- $$->list = $2;
- $$->rlist = $4;
- */
- $2, $<closure>$ = yylex.checkarglist($2, true)
- $$ = &Node{Pos: $<pos>1, Op: OTFUNC, LR: $2, L3: $4}
- }
- /*
- * function arguments.
- */
- node_arg_type:
- node_name_or_type
- | sym_sym node_name_or_type
- {
- /*
- $$ = nod(ONONAME, N, N);
- $$->sym_sym = $1;
- $$ = nod(OKEY, $$, $2);
- */
- $$ = &Node{Pos: $<pos>1, Op: OKEY, NR: $2}
- $$.NL = &Node{Pos: $<pos>1, Op: ONAME, Name: $1}
- }
- | sym_sym node_dotdotdot
- {
- /*
- $$ = nod(ONONAME, N, N);
- $$->sym_sym = $1;
- $$ = nod(OKEY, $$, $2);
- */
- $$ = &Node{Pos: $<pos>1, Op: OKEY, NR: $2}
- $$.NL = &Node{Pos: $<pos>1, Op: ONAME, Name: $1}
- }
- | node_dotdotdot
- list_arg_type_list:
- node_arg_type
- {
- /*
- $$ = list1($1);
- */
- $$ = $1.list()
- }
- | list_arg_type_list ',' node_arg_type
- {
- /*
- $$ = list($1, $3);
- */
- $$ = append($1, $3)
- }
- list_oarg_type_list_ocomma:
- {
- /*
- $$ = nil;
- */
- $$ = nil
- }
- | list_arg_type_list ocomma
- {
- /*
- $$ = $1;
- */
- $$ = $1
- }
- /*
- * statement
- */
- node_stmt:
- {
- /*
- $$ = N;
- */
- $$ = nil
- }
- | node_compound_stmt
- | list_common_dcl
- {
- /*
- $$ = liststmt($1);
- */
- $$ = &Node{Pos: $<pos>1, Op: OBLOCK, LL: $1}
- }
- | node_non_dcl_stmt
- | error
- {
- /*
- $$ = N;
- */
- $$ = nil
- //TODO yylex.error()?
- }
- node_non_dcl_stmt:
- node_simple_stmt
- | node_for_stmt
- | node_switch_stmt
- | node_select_stmt
- | node_if_stmt
- | node_labelname ':'
- {
- /*
- $1 = nod(OLABEL, $1, N);
- $1->sym_sym = dclstack; // context, for goto restrictions
- */
- $1 = &Node{Pos: $<pos>1, Op: OLABEL, NL: $1}
- }
- node_stmt
- {
- /*
- NodeList *l;
- $1->defn = $4;
- l = list1($1);
- if($4)
- l = list(l, $4);
- $$ = liststmt(l);
- */
- //TODO above?
- $$ = $1
- $$.NR = $4
- }
- | LFALL
- {
- /*
- // will be converted to OFALL
- $$ = nod(OXFALL, N, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OFALL}
- }
- | LBREAK node_onew_name
- {
- /*
- $$ = nod(OBREAK, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OBREAK, NL: $2}
- }
- | LCONTINUE node_onew_name
- {
- /*
- $$ = nod(OCONTINUE, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OCONTINUE, NL: $2}
- }
- | LGO node_pseudocall
- {
- /*
- $$ = nod(OPROC, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: OPROC, NL: $2}
- }
- | LDEFER node_pseudocall
- {
- /*
- $$ = nod(ODEFER, $2, N);
- */
- $$ = &Node{Pos: $<pos>1, Op: ODEFER, NL: $2}
- }
- | LGOTO node_new_name
- {
- /*
- $$ = nod(OGOTO, $2, N);
- $$->sym_sym = dclstack; // context, for goto restrictions
- */
- $$ = &Node{Pos: $<pos>1, Op: OGOTO, NL: $2}
- }
- | LRETURN list_oexpr_list
- {
- /*
- $$ = nod(ORETURN, N, N);
- $$->list = $2;
- if($$->list == nil && curfn != N) {
- NodeList *l;
- for(l=curfn->dcl; l; l=l->next) {
- if(l->n->class == PPARAM)
- continue;
- if(l->n->class != PPARAMOUT)
- break;
- if(l->n->sym_sym->def != l->n)
- yyerror("%s is shadowed during return", l->n->sym_sym->node_name);
- }
- }
- */
- //TODO above
- $$ = &Node{Pos: $<pos>1, Op: ORETURN, LL: $2}
- }
- list_stmt_list:
- node_stmt
- {
- /*
- $$ = nil;
- if($1 != N)
- $$ = list1($1);
- */
- $$ = nil
- if $1 != nil {
- $$ = $1.list()
- }
- }
- | list_stmt_list ';' node_stmt
- {
- /*
- $$ = $1;
- if($3 != N)
- $$ = list($$, $3);
- */
- $$ = $1
- if $3 != nil {
- $$ = append($$, $3)
- }
- }
- list_new_name_list:
- node_new_name
- {
- /*
- $$ = list1($1);
- */
- $$ = $1.list()
- }
- | list_new_name_list ',' node_new_name
- {
- /*
- $$ = list($1, $3);
- */
- $$ = append($1, $3)
- }
- list_dcl_name_list:
- node_dcl_name
- {
- /*
- $$ = list1($1);
- */
- $$ = $1.list()
- }
- | list_dcl_name_list ',' node_dcl_name
- {
- /*
- $$ = list($1, $3);
- */
- $$ = append($1, $3)
- }
- list_expr_list:
- node_expr
- {
- /*
- $$ = list1($1);
- */
- $$ = $1.list()
- }
- | list_expr_list ',' node_expr
- {
- /*
- $$ = list($1, $3);
- */
- $$ = append($1, $3)
- }
- list_expr_or_type_list:
- node_expr_or_type
- {
- /*
- $$ = list1($1);
- */
- $$ = $1.list()
- }
- | list_expr_or_type_list ',' node_expr_or_type
- {
- /*
- $$ = list($1, $3);
- */
- $$ = append($1, $3)
- }
- /*
- * list of combo of node_keyval and val
- */
- list_keyval_list:
- node_keyval
- {
- /*
- $$ = list1($1);
- */
- $$ = $1.list()
- }
- | node_complitexpr
- {
- /*
- $$ = list1($1);
- */
- $$ = $1.list()
- }
- | list_keyval_list ',' node_keyval
- {
- /*
- $$ = list($1, $3);
- */
- $$ = append($1, $3)
- }
- | list_keyval_list ',' node_complitexpr
- {
- /*
- $$ = list($1, $3);
- */
- $$ = append($1, $3)
- }
- list_braced_keyval_list:
- {
- /*
- $$ = nil;
- */
- $$ = nil
- }
- | list_keyval_list ocomma
- {
- /*
- $$ = $1;
- */
- $$ = $1
- }
- /*
- * optional things
- */
- osemi:
- | ';'
- ocomma:
- | ','
- node_oexpr:
- {
- /*
- $$ = N;
- */
- $$ = nil
- }
- | node_expr
- list_oexpr_list:
- {
- /*
- $$ = nil;
- */
- $$ = nil
- }
- | list_expr_list
- node_osimple_stmt:
- {
- /*
- $$ = N;
- */
- $$ = nil
- }
- | node_simple_stmt
- /*
- list_ohidden_funarg_list:
- {
- $$ = nil;
- }
- | list_hidden_funarg_list
- */
- /*
- list_ohidden_structdcl_list:
- {
- $$ = nil;
- }
- | list_hidden_structdcl_list
- */
- /*
- list_ohidden_interfacedcl_list:
- {
- $$ = nil;
- }
- | list_hidden_interfacedcl_list
- */
- val_oliteral:
- {
- /*
- $$.ctype = CTxxx;
- */
- $$ = nil
- }
- | val_LLITERAL
- /*
- * import syntax from package header
- */
- /*
- hidden_import:
- LIMPORT sym_LNAME val_LLITERAL ';'
- {
- importimport($2, $3.u.sval);
- }
- | LVAR sym_hidden_pkg_importsym type_hidden_type ';'
- {
- importvar($2, $3);
- }
- | LCONST sym_hidden_pkg_importsym '=' node_hidden_constant ';'
- {
- importconst($2, types[TIDEAL], $4);
- }
- | LCONST sym_hidden_pkg_importsym type_hidden_type '=' node_hidden_constant ';'
- {
- importconst($2, $3, $5);
- }
- | LTYPE type_hidden_pkgtype type_hidden_type ';'
- {
- importtype($2, $3);
- }
- | LFUNC node_hidden_fndcl list_fnbody ';'
- {
- if($2 == N)
- break;
- $2->inl = $3;
- funcbody($2);
- importlist = list(importlist, $2);
- if(debug['E']) {
- print("import [%Z] func %lN \n", importpkg->path, $2);
- if(debug['l'] > 2 && $2->inl)
- print("inl body:%+H\n", $2->inl);
- }
- }
- */
- /*
- sym_hidden_pkg_importsym:
- sym_hidden_importsym
- {
- $$ = $1;
- structpkg = $$->pkg;
- }
- type_hidden_pkgtype:
- sym_hidden_pkg_importsym
- {
- $$ = pkgtype($1);
- importsym($1, OTYPE);
- }
- */
- /*
- * importing types
- */
- /*
- type_hidden_type:
- type_hidden_type_misc
- | type_hidden_type_recv_chan
- | type_hidden_type_func
- */
- /*
- type_hidden_type_non_recv_chan:
- type_hidden_type_misc
- | type_hidden_type_func
- */
- /*
- type_hidden_type_misc:
- sym_hidden_importsym
- {
- $$ = pkgtype($1);
- }
- | sym_LNAME
- {
- // predefined node_name like uint8
- $1 = pkglookup($1->node_name, builtinpkg);
- if($1->def == N || $1->def->op != OTYPE) {
- yyerror("%s is not a type", $1->node_name);
- $$ = T;
- } else
- $$ = $1->def->type;
- }
- | '[' ']' type_hidden_type
- {
- $$ = aindex(N, $3);
- }
- | '[' val_LLITERAL ']' type_hidden_type
- {
- $$ = aindex(nodlit($2), $4);
- }
- | LMAP '[' type_hidden_type ']' type_hidden_type
- {
- $$ = maptype($3, $5);
- }
- | LSTRUCT '{' list_ohidden_structdcl_list '}'
- {
- $$ = tostruct($3);
- }
- | LINTERFACE '{' list_ohidden_interfacedcl_list '}'
- {
- $$ = tointerface($3);
- }
- | '*' type_hidden_type
- {
- $$ = ptrto($2);
- }
- | LCHAN type_hidden_type_non_recv_chan
- {
- $$ = typ(TCHAN);
- $$->type = $2;
- $$->chan = Cboth;
- }
- | LCHAN '(' type_hidden_type_recv_chan ')'
- {
- $$ = typ(TCHAN);
- $$->type = $3;
- $$->chan = Cboth;
- }
- | LCHAN LCOMM type_hidden_type
- {
- $$ = typ(TCHAN);
- $$->type = $3;
- $$->chan = Csend;
- }
- */
- /*
- type_hidden_type_recv_chan:
- LCOMM LCHAN type_hidden_type
- {
- $$ = typ(TCHAN);
- $$->type = $3;
- $$->chan = Crecv;
- }
- */
- /*
- type_hidden_type_func:
- LFUNC '(' list_ohidden_funarg_list ')' list_ohidden_funres
- {
- $$ = functype(nil, $3, $5);
- }
- */
- /*
- node_hidden_fun…
Large files files are truncated, but you can click here to view the full file