github.com/mattn/anko@v0.1.10/parser/parser.go.y (about)

     1  %{
     2  package parser
     3  
     4  import (
     5  	"github.com/mattn/anko/ast"
     6  )
     7  
     8  %}
     9  
    10  %type<compstmt> compstmt
    11  %type<stmts> stmts
    12  %type<stmt> stmt
    13  %type<stmt_var_or_lets> stmt_var_or_lets
    14  %type<stmt_var> stmt_var
    15  %type<stmt_lets> stmt_lets
    16  %type<stmt_if> stmt_if
    17  %type<stmt_for> stmt_for
    18  %type<stmt_switch> stmt_switch
    19  %type<stmt_switch_cases> stmt_switch_cases
    20  %type<stmt_switch_case> stmt_switch_case
    21  %type<stmt_switch_default> stmt_switch_default
    22  
    23  %type<exprs> exprs
    24  %type<expr> expr
    25  %type<expr_idents> expr_idents
    26  %type<type_data> type_data
    27  %type<type_data_struct> type_data_struct
    28  %type<slice_count> slice_count
    29  %type<expr_member_or_ident> expr_member_or_ident
    30  %type<expr_member> expr_member
    31  %type<expr_ident> expr_ident
    32  %type<expr_literals> expr_literals
    33  %type<expr_map> expr_map
    34  %type<expr_slice> expr_slice
    35  %type<expr_chan> expr_chan
    36  %type<expr> expr_unary
    37  %type<expr> expr_binary
    38  %type<expr> expr_lets
    39  
    40  %type<expr> op_binary
    41  %type<expr> op_comparison
    42  %type<expr> op_add
    43  %type<expr> op_multiply
    44  
    45  %union{
    46  	tok                    ast.Token
    47  
    48  	compstmt               ast.Stmt
    49  	stmts                  ast.Stmt
    50  	stmt                   ast.Stmt
    51  	stmt_var_or_lets       ast.Stmt
    52  	stmt_var               ast.Stmt
    53  	stmt_lets              ast.Stmt
    54  	stmt_if                ast.Stmt
    55  	stmt_for               ast.Stmt
    56  	stmt_switch            ast.Stmt
    57  	stmt_switch_cases      ast.Stmt
    58  	stmt_switch_case       ast.Stmt
    59  	stmt_switch_default    ast.Stmt
    60  
    61  	exprs                  []ast.Expr
    62  	expr                   ast.Expr
    63  	expr_idents            []string
    64  	type_data              *ast.TypeStruct
    65  	type_data_struct       *ast.TypeStruct
    66  	slice_count            int
    67  	expr_member_or_ident   ast.Expr
    68  	expr_member            *ast.MemberExpr
    69  	expr_ident             *ast.IdentExpr
    70  	expr_literals          ast.Expr
    71  	expr_map               *ast.MapExpr
    72  	expr_slice             ast.Expr
    73  	expr_chan              ast.Expr
    74  	expr_unary             ast.Expr
    75  	expr_binary            ast.Expr
    76  	expr_lets              ast.Expr
    77  
    78  	op_binary              ast.Operator
    79  	op_comparison          ast.Operator
    80  	op_add                 ast.Operator
    81  	op_multiply            ast.Operator
    82  }
    83  
    84  %token<tok> IDENT NUMBER STRING ARRAY VARARG FUNC RETURN VAR THROW IF ELSE FOR IN EQEQ NEQ GE LE OROR ANDAND NEW TRUE FALSE NIL NILCOALESCE MODULE TRY CATCH FINALLY PLUSEQ MINUSEQ MULEQ DIVEQ ANDEQ OREQ BREAK CONTINUE PLUSPLUS MINUSMINUS SHIFTLEFT SHIFTRIGHT SWITCH CASE DEFAULT GO CHAN STRUCT MAKE OPCHAN EQOPCHAN TYPE LEN DELETE CLOSE MAP IMPORT
    85  
    86  /* lowest precedence */
    87  %left ,
    88  %right '=' PLUSEQ MINUSEQ MULEQ DIVEQ ANDEQ OREQ EQOPCHAN
    89  %right ':'
    90  %right OPCHAN
    91  %right '?' NILCOALESCE
    92  %left OROR
    93  %left ANDAND
    94  %left EQEQ NEQ '<' LE '>' GE
    95  %left '+' '-' '|' '^'
    96  %left '*' '/' '%' SHIFTLEFT SHIFTRIGHT '&'
    97  %right IN
    98  %right PLUSPLUS MINUSMINUS
    99  %right UNARY
   100  /* highest precedence */
   101  /* https://golang.org/ref/spec#Expression */
   102  
   103  
   104  %%
   105  
   106  compstmt :
   107  	opt_term
   108  	{
   109  		$$ = nil
   110  	}
   111  	| stmts opt_term
   112  	{
   113  		$$ = $1
   114  	}
   115  
   116  stmts :
   117  	opt_term stmt
   118  	{
   119  		if $2 != nil {
   120  			$$ = &ast.StmtsStmt{Stmts: []ast.Stmt{$2}}
   121  		}
   122  		if l, ok := yylex.(*Lexer); ok {
   123  			l.stmt = $$
   124  		}
   125  	}
   126  	| stmts term stmt
   127  	{
   128  		if $3 != nil {
   129  			if $1 == nil {
   130  				$$ = &ast.StmtsStmt{Stmts: []ast.Stmt{$3}}
   131  			} else {
   132  				stmts := $1.(*ast.StmtsStmt)
   133  				stmts.Stmts = append(stmts.Stmts, $3)
   134  			}
   135  			if l, ok := yylex.(*Lexer); ok {
   136  				l.stmt = $$
   137  			}
   138  		}
   139  	}
   140  
   141  stmt :
   142  	/* nothing */
   143  	{
   144  		$$ = nil
   145  	}
   146  	| stmt_var_or_lets
   147  	{
   148  		$$ = $1
   149  	}
   150  	| BREAK
   151  	{
   152  		$$ = &ast.BreakStmt{}
   153  		$$.SetPosition($1.Position())
   154  	}
   155  	| CONTINUE
   156  	{
   157  		$$ = &ast.ContinueStmt{}
   158  		$$.SetPosition($1.Position())
   159  	}
   160  	| RETURN exprs
   161  	{
   162  		$$ = &ast.ReturnStmt{Exprs: $2}
   163  		$$.SetPosition($1.Position())
   164  	}
   165  	| THROW expr
   166  	{
   167  		$$ = &ast.ThrowStmt{Expr: $2}
   168  		$$.SetPosition($1.Position())
   169  	}
   170  	| MODULE IDENT '{' compstmt '}'
   171  	{
   172  		$$ = &ast.ModuleStmt{Name: $2.Lit, Stmt: $4}
   173  		$$.SetPosition($1.Position())
   174  	}
   175  	| TRY '{' compstmt '}' CATCH IDENT '{' compstmt '}' FINALLY '{' compstmt '}'
   176  	{
   177  		$$ = &ast.TryStmt{Try: $3, Var: $6.Lit, Catch: $8, Finally: $12}
   178  		$$.SetPosition($1.Position())
   179  	}
   180  	| TRY '{' compstmt '}' CATCH '{' compstmt '}' FINALLY '{' compstmt '}'
   181  	{
   182  		$$ = &ast.TryStmt{Try: $3, Catch: $7, Finally: $11}
   183  		$$.SetPosition($1.Position())
   184  	}
   185  	| TRY '{' compstmt '}' CATCH IDENT '{' compstmt '}'
   186  	{
   187  		$$ = &ast.TryStmt{Try: $3, Var: $6.Lit, Catch: $8}
   188  		$$.SetPosition($1.Position())
   189  	}
   190  	| TRY '{' compstmt '}' CATCH '{' compstmt '}'
   191  	{
   192  		$$ = &ast.TryStmt{Try: $3, Catch: $7}
   193  		$$.SetPosition($1.Position())
   194  	}
   195  	| GO IDENT '(' exprs VARARG ')'
   196  	{
   197  		$$ = &ast.GoroutineStmt{Expr: &ast.CallExpr{Name: $2.Lit, SubExprs: $4, VarArg: true, Go: true}}
   198  		$$.SetPosition($2.Position())
   199  	}
   200  	| GO IDENT '(' exprs ')'
   201  	{
   202  		$$ = &ast.GoroutineStmt{Expr: &ast.CallExpr{Name: $2.Lit, SubExprs: $4, Go: true}}
   203  		$$.SetPosition($2.Position())
   204  	}
   205  	| GO expr '(' exprs VARARG ')'
   206  	{
   207  		$$ = &ast.GoroutineStmt{Expr: &ast.AnonCallExpr{Expr: $2, SubExprs: $4, VarArg: true, Go: true}}
   208  		$$.SetPosition($2.Position())
   209  	}
   210  	| GO expr '(' exprs ')'
   211  	{
   212  		$$ = &ast.GoroutineStmt{Expr: &ast.AnonCallExpr{Expr: $2, SubExprs: $4, Go: true}}
   213  		$$.SetPosition($1.Position())
   214  	}
   215  	| DELETE '(' expr ')'
   216  	{
   217  		$$ = &ast.DeleteStmt{Item: $3}
   218  		$$.SetPosition($1.Position())
   219  	}
   220  	| DELETE '(' expr ',' expr ')'
   221  	{
   222  		$$ = &ast.DeleteStmt{Item: $3, Key: $5}
   223  		$$.SetPosition($1.Position())
   224  	}
   225  	| CLOSE '(' expr ')'
   226  	{
   227  		$$ = &ast.CloseStmt{Expr: $3}
   228  		$$.SetPosition($1.Position())
   229  	}
   230  	| stmt_if
   231  	{
   232  		$$ = $1
   233  	}
   234  	| stmt_for
   235  	{
   236  		$$ = $1
   237  	}
   238  	| stmt_switch
   239  	{
   240  		$$ = $1
   241  	}
   242  	| expr
   243  	{
   244  		$$ = &ast.ExprStmt{Expr: $1}
   245  		$$.SetPosition($1.Position())
   246  	}
   247  
   248  stmt_var_or_lets :
   249  	stmt_var
   250  	{
   251  		$$ = $1
   252  	}
   253  	| stmt_lets
   254  	{
   255  		$$ = $1
   256  	}
   257  
   258  stmt_var :
   259  	VAR expr_idents '=' exprs
   260  	{
   261  		$$ = &ast.VarStmt{Names: $2, Exprs: $4}
   262  		$$.SetPosition($1.Position())
   263  	}
   264  
   265  stmt_lets :
   266  	expr '=' expr
   267  	{
   268  		$$ = &ast.LetsStmt{LHSS: []ast.Expr{$1}, RHSS: []ast.Expr{$3}}
   269  		$$.SetPosition($1.Position())
   270  	}
   271  	| exprs '=' exprs
   272  	{
   273  		if len($1) == 2 && len($3) == 1 {
   274  			if _, ok := $3[0].(*ast.ItemExpr); ok {
   275  				$$ = &ast.LetMapItemStmt{LHSS: $1, RHS: $3[0]}
   276  			} else {
   277  				$$ = &ast.LetsStmt{LHSS: $1, RHSS: $3}
   278  			}
   279  		} else {
   280  			$$ = &ast.LetsStmt{LHSS: $1, RHSS: $3}
   281  		}
   282  		$$.SetPosition($1[0].Position())
   283  	}
   284  	| expr EQOPCHAN expr
   285  	{
   286  		$$ = &ast.ChanStmt{LHS: $1, RHS: $3}
   287  		$$.SetPosition($1.Position())
   288  	}
   289  	| exprs EQOPCHAN expr
   290  	{
   291  		if len($1) == 2 {
   292  			chanStmt := &ast.ChanStmt{LHS: $1[0].(ast.Expr), OkExpr: $1[1].(ast.Expr), RHS: $3}
   293  			$$ = chanStmt
   294  			$$.SetPosition(chanStmt.LHS.Position())
   295  		} else if len($1) < 2 {
   296  			yylex.Error("missing expressions on left side of channel operator")
   297  			$$ = &ast.ChanStmt{RHS: $3}
   298  			$$.SetPosition($2.Position())
   299  		}
   300  	}
   301  
   302  stmt_if :
   303  	IF expr '{' compstmt '}'
   304  	{
   305  		$$ = &ast.IfStmt{If: $2, Then: $4, Else: nil}
   306  		$$.SetPosition($1.Position())
   307  	}
   308  	| stmt_if ELSE IF expr '{' compstmt '}'
   309  	{
   310  		ifStmt := $1.(*ast.IfStmt)
   311  		ifStmt.ElseIf = append(ifStmt.ElseIf, &ast.IfStmt{If: $4, Then: $6})
   312  	}
   313  	| stmt_if ELSE '{' compstmt '}'
   314  	{
   315  		ifStmt := $1.(*ast.IfStmt)
   316  		if ifStmt.Else != nil {
   317  			yylex.Error("multiple else statement")
   318  		}
   319  		ifStmt.Else = $4
   320  	}
   321  
   322  stmt_for :
   323  	FOR '{' compstmt '}'
   324  	{
   325  		$$ = &ast.LoopStmt{Stmt: $3}
   326  		$$.SetPosition($1.Position())
   327  	}
   328  	| FOR expr_idents IN expr '{' compstmt '}'
   329  	{
   330  		if len($2) < 1 {
   331  			yylex.Error("missing identifier")
   332  		} else if len($2) > 2 {
   333  			yylex.Error("too many identifiers")
   334  		} else {
   335  			$$ = &ast.ForStmt{Vars: $2, Value: $4, Stmt: $6}
   336  			$$.SetPosition($1.Position())
   337  		}
   338  	}
   339  	| FOR expr '{' compstmt '}'
   340  	{
   341  		$$ = &ast.LoopStmt{Expr: $2, Stmt: $4}
   342  		$$.SetPosition($1.Position())
   343  	}
   344  	| FOR ';' ';' '{' compstmt '}'
   345  	{
   346  		$$ = &ast.CForStmt{Stmt: $5}
   347  		$$.SetPosition($1.Position())
   348  	}
   349  	| FOR ';' ';' expr '{' compstmt '}'
   350  	{
   351  		$$ = &ast.CForStmt{Expr3: $4, Stmt: $6}
   352  		$$.SetPosition($1.Position())
   353  	}
   354  	| FOR ';' expr ';' '{' compstmt '}'
   355  	{
   356  		$$ = &ast.CForStmt{Expr2: $3, Stmt: $6}
   357  		$$.SetPosition($1.Position())
   358  	}
   359  	| FOR ';' expr ';' expr '{' compstmt '}'
   360  	{
   361  		$$ = &ast.CForStmt{Expr2: $3, Expr3: $5, Stmt: $7}
   362  		$$.SetPosition($1.Position())
   363  	}
   364  	| FOR stmt_var_or_lets ';' ';' '{' compstmt '}'
   365  	{
   366  		$$ = &ast.CForStmt{Stmt1: $2, Stmt: $6}
   367  		$$.SetPosition($1.Position())
   368  	}
   369  	| FOR stmt_var_or_lets ';' ';' expr '{' compstmt '}'
   370  	{
   371  		$$ = &ast.CForStmt{Stmt1: $2, Expr3: $5, Stmt: $7}
   372  		$$.SetPosition($1.Position())
   373  	}
   374  	| FOR stmt_var_or_lets ';' expr ';' '{' compstmt '}'
   375  	{
   376  		$$ = &ast.CForStmt{Stmt1: $2, Expr2: $4, Stmt: $7}
   377  		$$.SetPosition($1.Position())
   378  	}
   379  	| FOR stmt_var_or_lets ';' expr ';' expr '{' compstmt '}'
   380  	{
   381  		$$ = &ast.CForStmt{Stmt1: $2, Expr2: $4, Expr3: $6, Stmt: $8}
   382  		$$.SetPosition($1.Position())
   383  	}
   384  
   385  stmt_switch :
   386  	SWITCH expr '{' opt_newlines stmt_switch_cases opt_newlines '}'
   387  	{
   388  		switchStmt := $5.(*ast.SwitchStmt)
   389  		switchStmt.Expr = $2
   390  		$$ = switchStmt
   391  		$$.SetPosition($1.Position())
   392  	}
   393  
   394  stmt_switch_cases :
   395  	/* nothing */
   396  	{
   397  		$$ = &ast.SwitchStmt{}
   398  	}
   399  	| stmt_switch_default
   400  	{
   401  		$$ = &ast.SwitchStmt{Default: $1}
   402  	}
   403  	| stmt_switch_case
   404  	{
   405  		$$ = &ast.SwitchStmt{Cases: []ast.Stmt{$1}}
   406  	}
   407  	| stmt_switch_cases stmt_switch_case
   408  	{
   409  		switchStmt := $1.(*ast.SwitchStmt)
   410  		switchStmt.Cases = append(switchStmt.Cases, $2)
   411  		$$ = switchStmt
   412  	}
   413  	| stmt_switch_cases stmt_switch_default
   414  	{
   415  		switchStmt := $1.(*ast.SwitchStmt)
   416  		if switchStmt.Default != nil {
   417  			yylex.Error("multiple default statement")
   418  		}
   419  		switchStmt.Default = $2
   420  	}
   421  
   422  stmt_switch_case :
   423  	CASE expr ':' compstmt
   424  	{
   425  		$$ = &ast.SwitchCaseStmt{Exprs: []ast.Expr{$2}, Stmt: $4}
   426  		$$.SetPosition($1.Position())
   427  	}
   428  	| CASE exprs ':' compstmt
   429  	{
   430  		$$ = &ast.SwitchCaseStmt{Exprs: $2, Stmt: $4}
   431  		$$.SetPosition($1.Position())
   432  	}
   433  
   434  stmt_switch_default :
   435  	DEFAULT ':' compstmt
   436  	{
   437  		$$ = $3
   438  	}
   439  
   440  
   441  exprs :
   442  	/* nothing */
   443  	{
   444  		$$ = nil
   445  	}
   446  	| expr 
   447  	{
   448  		$$ = []ast.Expr{$1}
   449  	}
   450  	| exprs ',' opt_newlines expr
   451  	{
   452  		if len($1) == 0 {
   453  			yylex.Error("syntax error: unexpected ','")
   454  		}
   455  		$$ = append($1, $4)
   456  	}
   457  	| exprs ',' opt_newlines expr_ident
   458  	{
   459  		if len($1) == 0 {
   460  			yylex.Error("syntax error: unexpected ','")
   461  		}
   462  		$$ = append($1, $4)
   463  	}
   464  
   465  expr :
   466  	expr_member_or_ident
   467  	{
   468  		$$ = $1
   469  	}
   470  	| expr_literals
   471  	{
   472  		$$ = $1
   473  	}
   474  	| expr '?' expr ':' expr
   475  	{
   476  		$$ = &ast.TernaryOpExpr{Expr: $1, LHS: $3, RHS: $5}
   477  		$$.SetPosition($1.Position())
   478  	}
   479  	| expr NILCOALESCE expr
   480  	{
   481  		$$ = &ast.NilCoalescingOpExpr{LHS: $1, RHS: $3}
   482  		$$.SetPosition($1.Position())
   483  	}
   484  	| FUNC '(' expr_idents ')' '{' compstmt '}'
   485  	{
   486  		$$ = &ast.FuncExpr{Params: $3, Stmt: $6}
   487  		$$.SetPosition($1.Position())
   488  	}
   489  	| FUNC '(' expr_idents VARARG ')' '{' compstmt '}'
   490  	{
   491  		$$ = &ast.FuncExpr{Params: $3, Stmt: $7, VarArg: true}
   492  		$$.SetPosition($1.Position())
   493  	}
   494  	| FUNC IDENT '(' expr_idents ')' '{' compstmt '}'
   495  	{
   496  		$$ = &ast.FuncExpr{Name: $2.Lit, Params: $4, Stmt: $7}
   497  		$$.SetPosition($1.Position())
   498  	}
   499  	| FUNC IDENT '(' expr_idents VARARG ')' '{' compstmt '}'
   500  	{
   501  		$$ = &ast.FuncExpr{Name: $2.Lit, Params: $4, Stmt: $8, VarArg: true}
   502  		$$.SetPosition($1.Position())
   503  	}
   504  	| '[' ']'
   505  	{
   506  		$$ = &ast.ArrayExpr{}
   507  		if l, ok := yylex.(*Lexer); ok { $$.SetPosition(l.pos) }
   508  	}
   509  	| '[' opt_newlines exprs opt_comma_newlines ']'
   510  	{
   511  		$$ = &ast.ArrayExpr{Exprs: $3}
   512  		if l, ok := yylex.(*Lexer); ok { $$.SetPosition(l.pos) }
   513  	}
   514  	| slice_count type_data '{' opt_newlines exprs opt_comma_newlines '}'
   515  	{
   516  		$$ = &ast.ArrayExpr{Exprs: $5, TypeData: &ast.TypeStruct{Kind: ast.TypeSlice, SubType: $2, Dimensions: $1}}
   517  		if l, ok := yylex.(*Lexer); ok { $$.SetPosition(l.pos) }
   518  	}
   519  	| '(' expr ')'
   520  	{
   521  		$$ = &ast.ParenExpr{SubExpr: $2}
   522  		if l, ok := yylex.(*Lexer); ok { $$.SetPosition(l.pos) }
   523  	}
   524  	| IDENT '(' exprs VARARG ')'
   525  	{
   526  		$$ = &ast.CallExpr{Name: $1.Lit, SubExprs: $3, VarArg: true}
   527  		$$.SetPosition($1.Position())
   528  	}
   529  	| IDENT '(' exprs ')'
   530  	{
   531  		$$ = &ast.CallExpr{Name: $1.Lit, SubExprs: $3}
   532  		$$.SetPosition($1.Position())
   533  	}
   534  	| expr '(' exprs VARARG ')'
   535  	{
   536  		$$ = &ast.AnonCallExpr{Expr: $1, SubExprs: $3, VarArg: true}
   537  		$$.SetPosition($1.Position())
   538  	}
   539  	| expr '(' exprs ')'
   540  	{
   541  		$$ = &ast.AnonCallExpr{Expr: $1, SubExprs: $3}
   542  		$$.SetPosition($1.Position())
   543  	}
   544  	| expr_ident '[' expr ']'
   545  	{
   546  		$$ = &ast.ItemExpr{Item: $1, Index: $3}
   547  		$$.SetPosition($1.Position())
   548  	}
   549  	| expr '[' expr ']'
   550  	{
   551  		$$ = &ast.ItemExpr{Item: $1, Index: $3}
   552  		$$.SetPosition($1.Position())
   553  	}
   554  	| LEN '(' expr ')'
   555  	{
   556  		$$ = &ast.LenExpr{Expr: $3}
   557  		$$.SetPosition($1.Position())
   558  	}
   559  	| IMPORT '(' expr ')'
   560  	{
   561  		$$ = &ast.ImportExpr{Name: $3}
   562  		$$.SetPosition($1.Position())
   563  	}
   564  	| NEW '(' type_data ')'
   565  	{
   566  		if $3.Kind == ast.TypeDefault {
   567  			$3.Kind = ast.TypePtr
   568  			$$ = &ast.MakeExpr{TypeData: $3}
   569  		} else {
   570  			$$ = &ast.MakeExpr{TypeData: &ast.TypeStruct{Kind: ast.TypePtr, SubType: $3}}
   571  		}
   572  		$$.SetPosition($1.Position())
   573  	}
   574  	| MAKE '(' type_data ')'
   575  	{
   576  		$$ = &ast.MakeExpr{TypeData: $3}
   577  		$$.SetPosition($1.Position())
   578  	}
   579  	| MAKE '(' type_data ',' expr ')'
   580  	{
   581  		$$ = &ast.MakeExpr{TypeData: $3, LenExpr: $5}
   582  		$$.SetPosition($1.Position())
   583  	}
   584  	| MAKE '(' type_data ',' expr ',' expr ')'
   585  	{
   586  		$$ = &ast.MakeExpr{TypeData: $3, LenExpr: $5, CapExpr: $7}
   587  		$$.SetPosition($1.Position())
   588  	}
   589  	| MAKE '(' TYPE IDENT ',' expr ')'
   590  	{
   591  		$$ = &ast.MakeTypeExpr{Name: $4.Lit, Type: $6}
   592  		$$.SetPosition($1.Position())
   593  	}
   594  	| expr IN expr
   595  	{
   596  		$$ = &ast.IncludeExpr{ItemExpr: $1, ListExpr: $3}
   597  		$$.SetPosition($1.Position())
   598  	}
   599  	| MAP '{' opt_newlines expr_map opt_comma_newlines '}'
   600  	{
   601  		$4.TypeData = &ast.TypeStruct{Kind: ast.TypeMap, Key: &ast.TypeStruct{Name: "interface"}, SubType: &ast.TypeStruct{Name: "interface"}}
   602  		$$ = $4
   603  		$$.SetPosition($1.Position())
   604  	}
   605  	| MAP '[' type_data ']' type_data '{' opt_newlines expr_map opt_comma_newlines '}'
   606  	{
   607  		$8.TypeData = &ast.TypeStruct{Kind: ast.TypeMap, Key: $3, SubType: $5}
   608  		$$ = $8
   609  		$$.SetPosition($1.Position())
   610  	}
   611  	| '{' opt_newlines expr_map opt_comma_newlines '}'
   612  	{
   613  		$$ = $3
   614  		$$.SetPosition($3.Position())
   615  	}
   616  	| expr_slice
   617  	{
   618  		$$ = $1
   619  		$$.SetPosition($1.Position())
   620  	}
   621  	| expr_chan
   622  	{
   623  		$$ = $1
   624  		$$.SetPosition($1.Position())
   625  	}
   626  	| expr_unary
   627  	| expr_binary
   628  	| expr_lets
   629  
   630  expr_idents :
   631  	{
   632  		$$ = []string{}
   633  	}
   634  	| IDENT
   635  	{
   636  		$$ = []string{$1.Lit}
   637  	}
   638  	| expr_idents ',' opt_newlines IDENT
   639  	{
   640  		if len($1) == 0 {
   641  			yylex.Error("syntax error: unexpected ','")
   642  		}
   643  		$$ = append($1, $4.Lit)
   644  	}
   645  
   646  type_data :
   647  	IDENT
   648  	{
   649  		$$ = &ast.TypeStruct{Name: $1.Lit}
   650  	}
   651  	| type_data '.' IDENT
   652  	{
   653  		if $1.Kind != ast.TypeDefault {
   654  			yylex.Error("not type default")
   655  		} else {
   656  			$1.Env = append($1.Env, $1.Name)
   657  			$1.Name = $3.Lit
   658  		}
   659  	}
   660  	| '*' type_data
   661  	{
   662  		if $2.Kind == ast.TypeDefault {
   663  			$2.Kind = ast.TypePtr
   664  			$$ = $2
   665  		} else {
   666  			$$ = &ast.TypeStruct{Kind: ast.TypePtr, SubType: $2}
   667  		}
   668  	}
   669  	| slice_count type_data
   670  	{
   671  		if $2.Kind == ast.TypeDefault {
   672  			$2.Kind = ast.TypeSlice
   673  			$2.Dimensions = $1
   674  			$$ = $2
   675  		} else {
   676  			$$ = &ast.TypeStruct{Kind: ast.TypeSlice, SubType: $2, Dimensions: $1}
   677  		}
   678  	}
   679  	| MAP '[' type_data ']' type_data
   680  	{
   681  		$$ = &ast.TypeStruct{Kind: ast.TypeMap, Key: $3, SubType: $5}
   682  	}
   683  	| CHAN type_data
   684  	{
   685  		if $2.Kind == ast.TypeDefault {
   686  			$2.Kind = ast.TypeChan
   687  			$$ = $2
   688  		} else {
   689  			$$ = &ast.TypeStruct{Kind: ast.TypeChan, SubType: $2}
   690  		}
   691  	}
   692  	| STRUCT '{' opt_newlines type_data_struct opt_newlines '}'
   693  	{
   694  		$$ = $4
   695  	}
   696  
   697  type_data_struct :
   698  	IDENT type_data
   699  	{
   700  		$$ = &ast.TypeStruct{Kind: ast.TypeStructType, StructNames: []string{$1.Lit}, StructTypes: []*ast.TypeStruct{$2}}
   701  	}
   702  	| type_data_struct ',' opt_newlines IDENT type_data
   703  	{
   704  		if $1 == nil {
   705  			yylex.Error("syntax error: unexpected ','")
   706  		}
   707  		$$.StructNames = append($$.StructNames, $4.Lit)
   708  		$$.StructTypes = append($$.StructTypes, $5)
   709  	}
   710  
   711  slice_count :
   712  	'[' ']'
   713  	{
   714  		$$ = 1
   715  	}
   716  	| '[' ']' slice_count
   717  	{
   718  		$$ = $3 + 1
   719  	}
   720  
   721  expr_member_or_ident :
   722  	expr_member
   723  	{
   724  		$$ = $1
   725  	}
   726  	| expr_ident
   727  	{
   728  		$$ = $1
   729  	}
   730  
   731  expr_member :
   732  	expr '.' IDENT
   733  	{
   734  		$$ = &ast.MemberExpr{Expr: $1, Name: $3.Lit}
   735  		$$.SetPosition($1.Position())
   736  	}
   737  
   738  expr_ident :
   739  	IDENT
   740  	{
   741  		$$ = &ast.IdentExpr{Lit: $1.Lit}
   742  		$$.SetPosition($1.Position())
   743  	}
   744  
   745  expr_literals :
   746  	'-' NUMBER
   747  	{
   748  		num, err := toNumber("-" + $2.Lit)
   749  		if err != nil {
   750  			yylex.Error("invalid number: -" + $2.Lit)
   751  		}
   752  		$$ = &ast.LiteralExpr{Literal: num}
   753  		$$.SetPosition($2.Position())
   754  	}
   755  	| NUMBER
   756  	{
   757  		num, err := toNumber($1.Lit)
   758  		if err != nil {
   759  			yylex.Error("invalid number: " + $1.Lit)
   760  		}
   761  		$$ = &ast.LiteralExpr{Literal: num}
   762  		$$.SetPosition($1.Position())
   763  	}
   764  	| STRING
   765  	{
   766  		$$ = &ast.LiteralExpr{Literal: stringToValue($1.Lit)}
   767  		$$.SetPosition($1.Position())
   768  	}
   769  	| TRUE
   770  	{
   771  		$$ = &ast.LiteralExpr{Literal: trueValue}
   772  		$$.SetPosition($1.Position())
   773  	}
   774  	| FALSE
   775  	{
   776  		$$ = &ast.LiteralExpr{Literal: falseValue}
   777  		$$.SetPosition($1.Position())
   778  	}
   779  	| NIL
   780  	{
   781  		$$ = &ast.LiteralExpr{Literal: nilValue}
   782  		$$.SetPosition($1.Position())
   783  	}
   784  
   785  expr_map :
   786  	/* nothing */
   787  	{
   788  		$$ = &ast.MapExpr{}
   789  	}
   790  	| expr ':' expr
   791  	{
   792  		$$ = &ast.MapExpr{Keys: []ast.Expr{$1}, Values: []ast.Expr{$3}}
   793  	}
   794  	| expr_map ',' opt_newlines expr ':' expr
   795  	{
   796  		if $1.Keys == nil {
   797  			yylex.Error("syntax error: unexpected ','")
   798  		}
   799  		$$.Keys = append($$.Keys, $4)
   800  		$$.Values = append($$.Values, $6)
   801  	}
   802  
   803  expr_slice :
   804  	expr_ident '[' expr ':' expr ']'
   805  	{
   806  		$$ = &ast.SliceExpr{Item: $1, Begin: $3, End: $5}
   807  	}
   808  	| expr_ident '[' expr ':' ']'
   809  	{
   810  		$$ = &ast.SliceExpr{Item: $1, Begin: $3, End: nil}
   811  	}
   812  	| expr_ident '[' ':' expr ']'
   813  	{
   814  		$$ = &ast.SliceExpr{Item: $1, Begin: nil, End: $4}
   815  	}
   816  	| expr_ident '[' ':' expr ':' expr ']'
   817  	{
   818  		$$ = &ast.SliceExpr{Item: $1, End: $4, Cap: $6}
   819  	}
   820  	| expr_ident '[' expr ':' expr ':' expr ']'
   821  	{
   822  		$$ = &ast.SliceExpr{Item: $1, Begin: $3, End: $5, Cap: $7}
   823  	}
   824  	| expr '[' expr ':' expr ']'
   825  	{
   826  		$$ = &ast.SliceExpr{Item: $1, Begin: $3, End: $5}
   827  	}
   828  	| expr '[' expr ':' ']'
   829  	{
   830  		$$ = &ast.SliceExpr{Item: $1, Begin: $3, End: nil}
   831  	}
   832  	| expr '[' ':' expr ']'
   833  	{
   834  		$$ = &ast.SliceExpr{Item: $1, Begin: nil, End: $4}
   835  	}
   836  	| expr '[' ':' expr ':' expr ']'
   837  	{
   838  		$$ = &ast.SliceExpr{Item: $1, End: $4, Cap: $6}
   839  	}
   840  	| expr '[' expr ':' expr ':' expr ']'
   841  	{
   842  		$$ = &ast.SliceExpr{Item: $1, Begin: $3, End: $5, Cap: $7}
   843  	}
   844  
   845  expr_chan :
   846  	expr OPCHAN expr
   847  	{
   848  		$$ = &ast.ChanExpr{LHS: $1, RHS: $3}
   849  	}
   850  	| OPCHAN expr
   851  	{
   852  		$$ = &ast.ChanExpr{RHS: $2}
   853  	}
   854  
   855  expr_unary :
   856  	'-' expr %prec UNARY
   857  	{
   858  		$$ = &ast.UnaryExpr{Operator: "-", Expr: $2}
   859  		$$.SetPosition($2.Position())
   860  	}
   861  	| '!' expr %prec UNARY
   862  	{
   863  		$$ = &ast.UnaryExpr{Operator: "!", Expr: $2}
   864  		$$.SetPosition($2.Position())
   865  	}
   866  	| '^' expr %prec UNARY
   867  	{
   868  		$$ = &ast.UnaryExpr{Operator: "^", Expr: $2}
   869  		$$.SetPosition($2.Position())
   870  	}
   871  	| '&' expr %prec UNARY
   872  	{
   873  		$$ = &ast.AddrExpr{Expr: $2}
   874  		$$.SetPosition($2.Position())
   875  	}
   876  	| '*' expr %prec UNARY
   877  	{
   878  		$$ = &ast.DerefExpr{Expr: $2}
   879  		$$.SetPosition($2.Position())
   880  	}
   881  
   882  expr_binary :
   883  	op_multiply
   884  	{
   885  		$$ = &ast.OpExpr{Op: $1}
   886  		$$.SetPosition($1.Position())
   887  	}
   888  	| op_add
   889  	{
   890  		$$ = &ast.OpExpr{Op: $1}
   891  		$$.SetPosition($1.Position())
   892  	}
   893  	| op_comparison
   894  	{
   895  		$$ = &ast.OpExpr{Op: $1}
   896  		$$.SetPosition($1.Position())
   897  	}
   898  	| op_binary
   899  	{
   900  		$$ = &ast.OpExpr{Op: $1}
   901  		$$.SetPosition($1.Position())
   902  	}
   903  
   904  expr_lets:
   905  	expr PLUSPLUS
   906  	{
   907  		rhs := &ast.OpExpr{Op: &ast.AddOperator{LHS: $1, Operator: "+", RHS: oneLiteral}}
   908  		rhs.Op.SetPosition($1.Position())
   909  		rhs.SetPosition($1.Position())
   910  		$$ = &ast.LetsExpr{LHSS: []ast.Expr{$1}, RHSS: []ast.Expr{rhs}}
   911  		$$.SetPosition($1.Position())
   912  	}
   913  	| expr MINUSMINUS
   914  	{
   915  		rhs := &ast.OpExpr{Op: &ast.AddOperator{LHS: $1, Operator: "-", RHS: oneLiteral}}
   916  		rhs.Op.SetPosition($1.Position())
   917  		rhs.SetPosition($1.Position())
   918  		$$ = &ast.LetsExpr{LHSS: []ast.Expr{$1}, RHSS: []ast.Expr{rhs}}
   919  		$$.SetPosition($1.Position())
   920  	}
   921  	| expr PLUSEQ expr
   922  	{
   923  		rhs := &ast.OpExpr{Op: &ast.AddOperator{LHS: $1, Operator: "+", RHS: $3}}
   924  		rhs.Op.SetPosition($1.Position())
   925  		rhs.SetPosition($1.Position())
   926  		$$ = &ast.LetsExpr{LHSS: []ast.Expr{$1}, RHSS: []ast.Expr{rhs}}
   927  		$$.SetPosition($1.Position())
   928  	}
   929  	| expr MINUSEQ expr
   930  	{
   931  		rhs := &ast.OpExpr{Op: &ast.AddOperator{LHS: $1, Operator: "-", RHS: $3}}
   932  		rhs.Op.SetPosition($1.Position())
   933  		rhs.SetPosition($1.Position())
   934  		$$ = &ast.LetsExpr{LHSS: []ast.Expr{$1}, RHSS: []ast.Expr{rhs}}
   935  		$$.SetPosition($1.Position())
   936  	}
   937  	| expr OREQ expr
   938  	{
   939  		rhs := &ast.OpExpr{Op: &ast.AddOperator{LHS: $1, Operator: "|", RHS: $3}}
   940  		rhs.Op.SetPosition($1.Position())
   941  		rhs.SetPosition($1.Position())
   942  		$$ = &ast.LetsExpr{LHSS: []ast.Expr{$1}, RHSS: []ast.Expr{rhs}}
   943  		$$.SetPosition($1.Position())
   944  	}
   945  	| expr MULEQ expr
   946  	{
   947  		rhs := &ast.OpExpr{Op: &ast.MultiplyOperator{LHS: $1, Operator: "*", RHS: $3}}
   948  		rhs.Op.SetPosition($1.Position())
   949  		rhs.SetPosition($1.Position())
   950  		$$ = &ast.LetsExpr{LHSS: []ast.Expr{$1}, RHSS: []ast.Expr{rhs}}
   951  		$$.SetPosition($1.Position())
   952  	}
   953  	| expr DIVEQ expr
   954  	{
   955  		rhs := &ast.OpExpr{Op: &ast.MultiplyOperator{LHS: $1, Operator: "/", RHS: $3}}
   956  		rhs.Op.SetPosition($1.Position())
   957  		rhs.SetPosition($1.Position())
   958  		$$ = &ast.LetsExpr{LHSS: []ast.Expr{$1}, RHSS: []ast.Expr{rhs}}
   959  		$$.SetPosition($1.Position())
   960  	}
   961  	| expr ANDEQ expr
   962  	{
   963  		rhs := &ast.OpExpr{Op: &ast.MultiplyOperator{LHS: $1, Operator: "&", RHS: $3}}
   964  		rhs.Op.SetPosition($1.Position())
   965  		rhs.SetPosition($1.Position())
   966  		$$ = &ast.LetsExpr{LHSS: []ast.Expr{$1}, RHSS: []ast.Expr{rhs}}
   967  		$$.SetPosition($1.Position())
   968  	}
   969  
   970  
   971  op_multiply :
   972  	expr '*' expr
   973  	{
   974  		$$ = &ast.MultiplyOperator{LHS: $1, Operator: "*", RHS: $3}
   975  		$$.SetPosition($1.Position())
   976  	}
   977  	| expr '/' expr
   978  	{
   979  		$$ = &ast.MultiplyOperator{LHS: $1, Operator: "/", RHS: $3}
   980  		$$.SetPosition($1.Position())
   981  	}
   982  	| expr '%' expr
   983  	{
   984  		$$ = &ast.MultiplyOperator{LHS: $1, Operator: "%", RHS: $3}
   985  		$$.SetPosition($1.Position())
   986  	}
   987  	| expr SHIFTLEFT expr
   988  	{
   989  		$$ = &ast.MultiplyOperator{LHS: $1, Operator: "<<", RHS: $3}
   990  		$$.SetPosition($1.Position())
   991  	}
   992  	| expr SHIFTRIGHT expr
   993  	{
   994  		$$ = &ast.MultiplyOperator{LHS: $1, Operator: ">>", RHS: $3}
   995  		$$.SetPosition($1.Position())
   996  	}
   997  	| expr '&' expr
   998  	{
   999  		$$ = &ast.MultiplyOperator{LHS: $1, Operator: "&", RHS: $3}
  1000  		$$.SetPosition($1.Position())
  1001  	}
  1002  
  1003  op_add :
  1004  	expr '+' expr
  1005  	{
  1006  		$$ = &ast.AddOperator{LHS: $1, Operator: "+", RHS: $3}
  1007  		$$.SetPosition($1.Position())
  1008  	}
  1009  	| expr '-' expr
  1010  	{
  1011  		$$ = &ast.AddOperator{LHS: $1, Operator: "-", RHS: $3}
  1012  		$$.SetPosition($1.Position())
  1013  	}
  1014  	| expr '|' expr
  1015  	{
  1016  		$$ = &ast.AddOperator{LHS: $1, Operator: "|", RHS: $3}
  1017  		$$.SetPosition($1.Position())
  1018  	}
  1019  
  1020  op_comparison :
  1021  	expr EQEQ expr
  1022  	{
  1023  		$$ = &ast.ComparisonOperator{LHS: $1, Operator: "==", RHS: $3}
  1024  		$$.SetPosition($1.Position())
  1025  	}
  1026  	| expr NEQ expr
  1027  	{
  1028  		$$ = &ast.ComparisonOperator{LHS: $1, Operator: "!=", RHS: $3}
  1029  		$$.SetPosition($1.Position())
  1030  	}
  1031  	| expr '<' expr
  1032  	{
  1033  		$$ = &ast.ComparisonOperator{LHS: $1, Operator: "<", RHS: $3}
  1034  		$$.SetPosition($1.Position())
  1035  	}
  1036  	| expr LE expr
  1037  	{
  1038  		$$ = &ast.ComparisonOperator{LHS: $1, Operator: "<=", RHS: $3}
  1039  		$$.SetPosition($1.Position())
  1040  	}
  1041  	| expr '>' expr
  1042  	{
  1043  		$$ = &ast.ComparisonOperator{LHS: $1, Operator: ">", RHS: $3}
  1044  		$$.SetPosition($1.Position())
  1045  	}
  1046  	| expr GE expr
  1047  	{
  1048  		$$ = &ast.ComparisonOperator{LHS: $1, Operator: ">=", RHS: $3}
  1049  		$$.SetPosition($1.Position())
  1050  	}
  1051  
  1052  op_binary :
  1053  	expr ANDAND expr
  1054  	{
  1055  		$$ = &ast.BinaryOperator{LHS: $1, Operator: "&&", RHS: $3}
  1056  		$$.SetPosition($1.Position())
  1057  	}
  1058  	| expr OROR expr
  1059  	{
  1060  		$$ = &ast.BinaryOperator{LHS: $1, Operator: "||", RHS: $3}
  1061  		$$.SetPosition($1.Position())
  1062  	}
  1063  
  1064  
  1065  opt_term :
  1066  	/* nothing */
  1067  	| term
  1068  	
  1069  term :
  1070  	';' newlines
  1071  	| newlines
  1072  	| ';'
  1073  
  1074  opt_newlines : 
  1075  	/* nothing */
  1076  	| newlines
  1077  
  1078  newlines : 
  1079  	newline
  1080  	| newlines newline
  1081  
  1082  newline : '\n'
  1083  
  1084  opt_comma_newlines : 
  1085  	/* nothing */
  1086  	| ',' newlines
  1087  	| newlines
  1088  	| ','
  1089  
  1090  %%