2008-06-04 15:37:38 -06:00
|
|
|
// Copyright 2009 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.
|
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
/*
|
|
|
|
* Go language grammar.
|
|
|
|
*
|
|
|
|
* The Go semicolon rules are:
|
|
|
|
*
|
2009-12-13 13:11:56 -07:00
|
|
|
* 1. all statements and declarations are terminated by semicolons.
|
|
|
|
* 2. semicolons can be omitted before a closing ) or }.
|
2009-12-11 16:59:41 -07:00
|
|
|
* 3. semicolons are inserted by the lexer before a newline
|
|
|
|
* following a specific list of tokens.
|
2009-06-06 13:46:38 -06:00
|
|
|
*
|
2009-12-11 16:59:41 -07:00
|
|
|
* Rules #1 and #2 are accomplished by writing the lists as
|
|
|
|
* semicolon-separated lists with an optional trailing semicolon.
|
|
|
|
* Rule #3 is implemented in yylex.
|
2009-06-06 13:46:38 -06:00
|
|
|
*/
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
%{
|
2009-11-13 00:38:48 -07:00
|
|
|
#include <stdio.h> /* if we don't, bison will, and go.h re-#defines getc */
|
2008-06-04 15:37:38 -06:00
|
|
|
#include "go.h"
|
|
|
|
%}
|
|
|
|
%union {
|
|
|
|
Node* node;
|
2009-07-17 02:00:44 -06:00
|
|
|
NodeList* list;
|
2008-06-04 15:37:38 -06:00
|
|
|
Type* type;
|
|
|
|
Sym* sym;
|
|
|
|
struct Val val;
|
|
|
|
int lint;
|
|
|
|
}
|
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
// |sed 's/.* //' |9 fmt -l1 |sort |9 fmt -l50 | sed 's/^/%xxx /'
|
|
|
|
|
|
|
|
%token <val> LLITERAL
|
|
|
|
%token <lint> LASOP
|
|
|
|
%token <sym> LBREAK LCASE LCHAN LCOLAS LCONST LCONTINUE LDDD
|
|
|
|
%token <sym> LDEFAULT LDEFER LELSE LFALL LFOR LFUNC LGO LGOTO
|
2010-01-27 00:13:22 -07:00
|
|
|
%token <sym> LIF LIMPORT LINTERFACE LMAP LNAME
|
2009-06-06 13:46:38 -06:00
|
|
|
%token <sym> LPACKAGE LRANGE LRETURN LSELECT LSTRUCT LSWITCH
|
|
|
|
%token <sym> LTYPE LVAR
|
|
|
|
|
|
|
|
%token LANDAND LANDNOT LBODY LCOMM LDEC LEQ LGE LGT
|
|
|
|
%token LIGNORE LINC LLE LLSH LLT LNE LOROR LRSH
|
|
|
|
|
2009-08-19 16:18:08 -06:00
|
|
|
%type <lint> lbrace import_here
|
2009-06-06 13:46:38 -06:00
|
|
|
%type <sym> sym packname
|
|
|
|
%type <val> oliteral
|
|
|
|
|
2009-07-14 00:38:39 -06:00
|
|
|
%type <node> stmt ntype
|
2009-07-17 02:00:44 -06:00
|
|
|
%type <node> arg_type
|
|
|
|
%type <node> case caseblock
|
|
|
|
%type <node> compound_stmt dotname embed expr
|
|
|
|
%type <node> expr_or_type
|
|
|
|
%type <node> fndcl fnliteral
|
2010-04-26 23:35:27 -06:00
|
|
|
%type <node> for_body for_header for_stmt if_header if_stmt non_dcl_stmt
|
2009-09-28 15:05:34 -06:00
|
|
|
%type <node> interfacedcl keyval labelname name
|
2009-07-17 15:42:14 -06:00
|
|
|
%type <node> name_or_type non_expr_type
|
2009-08-07 13:50:26 -06:00
|
|
|
%type <node> new_name dcl_name oexpr typedclname
|
2009-07-17 02:00:44 -06:00
|
|
|
%type <node> onew_name
|
|
|
|
%type <node> osimple_stmt pexpr
|
2009-06-06 20:27:48 -06:00
|
|
|
%type <node> pseudocall range_stmt select_stmt
|
2009-07-17 02:00:44 -06:00
|
|
|
%type <node> simple_stmt
|
|
|
|
%type <node> switch_stmt uexpr
|
2009-07-17 14:38:16 -06:00
|
|
|
%type <node> xfndcl typedcl
|
2009-07-17 02:00:44 -06:00
|
|
|
|
2009-07-17 14:38:16 -06:00
|
|
|
%type <list> xdcl fnbody fnres switch_body loop_body dcl_name_list
|
|
|
|
%type <list> new_name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list
|
2009-12-11 16:59:41 -07:00
|
|
|
%type <list> oexpr_list oexpr_or_type_list_ocomma caseblock_list stmt_list oarg_type_list_ocomma arg_type_list
|
2009-09-28 15:05:34 -06:00
|
|
|
%type <list> interfacedcl_list vardcl vardcl_list structdcl structdcl_list
|
2009-07-17 14:38:16 -06:00
|
|
|
%type <list> common_dcl constdcl constdcl1 constdcl_list typedcl_list
|
2009-06-06 13:46:38 -06:00
|
|
|
|
2010-05-24 16:25:30 -06:00
|
|
|
%type <node> convtype comptype dotdotdot
|
2009-07-17 15:42:14 -06:00
|
|
|
%type <node> indcl interfacetype structtype ptrtype
|
2010-01-26 11:40:28 -07:00
|
|
|
%type <node> recvchantype non_recvchantype othertype fnret_type fntype
|
2009-06-06 13:46:38 -06:00
|
|
|
|
2010-05-24 17:55:23 -06:00
|
|
|
%type <val> hidden_tag
|
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
%type <sym> hidden_importsym hidden_pkg_importsym
|
|
|
|
|
2010-02-18 15:46:28 -07:00
|
|
|
%type <node> hidden_constant hidden_literal hidden_dcl
|
|
|
|
%type <node> hidden_interfacedcl hidden_structdcl hidden_opt_sym
|
2009-07-17 02:00:44 -06:00
|
|
|
|
|
|
|
%type <list> hidden_funres
|
|
|
|
%type <list> ohidden_funres
|
|
|
|
%type <list> hidden_funarg_list ohidden_funarg_list
|
|
|
|
%type <list> hidden_interfacedcl_list ohidden_interfacedcl_list
|
|
|
|
%type <list> hidden_structdcl_list ohidden_structdcl_list
|
2009-06-06 13:46:38 -06:00
|
|
|
|
2009-12-03 01:10:32 -07:00
|
|
|
%type <type> hidden_type hidden_type_misc hidden_pkgtype
|
2010-01-26 11:40:28 -07:00
|
|
|
%type <type> hidden_type_func
|
|
|
|
%type <type> hidden_type_recv_chan hidden_type_non_recv_chan
|
2009-06-06 13:46:38 -06:00
|
|
|
|
|
|
|
%left LOROR
|
|
|
|
%left LANDAND
|
|
|
|
%left LCOMM
|
|
|
|
%left LEQ LNE LLE LGE LLT LGT
|
|
|
|
%left '+' '-' '|' '^'
|
|
|
|
%left '*' '/' '%' '&' LLSH LRSH LANDNOT
|
2008-10-03 17:15:55 -06:00
|
|
|
|
2009-03-03 09:41:02 -07:00
|
|
|
/*
|
2009-06-06 13:46:38 -06:00
|
|
|
* 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.
|
2009-03-03 09:41:02 -07:00
|
|
|
*/
|
2009-06-06 13:46:38 -06:00
|
|
|
%left NotPackage
|
|
|
|
%left LPACKAGE
|
2009-03-03 09:41:02 -07:00
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
%left NotParen
|
|
|
|
%left '('
|
2009-03-05 16:57:03 -07:00
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
%left ')'
|
|
|
|
%left PreferToRightParen
|
2009-03-05 16:57:03 -07:00
|
|
|
|
2010-01-27 00:13:22 -07:00
|
|
|
%error-verbose
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
%%
|
|
|
|
file:
|
2009-05-08 16:40:31 -06:00
|
|
|
loadsys
|
|
|
|
package
|
|
|
|
imports
|
2009-07-17 02:00:44 -06:00
|
|
|
xdcl_list
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-08-12 14:18:19 -06:00
|
|
|
xtop = concat(xtop, $4);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
package:
|
2009-03-05 16:57:03 -07:00
|
|
|
%prec NotPackage
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-08-19 16:18:08 -06:00
|
|
|
prevlineno = lineno;
|
2008-06-04 15:37:38 -06:00
|
|
|
yyerror("package statement must be first");
|
2009-12-11 16:59:41 -07:00
|
|
|
flusherrors();
|
2008-06-04 15:37:38 -06:00
|
|
|
mkpackage("main");
|
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| LPACKAGE sym ';'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
mkpackage($2->name);
|
2009-05-08 16:40:31 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-10-16 00:10:49 -06:00
|
|
|
* this loads the definitions for the low-level runtime functions,
|
2009-05-08 16:40:31 -06:00
|
|
|
* so that the compiler can generate calls to them,
|
2009-10-16 00:10:49 -06:00
|
|
|
* but does not make the name "runtime" visible as a package.
|
2009-05-08 16:40:31 -06:00
|
|
|
*/
|
|
|
|
loadsys:
|
|
|
|
{
|
2010-01-22 18:06:20 -07:00
|
|
|
importpkg = runtimepkg;
|
|
|
|
|
2010-01-19 22:34:44 -07:00
|
|
|
if(debug['A'])
|
|
|
|
cannedimports("runtime.builtin", "package runtime\n\n$$\n\n");
|
|
|
|
else
|
|
|
|
cannedimports("runtime.builtin", runtimeimport);
|
2010-06-11 16:28:43 -06:00
|
|
|
curio.importsafe = 1;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-05-08 16:40:31 -06:00
|
|
|
import_package
|
|
|
|
import_there
|
|
|
|
{
|
2010-01-22 18:06:20 -07:00
|
|
|
importpkg = nil;
|
2009-05-08 16:40:31 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
imports:
|
2009-12-11 16:59:41 -07:00
|
|
|
| imports import ';'
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
import:
|
2009-12-11 16:59:41 -07:00
|
|
|
LIMPORT import_stmt
|
|
|
|
| LIMPORT '(' import_stmt_list osemi ')'
|
|
|
|
| LIMPORT '(' ')'
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
import_stmt:
|
2009-08-19 16:18:08 -06:00
|
|
|
import_here import_package import_there
|
|
|
|
{
|
2010-01-22 18:06:20 -07:00
|
|
|
Pkg *ipkg;
|
|
|
|
Sym *my;
|
2009-09-17 17:42:10 -06:00
|
|
|
Node *pack;
|
2010-01-22 18:06:20 -07:00
|
|
|
|
|
|
|
ipkg = importpkg;
|
|
|
|
my = importmyname;
|
|
|
|
importpkg = nil;
|
|
|
|
importmyname = S;
|
2009-08-19 16:18:08 -06:00
|
|
|
|
2010-01-22 18:06:20 -07:00
|
|
|
if(my == nil)
|
|
|
|
my = lookup(ipkg->name);
|
2009-09-17 17:42:10 -06:00
|
|
|
|
|
|
|
pack = nod(OPACK, N, N);
|
2010-01-22 18:06:20 -07:00
|
|
|
pack->sym = my;
|
|
|
|
pack->pkg = ipkg;
|
2009-09-17 17:42:10 -06:00
|
|
|
pack->lineno = $1;
|
|
|
|
|
2009-08-19 16:18:08 -06:00
|
|
|
if(my->name[0] == '.') {
|
2010-01-22 18:06:20 -07:00
|
|
|
importdot(ipkg, pack);
|
2009-08-19 16:18:08 -06:00
|
|
|
break;
|
|
|
|
}
|
2009-09-09 17:59:41 -06:00
|
|
|
if(my->name[0] == '_' && my->name[1] == '\0')
|
|
|
|
break;
|
2010-06-12 12:17:24 -06:00
|
|
|
if(my->def) {
|
2009-10-07 15:55:12 -06:00
|
|
|
lineno = $1;
|
|
|
|
redeclare(my, "as imported package name");
|
|
|
|
}
|
2009-09-17 17:42:10 -06:00
|
|
|
my->def = pack;
|
2009-08-19 16:18:08 -06:00
|
|
|
my->lastlineno = $1;
|
2009-12-15 17:44:28 -07:00
|
|
|
my->block = 1; // at top level
|
2009-08-19 16:18:08 -06:00
|
|
|
}
|
2009-09-09 01:18:16 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
import_stmt_list:
|
|
|
|
import_stmt
|
|
|
|
| import_stmt_list ';' import_stmt
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
import_here:
|
|
|
|
LLITERAL
|
|
|
|
{
|
|
|
|
// import with original name
|
2009-08-19 16:18:08 -06:00
|
|
|
$$ = parserline();
|
2010-01-22 18:06:20 -07:00
|
|
|
importmyname = S;
|
2009-09-17 17:42:10 -06:00
|
|
|
importfile(&$1, $$);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
| sym LLITERAL
|
|
|
|
{
|
|
|
|
// import with given name
|
2009-08-19 16:18:08 -06:00
|
|
|
$$ = parserline();
|
2010-01-22 18:06:20 -07:00
|
|
|
importmyname = $1;
|
2009-09-17 17:42:10 -06:00
|
|
|
importfile(&$2, $$);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
| '.' LLITERAL
|
|
|
|
{
|
2009-05-08 16:40:31 -06:00
|
|
|
// import into my name space
|
2009-08-19 16:18:08 -06:00
|
|
|
$$ = parserline();
|
2010-01-22 18:06:20 -07:00
|
|
|
importmyname = lookup(".");
|
2009-09-17 17:42:10 -06:00
|
|
|
importfile(&$2, $$);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2008-06-12 22:48:56 -06:00
|
|
|
import_package:
|
2010-06-11 16:28:43 -06:00
|
|
|
LPACKAGE sym import_safety ';'
|
2008-06-12 22:48:56 -06:00
|
|
|
{
|
2010-01-22 18:06:20 -07:00
|
|
|
importpkg->name = $2->name;
|
2010-01-25 00:33:59 -07:00
|
|
|
importpkg->direct = 1;
|
2010-06-11 16:28:43 -06:00
|
|
|
|
|
|
|
if(safemode && !curio.importsafe)
|
|
|
|
yyerror("cannot import unsafe package %Z", importpkg->path);
|
2010-01-22 18:06:20 -07:00
|
|
|
|
2010-01-25 19:31:35 -07:00
|
|
|
// NOTE(rsc): This is no longer a technical restriction:
|
|
|
|
// the 6g tool chain would work just fine without giving
|
|
|
|
// special meaning to a package being named main.
|
|
|
|
// Other implementations might need the restriction
|
|
|
|
// (gccgo does), so it stays in the language and the compiler.
|
2009-04-02 22:46:19 -06:00
|
|
|
if(strcmp($2->name, "main") == 0)
|
|
|
|
yyerror("cannot import package main");
|
2008-06-12 22:48:56 -06:00
|
|
|
}
|
|
|
|
|
2010-06-11 16:28:43 -06:00
|
|
|
import_safety:
|
|
|
|
| LNAME
|
|
|
|
{
|
|
|
|
if(strcmp($1->name, "safe") == 0)
|
|
|
|
curio.importsafe = 1;
|
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
import_there:
|
2009-07-17 02:00:44 -06:00
|
|
|
{
|
|
|
|
defercheckwidth();
|
|
|
|
}
|
2008-10-06 17:44:17 -06:00
|
|
|
hidden_import_list '$' '$'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
resumecheckwidth();
|
2008-06-04 15:37:38 -06:00
|
|
|
unimportfile();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* declarations
|
|
|
|
*/
|
|
|
|
xdcl:
|
2008-08-03 19:47:02 -06:00
|
|
|
{
|
2009-12-11 16:59:41 -07:00
|
|
|
yyerror("empty top-level declaration");
|
|
|
|
$$ = nil;
|
2008-08-03 19:47:02 -06:00
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| common_dcl
|
|
|
|
| xfndcl
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-12-11 16:59:41 -07:00
|
|
|
$$ = list1($1);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2010-04-26 23:35:27 -06:00
|
|
|
| non_dcl_stmt
|
|
|
|
{
|
|
|
|
yyerror("non-declaration statement outside function body");
|
|
|
|
$$ = nil;
|
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| error
|
2008-07-03 19:05:20 -06:00
|
|
|
{
|
2009-09-15 18:29:08 -06:00
|
|
|
$$ = nil;
|
2008-07-03 19:05:20 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
common_dcl:
|
2009-06-06 20:27:48 -06:00
|
|
|
LVAR vardcl
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| LVAR '(' vardcl_list osemi ')'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = $3;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-08 16:33:09 -06:00
|
|
|
| LVAR '(' ')'
|
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2009-06-06 20:27:48 -06:00
|
|
|
}
|
2010-06-12 12:17:24 -06:00
|
|
|
| lconst constdcl
|
2009-06-06 20:27:48 -06:00
|
|
|
{
|
2009-08-07 13:50:26 -06:00
|
|
|
$$ = $2;
|
2010-06-12 12:17:24 -06:00
|
|
|
iota = -100000;
|
2009-07-17 02:00:44 -06:00
|
|
|
lastconst = nil;
|
2008-10-08 16:33:09 -06:00
|
|
|
}
|
2010-06-12 12:17:24 -06:00
|
|
|
| lconst '(' constdcl osemi ')'
|
2008-09-04 13:21:10 -06:00
|
|
|
{
|
2009-08-07 13:50:26 -06:00
|
|
|
$$ = $3;
|
2010-06-12 12:17:24 -06:00
|
|
|
iota = -100000;
|
2009-07-17 02:00:44 -06:00
|
|
|
lastconst = nil;
|
2008-09-04 13:21:10 -06:00
|
|
|
}
|
2010-06-12 12:17:24 -06:00
|
|
|
| lconst '(' constdcl ';' constdcl_list osemi ')'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-08-07 13:50:26 -06:00
|
|
|
$$ = concat($3, $5);
|
2010-06-12 12:17:24 -06:00
|
|
|
iota = -100000;
|
2009-07-17 02:00:44 -06:00
|
|
|
lastconst = nil;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2010-06-12 12:17:24 -06:00
|
|
|
| lconst '(' ')'
|
2008-10-08 16:33:09 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2010-06-12 12:17:24 -06:00
|
|
|
iota = -100000;
|
2008-10-08 16:33:09 -06:00
|
|
|
}
|
2009-06-06 20:27:48 -06:00
|
|
|
| LTYPE typedcl
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-08-07 13:50:26 -06:00
|
|
|
$$ = list1($2);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| LTYPE '(' typedcl_list osemi ')'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-08-07 13:50:26 -06:00
|
|
|
$$ = $3;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-08 16:33:09 -06:00
|
|
|
| LTYPE '(' ')'
|
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2010-06-12 12:17:24 -06:00
|
|
|
lconst:
|
|
|
|
LCONST
|
|
|
|
{
|
|
|
|
iota = 0;
|
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
vardcl:
|
2009-12-11 16:59:41 -07:00
|
|
|
dcl_name_list ntype
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = variter($1, $2, nil);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| dcl_name_list ntype '=' expr_list
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-12-11 16:59:41 -07:00
|
|
|
$$ = variter($1, $2, $4);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-07-17 14:38:16 -06:00
|
|
|
| dcl_name_list '=' expr_list
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 15:42:14 -06:00
|
|
|
$$ = variter($1, nil, $3);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
constdcl:
|
2009-07-17 14:38:16 -06:00
|
|
|
dcl_name_list ntype '=' expr_list
|
2008-07-03 17:41:32 -06:00
|
|
|
{
|
2009-07-17 14:38:16 -06:00
|
|
|
$$ = constiter($1, $2, $4);
|
2008-07-03 17:41:32 -06:00
|
|
|
}
|
2009-07-17 14:38:16 -06:00
|
|
|
| dcl_name_list '=' expr_list
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 14:38:16 -06:00
|
|
|
$$ = constiter($1, N, $3);
|
2008-07-03 17:41:32 -06:00
|
|
|
}
|
|
|
|
|
2008-09-04 13:21:10 -06:00
|
|
|
constdcl1:
|
|
|
|
constdcl
|
2009-07-17 14:38:16 -06:00
|
|
|
| dcl_name_list ntype
|
2008-07-03 17:41:32 -06:00
|
|
|
{
|
2009-07-17 14:38:16 -06:00
|
|
|
$$ = constiter($1, $2, nil);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-07-17 14:38:16 -06:00
|
|
|
| dcl_name_list
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 14:38:16 -06:00
|
|
|
$$ = constiter($1, N, nil);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2008-10-06 17:44:17 -06:00
|
|
|
typedclname:
|
2009-08-07 13:50:26 -06:00
|
|
|
sym
|
2008-10-06 17:44:17 -06:00
|
|
|
{
|
2009-08-07 13:50:26 -06:00
|
|
|
// different from dclname because the name
|
|
|
|
// becomes visible right here, not at the end
|
|
|
|
// of the declaration.
|
|
|
|
$$ = typedcl0($1);
|
2008-10-06 17:44:17 -06:00
|
|
|
}
|
|
|
|
|
2008-10-07 13:36:30 -06:00
|
|
|
typedcl:
|
2009-07-17 15:42:14 -06:00
|
|
|
typedclname ntype
|
2008-10-06 17:44:17 -06:00
|
|
|
{
|
2009-08-07 13:50:26 -06:00
|
|
|
$$ = typedcl1($1, $2, 1);
|
2008-10-06 17:44:17 -06:00
|
|
|
}
|
2009-08-07 13:50:26 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
simple_stmt:
|
|
|
|
expr
|
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
| expr LASOP expr
|
|
|
|
{
|
|
|
|
$$ = nod(OASOP, $1, $3);
|
2008-08-08 18:13:31 -06:00
|
|
|
$$->etype = $2; // rathole to pass opcode
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| expr_list '=' expr_list
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
if($1->next == nil && $3->next == nil) {
|
|
|
|
// simple
|
|
|
|
$$ = nod(OAS, $1->n, $3->n);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// multiple
|
|
|
|
$$ = nod(OAS2, N, N);
|
|
|
|
$$->list = $1;
|
|
|
|
$$->rlist = $3;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| expr_list LCOLAS expr_list
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
if($3->n->op == OTYPESW) {
|
|
|
|
if($3->next != nil)
|
|
|
|
yyerror("expr.(type) must be alone in list");
|
|
|
|
else if($1->next != nil)
|
|
|
|
yyerror("argument count mismatch: %d = %d", count($1), 1);
|
2009-09-09 01:18:16 -06:00
|
|
|
$$ = nod(OTYPESW, $1->n, $3->n->right);
|
2009-03-06 18:50:43 -07:00
|
|
|
break;
|
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = colas($1, $3);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-07 13:36:30 -06:00
|
|
|
| expr LINC
|
2008-06-17 23:33:32 -06:00
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
$$ = nod(OASOP, $1, nodintconst(1));
|
2008-06-17 23:33:32 -06:00
|
|
|
$$->etype = OADD;
|
|
|
|
}
|
|
|
|
| expr LDEC
|
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
$$ = nod(OASOP, $1, nodintconst(1));
|
2008-06-17 23:33:32 -06:00
|
|
|
$$->etype = OSUB;
|
|
|
|
}
|
|
|
|
|
2009-05-30 22:18:15 -06:00
|
|
|
case:
|
2009-07-17 15:42:14 -06:00
|
|
|
LCASE expr_or_type_list ':'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-09-09 01:18:16 -06:00
|
|
|
Node *n;
|
2009-07-10 17:29:26 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
// will be converted to OCASE
|
|
|
|
// right will point to next case
|
|
|
|
// done in casebody()
|
|
|
|
poptodcl();
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(OXCASE, N, N);
|
2009-09-09 01:18:16 -06:00
|
|
|
$$->list = $2;
|
|
|
|
if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
|
|
|
|
// type switch - declare variable
|
|
|
|
n = newname(n->sym);
|
2009-09-14 19:38:30 -06:00
|
|
|
n->used = 1; // TODO(rsc): better job here
|
2009-08-05 03:33:30 -06:00
|
|
|
declare(n, dclcontext);
|
2009-09-09 01:18:16 -06:00
|
|
|
$$->nname = n;
|
2009-03-17 14:58:38 -06:00
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
break;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-09-16 20:14:33 -06:00
|
|
|
| LCASE name '=' expr ':'
|
|
|
|
{
|
|
|
|
// will be converted to OCASE
|
|
|
|
// right will point to next case
|
|
|
|
// done in casebody()
|
|
|
|
poptodcl();
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(OXCASE, N, N);
|
|
|
|
$$->list = list1(nod(OAS, $2, $4));
|
2008-09-16 20:14:33 -06:00
|
|
|
}
|
|
|
|
| LCASE name LCOLAS expr ':'
|
|
|
|
{
|
|
|
|
// will be converted to OCASE
|
|
|
|
// right will point to next case
|
|
|
|
// done in casebody()
|
|
|
|
poptodcl();
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(OXCASE, N, N);
|
2009-08-05 01:42:44 -06:00
|
|
|
$$->list = list1(colas(list1($2), list1($4)));
|
2008-09-16 20:14:33 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
| LDEFAULT ':'
|
|
|
|
{
|
2009-09-09 01:18:16 -06:00
|
|
|
Node *n;
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
poptodcl();
|
|
|
|
$$ = nod(OXCASE, N, N);
|
2009-09-09 01:18:16 -06:00
|
|
|
if(typesw != N && typesw->right != N && (n=typesw->right->left) != N) {
|
|
|
|
// type switch - declare variable
|
|
|
|
n = newname(n->sym);
|
2009-09-14 19:38:30 -06:00
|
|
|
n->used = 1; // TODO(rsc): better job here
|
2009-09-09 01:18:16 -06:00
|
|
|
declare(n, dclcontext);
|
|
|
|
$$->nname = n;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-06-08 13:48:37 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
compound_stmt:
|
|
|
|
'{'
|
|
|
|
{
|
2008-07-05 13:49:25 -06:00
|
|
|
markdcl();
|
2009-06-06 13:46:38 -06:00
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
stmt_list '}'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = liststmt($3);
|
2008-07-05 13:49:25 -06:00
|
|
|
popdcl();
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2009-05-30 22:18:15 -06:00
|
|
|
switch_body:
|
2009-06-06 13:46:38 -06:00
|
|
|
LBODY
|
2009-05-30 22:18:15 -06:00
|
|
|
{
|
|
|
|
markdcl();
|
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
caseblock_list '}'
|
2009-05-30 22:18:15 -06:00
|
|
|
{
|
|
|
|
$$ = $3;
|
|
|
|
popdcl();
|
|
|
|
}
|
|
|
|
|
|
|
|
caseblock:
|
2009-07-17 02:00:44 -06:00
|
|
|
case stmt_list
|
2009-05-30 22:18:15 -06:00
|
|
|
{
|
|
|
|
$$ = $1;
|
|
|
|
$$->nbody = $2;
|
|
|
|
}
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
caseblock_list:
|
2009-05-30 22:18:15 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
|
|
|
}
|
|
|
|
| caseblock_list caseblock
|
|
|
|
{
|
|
|
|
$$ = list($1, $2);
|
2009-05-30 22:18:15 -06:00
|
|
|
}
|
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
loop_body:
|
|
|
|
LBODY
|
|
|
|
{
|
|
|
|
markdcl();
|
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
stmt_list '}'
|
2009-06-06 13:46:38 -06:00
|
|
|
{
|
|
|
|
$$ = $3;
|
|
|
|
popdcl();
|
|
|
|
}
|
|
|
|
|
2009-01-28 16:41:50 -07:00
|
|
|
range_stmt:
|
2009-06-06 13:46:38 -06:00
|
|
|
expr_list '=' LRANGE expr
|
2008-12-06 14:40:30 -07:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(ORANGE, N, $4);
|
|
|
|
$$->list = $1;
|
2008-12-06 14:40:30 -07:00
|
|
|
$$->etype = 0; // := flag
|
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| expr_list LCOLAS LRANGE expr
|
2008-12-06 14:40:30 -07:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(ORANGE, N, $4);
|
|
|
|
$$->list = $1;
|
2009-08-05 03:33:30 -06:00
|
|
|
$$->colas = 1;
|
|
|
|
colasdefn($1, $$);
|
2008-12-06 14:40:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
for_header:
|
2009-01-28 16:41:50 -07:00
|
|
|
osimple_stmt ';' osimple_stmt ';' osimple_stmt
|
|
|
|
{
|
2008-06-04 15:37:38 -06:00
|
|
|
// init ; test ; incr
|
2008-12-15 14:44:27 -07:00
|
|
|
if($5 != N && $5->colas != 0)
|
|
|
|
yyerror("cannot declare in the for-increment");
|
2008-06-04 15:37:38 -06:00
|
|
|
$$ = nod(OFOR, N, N);
|
2009-07-17 02:00:44 -06:00
|
|
|
if($1 != N)
|
|
|
|
$$->ninit = list1($1);
|
2008-06-04 15:37:38 -06:00
|
|
|
$$->ntest = $3;
|
|
|
|
$$->nincr = $5;
|
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| osimple_stmt
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-12-06 14:40:30 -07:00
|
|
|
// normal test
|
2008-06-04 15:37:38 -06:00
|
|
|
$$ = nod(OFOR, N, N);
|
|
|
|
$$->ntest = $1;
|
|
|
|
}
|
2009-01-28 16:41:50 -07:00
|
|
|
| range_stmt
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
for_body:
|
2009-06-06 13:46:38 -06:00
|
|
|
for_header loop_body
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
$$ = $1;
|
2009-07-17 02:00:44 -06:00
|
|
|
$$->nbody = concat($$->nbody, $2);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
for_stmt:
|
2009-05-30 22:18:15 -06:00
|
|
|
LFOR
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-07-05 13:49:25 -06:00
|
|
|
markdcl();
|
2009-05-30 22:18:15 -06:00
|
|
|
}
|
|
|
|
for_body
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-05-30 22:18:15 -06:00
|
|
|
$$ = $3;
|
|
|
|
popdcl();
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if_header:
|
2009-06-06 13:46:38 -06:00
|
|
|
osimple_stmt
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
// test
|
|
|
|
$$ = nod(OIF, N, N);
|
|
|
|
$$->ntest = $1;
|
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| osimple_stmt ';' osimple_stmt
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
// init ; test
|
|
|
|
$$ = nod(OIF, N, N);
|
2009-07-17 02:00:44 -06:00
|
|
|
if($1 != N)
|
|
|
|
$$->ninit = list1($1);
|
2008-06-04 15:37:38 -06:00
|
|
|
$$->ntest = $3;
|
|
|
|
}
|
|
|
|
|
2009-05-30 22:18:15 -06:00
|
|
|
if_stmt:
|
|
|
|
LIF
|
|
|
|
{
|
|
|
|
markdcl();
|
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
if_header loop_body
|
2009-05-30 22:18:15 -06:00
|
|
|
{
|
|
|
|
$$ = $3;
|
|
|
|
$$->nbody = $4;
|
|
|
|
// no popdcl; maybe there's an LELSE
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_stmt:
|
|
|
|
LSWITCH
|
|
|
|
{
|
|
|
|
markdcl();
|
|
|
|
}
|
2009-03-06 18:50:43 -07:00
|
|
|
if_header
|
|
|
|
{
|
|
|
|
Node *n;
|
2009-05-30 22:18:15 -06:00
|
|
|
n = $3->ntest;
|
2009-09-09 01:18:16 -06:00
|
|
|
if(n != N && n->op != OTYPESW)
|
2009-03-06 18:50:43 -07:00
|
|
|
n = N;
|
2009-09-09 01:18:16 -06:00
|
|
|
typesw = nod(OXXX, typesw, n);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-05-30 22:18:15 -06:00
|
|
|
switch_body
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-05-30 22:18:15 -06:00
|
|
|
$$ = $3;
|
|
|
|
$$->op = OSWITCH;
|
2009-07-17 02:00:44 -06:00
|
|
|
$$->list = $5;
|
2009-09-09 01:18:16 -06:00
|
|
|
typesw = typesw->left;
|
2009-05-30 22:18:15 -06:00
|
|
|
popdcl();
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2008-07-20 21:13:07 -06:00
|
|
|
select_stmt:
|
2009-05-30 22:18:15 -06:00
|
|
|
LSELECT
|
2008-07-20 21:13:07 -06:00
|
|
|
{
|
|
|
|
markdcl();
|
|
|
|
}
|
2009-05-30 22:18:15 -06:00
|
|
|
switch_body
|
2008-07-20 21:13:07 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(OSELECT, N, N);
|
|
|
|
$$->list = $3;
|
2009-05-30 22:18:15 -06:00
|
|
|
popdcl();
|
2008-07-20 21:13:07 -06:00
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
/*
|
|
|
|
* expressions
|
|
|
|
*/
|
|
|
|
expr:
|
|
|
|
uexpr
|
|
|
|
| expr LOROR expr
|
|
|
|
{
|
|
|
|
$$ = nod(OOROR, $1, $3);
|
|
|
|
}
|
|
|
|
| expr LANDAND expr
|
|
|
|
{
|
|
|
|
$$ = nod(OANDAND, $1, $3);
|
|
|
|
}
|
|
|
|
| expr LEQ expr
|
|
|
|
{
|
|
|
|
$$ = nod(OEQ, $1, $3);
|
|
|
|
}
|
|
|
|
| expr LNE expr
|
|
|
|
{
|
|
|
|
$$ = nod(ONE, $1, $3);
|
|
|
|
}
|
|
|
|
| expr LLT expr
|
|
|
|
{
|
|
|
|
$$ = nod(OLT, $1, $3);
|
|
|
|
}
|
|
|
|
| expr LLE expr
|
|
|
|
{
|
|
|
|
$$ = nod(OLE, $1, $3);
|
|
|
|
}
|
|
|
|
| expr LGE expr
|
|
|
|
{
|
|
|
|
$$ = nod(OGE, $1, $3);
|
|
|
|
}
|
|
|
|
| expr LGT expr
|
|
|
|
{
|
|
|
|
$$ = nod(OGT, $1, $3);
|
|
|
|
}
|
|
|
|
| expr '+' expr
|
|
|
|
{
|
|
|
|
$$ = nod(OADD, $1, $3);
|
|
|
|
}
|
|
|
|
| expr '-' expr
|
|
|
|
{
|
|
|
|
$$ = nod(OSUB, $1, $3);
|
|
|
|
}
|
|
|
|
| expr '|' expr
|
|
|
|
{
|
|
|
|
$$ = nod(OOR, $1, $3);
|
|
|
|
}
|
|
|
|
| expr '^' expr
|
|
|
|
{
|
|
|
|
$$ = nod(OXOR, $1, $3);
|
|
|
|
}
|
|
|
|
| expr '*' expr
|
|
|
|
{
|
|
|
|
$$ = nod(OMUL, $1, $3);
|
|
|
|
}
|
|
|
|
| expr '/' expr
|
|
|
|
{
|
|
|
|
$$ = nod(ODIV, $1, $3);
|
|
|
|
}
|
|
|
|
| expr '%' expr
|
|
|
|
{
|
|
|
|
$$ = nod(OMOD, $1, $3);
|
|
|
|
}
|
|
|
|
| expr '&' expr
|
|
|
|
{
|
|
|
|
$$ = nod(OAND, $1, $3);
|
|
|
|
}
|
2009-03-11 20:59:35 -06:00
|
|
|
| expr LANDNOT expr
|
|
|
|
{
|
|
|
|
$$ = nod(OANDNOT, $1, $3);
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
| expr LLSH expr
|
|
|
|
{
|
|
|
|
$$ = nod(OLSH, $1, $3);
|
|
|
|
}
|
|
|
|
| expr LRSH expr
|
|
|
|
{
|
|
|
|
$$ = nod(ORSH, $1, $3);
|
|
|
|
}
|
2008-09-16 20:14:33 -06:00
|
|
|
| expr LCOMM expr
|
2008-07-15 22:07:59 -06:00
|
|
|
{
|
|
|
|
$$ = nod(OSEND, $1, $3);
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
uexpr:
|
|
|
|
pexpr
|
|
|
|
| '*' uexpr
|
|
|
|
{
|
|
|
|
$$ = nod(OIND, $2, N);
|
|
|
|
}
|
|
|
|
| '&' uexpr
|
|
|
|
{
|
|
|
|
$$ = nod(OADDR, $2, N);
|
|
|
|
}
|
|
|
|
| '+' uexpr
|
|
|
|
{
|
|
|
|
$$ = nod(OPLUS, $2, N);
|
|
|
|
}
|
|
|
|
| '-' uexpr
|
|
|
|
{
|
|
|
|
$$ = nod(OMINUS, $2, N);
|
|
|
|
}
|
|
|
|
| '!' uexpr
|
|
|
|
{
|
|
|
|
$$ = nod(ONOT, $2, N);
|
|
|
|
}
|
|
|
|
| '~' uexpr
|
|
|
|
{
|
2010-06-07 19:27:26 -06:00
|
|
|
yyerror("the bitwise complement operator is ^");
|
2008-06-04 15:37:38 -06:00
|
|
|
$$ = nod(OCOM, $2, N);
|
|
|
|
}
|
|
|
|
| '^' uexpr
|
|
|
|
{
|
|
|
|
$$ = nod(OCOM, $2, N);
|
|
|
|
}
|
2008-09-16 20:14:33 -06:00
|
|
|
| LCOMM uexpr
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
$$ = nod(ORECV, $2, N);
|
|
|
|
}
|
|
|
|
|
2009-04-28 18:20:18 -06:00
|
|
|
/*
|
|
|
|
* call-like statements that
|
2009-07-17 02:00:44 -06:00
|
|
|
* can be preceded by 'defer' and 'go'
|
2009-04-28 18:20:18 -06:00
|
|
|
*/
|
|
|
|
pseudocall:
|
2009-12-11 16:59:41 -07:00
|
|
|
pexpr '(' oexpr_or_type_list_ocomma ')'
|
2009-04-28 18:20:18 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(OCALL, $1, N);
|
|
|
|
$$->list = $3;
|
2009-04-28 18:20:18 -06:00
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
pexpr:
|
|
|
|
LLITERAL
|
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
$$ = nodlit($1);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-07-17 15:42:14 -06:00
|
|
|
| name
|
2009-06-06 13:46:38 -06:00
|
|
|
| pexpr '.' sym
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-06-06 13:46:38 -06:00
|
|
|
if($1->op == OPACK) {
|
|
|
|
Sym *s;
|
2010-01-22 18:06:20 -07:00
|
|
|
s = restrictlookup($3->name, $1->pkg);
|
2009-09-17 17:42:10 -06:00
|
|
|
$1->used = 1;
|
2009-06-06 13:46:38 -06:00
|
|
|
$$ = oldname(s);
|
|
|
|
break;
|
|
|
|
}
|
2009-08-05 03:33:30 -06:00
|
|
|
$$ = nod(OXDOT, $1, newname($3));
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| '(' expr_or_type ')'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| pexpr '.' '(' expr_or_type ')'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-14 00:38:39 -06:00
|
|
|
$$ = nod(ODOTTYPE, $1, $4);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-03-06 18:50:43 -07:00
|
|
|
| pexpr '.' '(' LTYPE ')'
|
|
|
|
{
|
2009-09-09 01:18:16 -06:00
|
|
|
$$ = nod(OTYPESW, N, $1);
|
2009-03-06 18:50:43 -07:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
| pexpr '[' expr ']'
|
|
|
|
{
|
|
|
|
$$ = nod(OINDEX, $1, $3);
|
|
|
|
}
|
2010-01-27 00:13:22 -07:00
|
|
|
| pexpr '[' oexpr ':' oexpr ']'
|
2009-11-20 10:11:46 -07:00
|
|
|
{
|
2010-01-27 00:13:22 -07:00
|
|
|
if($3 == N) {
|
|
|
|
yyerror("missing lower bound in slice expression");
|
|
|
|
$3 = nodintconst(0);
|
|
|
|
}
|
2009-11-20 10:11:46 -07:00
|
|
|
$$ = nod(OSLICE, $1, nod(OKEY, $3, $5));
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-04-28 18:20:18 -06:00
|
|
|
| pseudocall
|
2009-03-03 09:41:02 -07:00
|
|
|
| convtype '(' expr ')'
|
2008-09-05 20:50:34 -06:00
|
|
|
{
|
2009-03-03 09:41:02 -07:00
|
|
|
// conversion
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(OCALL, $1, N);
|
|
|
|
$$->list = list1($3);
|
2009-06-06 13:46:38 -06:00
|
|
|
}
|
2010-05-24 16:25:30 -06:00
|
|
|
| comptype lbrace braced_keyval_list '}'
|
2009-06-06 13:46:38 -06:00
|
|
|
{
|
|
|
|
// composite expression
|
2009-08-03 12:58:52 -06:00
|
|
|
$$ = nod(OCOMPLIT, N, $1);
|
2009-07-17 02:00:44 -06:00
|
|
|
$$->list = $3;
|
2009-06-06 13:46:38 -06:00
|
|
|
|
|
|
|
// If the opening brace was an LBODY,
|
|
|
|
// set up for another one now that we're done.
|
|
|
|
// See comment in lex.c about loophack.
|
|
|
|
if($2 == LBODY)
|
|
|
|
loophack = 1;
|
2008-09-05 20:50:34 -06:00
|
|
|
}
|
2009-09-29 22:21:14 -06:00
|
|
|
| pexpr '{' braced_keyval_list '}'
|
2008-09-05 20:50:34 -06:00
|
|
|
{
|
2009-03-03 09:41:02 -07:00
|
|
|
// composite expression
|
2009-08-03 12:58:52 -06:00
|
|
|
$$ = nod(OCOMPLIT, N, $1);
|
2009-07-17 02:00:44 -06:00
|
|
|
$$->list = $3;
|
2008-09-05 20:50:34 -06:00
|
|
|
}
|
|
|
|
| fnliteral
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
expr_or_type:
|
|
|
|
expr
|
2009-07-17 15:42:14 -06:00
|
|
|
| non_expr_type %prec PreferToRightParen
|
2009-06-06 13:46:38 -06:00
|
|
|
|
|
|
|
name_or_type:
|
2009-07-17 15:42:14 -06:00
|
|
|
ntype
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
lbrace:
|
|
|
|
LBODY
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-06-06 13:46:38 -06:00
|
|
|
$$ = LBODY;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| '{'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-06-06 13:46:38 -06:00
|
|
|
$$ = '{';
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* names and types
|
|
|
|
* newname is used before declared
|
|
|
|
* oldname is used after declared
|
|
|
|
*/
|
|
|
|
new_name:
|
2009-06-06 13:46:38 -06:00
|
|
|
sym
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
$$ = newname($1);
|
|
|
|
}
|
|
|
|
|
2009-07-17 14:38:16 -06:00
|
|
|
dcl_name:
|
|
|
|
sym
|
|
|
|
{
|
|
|
|
$$ = dclname($1);
|
|
|
|
}
|
|
|
|
|
2008-08-29 21:30:19 -06:00
|
|
|
onew_name:
|
|
|
|
{
|
|
|
|
$$ = N;
|
|
|
|
}
|
|
|
|
| new_name
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
sym:
|
2009-06-06 13:46:38 -06:00
|
|
|
LNAME
|
2008-10-26 15:04:09 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
name:
|
2010-05-24 16:25:30 -06:00
|
|
|
sym %prec NotParen
|
2009-03-05 16:57:03 -07:00
|
|
|
{
|
|
|
|
$$ = oldname($1);
|
2009-09-17 17:42:10 -06:00
|
|
|
if($$->pack != N)
|
|
|
|
$$->pack->used = 1;
|
2009-03-05 16:57:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
labelname:
|
2009-08-07 13:50:26 -06:00
|
|
|
new_name
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-10-07 13:36:30 -06:00
|
|
|
/*
|
|
|
|
* to avoid parsing conflicts, type is split into
|
|
|
|
* channel types
|
|
|
|
* function types
|
2009-06-06 20:27:48 -06:00
|
|
|
* parenthesized types
|
2008-10-07 13:36:30 -06:00
|
|
|
* any other type
|
|
|
|
* the type system makes additional restrictions,
|
|
|
|
* but those are not implemented in the grammar.
|
|
|
|
*/
|
2008-10-29 13:46:44 -06:00
|
|
|
dotdotdot:
|
|
|
|
LDDD
|
|
|
|
{
|
2010-02-01 01:25:59 -07:00
|
|
|
$$ = nod(ODDD, N, N);
|
|
|
|
}
|
|
|
|
| LDDD ntype
|
|
|
|
{
|
|
|
|
$$ = nod(ODDD, $2, N);
|
2008-10-29 13:46:44 -06:00
|
|
|
}
|
2008-10-07 13:36:30 -06:00
|
|
|
|
2009-07-17 15:42:14 -06:00
|
|
|
ntype:
|
2010-01-26 11:40:28 -07:00
|
|
|
recvchantype
|
2009-07-17 15:42:14 -06:00
|
|
|
| fntype
|
|
|
|
| othertype
|
|
|
|
| ptrtype
|
|
|
|
| dotname
|
|
|
|
| '(' ntype ')'
|
2009-07-14 00:38:39 -06:00
|
|
|
{
|
2009-07-17 15:42:14 -06:00
|
|
|
$$ = $2;
|
2009-07-14 00:38:39 -06:00
|
|
|
}
|
|
|
|
|
2009-07-17 15:42:14 -06:00
|
|
|
non_expr_type:
|
2010-01-26 11:40:28 -07:00
|
|
|
recvchantype
|
2009-07-17 14:38:16 -06:00
|
|
|
| fntype
|
2009-06-06 20:27:48 -06:00
|
|
|
| othertype
|
2009-07-17 15:42:14 -06:00
|
|
|
| '*' non_expr_type
|
|
|
|
{
|
|
|
|
$$ = nod(OIND, $2, N);
|
|
|
|
}
|
2008-10-07 13:36:30 -06:00
|
|
|
|
2010-01-26 11:40:28 -07:00
|
|
|
non_recvchantype:
|
2009-07-17 14:38:16 -06:00
|
|
|
fntype
|
2009-06-06 20:27:48 -06:00
|
|
|
| othertype
|
2009-07-17 15:42:14 -06:00
|
|
|
| ptrtype
|
|
|
|
| dotname
|
2009-07-14 00:38:39 -06:00
|
|
|
| '(' ntype ')'
|
fix up arg list parsing to handle any names:
type t1 int;
type t2 int;
type t3 int;
func f1(t1, t2, t3);
func f2(t1, t2, t3 bool);
func f3(t1, t2, x t3);
func f4(*t2, x t3); // error: cannot mix
func f5(t1, *t3);
func (x *t1) f6(y *[]t2) (t1, *t3);
func f7() (int, *string);
func f8(t1, *t2, x t3); // error: cannot mix
func f9() (x int, *string);
func f10(*t2, t3);
R=ken
OCL=16202
CL=16210
2008-09-30 13:53:11 -06:00
|
|
|
{
|
2009-06-06 20:27:48 -06:00
|
|
|
$$ = $2;
|
fix up arg list parsing to handle any names:
type t1 int;
type t2 int;
type t3 int;
func f1(t1, t2, t3);
func f2(t1, t2, t3 bool);
func f3(t1, t2, x t3);
func f4(*t2, x t3); // error: cannot mix
func f5(t1, *t3);
func (x *t1) f6(y *[]t2) (t1, *t3);
func f7() (int, *string);
func f8(t1, *t2, x t3); // error: cannot mix
func f9() (x int, *string);
func f10(*t2, t3);
R=ken
OCL=16202
CL=16210
2008-09-30 13:53:11 -06:00
|
|
|
}
|
|
|
|
|
2010-05-24 16:25:30 -06:00
|
|
|
convtype:
|
|
|
|
fntype
|
|
|
|
| othertype
|
|
|
|
|
|
|
|
comptype:
|
|
|
|
othertype
|
|
|
|
|
2010-01-26 11:40:28 -07:00
|
|
|
fnret_type:
|
|
|
|
recvchantype
|
|
|
|
| fntype
|
2009-06-06 20:27:48 -06:00
|
|
|
| othertype
|
2009-07-17 15:42:14 -06:00
|
|
|
| ptrtype
|
|
|
|
| dotname
|
2009-06-06 20:27:48 -06:00
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
dotname:
|
2009-07-17 15:42:14 -06:00
|
|
|
name
|
2009-06-06 13:46:38 -06:00
|
|
|
| name '.' sym
|
|
|
|
{
|
|
|
|
if($1->op == OPACK) {
|
|
|
|
Sym *s;
|
2010-01-22 18:06:20 -07:00
|
|
|
s = restrictlookup($3->name, $1->pkg);
|
2009-09-17 17:42:10 -06:00
|
|
|
$1->used = 1;
|
2009-06-06 13:46:38 -06:00
|
|
|
$$ = oldname(s);
|
|
|
|
break;
|
|
|
|
}
|
2009-08-05 03:33:30 -06:00
|
|
|
$$ = nod(OXDOT, $1, newname($3));
|
2009-06-06 13:46:38 -06:00
|
|
|
}
|
2008-10-07 13:36:30 -06:00
|
|
|
|
2009-06-06 20:27:48 -06:00
|
|
|
othertype:
|
2009-07-17 15:42:14 -06:00
|
|
|
'[' oexpr ']' ntype
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 15:42:14 -06:00
|
|
|
$$ = nod(OTARRAY, $2, $4);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2010-02-01 01:25:59 -07:00
|
|
|
| '[' LDDD ']' ntype
|
2009-09-29 22:21:14 -06:00
|
|
|
{
|
|
|
|
// array literal of nelem
|
2010-02-01 01:25:59 -07:00
|
|
|
$$ = nod(OTARRAY, nod(ODDD, N, N), $4);
|
2009-09-29 22:21:14 -06:00
|
|
|
}
|
2010-01-26 11:40:28 -07:00
|
|
|
| LCHAN non_recvchantype
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2010-01-26 11:40:28 -07:00
|
|
|
$$ = nod(OTCHAN, $2, N);
|
|
|
|
$$->etype = Cboth;
|
2008-09-16 20:14:33 -06:00
|
|
|
}
|
2010-01-26 11:40:28 -07:00
|
|
|
| LCHAN LCOMM ntype
|
2008-09-16 20:14:33 -06:00
|
|
|
{
|
2009-07-14 00:38:39 -06:00
|
|
|
$$ = nod(OTCHAN, $3, N);
|
|
|
|
$$->etype = Csend;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-07-14 00:38:39 -06:00
|
|
|
| LMAP '[' ntype ']' ntype
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-14 00:38:39 -06:00
|
|
|
$$ = nod(OTMAP, $3, $5);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-07-17 15:42:14 -06:00
|
|
|
| structtype
|
|
|
|
| interfacetype
|
|
|
|
|
|
|
|
ptrtype:
|
|
|
|
'*' ntype
|
2008-06-21 16:11:29 -06:00
|
|
|
{
|
2009-07-14 00:38:39 -06:00
|
|
|
$$ = nod(OIND, $2, N);
|
2008-06-21 16:11:29 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2010-01-26 11:40:28 -07:00
|
|
|
recvchantype:
|
|
|
|
LCOMM LCHAN ntype
|
2008-09-16 20:14:33 -06:00
|
|
|
{
|
2010-01-26 11:40:28 -07:00
|
|
|
$$ = nod(OTCHAN, $3, N);
|
|
|
|
$$->etype = Crecv;
|
2008-09-16 20:14:33 -06:00
|
|
|
}
|
|
|
|
|
2008-09-05 20:50:34 -06:00
|
|
|
structtype:
|
2009-07-17 02:00:44 -06:00
|
|
|
LSTRUCT '{' structdcl_list osemi '}'
|
2008-09-05 20:50:34 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(OTSTRUCT, N, N);
|
|
|
|
$$->list = $3;
|
2008-09-05 20:50:34 -06:00
|
|
|
}
|
|
|
|
| LSTRUCT '{' '}'
|
|
|
|
{
|
2009-07-14 00:38:39 -06:00
|
|
|
$$ = nod(OTSTRUCT, N, N);
|
2008-09-05 20:50:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
interfacetype:
|
2009-07-17 02:00:44 -06:00
|
|
|
LINTERFACE '{' interfacedcl_list osemi '}'
|
2008-09-05 20:50:34 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(OTINTER, N, N);
|
|
|
|
$$->list = $3;
|
2008-09-05 20:50:34 -06:00
|
|
|
}
|
|
|
|
| LINTERFACE '{' '}'
|
|
|
|
{
|
2009-07-14 00:38:39 -06:00
|
|
|
$$ = nod(OTINTER, N, N);
|
2008-09-05 20:50:34 -06:00
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
keyval:
|
|
|
|
expr ':' expr
|
|
|
|
{
|
2008-09-03 15:40:22 -06:00
|
|
|
$$ = nod(OKEY, $1, $3);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-05-21 17:31:10 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
/*
|
|
|
|
* function stuff
|
|
|
|
* all in one place to show how crappy it all is
|
|
|
|
*/
|
|
|
|
xfndcl:
|
2009-08-07 13:50:26 -06:00
|
|
|
LFUNC fndcl fnbody
|
2008-06-11 22:06:26 -06:00
|
|
|
{
|
2009-08-07 13:50:26 -06:00
|
|
|
$$ = $2;
|
2009-11-15 13:57:09 -07:00
|
|
|
if($$ == N)
|
|
|
|
break;
|
2009-08-07 13:50:26 -06:00
|
|
|
$$->nbody = $3;
|
2008-06-04 15:37:38 -06:00
|
|
|
funcbody($$);
|
|
|
|
}
|
|
|
|
|
|
|
|
fndcl:
|
2009-12-11 16:59:41 -07:00
|
|
|
dcl_name '(' oarg_type_list_ocomma ')' fnres
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 15:42:14 -06:00
|
|
|
Node *n;
|
|
|
|
|
2009-12-15 15:26:50 -07:00
|
|
|
$3 = checkarglist($3, 1);
|
2008-06-04 15:37:38 -06:00
|
|
|
$$ = nod(ODCLFUNC, N, N);
|
|
|
|
$$->nname = $1;
|
2009-07-17 15:42:14 -06:00
|
|
|
n = nod(OTFUNC, N, N);
|
|
|
|
n->list = $3;
|
|
|
|
n->rlist = $5;
|
2010-04-11 15:51:35 -06:00
|
|
|
if(strcmp($1->sym->name, "init") == 0) {
|
|
|
|
$$->nname = renameinit($1);
|
|
|
|
if($3 != nil || $5 != nil)
|
|
|
|
yyerror("func init must have no arguments and no return values");
|
|
|
|
}
|
|
|
|
if(strcmp(localpkg->name, "main") == 0 && strcmp($1->sym->name, "main") == 0) {
|
|
|
|
if($3 != nil || $5 != nil)
|
|
|
|
yyerror("func main must have no arguments and no return values");
|
|
|
|
}
|
2009-08-07 13:50:26 -06:00
|
|
|
// TODO: check if nname already has an ntype
|
|
|
|
$$->nname->ntype = n;
|
2008-06-04 15:37:38 -06:00
|
|
|
funchdr($$);
|
|
|
|
}
|
2010-04-26 23:35:27 -06:00
|
|
|
| '(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-08-07 13:50:26 -06:00
|
|
|
Node *rcvr, *t;
|
2010-04-26 23:35:27 -06:00
|
|
|
Node *name;
|
|
|
|
|
|
|
|
name = newname($4);
|
2009-12-15 15:26:50 -07:00
|
|
|
$2 = checkarglist($2, 0);
|
|
|
|
$6 = checkarglist($6, 1);
|
2009-11-15 13:57:09 -07:00
|
|
|
$$ = N;
|
|
|
|
if($2 == nil) {
|
|
|
|
yyerror("method has no receiver");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if($2->next != nil) {
|
|
|
|
yyerror("method has multiple receivers");
|
|
|
|
break;
|
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
rcvr = $2->n;
|
2009-11-15 13:57:09 -07:00
|
|
|
if(rcvr->op != ODCLFIELD) {
|
2009-07-17 02:00:44 -06:00
|
|
|
yyerror("bad receiver in method");
|
2009-11-15 13:57:09 -07:00
|
|
|
break;
|
2009-07-17 02:00:44 -06:00
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
$$ = nod(ODCLFUNC, N, N);
|
2010-04-26 23:35:27 -06:00
|
|
|
$$->nname = methodname1(name, rcvr->right);
|
2009-08-07 13:50:26 -06:00
|
|
|
t = nod(OTFUNC, rcvr, N);
|
|
|
|
t->list = $6;
|
|
|
|
t->rlist = $8;
|
|
|
|
$$->nname->ntype = t;
|
2010-04-26 23:35:27 -06:00
|
|
|
$$->shortname = name;
|
2009-07-17 02:00:44 -06:00
|
|
|
funchdr($$);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2008-09-05 20:50:34 -06:00
|
|
|
fntype:
|
2009-12-11 16:59:41 -07:00
|
|
|
LFUNC '(' oarg_type_list_ocomma ')' fnres
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-12-15 15:26:50 -07:00
|
|
|
$3 = checkarglist($3, 1);
|
2009-07-17 14:38:16 -06:00
|
|
|
$$ = nod(OTFUNC, N, N);
|
|
|
|
$$->list = $3;
|
|
|
|
$$->rlist = $5;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
fnbody:
|
2009-07-17 02:00:44 -06:00
|
|
|
{
|
|
|
|
$$ = nil;
|
|
|
|
}
|
|
|
|
| '{' stmt_list '}'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-07-05 13:49:25 -06:00
|
|
|
$$ = $2;
|
2009-07-17 02:00:44 -06:00
|
|
|
if($$ == nil)
|
2009-07-27 15:36:32 -06:00
|
|
|
$$ = list1(nod(OEMPTY, N, N));
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-07-05 13:49:25 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
fnres:
|
2009-03-05 16:57:03 -07:00
|
|
|
%prec NotParen
|
2008-06-21 16:11:29 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2008-06-21 16:11:29 -06:00
|
|
|
}
|
2010-01-26 11:40:28 -07:00
|
|
|
| fnret_type
|
2008-06-21 16:11:29 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = list1(nod(ODCLFIELD, N, $1));
|
2008-06-21 16:11:29 -06:00
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| '(' oarg_type_list_ocomma ')'
|
2008-10-07 13:36:30 -06:00
|
|
|
{
|
2009-12-15 15:26:50 -07:00
|
|
|
$2 = checkarglist($2, 0);
|
2008-10-07 13:36:30 -06:00
|
|
|
$$ = $2;
|
|
|
|
}
|
2008-06-21 16:11:29 -06:00
|
|
|
|
2009-08-07 13:50:26 -06:00
|
|
|
fnlitdcl:
|
|
|
|
fntype
|
|
|
|
{
|
|
|
|
closurehdr($1);
|
|
|
|
}
|
|
|
|
|
|
|
|
fnliteral:
|
|
|
|
fnlitdcl '{' stmt_list '}'
|
|
|
|
{
|
|
|
|
$$ = closurebody($3);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
/*
|
|
|
|
* lists of things
|
|
|
|
* note that they are left recursive
|
|
|
|
* to conserve yacc stack. they need to
|
|
|
|
* be reversed to interpret correctly
|
|
|
|
*/
|
2009-07-17 02:00:44 -06:00
|
|
|
xdcl_list:
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| xdcl_list xdcl ';'
|
2009-07-17 02:00:44 -06:00
|
|
|
{
|
|
|
|
$$ = concat($1, $2);
|
2009-10-12 12:03:48 -06:00
|
|
|
if(nsyntaxerrors == 0)
|
|
|
|
testdclstack();
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
vardcl_list:
|
2008-06-04 15:37:38 -06:00
|
|
|
vardcl
|
2009-07-17 02:00:44 -06:00
|
|
|
| vardcl_list ';' vardcl
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = concat($1, $3);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
constdcl_list:
|
2008-09-04 13:21:10 -06:00
|
|
|
constdcl1
|
2009-07-17 02:00:44 -06:00
|
|
|
| constdcl_list ';' constdcl1
|
2009-07-17 14:38:16 -06:00
|
|
|
{
|
|
|
|
$$ = concat($1, $3);
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
typedcl_list:
|
2008-06-04 15:37:38 -06:00
|
|
|
typedcl
|
2009-07-17 14:38:16 -06:00
|
|
|
{
|
|
|
|
$$ = list1($1);
|
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| typedcl_list ';' typedcl
|
2009-07-17 14:38:16 -06:00
|
|
|
{
|
|
|
|
$$ = list($1, $3);
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
structdcl_list:
|
2008-06-04 15:37:38 -06:00
|
|
|
structdcl
|
2009-07-17 02:00:44 -06:00
|
|
|
| structdcl_list ';' structdcl
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = concat($1, $3);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
interfacedcl_list:
|
2008-06-04 15:37:38 -06:00
|
|
|
interfacedcl
|
2009-09-28 15:05:34 -06:00
|
|
|
{
|
|
|
|
$$ = list1($1);
|
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| interfacedcl_list ';' interfacedcl
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-09-28 15:05:34 -06:00
|
|
|
$$ = list($1, $3);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
structdcl:
|
2009-07-17 14:38:16 -06:00
|
|
|
new_name_list ntype oliteral
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
NodeList *l;
|
|
|
|
|
|
|
|
for(l=$1; l; l=l->next) {
|
|
|
|
l->n = nod(ODCLFIELD, l->n, $2);
|
|
|
|
l->n->val = $3;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-30 16:29:55 -06:00
|
|
|
| embed oliteral
|
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$1->val = $2;
|
|
|
|
$$ = list1($1);
|
2008-10-30 16:29:55 -06:00
|
|
|
}
|
|
|
|
| '*' embed oliteral
|
2008-09-26 22:27:26 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$2->right = nod(OIND, $2->right, N);
|
|
|
|
$2->val = $3;
|
|
|
|
$$ = list1($2);
|
2008-10-21 16:04:10 -06:00
|
|
|
}
|
|
|
|
|
2009-06-06 13:46:38 -06:00
|
|
|
packname:
|
|
|
|
LNAME
|
2009-09-17 17:42:10 -06:00
|
|
|
{
|
|
|
|
Node *n;
|
|
|
|
|
|
|
|
$$ = $1;
|
|
|
|
n = oldname($1);
|
|
|
|
if(n->pack != N)
|
|
|
|
n->pack->used = 1;
|
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| LNAME '.' sym
|
2008-10-21 16:04:10 -06:00
|
|
|
{
|
2010-01-22 18:06:20 -07:00
|
|
|
Pkg *pkg;
|
2009-06-06 13:46:38 -06:00
|
|
|
|
|
|
|
if($1->def == N || $1->def->op != OPACK) {
|
|
|
|
yyerror("%S is not a package", $1);
|
2010-01-22 18:06:20 -07:00
|
|
|
pkg = localpkg;
|
2009-09-17 17:42:10 -06:00
|
|
|
} else {
|
|
|
|
$1->def->used = 1;
|
2010-01-22 18:06:20 -07:00
|
|
|
pkg = $1->def->pkg;
|
2009-09-17 17:42:10 -06:00
|
|
|
}
|
2009-07-14 00:38:39 -06:00
|
|
|
$$ = restrictlookup($3->name, pkg);
|
2008-10-19 21:13:37 -06:00
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
|
|
|
|
embed:
|
|
|
|
packname
|
2008-10-19 21:13:37 -06:00
|
|
|
{
|
2009-06-06 13:46:38 -06:00
|
|
|
$$ = embedded($1);
|
2008-09-26 22:27:26 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
interfacedcl:
|
2009-09-28 15:05:34 -06:00
|
|
|
new_name indcl
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-09-28 15:05:34 -06:00
|
|
|
$$ = nod(ODCLFIELD, $1, $2);
|
2009-07-17 02:00:44 -06:00
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| packname
|
2009-02-16 17:36:18 -07:00
|
|
|
{
|
2009-09-28 15:05:34 -06:00
|
|
|
$$ = nod(ODCLFIELD, N, oldname($1));
|
2009-02-16 17:36:18 -07:00
|
|
|
}
|
|
|
|
|
2008-09-05 20:50:34 -06:00
|
|
|
indcl:
|
2009-12-11 16:59:41 -07:00
|
|
|
'(' oarg_type_list_ocomma ')' fnres
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
|
|
|
// without func keyword
|
2009-12-15 17:20:37 -07:00
|
|
|
$2 = checkarglist($2, 1);
|
2009-07-17 15:42:14 -06:00
|
|
|
$$ = nod(OTFUNC, fakethis(), N);
|
|
|
|
$$->list = $2;
|
|
|
|
$$->rlist = $4;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
fix up arg list parsing to handle any names:
type t1 int;
type t2 int;
type t3 int;
func f1(t1, t2, t3);
func f2(t1, t2, t3 bool);
func f3(t1, t2, x t3);
func f4(*t2, x t3); // error: cannot mix
func f5(t1, *t3);
func (x *t1) f6(y *[]t2) (t1, *t3);
func f7() (int, *string);
func f8(t1, *t2, x t3); // error: cannot mix
func f9() (x int, *string);
func f10(*t2, t3);
R=ken
OCL=16202
CL=16210
2008-09-30 13:53:11 -06:00
|
|
|
/*
|
|
|
|
* function arguments.
|
|
|
|
*/
|
2009-06-06 13:46:38 -06:00
|
|
|
arg_type:
|
|
|
|
name_or_type
|
|
|
|
| sym name_or_type
|
|
|
|
{
|
2009-09-09 01:18:16 -06:00
|
|
|
$$ = nod(ONONAME, N, N);
|
|
|
|
$$->sym = $1;
|
2009-06-06 13:46:38 -06:00
|
|
|
$$ = nod(OKEY, $$, $2);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| sym dotdotdot
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-09-09 01:18:16 -06:00
|
|
|
$$ = nod(ONONAME, N, N);
|
|
|
|
$$->sym = $1;
|
2009-07-14 00:38:39 -06:00
|
|
|
$$ = nod(OKEY, $$, $2);
|
fix up arg list parsing to handle any names:
type t1 int;
type t2 int;
type t3 int;
func f1(t1, t2, t3);
func f2(t1, t2, t3 bool);
func f3(t1, t2, x t3);
func f4(*t2, x t3); // error: cannot mix
func f5(t1, *t3);
func (x *t1) f6(y *[]t2) (t1, *t3);
func f7() (int, *string);
func f8(t1, *t2, x t3); // error: cannot mix
func f9() (x int, *string);
func f10(*t2, t3);
R=ken
OCL=16202
CL=16210
2008-09-30 13:53:11 -06:00
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| dotdotdot
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
arg_type_list:
|
2009-06-06 13:46:38 -06:00
|
|
|
arg_type
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = list1($1);
|
|
|
|
}
|
|
|
|
| arg_type_list ',' arg_type
|
|
|
|
{
|
|
|
|
$$ = list($1, $3);
|
fix up arg list parsing to handle any names:
type t1 int;
type t2 int;
type t3 int;
func f1(t1, t2, t3);
func f2(t1, t2, t3 bool);
func f3(t1, t2, x t3);
func f4(*t2, x t3); // error: cannot mix
func f5(t1, *t3);
func (x *t1) f6(y *[]t2) (t1, *t3);
func f7() (int, *string);
func f8(t1, *t2, x t3); // error: cannot mix
func f9() (x int, *string);
func f10(*t2, t3);
R=ken
OCL=16202
CL=16210
2008-09-30 13:53:11 -06:00
|
|
|
}
|
|
|
|
|
2009-12-11 16:59:41 -07:00
|
|
|
oarg_type_list_ocomma:
|
2009-07-17 02:00:44 -06:00
|
|
|
{
|
|
|
|
$$ = nil;
|
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| arg_type_list ocomma
|
fix up arg list parsing to handle any names:
type t1 int;
type t2 int;
type t3 int;
func f1(t1, t2, t3);
func f2(t1, t2, t3 bool);
func f3(t1, t2, x t3);
func f4(*t2, x t3); // error: cannot mix
func f5(t1, *t3);
func (x *t1) f6(y *[]t2) (t1, *t3);
func f7() (int, *string);
func f8(t1, *t2, x t3); // error: cannot mix
func f9() (x int, *string);
func f10(*t2, t3);
R=ken
OCL=16202
CL=16210
2008-09-30 13:53:11 -06:00
|
|
|
{
|
2009-12-15 15:26:50 -07:00
|
|
|
$$ = $1;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2008-06-08 17:11:14 -06:00
|
|
|
/*
|
2009-06-06 20:27:48 -06:00
|
|
|
* statement
|
2008-06-08 17:11:14 -06:00
|
|
|
*/
|
2009-06-06 20:27:48 -06:00
|
|
|
stmt:
|
2008-06-08 18:21:46 -06:00
|
|
|
{
|
|
|
|
$$ = N;
|
|
|
|
}
|
2009-06-06 20:27:48 -06:00
|
|
|
| compound_stmt
|
|
|
|
| common_dcl
|
2009-07-17 02:00:44 -06:00
|
|
|
{
|
|
|
|
$$ = liststmt($1);
|
|
|
|
}
|
2010-04-26 23:35:27 -06:00
|
|
|
| non_dcl_stmt
|
|
|
|
| error
|
|
|
|
{
|
|
|
|
$$ = N;
|
|
|
|
}
|
|
|
|
|
|
|
|
non_dcl_stmt:
|
|
|
|
simple_stmt
|
2009-06-06 20:27:48 -06:00
|
|
|
| for_stmt
|
|
|
|
| switch_stmt
|
|
|
|
| select_stmt
|
|
|
|
| if_stmt
|
|
|
|
{
|
|
|
|
popdcl();
|
|
|
|
$$ = $1;
|
|
|
|
}
|
|
|
|
| if_stmt LELSE stmt
|
|
|
|
{
|
|
|
|
popdcl();
|
|
|
|
$$ = $1;
|
2009-07-17 02:00:44 -06:00
|
|
|
$$->nelse = list1($3);
|
2009-06-06 20:27:48 -06:00
|
|
|
}
|
|
|
|
| labelname ':' stmt
|
2008-10-07 13:36:30 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
NodeList *l;
|
|
|
|
|
2009-10-19 21:39:18 -06:00
|
|
|
l = list1(nod(OLABEL, $1, $3));
|
2009-07-17 02:00:44 -06:00
|
|
|
if($3)
|
|
|
|
l = list(l, $3);
|
|
|
|
$$ = liststmt(l);
|
2008-10-07 13:36:30 -06:00
|
|
|
}
|
2009-06-06 20:27:48 -06:00
|
|
|
| LFALL
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-06-06 20:27:48 -06:00
|
|
|
// will be converted to OFALL
|
|
|
|
$$ = nod(OXFALL, N, N);
|
2008-06-08 13:48:37 -06:00
|
|
|
}
|
2009-06-06 20:27:48 -06:00
|
|
|
| LBREAK onew_name
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-06-06 20:27:48 -06:00
|
|
|
$$ = nod(OBREAK, $2, N);
|
|
|
|
}
|
|
|
|
| LCONTINUE onew_name
|
|
|
|
{
|
|
|
|
$$ = nod(OCONTINUE, $2, N);
|
|
|
|
}
|
|
|
|
| LGO pseudocall
|
|
|
|
{
|
|
|
|
$$ = nod(OPROC, $2, N);
|
|
|
|
}
|
|
|
|
| LDEFER pseudocall
|
|
|
|
{
|
|
|
|
$$ = nod(ODEFER, $2, N);
|
|
|
|
}
|
|
|
|
| LGOTO new_name
|
|
|
|
{
|
|
|
|
$$ = nod(OGOTO, $2, N);
|
|
|
|
}
|
|
|
|
| LRETURN oexpr_list
|
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nod(ORETURN, N, N);
|
|
|
|
$$->list = $2;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-06-08 13:48:37 -06:00
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
stmt_list:
|
2009-06-06 20:27:48 -06:00
|
|
|
stmt
|
2009-04-28 13:28:31 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
|
|
|
if($1 != N)
|
|
|
|
$$ = list1($1);
|
2009-04-28 13:28:31 -06:00
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| stmt_list ';' stmt
|
2008-10-26 15:04:09 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = $1;
|
|
|
|
if($3 != N)
|
|
|
|
$$ = list($$, $3);
|
2008-10-26 15:04:09 -06:00
|
|
|
}
|
|
|
|
|
2009-07-17 14:38:16 -06:00
|
|
|
new_name_list:
|
|
|
|
new_name
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2009-07-17 14:38:16 -06:00
|
|
|
$$ = list1($1);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
2009-07-17 14:38:16 -06:00
|
|
|
| new_name_list ',' new_name
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2009-07-17 14:38:16 -06:00
|
|
|
$$ = list($1, $3);
|
|
|
|
}
|
|
|
|
|
|
|
|
dcl_name_list:
|
|
|
|
dcl_name
|
|
|
|
{
|
|
|
|
$$ = list1($1);
|
|
|
|
}
|
|
|
|
| dcl_name_list ',' dcl_name
|
|
|
|
{
|
|
|
|
$$ = list($1, $3);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
expr_list:
|
|
|
|
expr
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = list1($1);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| expr_list ',' expr
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = list($1, $3);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
expr_or_type_list:
|
|
|
|
expr_or_type
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = list1($1);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| expr_or_type_list ',' expr_or_type
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = list($1, $3);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2009-05-21 14:46:07 -06:00
|
|
|
/*
|
|
|
|
* list of combo of keyval and val
|
|
|
|
*/
|
2009-07-17 02:00:44 -06:00
|
|
|
keyval_list:
|
2008-06-04 15:37:38 -06:00
|
|
|
keyval
|
2009-05-21 14:46:07 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = list1($1);
|
2009-05-21 14:46:07 -06:00
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| expr
|
2008-10-14 18:10:39 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = list1($1);
|
2008-10-14 18:10:39 -06:00
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| keyval_list ',' keyval
|
2008-10-14 18:10:39 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = list($1, $3);
|
2008-10-14 18:10:39 -06:00
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| keyval_list ',' expr
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = list($1, $3);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
braced_keyval_list:
|
2009-06-06 13:46:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2009-06-06 13:46:38 -06:00
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
| keyval_list ocomma
|
2009-06-06 13:46:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = $1;
|
2009-06-06 13:46:38 -06:00
|
|
|
}
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
/*
|
|
|
|
* optional things
|
|
|
|
*/
|
|
|
|
osemi:
|
|
|
|
| ';'
|
|
|
|
|
|
|
|
ocomma:
|
|
|
|
| ','
|
|
|
|
|
|
|
|
oexpr:
|
|
|
|
{
|
|
|
|
$$ = N;
|
|
|
|
}
|
|
|
|
| expr
|
|
|
|
|
|
|
|
oexpr_list:
|
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
| expr_list
|
|
|
|
|
2009-12-11 16:59:41 -07:00
|
|
|
oexpr_or_type_list_ocomma:
|
2009-06-06 13:46:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2009-06-06 13:46:38 -06:00
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| expr_or_type_list ocomma
|
2009-06-06 13:46:38 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
osimple_stmt:
|
|
|
|
{
|
|
|
|
$$ = N;
|
|
|
|
}
|
|
|
|
| simple_stmt
|
|
|
|
|
2008-10-03 17:15:55 -06:00
|
|
|
ohidden_funarg_list:
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-03 17:15:55 -06:00
|
|
|
| hidden_funarg_list
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-10-03 17:15:55 -06:00
|
|
|
ohidden_structdcl_list:
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-03 17:15:55 -06:00
|
|
|
| hidden_structdcl_list
|
|
|
|
|
|
|
|
ohidden_interfacedcl_list:
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-03 17:15:55 -06:00
|
|
|
| hidden_interfacedcl_list
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2008-10-30 16:13:09 -06:00
|
|
|
oliteral:
|
|
|
|
{
|
|
|
|
$$.ctype = CTxxx;
|
|
|
|
}
|
|
|
|
| LLITERAL
|
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
/*
|
|
|
|
* import syntax from header of
|
|
|
|
* an output package
|
|
|
|
*/
|
|
|
|
hidden_import:
|
2010-01-22 18:06:20 -07:00
|
|
|
LIMPORT sym LLITERAL ';'
|
2010-01-19 22:34:44 -07:00
|
|
|
{
|
|
|
|
// Informational: record package name
|
|
|
|
// associated with import path, for use in
|
|
|
|
// human-readable messages.
|
2010-01-22 18:06:20 -07:00
|
|
|
Pkg *p;
|
2010-01-19 22:34:44 -07:00
|
|
|
|
2010-01-22 18:06:20 -07:00
|
|
|
p = mkpkg($3.u.sval);
|
|
|
|
p->name = $2->name;
|
2010-01-19 22:34:44 -07:00
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| LVAR hidden_pkg_importsym hidden_type ';'
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2009-01-30 15:39:42 -07:00
|
|
|
importvar($2, $3, PEXTERN);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| LCONST hidden_pkg_importsym '=' hidden_constant ';'
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
importconst($2, types[TIDEAL], $4);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| LCONST hidden_pkg_importsym hidden_type '=' hidden_constant ';'
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
importconst($2, $3, $5);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| LTYPE hidden_pkgtype hidden_type ';'
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2009-01-20 15:40:00 -07:00
|
|
|
importtype($2, $3);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| LFUNC hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres ';'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-01-30 15:39:42 -07:00
|
|
|
importvar($2, functype(N, $4, $6), PFUNC);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-12-11 16:59:41 -07:00
|
|
|
| LFUNC '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres ';'
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
if($3->next != nil || $3->n->op != ODCLFIELD) {
|
2008-10-03 17:15:55 -06:00
|
|
|
yyerror("bad receiver in method");
|
|
|
|
YYERROR;
|
|
|
|
}
|
2009-07-17 02:00:44 -06:00
|
|
|
importmethod($5, functype($3->n, $7, $9));
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
|
|
|
|
2009-08-07 13:50:26 -06:00
|
|
|
hidden_pkgtype:
|
|
|
|
hidden_pkg_importsym
|
|
|
|
{
|
|
|
|
$$ = pkgtype($1);
|
|
|
|
importsym($1, OTYPE);
|
|
|
|
}
|
|
|
|
|
2008-10-03 17:15:55 -06:00
|
|
|
hidden_type:
|
2009-12-03 01:10:32 -07:00
|
|
|
hidden_type_misc
|
2010-01-26 11:40:28 -07:00
|
|
|
| hidden_type_recv_chan
|
2009-12-03 01:10:32 -07:00
|
|
|
| hidden_type_func
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2010-01-26 11:40:28 -07:00
|
|
|
hidden_type_non_recv_chan:
|
2009-12-03 01:10:32 -07:00
|
|
|
hidden_type_misc
|
|
|
|
| hidden_type_func
|
|
|
|
|
|
|
|
hidden_type_misc:
|
2008-10-03 17:15:55 -06:00
|
|
|
hidden_importsym
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-06-06 13:46:38 -06:00
|
|
|
$$ = pkgtype($1);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-06-06 13:46:38 -06:00
|
|
|
| LNAME
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-08-04 23:59:23 -06:00
|
|
|
// predefined name like uint8
|
2010-01-22 18:06:20 -07:00
|
|
|
$1 = pkglookup($1->name, builtinpkg);
|
2009-08-04 23:59:23 -06:00
|
|
|
if($1->def == N || $1->def->op != OTYPE) {
|
2009-09-09 02:01:39 -06:00
|
|
|
yyerror("%s is not a type", $1->name);
|
2009-08-04 23:59:23 -06:00
|
|
|
$$ = T;
|
|
|
|
} else
|
|
|
|
$$ = $1->def->type;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-03 17:15:55 -06:00
|
|
|
| '[' ']' hidden_type
|
|
|
|
{
|
|
|
|
$$ = aindex(N, $3);
|
|
|
|
}
|
|
|
|
| '[' LLITERAL ']' hidden_type
|
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
$$ = aindex(nodlit($2), $4);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
|
|
|
| LMAP '[' hidden_type ']' hidden_type
|
|
|
|
{
|
2009-03-04 18:38:37 -07:00
|
|
|
$$ = maptype($3, $5);
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
|
|
|
| LSTRUCT '{' ohidden_structdcl_list '}'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-10-03 17:15:55 -06:00
|
|
|
$$ = dostruct($3, TSTRUCT);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-03 17:15:55 -06:00
|
|
|
| LINTERFACE '{' ohidden_interfacedcl_list '}'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-10-03 17:15:55 -06:00
|
|
|
$$ = dostruct($3, TINTER);
|
|
|
|
$$ = sortinter($$);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-03 17:15:55 -06:00
|
|
|
| '*' hidden_type
|
2008-08-27 18:28:30 -06:00
|
|
|
{
|
2008-10-03 17:15:55 -06:00
|
|
|
$$ = ptrto($2);
|
2008-08-27 18:28:30 -06:00
|
|
|
}
|
2010-01-26 11:40:28 -07:00
|
|
|
| LCHAN hidden_type_non_recv_chan
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-10-03 17:15:55 -06:00
|
|
|
$$ = typ(TCHAN);
|
2010-01-26 11:40:28 -07:00
|
|
|
$$->type = $2;
|
|
|
|
$$->chan = Cboth;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2010-01-26 11:40:28 -07:00
|
|
|
| LCHAN '(' hidden_type_recv_chan ')'
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-10-03 17:15:55 -06:00
|
|
|
$$ = typ(TCHAN);
|
|
|
|
$$->type = $3;
|
2010-01-26 11:40:28 -07:00
|
|
|
$$->chan = Cboth;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2010-01-26 11:40:28 -07:00
|
|
|
| LCHAN LCOMM hidden_type
|
2009-12-03 01:10:32 -07:00
|
|
|
{
|
|
|
|
$$ = typ(TCHAN);
|
2010-01-26 11:40:28 -07:00
|
|
|
$$->type = $3;
|
2009-12-03 01:10:32 -07:00
|
|
|
$$->chan = Csend;
|
|
|
|
}
|
2008-10-03 17:15:55 -06:00
|
|
|
|
2010-01-26 11:40:28 -07:00
|
|
|
hidden_type_recv_chan:
|
|
|
|
LCOMM LCHAN hidden_type
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2008-10-03 17:15:55 -06:00
|
|
|
$$ = typ(TCHAN);
|
2010-01-26 11:40:28 -07:00
|
|
|
$$->type = $3;
|
|
|
|
$$->chan = Crecv;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2009-12-03 01:10:32 -07:00
|
|
|
|
|
|
|
hidden_type_func:
|
|
|
|
LFUNC '(' ohidden_funarg_list ')' ohidden_funres
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = functype(nil, $3, $5);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-10-03 17:15:55 -06:00
|
|
|
|
2010-02-01 01:25:59 -07:00
|
|
|
hidden_opt_sym:
|
|
|
|
sym
|
|
|
|
{
|
|
|
|
$$ = newname($1);
|
|
|
|
}
|
|
|
|
| '?'
|
|
|
|
{
|
|
|
|
$$ = N;
|
|
|
|
}
|
|
|
|
|
2008-10-03 17:15:55 -06:00
|
|
|
hidden_dcl:
|
2010-02-01 01:25:59 -07:00
|
|
|
hidden_opt_sym hidden_type
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2010-02-01 01:25:59 -07:00
|
|
|
$$ = nod(ODCLFIELD, $1, typenod($2));
|
|
|
|
}
|
|
|
|
| hidden_opt_sym LDDD
|
|
|
|
{
|
|
|
|
$$ = nod(ODCLFIELD, $1, typenod(typ(TINTER)));
|
|
|
|
$$->isddd = 1;
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2010-02-01 01:25:59 -07:00
|
|
|
| hidden_opt_sym LDDD hidden_type
|
2008-07-12 14:08:53 -06:00
|
|
|
{
|
2010-02-01 01:25:59 -07:00
|
|
|
Type *t;
|
|
|
|
|
|
|
|
t = typ(TARRAY);
|
|
|
|
t->bound = -1;
|
|
|
|
t->type = $3;
|
|
|
|
$$ = nod(ODCLFIELD, $1, typenod(t));
|
|
|
|
$$->isddd = 1;
|
2008-07-12 14:08:53 -06:00
|
|
|
}
|
2008-10-03 17:15:55 -06:00
|
|
|
|
2008-10-22 14:22:56 -06:00
|
|
|
hidden_structdcl:
|
2010-05-24 17:55:23 -06:00
|
|
|
sym hidden_type hidden_tag
|
2008-10-22 14:22:56 -06:00
|
|
|
{
|
2009-07-14 00:38:39 -06:00
|
|
|
$$ = nod(ODCLFIELD, newname($1), typenod($2));
|
2008-10-30 16:25:26 -06:00
|
|
|
$$->val = $3;
|
2008-10-22 14:22:56 -06:00
|
|
|
}
|
2010-05-24 17:55:23 -06:00
|
|
|
| '?' hidden_type hidden_tag
|
2008-10-22 14:22:56 -06:00
|
|
|
{
|
2009-09-09 02:01:39 -06:00
|
|
|
Sym *s;
|
|
|
|
|
|
|
|
s = $2->sym;
|
|
|
|
if(s == S && isptr[$2->etype])
|
|
|
|
s = $2->type->sym;
|
2010-01-22 18:06:20 -07:00
|
|
|
if(s && s->pkg == builtinpkg)
|
2009-09-09 02:01:39 -06:00
|
|
|
s = lookup(s->name);
|
|
|
|
$$ = embedded(s);
|
|
|
|
$$->right = typenod($2);
|
2008-10-30 16:29:55 -06:00
|
|
|
$$->val = $3;
|
2008-10-22 14:22:56 -06:00
|
|
|
}
|
|
|
|
|
2010-05-24 17:55:23 -06:00
|
|
|
hidden_tag:
|
|
|
|
{
|
|
|
|
$$.ctype = CTxxx;
|
|
|
|
}
|
|
|
|
| ':' LLITERAL // extra colon avoids conflict with "" looking like beginning of "".typename
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
|
|
|
|
2008-10-03 17:15:55 -06:00
|
|
|
hidden_interfacedcl:
|
2009-06-06 13:46:38 -06:00
|
|
|
sym '(' ohidden_funarg_list ')' ohidden_funres
|
2008-09-14 17:57:55 -06:00
|
|
|
{
|
2009-07-14 00:38:39 -06:00
|
|
|
$$ = nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
ohidden_funres:
|
|
|
|
{
|
2009-07-17 02:00:44 -06:00
|
|
|
$$ = nil;
|
2008-10-03 17:15:55 -06:00
|
|
|
}
|
|
|
|
| hidden_funres
|
|
|
|
|
|
|
|
hidden_funres:
|
|
|
|
'(' ohidden_funarg_list ')'
|
|
|
|
{
|
|
|
|
$$ = $2;
|
|
|
|
}
|
2010-01-26 11:40:28 -07:00
|
|
|
| hidden_type
|
2008-10-03 17:15:55 -06:00
|
|
|
{
|
2009-08-07 13:50:26 -06:00
|
|
|
$$ = list1(nod(ODCLFIELD, N, typenod($1)));
|
2008-09-14 17:57:55 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
2010-02-18 15:46:28 -07:00
|
|
|
hidden_literal:
|
2008-09-26 12:44:20 -06:00
|
|
|
LLITERAL
|
2009-03-12 20:04:38 -06:00
|
|
|
{
|
|
|
|
$$ = nodlit($1);
|
|
|
|
}
|
2008-09-26 12:44:20 -06:00
|
|
|
| '-' LLITERAL
|
|
|
|
{
|
2009-03-12 20:04:38 -06:00
|
|
|
$$ = nodlit($2);
|
|
|
|
switch($$->val.ctype){
|
2008-09-26 12:44:20 -06:00
|
|
|
case CTINT:
|
2009-03-12 20:04:38 -06:00
|
|
|
mpnegfix($$->val.u.xval);
|
2008-09-26 12:44:20 -06:00
|
|
|
break;
|
|
|
|
case CTFLT:
|
2009-03-12 20:04:38 -06:00
|
|
|
mpnegflt($$->val.u.fval);
|
2008-09-26 12:44:20 -06:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
yyerror("bad negated constant");
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 02:01:39 -06:00
|
|
|
| sym
|
2009-01-16 11:45:28 -07:00
|
|
|
{
|
2010-01-22 18:06:20 -07:00
|
|
|
$$ = oldname(pkglookup($1->name, builtinpkg));
|
2009-06-06 13:46:38 -06:00
|
|
|
if($$->op != OLITERAL)
|
|
|
|
yyerror("bad constant %S", $$->sym);
|
2009-01-16 11:45:28 -07:00
|
|
|
}
|
2008-09-26 12:44:20 -06:00
|
|
|
|
2010-02-18 15:46:28 -07:00
|
|
|
hidden_constant:
|
|
|
|
hidden_literal
|
|
|
|
| '(' hidden_literal '+' hidden_literal ')'
|
|
|
|
{
|
|
|
|
$$ = nodcplxlit($2->val, $4->val);
|
|
|
|
}
|
|
|
|
|
2008-10-03 17:15:55 -06:00
|
|
|
hidden_importsym:
|
2010-01-19 22:34:44 -07:00
|
|
|
LLITERAL '.' sym
|
2008-06-04 15:37:38 -06:00
|
|
|
{
|
2010-01-22 18:06:20 -07:00
|
|
|
Pkg *p;
|
|
|
|
|
|
|
|
if($1.u.sval->len == 0)
|
|
|
|
p = importpkg;
|
|
|
|
else
|
|
|
|
p = mkpkg($1.u.sval);
|
|
|
|
$$ = pkglookup($3->name, p);
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
2008-09-18 14:32:14 -06:00
|
|
|
|
2009-01-26 17:57:24 -07:00
|
|
|
hidden_pkg_importsym:
|
|
|
|
hidden_importsym
|
|
|
|
{
|
|
|
|
$$ = $1;
|
2010-01-22 18:06:20 -07:00
|
|
|
structpkg = $$->pkg;
|
2008-12-16 18:45:28 -07:00
|
|
|
}
|
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
hidden_import_list:
|
|
|
|
| hidden_import_list hidden_import
|
|
|
|
|
|
|
|
hidden_funarg_list:
|
|
|
|
hidden_dcl
|
|
|
|
{
|
|
|
|
$$ = list1($1);
|
|
|
|
}
|
|
|
|
| hidden_funarg_list ',' hidden_dcl
|
|
|
|
{
|
|
|
|
$$ = list($1, $3);
|
|
|
|
}
|
|
|
|
|
|
|
|
hidden_structdcl_list:
|
|
|
|
hidden_structdcl
|
|
|
|
{
|
|
|
|
$$ = list1($1);
|
|
|
|
}
|
|
|
|
| hidden_structdcl_list ';' hidden_structdcl
|
|
|
|
{
|
|
|
|
$$ = list($1, $3);
|
|
|
|
}
|
2008-09-18 14:32:14 -06:00
|
|
|
|
2009-07-17 02:00:44 -06:00
|
|
|
hidden_interfacedcl_list:
|
|
|
|
hidden_interfacedcl
|
|
|
|
{
|
|
|
|
$$ = list1($1);
|
|
|
|
}
|
|
|
|
| hidden_interfacedcl_list ';' hidden_interfacedcl
|
|
|
|
{
|
|
|
|
$$ = list($1, $3);
|
|
|
|
}
|