github.com/yuin/gopher-lua@v1.1.2-0.20231212122839-2348fd042596/parse/parser.go.y (about) 1 %{ 2 package parse 3 4 import ( 5 "github.com/yuin/gopher-lua/ast" 6 ) 7 %} 8 %type<stmts> chunk 9 %type<stmts> chunk1 10 %type<stmts> block 11 %type<stmt> stat 12 %type<stmts> elseifs 13 %type<stmt> laststat 14 %type<funcname> funcname 15 %type<funcname> funcname1 16 %type<exprlist> varlist 17 %type<expr> var 18 %type<namelist> namelist 19 %type<exprlist> exprlist 20 %type<expr> expr 21 %type<expr> string 22 %type<expr> prefixexp 23 %type<expr> functioncall 24 %type<expr> afunctioncall 25 %type<exprlist> args 26 %type<expr> function 27 %type<funcexpr> funcbody 28 %type<parlist> parlist 29 %type<expr> tableconstructor 30 %type<fieldlist> fieldlist 31 %type<field> field 32 %type<fieldsep> fieldsep 33 34 %union { 35 token ast.Token 36 37 stmts []ast.Stmt 38 stmt ast.Stmt 39 40 funcname *ast.FuncName 41 funcexpr *ast.FunctionExpr 42 43 exprlist []ast.Expr 44 expr ast.Expr 45 46 fieldlist []*ast.Field 47 field *ast.Field 48 fieldsep string 49 50 namelist []string 51 parlist *ast.ParList 52 } 53 54 /* Reserved words */ 55 %token<token> TAnd TBreak TDo TElse TElseIf TEnd TFalse TFor TFunction TIf TIn TLocal TNil TNot TOr TReturn TRepeat TThen TTrue TUntil TWhile TGoto 56 57 /* Literals */ 58 %token<token> TEqeq TNeq TLte TGte T2Comma T3Comma T2Colon TIdent TNumber TString '{' '(' 59 60 /* Operators */ 61 %left TOr 62 %left TAnd 63 %left '>' '<' TGte TLte TEqeq TNeq 64 %right T2Comma 65 %left '+' '-' 66 %left '*' '/' '%' 67 %right UNARY /* not # -(unary) */ 68 %right '^' 69 70 %% 71 72 chunk: 73 chunk1 { 74 $$ = $1 75 if l, ok := yylex.(*Lexer); ok { 76 l.Stmts = $$ 77 } 78 } | 79 chunk1 laststat { 80 $$ = append($1, $2) 81 if l, ok := yylex.(*Lexer); ok { 82 l.Stmts = $$ 83 } 84 } | 85 chunk1 laststat ';' { 86 $$ = append($1, $2) 87 if l, ok := yylex.(*Lexer); ok { 88 l.Stmts = $$ 89 } 90 } 91 92 chunk1: 93 { 94 $$ = []ast.Stmt{} 95 } | 96 chunk1 stat { 97 $$ = append($1, $2) 98 } | 99 chunk1 ';' { 100 $$ = $1 101 } 102 103 block: 104 chunk { 105 $$ = $1 106 } 107 108 stat: 109 varlist '=' exprlist { 110 $$ = &ast.AssignStmt{Lhs: $1, Rhs: $3} 111 $$.SetLine($1[0].Line()) 112 } | 113 /* 'stat = functioncal' causes a reduce/reduce conflict */ 114 prefixexp { 115 if _, ok := $1.(*ast.FuncCallExpr); !ok { 116 yylex.(*Lexer).Error("parse error") 117 } else { 118 $$ = &ast.FuncCallStmt{Expr: $1} 119 $$.SetLine($1.Line()) 120 } 121 } | 122 TDo block TEnd { 123 $$ = &ast.DoBlockStmt{Stmts: $2} 124 $$.SetLine($1.Pos.Line) 125 $$.SetLastLine($3.Pos.Line) 126 } | 127 TWhile expr TDo block TEnd { 128 $$ = &ast.WhileStmt{Condition: $2, Stmts: $4} 129 $$.SetLine($1.Pos.Line) 130 $$.SetLastLine($5.Pos.Line) 131 } | 132 TRepeat block TUntil expr { 133 $$ = &ast.RepeatStmt{Condition: $4, Stmts: $2} 134 $$.SetLine($1.Pos.Line) 135 $$.SetLastLine($4.Line()) 136 } | 137 TIf expr TThen block elseifs TEnd { 138 $$ = &ast.IfStmt{Condition: $2, Then: $4} 139 cur := $$ 140 for _, elseif := range $5 { 141 cur.(*ast.IfStmt).Else = []ast.Stmt{elseif} 142 cur = elseif 143 } 144 $$.SetLine($1.Pos.Line) 145 $$.SetLastLine($6.Pos.Line) 146 } | 147 TIf expr TThen block elseifs TElse block TEnd { 148 $$ = &ast.IfStmt{Condition: $2, Then: $4} 149 cur := $$ 150 for _, elseif := range $5 { 151 cur.(*ast.IfStmt).Else = []ast.Stmt{elseif} 152 cur = elseif 153 } 154 cur.(*ast.IfStmt).Else = $7 155 $$.SetLine($1.Pos.Line) 156 $$.SetLastLine($8.Pos.Line) 157 } | 158 TFor TIdent '=' expr ',' expr TDo block TEnd { 159 $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Stmts: $8} 160 $$.SetLine($1.Pos.Line) 161 $$.SetLastLine($9.Pos.Line) 162 } | 163 TFor TIdent '=' expr ',' expr ',' expr TDo block TEnd { 164 $$ = &ast.NumberForStmt{Name: $2.Str, Init: $4, Limit: $6, Step:$8, Stmts: $10} 165 $$.SetLine($1.Pos.Line) 166 $$.SetLastLine($11.Pos.Line) 167 } | 168 TFor namelist TIn exprlist TDo block TEnd { 169 $$ = &ast.GenericForStmt{Names:$2, Exprs:$4, Stmts: $6} 170 $$.SetLine($1.Pos.Line) 171 $$.SetLastLine($7.Pos.Line) 172 } | 173 TFunction funcname funcbody { 174 $$ = &ast.FuncDefStmt{Name: $2, Func: $3} 175 $$.SetLine($1.Pos.Line) 176 $$.SetLastLine($3.LastLine()) 177 } | 178 TLocal TFunction TIdent funcbody { 179 $$ = &ast.LocalAssignStmt{Names:[]string{$3.Str}, Exprs: []ast.Expr{$4}} 180 $$.SetLine($1.Pos.Line) 181 $$.SetLastLine($4.LastLine()) 182 } | 183 TLocal namelist '=' exprlist { 184 $$ = &ast.LocalAssignStmt{Names: $2, Exprs:$4} 185 $$.SetLine($1.Pos.Line) 186 } | 187 TLocal namelist { 188 $$ = &ast.LocalAssignStmt{Names: $2, Exprs:[]ast.Expr{}} 189 $$.SetLine($1.Pos.Line) 190 } | 191 T2Colon TIdent T2Colon { 192 $$ = &ast.LabelStmt{Name: $2.Str} 193 $$.SetLine($1.Pos.Line) 194 } | 195 TGoto TIdent { 196 $$ = &ast.GotoStmt{Label: $2.Str} 197 $$.SetLine($1.Pos.Line) 198 } 199 200 elseifs: 201 { 202 $$ = []ast.Stmt{} 203 } | 204 elseifs TElseIf expr TThen block { 205 $$ = append($1, &ast.IfStmt{Condition: $3, Then: $5}) 206 $$[len($$)-1].SetLine($2.Pos.Line) 207 } 208 209 laststat: 210 TReturn { 211 $$ = &ast.ReturnStmt{Exprs:nil} 212 $$.SetLine($1.Pos.Line) 213 } | 214 TReturn exprlist { 215 $$ = &ast.ReturnStmt{Exprs:$2} 216 $$.SetLine($1.Pos.Line) 217 } | 218 TBreak { 219 $$ = &ast.BreakStmt{} 220 $$.SetLine($1.Pos.Line) 221 } 222 223 funcname: 224 funcname1 { 225 $$ = $1 226 } | 227 funcname1 ':' TIdent { 228 $$ = &ast.FuncName{Func:nil, Receiver:$1.Func, Method: $3.Str} 229 } 230 231 funcname1: 232 TIdent { 233 $$ = &ast.FuncName{Func: &ast.IdentExpr{Value:$1.Str}} 234 $$.Func.SetLine($1.Pos.Line) 235 } | 236 funcname1 '.' TIdent { 237 key:= &ast.StringExpr{Value:$3.Str} 238 key.SetLine($3.Pos.Line) 239 fn := &ast.AttrGetExpr{Object: $1.Func, Key: key} 240 fn.SetLine($3.Pos.Line) 241 $$ = &ast.FuncName{Func: fn} 242 } 243 244 varlist: 245 var { 246 $$ = []ast.Expr{$1} 247 } | 248 varlist ',' var { 249 $$ = append($1, $3) 250 } 251 252 var: 253 TIdent { 254 $$ = &ast.IdentExpr{Value:$1.Str} 255 $$.SetLine($1.Pos.Line) 256 } | 257 prefixexp '[' expr ']' { 258 $$ = &ast.AttrGetExpr{Object: $1, Key: $3} 259 $$.SetLine($1.Line()) 260 } | 261 prefixexp '.' TIdent { 262 key := &ast.StringExpr{Value:$3.Str} 263 key.SetLine($3.Pos.Line) 264 $$ = &ast.AttrGetExpr{Object: $1, Key: key} 265 $$.SetLine($1.Line()) 266 } 267 268 namelist: 269 TIdent { 270 $$ = []string{$1.Str} 271 } | 272 namelist ',' TIdent { 273 $$ = append($1, $3.Str) 274 } 275 276 exprlist: 277 expr { 278 $$ = []ast.Expr{$1} 279 } | 280 exprlist ',' expr { 281 $$ = append($1, $3) 282 } 283 284 expr: 285 TNil { 286 $$ = &ast.NilExpr{} 287 $$.SetLine($1.Pos.Line) 288 } | 289 TFalse { 290 $$ = &ast.FalseExpr{} 291 $$.SetLine($1.Pos.Line) 292 } | 293 TTrue { 294 $$ = &ast.TrueExpr{} 295 $$.SetLine($1.Pos.Line) 296 } | 297 TNumber { 298 $$ = &ast.NumberExpr{Value: $1.Str} 299 $$.SetLine($1.Pos.Line) 300 } | 301 T3Comma { 302 $$ = &ast.Comma3Expr{} 303 $$.SetLine($1.Pos.Line) 304 } | 305 function { 306 $$ = $1 307 } | 308 prefixexp { 309 $$ = $1 310 } | 311 string { 312 $$ = $1 313 } | 314 tableconstructor { 315 $$ = $1 316 } | 317 expr TOr expr { 318 $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "or", Rhs: $3} 319 $$.SetLine($1.Line()) 320 } | 321 expr TAnd expr { 322 $$ = &ast.LogicalOpExpr{Lhs: $1, Operator: "and", Rhs: $3} 323 $$.SetLine($1.Line()) 324 } | 325 expr '>' expr { 326 $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">", Rhs: $3} 327 $$.SetLine($1.Line()) 328 } | 329 expr '<' expr { 330 $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<", Rhs: $3} 331 $$.SetLine($1.Line()) 332 } | 333 expr TGte expr { 334 $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: ">=", Rhs: $3} 335 $$.SetLine($1.Line()) 336 } | 337 expr TLte expr { 338 $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "<=", Rhs: $3} 339 $$.SetLine($1.Line()) 340 } | 341 expr TEqeq expr { 342 $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "==", Rhs: $3} 343 $$.SetLine($1.Line()) 344 } | 345 expr TNeq expr { 346 $$ = &ast.RelationalOpExpr{Lhs: $1, Operator: "~=", Rhs: $3} 347 $$.SetLine($1.Line()) 348 } | 349 expr T2Comma expr { 350 $$ = &ast.StringConcatOpExpr{Lhs: $1, Rhs: $3} 351 $$.SetLine($1.Line()) 352 } | 353 expr '+' expr { 354 $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "+", Rhs: $3} 355 $$.SetLine($1.Line()) 356 } | 357 expr '-' expr { 358 $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "-", Rhs: $3} 359 $$.SetLine($1.Line()) 360 } | 361 expr '*' expr { 362 $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "*", Rhs: $3} 363 $$.SetLine($1.Line()) 364 } | 365 expr '/' expr { 366 $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "/", Rhs: $3} 367 $$.SetLine($1.Line()) 368 } | 369 expr '%' expr { 370 $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "%", Rhs: $3} 371 $$.SetLine($1.Line()) 372 } | 373 expr '^' expr { 374 $$ = &ast.ArithmeticOpExpr{Lhs: $1, Operator: "^", Rhs: $3} 375 $$.SetLine($1.Line()) 376 } | 377 '-' expr %prec UNARY { 378 $$ = &ast.UnaryMinusOpExpr{Expr: $2} 379 $$.SetLine($2.Line()) 380 } | 381 TNot expr %prec UNARY { 382 $$ = &ast.UnaryNotOpExpr{Expr: $2} 383 $$.SetLine($2.Line()) 384 } | 385 '#' expr %prec UNARY { 386 $$ = &ast.UnaryLenOpExpr{Expr: $2} 387 $$.SetLine($2.Line()) 388 } 389 390 string: 391 TString { 392 $$ = &ast.StringExpr{Value: $1.Str} 393 $$.SetLine($1.Pos.Line) 394 } 395 396 prefixexp: 397 var { 398 $$ = $1 399 } | 400 afunctioncall { 401 $$ = $1 402 } | 403 functioncall { 404 $$ = $1 405 } | 406 '(' expr ')' { 407 if ex, ok := $2.(*ast.Comma3Expr); ok { 408 ex.AdjustRet = true 409 } 410 $$ = $2 411 $$.SetLine($1.Pos.Line) 412 } 413 414 afunctioncall: 415 '(' functioncall ')' { 416 $2.(*ast.FuncCallExpr).AdjustRet = true 417 $$ = $2 418 } 419 420 functioncall: 421 prefixexp args { 422 $$ = &ast.FuncCallExpr{Func: $1, Args: $2} 423 $$.SetLine($1.Line()) 424 } | 425 prefixexp ':' TIdent args { 426 $$ = &ast.FuncCallExpr{Method: $3.Str, Receiver: $1, Args: $4} 427 $$.SetLine($1.Line()) 428 } 429 430 args: 431 '(' ')' { 432 if yylex.(*Lexer).PNewLine { 433 yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)") 434 } 435 $$ = []ast.Expr{} 436 } | 437 '(' exprlist ')' { 438 if yylex.(*Lexer).PNewLine { 439 yylex.(*Lexer).TokenError($1, "ambiguous syntax (function call x new statement)") 440 } 441 $$ = $2 442 } | 443 tableconstructor { 444 $$ = []ast.Expr{$1} 445 } | 446 string { 447 $$ = []ast.Expr{$1} 448 } 449 450 function: 451 TFunction funcbody { 452 $$ = &ast.FunctionExpr{ParList:$2.ParList, Stmts: $2.Stmts} 453 $$.SetLine($1.Pos.Line) 454 $$.SetLastLine($2.LastLine()) 455 } 456 457 funcbody: 458 '(' parlist ')' block TEnd { 459 $$ = &ast.FunctionExpr{ParList: $2, Stmts: $4} 460 $$.SetLine($1.Pos.Line) 461 $$.SetLastLine($5.Pos.Line) 462 } | 463 '(' ')' block TEnd { 464 $$ = &ast.FunctionExpr{ParList: &ast.ParList{HasVargs: false, Names: []string{}}, Stmts: $3} 465 $$.SetLine($1.Pos.Line) 466 $$.SetLastLine($4.Pos.Line) 467 } 468 469 parlist: 470 T3Comma { 471 $$ = &ast.ParList{HasVargs: true, Names: []string{}} 472 } | 473 namelist { 474 $$ = &ast.ParList{HasVargs: false, Names: []string{}} 475 $$.Names = append($$.Names, $1...) 476 } | 477 namelist ',' T3Comma { 478 $$ = &ast.ParList{HasVargs: true, Names: []string{}} 479 $$.Names = append($$.Names, $1...) 480 } 481 482 483 tableconstructor: 484 '{' '}' { 485 $$ = &ast.TableExpr{Fields: []*ast.Field{}} 486 $$.SetLine($1.Pos.Line) 487 } | 488 '{' fieldlist '}' { 489 $$ = &ast.TableExpr{Fields: $2} 490 $$.SetLine($1.Pos.Line) 491 } 492 493 494 fieldlist: 495 field { 496 $$ = []*ast.Field{$1} 497 } | 498 fieldlist fieldsep field { 499 $$ = append($1, $3) 500 } | 501 fieldlist fieldsep { 502 $$ = $1 503 } 504 505 field: 506 TIdent '=' expr { 507 $$ = &ast.Field{Key: &ast.StringExpr{Value:$1.Str}, Value: $3} 508 $$.Key.SetLine($1.Pos.Line) 509 } | 510 '[' expr ']' '=' expr { 511 $$ = &ast.Field{Key: $2, Value: $5} 512 } | 513 expr { 514 $$ = &ast.Field{Value: $1} 515 } 516 517 fieldsep: 518 ',' { 519 $$ = "," 520 } | 521 ';' { 522 $$ = ";" 523 } 524 525 %% 526 527 func TokenName(c int) string { 528 if c >= TAnd && c-TAnd < len(yyToknames) { 529 if yyToknames[c-TAnd] != "" { 530 return yyToknames[c-TAnd] 531 } 532 } 533 return string([]byte{byte(c)}) 534 } 535