blob: 13c08baf023fe86f0786b198999bfd4854a94d4d [file] [log] [blame]
// 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.
%{
#include "go.h"
%}
%union {
Node* node;
Type* type;
Sym* sym;
struct Val val;
int lint;
}
%token <sym> LNAME LBASETYPE LATYPE LPACK LACONST
%token <val> LLITERAL LASOP
%token LPACKAGE LIMPORT LEXPORT
%token LMAP LCHAN LINTERFACE LFUNC LSTRUCT
%token LCOLAS LFALL LRETURN
%token LNEW LLEN
%token LVAR LTYPE LCONST LCONVERT LSELECT
%token LFOR LIF LELSE LSWITCH LCASE LDEFAULT
%token LBREAK LCONTINUE LGO LGOTO LRANGE
%token LOROR LANDAND LEQ LNE LLE LLT LGE LGT
%token LLSH LRSH LINC LDEC LSEND LRECV
%token LNIL LTRUE LFALSE LIOTA
%token LPANIC LPRINT LIGNORE
%type <sym> sym laconst lname latype
%type <lint> chandir
%type <node> xdcl xdcl_list_r oxdcl_list
%type <node> common_dcl Acommon_dcl Bcommon_dcl
%type <node> oarg_type_list arg_type_list_r arg_type
%type <node> else_stmt1 else_stmt2 inc_stmt noninc_stmt
%type <node> complex_stmt compound_stmt ostmt_list
%type <node> stmt_list_r Astmt_list_r Bstmt_list_r
%type <node> Astmt Bstmt Cstmt Dstmt
%type <node> for_stmt for_body for_header
%type <node> if_stmt if_body if_header
%type <node> range_header range_body range_stmt select_stmt
%type <node> simple_stmt osimple_stmt semi_stmt
%type <node> expr uexpr pexpr expr_list oexpr oexpr_list expr_list_r
%type <node> name name_name new_name new_name_list_r conexpr
%type <node> vardcl_list_r vardcl Avardcl Bvardcl
%type <node> interfacedcl_list_r interfacedcl
%type <node> structdcl_list_r structdcl
%type <node> export_list_r export
%type <node> hidden_importsym_list_r ohidden_importsym_list hidden_importsym isym
%type <node> hidden_importfield_list_r ohidden_importfield_list hidden_importfield
%type <node> fnres Afnres Bfnres fnliteral xfndcl fndcl fnbody
%type <node> keyval_list_r keyval
%type <node> typedcl Atypedcl Btypedcl
%type <type> fntype fnlitdcl intype new_type typeconv
%type <type> type Atype Btype fntypeh Afntypeh Bfntypeh
%left LOROR
%left LANDAND
%left LSEND LRECV
%left LEQ LNE LLE LGE LLT LGT
%left '+' '-' '|' '^'
%left '*' '/' '%' '&' LLSH LRSH
%%
file:
package import_there imports oxdcl_list
{
if(debug['f'])
frame(1);
fninit($4);
testdclstack();
}
package:
{
yyerror("package statement must be first");
mkpackage("main");
cannedimports();
}
| LPACKAGE sym
{
mkpackage($2->name);
cannedimports();
}
imports:
| imports import
import:
LIMPORT import_stmt
| LIMPORT '(' import_stmt_list_r osemi ')'
import_stmt:
import_here import_package import_there
import_here:
LLITERAL
{
// import with original name
pkgmyname = S;
importfile(&$1);
}
| sym LLITERAL
{
// import with given name
pkgmyname = $1;
pkgmyname->lexical = LPACK;
importfile(&$2);
}
| '.' LLITERAL
{
// import with my name
pkgmyname = lookup(package);
importfile(&$2);
}
import_package:
LPACKAGE sym
{
pkgimportname = $2;
// if we are not remapping the package name
// then the imported package name is LPACK
if(pkgmyname == S)
pkgimportname->lexical = LPACK;
}
import_there:
hidden_import_list_r ')' ')'
{
unimportfile();
}
| LIMPORT '(' '(' hidden_import_list_r ')' ')'
/*
* declarations
*/
xdcl:
common_dcl
| LEXPORT export_list_r
{
markexport(rev($2));
$$ = N;
}
| LEXPORT '(' export_list_r ')'
{
markexport(rev($3));
$$ = N;
}
| xfndcl
{
$$ = N;
}
| ';'
{
$$ = N;
}
| error xdcl
{
$$ = $2;
}
common_dcl:
Acommon_dcl
| Bcommon_dcl
Acommon_dcl:
LVAR Avardcl
{
$$ = $2;
}
| LVAR '(' vardcl_list_r osemi ')'
{
$$ = rev($3);
}
| LCONST '(' constdcl_list_r osemi ')'
{
iota = 0;
lastconst = N;
$$ = N;
}
| LTYPE Atypedcl
{
$$ = N;
}
| LTYPE '(' typedcl_list_r osemi ')'
{
$$ = N;
}
Bcommon_dcl:
LVAR Bvardcl
{
$$ = $2;
}
| LCONST constdcl
{
$$ = N;
iota = 0;
lastconst = N;
}
| LTYPE Btypedcl
{
$$ = N;
}
vardcl:
Avardcl
| Bvardcl
Avardcl:
new_name_list_r Atype
{
$$ = rev($1);
dodclvar($$, $2);
$$ = nod(OAS, $$, N);
}
Bvardcl:
new_name_list_r Btype
{
$$ = rev($1);
dodclvar($$, $2);
$$ = nod(OAS, $$, N);
}
| new_name_list_r type '=' oexpr_list
{
$$ = rev($1);
dodclvar($$, $2);
$$ = nod(OAS, $$, $4);
}
| new_name '=' expr
{
walktype($3, Erv); // this is a little harry
defaultlit($3);
dodclvar($1, $3->type);
$$ = nod(OAS, $1, $3);
}
constdcl:
new_name conexpr
{
walktype($2, Erv);
dodclconst($1, $2);
}
| new_name type conexpr
{
walktype($3, Erv);
convlit($3, $2);
dodclconst($1, $3);
}
conexpr:
{
if(lastconst == N)
yyerror("first constant must evaluate an expression");
$$ = treecopy(lastconst);
iota += 1;
}
| '=' expr
{
$$ = $2;
lastconst = treecopy($$);
iota += 1;
}
typedcl:
Atypedcl
| Btypedcl
Atypedcl:
new_type Atype
{
dodcltype($1, $2);
}
Btypedcl:
new_type Btype
{
dodcltype($1, $2);
}
else_stmt1:
complex_stmt
| compound_stmt
else_stmt2:
simple_stmt
| semi_stmt
| ';'
{
$$ = N;
}
simple_stmt:
inc_stmt
| noninc_stmt
noninc_stmt:
expr
{
$$ = $1;
}
| expr LASOP expr
{
$$ = nod(OASOP, $1, $3);
$$->etype = $2.vval; // rathole to pass opcode
}
| expr_list '=' expr_list
{
$$ = nod(OAS, $1, $3);
}
| expr_list LCOLAS expr_list
{
$$ = nod(OAS, colas($1, $3), $3);
}
inc_stmt:
expr LINC
{
$$ = nod(OASOP, $1, literal(1));
$$->etype = OADD;
}
| expr LDEC
{
$$ = nod(OASOP, $1, literal(1));
$$->etype = OSUB;
}
complex_stmt:
LFOR for_stmt
{
popdcl();
$$ = $2;
}
| LSWITCH if_stmt
{
popdcl();
if(!casebody($2->nbody))
yyerror("switch statement must have case labels");
$$ = $2;
$$->op = OSWITCH;
//if($$->ninit != N && $$->ntest == N)
// yyerror("switch expression should not be missing");
}
| LIF if_stmt
{
popdcl();
$$ = $2;
//if($$->ninit != N && $$->ntest == N)
// yyerror("if conditional should not be missing");
}
| LIF if_stmt LELSE else_stmt1
{
popdcl();
$$ = $2;
$$->nelse = $4;
//if($$->ninit != N && $$->ntest == N)
// yyerror("if conditional should not be missing");
}
| LSELECT select_stmt
{
popdcl();
$$ = $2;
}
| LRANGE range_stmt
{
popdcl();
$$ = $2;
}
| LCASE expr_list ':'
{
// will be converted to OCASE
// right will point to next case
// done in casebody()
poptodcl();
$$ = nod(OXCASE, $2, N);
}
| LDEFAULT ':'
{
poptodcl();
$$ = nod(OXCASE, N, N);
}
semi_stmt:
LFALL
{
// will be converted to OFALL
$$ = nod(OXFALL, N, N);
}
| LBREAK oexpr
{
$$ = nod(OBREAK, $2, N);
}
| LCONTINUE oexpr
{
$$ = nod(OCONTINUE, $2, N);
}
| LGO pexpr '(' oexpr_list ')'
{
$$ = nod(OCALL, $2, $4);
$$ = nod(OPROC, $$, N);
}
| LPRINT expr_list
{
$$ = nod(OPRINT, $2, N);
}
| LPANIC oexpr_list
{
$$ = nod(OPANIC, $2, N);
}
| LGOTO new_name
{
$$ = nod(OGOTO, $2, N);
}
| LRETURN oexpr_list
{
$$ = nod(ORETURN, $2, N);
}
| LIF if_stmt LELSE else_stmt2
{
popdcl();
$$ = $2;
$$->nelse = $4;
//if($$->ninit != N && $$->ntest == N)
// yyerror("if conditional should not be missing");
}
compound_stmt:
'{'
{
markdcl();
} ostmt_list '}'
{
$$ = $3;
if($$ == N)
$$ = nod(OEMPTY, N, N);
popdcl();
}
for_header:
osimple_stmt ';' osimple_stmt ';' osimple_stmt
{
// init ; test ; incr
$$ = nod(OFOR, N, N);
$$->ninit = $1;
$$->ntest = $3;
$$->nincr = $5;
}
| osimple_stmt
{
// test
$$ = nod(OFOR, N, N);
$$->ninit = N;
$$->ntest = $1;
$$->nincr = N;
}
for_body:
for_header compound_stmt
{
$$ = $1;
$$->nbody = $2;
}
for_stmt:
{
markdcl();
} for_body
{
$$ = $2;
}
if_header:
osimple_stmt
{
// test
$$ = nod(OIF, N, N);
$$->ninit = N;
$$->ntest = $1;
}
| osimple_stmt ';' osimple_stmt
{
// init ; test
$$ = nod(OIF, N, N);
$$->ninit = $1;
$$->ntest = $3;
}
if_body:
if_header compound_stmt
{
$$ = $1;
$$->nbody = $2;
}
if_stmt:
{
markdcl();
} if_body
{
$$ = $2;
}
range_header:
new_name LCOLAS expr
{
$$ = N;
}
| new_name ',' new_name LCOLAS expr
{
$$ = N;
}
| new_name ',' new_name '=' expr
{
yyerror("range statement only allows := assignment");
$$ = N;
}
range_body:
range_header compound_stmt
{
$$ = $1;
$$->nbody = $2;
}
range_stmt:
{
markdcl();
} range_body
{
$$ = $2;
}
select_stmt:
{
markdcl();
}
compound_stmt
{
$$ = nod(OSELECT, $2, N);
}
/*
* 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);
}
| expr LLSH expr
{
$$ = nod(OLSH, $1, $3);
}
| expr LRSH expr
{
$$ = nod(ORSH, $1, $3);
}
| expr LSEND expr
{
$$ = nod(OSEND, $1, $3);
}
| expr LRECV expr
{
$$ = nod(ORECV, $1, $3);
}
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
{
yyerror("the OCOM operator is ^");
$$ = nod(OCOM, $2, N);
}
| '^' uexpr
{
$$ = nod(OCOM, $2, N);
}
| LRECV uexpr
{
$$ = nod(ORECV, $2, N);
}
pexpr:
LLITERAL
{
$$ = nod(OLITERAL, N, N);
$$->val = $1;
}
| laconst
{
$$ = nod(OLITERAL, N, N);
$$->val = $1->oconst->val;
$$->type = $1->oconst->type;
}
| LNIL
{
$$ = nod(OLITERAL, N, N);
$$->val.ctype = CTNIL;
$$->val.vval = 0;
}
| LTRUE
{
$$ = booltrue;
}
| LFALSE
{
$$ = boolfalse;
}
| LIOTA
{
$$ = literal(iota);
$$->iota = 1; // flag to reevaluate on copy
}
| name
| '(' expr ')'
{
$$ = $2;
}
| pexpr '.' sym
{
$$ = nod(ODOT, $1, newname($3));
}
| pexpr '.' '(' type ')'
{
$$ = nod(OCONV, $1, N);
$$->type = $4;
}
| pexpr '[' expr ']'
{
$$ = nod(OINDEX, $1, $3);
}
| pexpr '[' keyval ']'
{
$$ = nod(OSLICE, $1, $3);
}
| pexpr '(' oexpr_list ')'
{
$$ = nod(OCALL, $1, $3);
}
| LLEN '(' name ')'
{
$$ = nod(OLEN, $3, N);
}
| LNEW '(' type ')'
{
$$ = nod(ONEW, N, N);
$$->type = ptrto($3);
}
| LNEW '(' type ',' expr_list ')'
{
$$ = nod(ONEW, $5, N);
$$->type = ptrto($3);
}
| fnliteral
| '[' expr_list ']'
{
// array literal
$$ = N;
}
| '[' keyval_list_r ']'
{
// map literal
$$ = N;
}
| typeconv '(' oexpr_list ')'
{
// struct literal and conversions
$$ = nod(OCONV, $3, N);
$$->type = $1;
}
| LCONVERT '(' type ',' expr ')'
{
$$ = nod(OCONV, $5, N);
$$->type = $3;
}
/*
* lexical symbols that can be
* from other packages
*/
lpack:
LPACK
{
context = $1->name;
}
laconst:
LACONST
| lpack '.' LACONST
{
$$ = $3;
context = nil;
}
lname:
LNAME
| lpack '.' LNAME
{
$$ = $3;
context = nil;
}
latype:
LATYPE
| lpack '.' LATYPE
{
$$ = $3;
context = nil;
}
/*
* names and types
* newname is used before declared
* oldname is used after declared
*/
name_name:
LNAME
{
$$ = newname($1);
}
new_name:
sym
{
$$ = newname($1);
}
new_type:
sym
{
$$ = newtype($1);
}
sym:
LATYPE
| LNAME
| LACONST
| LPACK
name:
lname
{
$$ = oldname($1);
}
typeconv:
latype
{
$$ = oldtype($1);
}
| '[' ']' typeconv
{
$$ = aindex(N, $3);
}
| LCHAN chandir typeconv
{
$$ = typ(TCHAN);
$$->type = $3;
$$->chan = $2;
}
| LMAP '[' typeconv ']' typeconv
{
$$ = typ(TMAP);
$$->down = $3;
$$->type = $5;
}
type:
Atype
| Btype
Atype:
latype
{
$$ = oldtype($1);
}
| '[' oexpr ']' Atype
{
$$ = aindex($2, $4);
}
| LCHAN chandir Atype
{
$$ = typ(TCHAN);
$$->type = $3;
$$->chan = $2;
}
| LMAP '[' type ']' Atype
{
$$ = typ(TMAP);
$$->down = $3;
$$->type = $5;
}
| LSTRUCT '{' structdcl_list_r osemi '}'
{
$$ = dostruct(rev($3), TSTRUCT);
}
| LSTRUCT '{' '}'
{
$$ = dostruct(N, TSTRUCT);
}
| LINTERFACE '{' interfacedcl_list_r osemi '}'
{
$$ = dostruct(rev($3), TINTER);
$$ = sortinter($$);
}
| LINTERFACE '{' '}'
{
$$ = dostruct(N, TINTER);
}
| Afntypeh
| '*' Atype
{
$$ = ptrto($2);
}
Btype:
'[' oexpr ']' Btype
{
$$ = aindex($2, $4);
}
| LCHAN chandir Btype
{
$$ = typ(TCHAN);
$$->type = $3;
$$->chan = $2;
}
| LMAP '[' type ']' Btype
{
$$ = typ(TMAP);
$$->down = $3;
$$->type = $5;
}
| Bfntypeh
| '*' Btype
{
$$ = ptrto($2);
}
| '*' lname
{
// dont know if this is an error or not
if(dclcontext != PEXTERN)
yyerror("forward type in function body %s", $2->name);
$$ = forwdcl($2);
}
chandir:
{
$$ = Cboth;
}
| LRECV
{
$$ = Crecv;
}
| LSEND
{
$$ = Csend;
}
keyval:
expr ':' expr
{
$$ = nod(OLIST, $1, $3);
}
/*
* function stuff
* all in one place to show how crappy it all is
*/
xfndcl:
LFUNC
{
maxarg = 0;
stksize = 0;
} fndcl fnbody
{
$$ = $3;
$$->nbody = $4;
funcbody($$);
}
fndcl:
new_name '(' oarg_type_list ')' fnres
{
b0stack = dclstack; // mark base for fn literals
$$ = nod(ODCLFUNC, N, N);
$$->nname = $1;
if($3 == N && $5 == N)
$$->nname = renameinit($1);
$$->type = functype(N, $3, $5);
funchdr($$);
}
| '(' oarg_type_list ')' new_name '(' oarg_type_list ')' fnres
{
b0stack = dclstack; // mark base for fn literals
if($2 == N || $2->op == OLIST)
yyerror("syntax error in method receiver");
$$ = nod(ODCLFUNC, N, N);
$$->nname = methodname($4, $2->type);
$$->type = functype($2, $6, $8);
funchdr($$);
}
fntypeh:
Afntypeh
| Bfntypeh
Afntypeh:
LFUNC '(' oarg_type_list ')' Afnres
{
$$ = functype(N, $3, $5);
funcnam($$, nil);
}
| LFUNC '(' oarg_type_list ')' '.' '(' oarg_type_list ')' Afnres
/* i dont believe that this form is useful for anything */
{
if($3 == N || $3->op == OLIST)
yyerror("syntax error in method receiver");
$$ = functype($3, $7, $9);
funcnam($$, nil);
}
Bfntypeh:
LFUNC '(' oarg_type_list ')' Bfnres
{
$$ = functype(N, $3, $5);
funcnam($$, nil);
}
| LFUNC '(' oarg_type_list ')' '.' '(' oarg_type_list ')' Bfnres
/* i dont believe that this form is useful for anything */
{
if($3 == N || $3->op == OLIST)
yyerror("syntax error in method receiver");
$$ = functype($3, $7, $9);
funcnam($$, nil);
}
fntype:
fntypeh
| latype
{
$$ = oldtype($1);
if($$ == T || $$->etype != TFUNC)
yyerror("illegal type for function literal");
}
fnlitdcl:
fntype
{
markdclstack(); // save dcl stack and revert to block0
$$ = $1;
funcargs($$);
}
fnliteral:
fnlitdcl '{' ostmt_list '}'
{
popdcl();
vargen++;
snprint(namebuf, sizeof(namebuf), "_f%.3ld", vargen);
$$ = newname(lookup(namebuf));
addvar($$, $1, PEXTERN);
{
Node *n;
n = nod(ODCLFUNC, N, N);
n->nname = $$;
n->type = $1;
n->nbody = $3;
if(n->nbody == N)
n->nbody = nod(ORETURN, N, N);
compile(n);
}
$$ = nod(OADDR, $$, N);
}
fnbody:
'{' ostmt_list '}'
{
$$ = $2;
if($$ == N)
$$ = nod(ORETURN, N, N);
}
| ';'
{
$$ = N;
}
fnres:
Afnres
| Bfnres
Afnres:
Atype
{
$$ = nod(ODCLFIELD, N, N);
$$->type = $1;
$$ = cleanidlist($$);
}
| '(' oarg_type_list ')'
{
$$ = $2;
}
Bfnres:
{
$$ = N;
}
| Btype
{
$$ = nod(ODCLFIELD, N, N);
$$->type = $1;
$$ = cleanidlist($$);
}
/*
* lists of things
* note that they are left recursive
* to conserve yacc stack. they need to
* be reversed to interpret correctly
*/
xdcl_list_r:
xdcl
| xdcl_list_r xdcl
{
$$ = list($1, $2);
}
vardcl_list_r:
vardcl
| vardcl_list_r ';' vardcl
{
$$ = nod(OLIST, $1, $3);
}
constdcl_list_r:
constdcl
| constdcl_list_r ';' constdcl
typedcl_list_r:
typedcl
| typedcl_list_r ';' typedcl
structdcl_list_r:
structdcl
{
$$ = cleanidlist($1);
}
| structdcl_list_r ';' structdcl
{
$$ = cleanidlist($3);
$$ = nod(OLIST, $1, $$);
}
interfacedcl_list_r:
interfacedcl
{
$$ = cleanidlist($1);
}
| interfacedcl_list_r ';' interfacedcl
{
$$ = cleanidlist($3);
$$ = nod(OLIST, $1, $$);
}
structdcl:
new_name ',' structdcl
{
$$ = nod(ODCLFIELD, $1, N);
$$ = nod(OLIST, $$, $3);
}
| new_name type
{
$$ = nod(ODCLFIELD, $1, N);
$$->type = $2;
}
interfacedcl:
new_name ',' interfacedcl
{
$$ = nod(ODCLFIELD, $1, N);
$$ = nod(OLIST, $$, $3);
}
| new_name intype
{
$$ = nod(ODCLFIELD, $1, N);
$$->type = $2;
}
intype:
'(' oarg_type_list ')' fnres
{
// without func keyword
$$ = functype(fakethis(), $2, $4);
funcnam($$, nil);
}
| LFUNC '(' oarg_type_list ')' fnres
{
// with func keyword
$$ = functype(fakethis(), $3, $5);
funcnam($$, nil);
}
| latype
{
$$ = oldtype($1);
if($$ == T || $$->etype != TFUNC)
yyerror("illegal type for function literal");
}
arg_type:
name_name
{
$$ = nod(ODCLFIELD, $1, N);
}
| type
{
$$ = nod(ODCLFIELD, N, N);
$$->type = $1;
}
| new_name type
{
$$ = nod(ODCLFIELD, $1, N);
$$->type = $2;
}
arg_type_list_r:
arg_type
| arg_type_list_r ',' arg_type
{
$$ = nod(OLIST, $1, $3);
}
/*
* need semi in front NO
* need semi in back NO
*/
Astmt:
complex_stmt
| compound_stmt
| Acommon_dcl
| ';'
{
$$ = N;
}
| error Astmt
{
$$ = N;
}
/*
* need semi in front NO
* need semi in back YES
*/
Bstmt:
semi_stmt
| Bcommon_dcl
| error Bstmt
{
$$ = N;
}
/*
* need semi in front YES
* need semi in back YES
*/
Cstmt:
noninc_stmt
/*
* need semi in front YES
* need semi in back NO
*/
Dstmt:
inc_stmt
| new_name ':'
{
$$ = nod(OLABEL, $1, N);
}
/*
* statement list that ends AorD
*/
Astmt_list_r:
Astmt
| Dstmt
| Astmt_list_r Astmt
{
$$ = list($1, $2);
}
| Astmt_list_r Dstmt
{
$$ = list($1, $2);
}
| Bstmt_list_r Astmt
{
$$ = list($1, $2);
}
/*
* statement list that ends BorC
*/
Bstmt_list_r:
Bstmt
| Cstmt
| Astmt_list_r Bstmt
{
$$ = list($1, $2);
}
| Astmt_list_r Cstmt
{
$$ = list($1, $2);
}
| Bstmt_list_r Bstmt
{
$$ = list($1, $2);
}
stmt_list_r:
Astmt_list_r
| Bstmt_list_r
expr_list_r:
expr
| expr_list_r ',' expr
{
$$ = nod(OLIST, $1, $3);
}
new_name_list_r:
new_name
| new_name_list_r ',' new_name
{
$$ = nod(OLIST, $1, $3);
}
export_list_r:
export
| export_list_r ocomma export
{
$$ = nod(OLIST, $1, $3);
}
export:
sym
{
$$ = nod(OEXPORT, N, N);
$$->sym = $1;
}
| sym '.' sym
{
$$ = nod(OEXPORT, N, N);
$$->psym = $1;
$$->sym = $3;
}
import_stmt_list_r:
import_stmt
| import_stmt_list_r osemi import_stmt
hidden_import_list_r:
hidden_import
| hidden_import_list_r hidden_import
hidden_importsym_list_r:
hidden_importsym
| hidden_importsym_list_r hidden_importsym
{
$$ = nod(OLIST, $1, $2);
}
hidden_importfield_list_r:
hidden_importfield
| hidden_importfield_list_r hidden_importfield
{
$$ = nod(OLIST, $1, $2);
}
keyval_list_r:
keyval
| keyval_list_r ',' keyval
{
$$ = nod(OLIST, $1, $3);
}
/*
* the one compromise of a
* non-reversed list
*/
expr_list:
expr_list_r
{
$$ = rev($1);
}
/*
* optional things
*/
osemi:
| ';'
ocomma:
| ','
oexpr:
{
$$ = N;
}
| expr
oexpr_list:
{
$$ = N;
}
| expr_list
osimple_stmt:
{
$$ = N;
}
| simple_stmt
ostmt_list:
{
$$ = N;
}
| stmt_list_r
{
$$ = rev($1);
}
oxdcl_list:
{
$$ = N;
}
| xdcl_list_r
{
$$ = rev($1);
}
ohidden_importsym_list:
{
$$ = N;
}
| hidden_importsym_list_r
{
$$ = rev($1);
}
ohidden_importfield_list:
{
$$ = N;
}
| hidden_importfield_list_r
{
$$ = rev($1);
}
oarg_type_list:
{
$$ = N;
}
| arg_type_list_r
{
$$ = cleanidlist(rev($1));
}
/*
* import syntax from header of
* an output package
*/
hidden_import:
/* leftover import ignored */
LPACKAGE sym
/* variables */
| LVAR hidden_importsym hidden_importsym
{
// var
doimportv1($2, $3);
}
/* constants */
| LCONST hidden_importsym LLITERAL
{
doimportc1($2, &$3);
}
| LCONST hidden_importsym hidden_importsym LLITERAL
{
doimportc2($2, $3, &$4);
}
/* types */
| LTYPE hidden_importsym '[' hidden_importsym ']' hidden_importsym
{
// type map
doimport1($2, $4, $6);
}
| LTYPE hidden_importsym '[' LLITERAL ']' hidden_importsym
{
// type array
doimport2($2, &$4, $6);
}
| LTYPE hidden_importsym '(' ohidden_importsym_list ')'
{
// type function
doimport3($2, $4);
}
| LTYPE hidden_importsym '{' ohidden_importfield_list '}'
{
// type structure
doimport4($2, $4);
}
| LTYPE hidden_importsym LLITERAL
{
// type basic
doimport5($2, &$3);
}
| LTYPE hidden_importsym '*' hidden_importsym
{
// type pointer
doimport6($2, $4);
}
| LTYPE hidden_importsym LLT ohidden_importfield_list LGT
{
// type interface
doimport7($2, $4);
}
| LTYPE hidden_importsym LLITERAL hidden_importsym
{
// type interface
doimport8($2, &$3, $4);
}
isym:
sym '.' sym
{
$$ = nod(OIMPORT, N, N);
$$->osym = $1;
$$->psym = $1;
$$->sym = $3;
renamepkg($$);
}
| '(' sym ')' sym '.' sym
{
$$ = nod(OIMPORT, N, N);
$$->osym = $2;
$$->psym = $4;
$$->sym = $6;
renamepkg($$);
}
hidden_importsym:
isym
| '!' isym
{
$$ = $2;
$$->etype = 1;
}
hidden_importfield:
sym isym
{
$$ = $2;
$$->fsym = $1;
}