github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/compiler/parser/parser.go (about) 1 // Original: src/go/parser/parser.go 2 // 3 // Copyright 2009 The Go Authors. All rights reserved. 4 // Portions Copyright 2016 Hiroshi Ioka. All rights reserved. 5 // 6 // Redistribution and use in source and binary forms, with or without 7 // modification, are permitted provided that the following conditions are 8 // met: 9 // 10 // * Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // * Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following disclaimer 14 // in the documentation and/or other materials provided with the 15 // distribution. 16 // * Neither the name of Google Inc. nor the names of its 17 // contributors may be used to endorse or promote products derived from 18 // this software without specific prior written permission. 19 // 20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32 package parser 33 34 import ( 35 "errors" 36 "fmt" 37 "os" 38 39 "github.com/hirochachacha/plua/compiler/ast" 40 "github.com/hirochachacha/plua/compiler/scanner" 41 "github.com/hirochachacha/plua/compiler/token" 42 "github.com/hirochachacha/plua/position" 43 ) 44 45 var ( 46 errIllegalVararg = errors.New("cannot use '...' outside of vararg function") 47 errIllegalBreak = errors.New("cannot use 'break' outside of loop") 48 ) 49 50 type Mode uint 51 52 const ( 53 ParseComments Mode = 1 << iota 54 ) 55 56 func ParseFile(filename string, mode Mode) (*ast.File, error) { 57 f, err := os.Open(filename) 58 if err != nil { 59 return nil, err 60 } 61 defer f.Close() 62 63 var m scanner.Mode 64 if mode&ParseComments != 0 { 65 m = scanner.ScanComments 66 } 67 68 s := scanner.Scan(f, "@"+filename, m) 69 70 return Parse(s, mode) 71 } 72 73 func Parse(s *scanner.ScanState, mode Mode) (f *ast.File, err error) { 74 p := &parser{ 75 scanState: s, 76 } 77 78 defer func() { 79 if r := recover(); r != nil { 80 _ = r.(bailout) 81 82 err = p.err 83 } 84 }() 85 86 p.next() 87 88 f = p.parseFile() 89 90 return 91 } 92 93 // The parser structure holds the parser's internal state. 94 type parser struct { 95 scanState *scanner.ScanState 96 97 // Comments 98 comments []*ast.CommentGroup 99 leadComment *ast.CommentGroup // last lead comment 100 lineComment *ast.CommentGroup // last line comment 101 102 // Next token 103 tok token.Token 104 105 // allow vararg in this function scope? 106 allowEllipsis bool 107 108 // allow break in this scope? 109 allowBreak bool 110 111 err error 112 } 113 114 type bailout struct{} 115 116 func (p *parser) markLHS(x ast.Expr) { 117 // switch t := x.(type) { 118 // case *ast.Name: 119 // t.IsLHS = true 120 // case *ast.SelectorExpr: 121 // t.IsLHS = true 122 // case *ast.IndexExpr: 123 // t.IsLHS = true 124 // } 125 } 126 127 func (p *parser) markRHS(x ast.Expr) { 128 // switch t := x.(type) { 129 // case *ast.Name: 130 // if !t.IsLHS { 131 // panic("name already marked as RHS") 132 // } 133 134 // t.IsLHS = false 135 // case *ast.SelectorExpr: 136 // if !t.IsLHS { 137 // panic("selector expression already marked as RHS") 138 // } 139 140 // t.IsLHS = false 141 // case *ast.IndexExpr: 142 // if !t.IsLHS { 143 // panic("index expression already marked as RHS") 144 // } 145 146 // t.IsLHS = false 147 // } 148 } 149 150 // ---------------------------------------------------------------------------- 151 // Parsing support 152 153 // Advance to the next token. 154 func (p *parser) next0() { 155 tok, err := p.scanState.Token() 156 if err != nil { 157 p.err = err 158 panic(bailout{}) 159 } 160 p.tok = tok 161 } 162 163 // Consume a comment and return it and the line on which it ends. 164 func (p *parser) consumeComment() (comment *ast.Comment, endLine int) { 165 endLine = p.tok.Pos.Line 166 for _, r := range p.tok.Lit { 167 if r == '\n' { 168 endLine++ 169 } 170 } 171 172 if p.tok.Type == token.COMMENT { 173 comment = &ast.Comment{Hyphen: p.tok.Pos, Text: p.tok.Lit} 174 p.next0() 175 176 return 177 } 178 179 comment = &ast.Comment{Hyphen: p.tok.Pos, Text: p.tok.Lit} 180 p.next0() 181 182 return 183 } 184 185 // Consume a group of adjacent comments, add it to the parser's 186 // comments list, and return it together with the line at which 187 // the last comment in the group ends. A non-comment token or n 188 // empty lines terminate a comment group. 189 // 190 func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endLine int) { 191 var list []*ast.Comment 192 endLine = p.tok.Pos.Line 193 for p.tok.Type == token.COMMENT && p.tok.Pos.Line <= endLine+n { 194 var comment *ast.Comment 195 comment, endLine = p.consumeComment() 196 list = append(list, comment) 197 } 198 199 // add comment group to the comments list 200 comments = &ast.CommentGroup{List: list} 201 p.comments = append(p.comments, comments) 202 203 return 204 } 205 206 // Advance to the next non-comment token. In the process, collect 207 // any comment groups encountered, and remember the last lead and 208 // and line comments. 209 // 210 // A lead comment is a comment group that starts and ends in a 211 // line without any other tokens and that is followed by a non-comment 212 // token on the line immediately after the comment group. 213 // 214 // A line comment is a comment group that follows a non-comment 215 // token on the same line, and that has no tokens after it on the line 216 // where it ends. 217 // 218 // Lead and line comments may be considered documentation that is 219 // stored in the AST. 220 // 221 func (p *parser) next() { 222 p.leadComment = nil 223 p.lineComment = nil 224 prevLine := p.tok.Pos.Line 225 p.next0() 226 227 if p.tok.Type == token.COMMENT { 228 var comment *ast.CommentGroup 229 var endLine int 230 231 if p.tok.Pos.Line == prevLine { 232 // The comment is on same line as the previous token; it 233 // cannot be a lead comment but may be a line comment. 234 comment, endLine = p.consumeCommentGroup(0) 235 if p.tok.Pos.Line != endLine { 236 // The next token is on a different line, thus 237 // the last comment group is a line comment. 238 p.lineComment = comment 239 } 240 } 241 242 // consume successor comments, if any 243 endLine = -1 244 for p.tok.Type == token.COMMENT { 245 comment, endLine = p.consumeCommentGroup(1) 246 } 247 248 if endLine+1 == p.tok.Pos.Line { 249 // The next token is following on the line immediately after the 250 // comment group, thus the last comment group is a lead comment. 251 p.leadComment = comment 252 } 253 } 254 } 255 256 func (p *parser) error(pos position.Position, err error) { 257 pos.SourceName = p.scanState.SourceName() 258 259 p.err = &Error{ 260 Pos: pos, 261 Err: err, 262 } 263 264 panic(bailout{}) 265 } 266 267 func (p *parser) errorExpected(actual token.Token, expected string) { 268 found := "'" + actual.Type.String() + "'" 269 if len(actual.Lit) > 0 { 270 found += " " + actual.Lit 271 } 272 273 p.error(actual.Pos, fmt.Errorf("expected %s, found %s", expected, found)) 274 } 275 276 func (p *parser) expect(expected token.Type) position.Position { 277 if p.tok.Type != expected { 278 p.errorExpected(p.tok, "'"+expected.String()+"'") 279 280 return position.NoPos 281 } 282 283 pos := p.tok.Pos 284 285 p.next() // make progress 286 287 return pos 288 } 289 290 func (p *parser) skip() position.Position { 291 pos := p.tok.Pos 292 293 p.next() // make progress 294 295 return pos 296 } 297 298 func (p *parser) accept(tok token.Type, toks ...token.Type) bool { 299 if p.tok.Type == tok { 300 p.next() // make progress 301 return true 302 } 303 304 for _, tok := range toks { 305 if p.tok.Type == tok { 306 p.next() // make progress 307 return true 308 } 309 } 310 return false 311 } 312 313 // ---------------------------------------------------------------------------- 314 // Name 315 316 func (p *parser) parseName() *ast.Name { 317 pos := p.tok.Pos 318 name := "_" 319 if p.tok.Type == token.NAME { 320 name = p.tok.Lit 321 p.next() 322 } else { 323 p.expect(token.NAME) // use expect() error handling 324 } 325 // return &ast.Name{NamePos: pos, Name: name, IsLHS: true} 326 return &ast.Name{NamePos: pos, Name: name} 327 } 328 329 func (p *parser) parseNameList() (list []*ast.Name) { 330 list = append(list, p.parseName()) 331 for p.accept(token.COMMA) { 332 list = append(list, p.parseName()) 333 } 334 335 return 336 } 337 338 // ---------------------------------------------------------------------------- 339 // Common productions 340 341 func (p *parser) parseCallExprOrLHSList() (CallExpr *ast.CallExpr, LHS []ast.Expr) { 342 expr := p.parseBinaryExpr(true, token.LowestPrec) 343 344 if expr, ok := expr.(*ast.CallExpr); ok { 345 return expr, nil 346 } 347 348 LHS = append(LHS, p.checkLHS(expr)) 349 for p.accept(token.COMMA) { 350 LHS = append(LHS, p.parseLHS()) 351 } 352 353 return 354 } 355 356 func (p *parser) parseRHSList() (rhs []ast.Expr) { 357 rhs = append(rhs, p.parseRHS()) 358 for p.accept(token.COMMA) { 359 rhs = append(rhs, p.parseRHS()) 360 } 361 362 return 363 } 364 365 func (p *parser) parseReturnList() (rhs []ast.Expr) { 366 rhs = append(rhs, p.parseRHS()) 367 for p.accept(token.COMMA) { 368 rhs = append(rhs, p.parseRHS()) 369 } 370 371 return 372 } 373 374 func (p *parser) parseParameterList() (params []*ast.Name) { 375 if p.tok.Type == token.ELLIPSIS { 376 return 377 } 378 379 name := p.parseName() 380 params = append(params, name) 381 382 for p.accept(token.COMMA) { 383 if p.tok.Type == token.ELLIPSIS { 384 break 385 } 386 387 name := p.parseName() 388 389 params = append(params, name) 390 } 391 392 return 393 } 394 395 func (p *parser) parseParameters() *ast.ParamList { 396 var params []*ast.Name 397 398 ellipsis := position.NoPos 399 400 lparen := p.expect(token.LPAREN) 401 if p.tok.Type != token.RPAREN { 402 params = p.parseParameterList() 403 if p.tok.Type == token.ELLIPSIS { 404 ellipsis = p.tok.Pos 405 p.next() 406 } 407 } 408 rparen := p.expect(token.RPAREN) 409 410 return &ast.ParamList{Lparen: lparen, List: params, Ellipsis: ellipsis, Rparen: rparen} 411 } 412 413 // ---------------------------------------------------------------------------- 414 // Blocks 415 416 func (p *parser) isEndOfBlock() bool { 417 switch p.tok.Type { 418 case token.EOF, token.ELSE, token.ELSEIF, token.END: 419 return true 420 case token.UNTIL: 421 return true 422 } 423 424 return false 425 } 426 427 func (p *parser) parseStmtList() (list []ast.Stmt, closing position.Position) { 428 for { 429 if p.isEndOfBlock() { 430 break 431 } 432 if p.tok.Type == token.RETURN { 433 list = append(list, p.parseReturnStmt()) 434 break 435 } 436 list = append(list, p.parseStmt()) 437 } 438 439 closing = p.tok.Pos 440 441 return list, closing 442 } 443 444 func (p *parser) parseChunk() []ast.Stmt { 445 p.allowEllipsis = true 446 447 list, _ := p.parseStmtList() 448 449 p.expect(token.EOF) 450 451 return list 452 } 453 454 func (p *parser) parseThenBlock() (then position.Position, body *ast.Block) { 455 then = p.expect(token.THEN) 456 457 body = p.parseBody(then.Offset("then")) 458 459 switch p.tok.Type { 460 case token.ELSEIF: 461 case token.ELSE: 462 case token.END: 463 default: 464 p.errorExpected(p.tok, "ELSEIF, ELSE or END") 465 } 466 467 return then, body 468 } 469 470 func (p *parser) parseRepeatBlockUntil() (repeat position.Position, body *ast.Block, until position.Position) { 471 repeat = p.skip() 472 body = p.parseBody(repeat.Offset("repeat")) 473 until = p.expect(token.UNTIL) 474 475 return repeat, body, until 476 } 477 478 func (p *parser) parseDoBlockEnd() (do position.Position, body *ast.Block, end position.Position) { 479 do = p.expect(token.DO) 480 body = p.parseBody(do.Offset("do")) 481 end = p.expect(token.END) 482 483 return do, body, end 484 } 485 486 func (p *parser) parseBody(opening position.Position) *ast.Block { 487 list, closing := p.parseStmtList() 488 489 return &ast.Block{ 490 Opening: opening, 491 List: list, 492 Closing: closing, 493 } 494 } 495 496 func (p *parser) parseFuncBodyEnd() (fbody *ast.FuncBody, end position.Position) { 497 params := p.parseParameters() 498 499 old := p.allowEllipsis 500 p.allowEllipsis = params.Ellipsis.IsValid() 501 502 body := p.parseBody(params.End()) 503 504 p.allowEllipsis = old 505 506 end = p.expect(token.END) 507 508 fbody = &ast.FuncBody{ 509 Params: params, 510 Body: body, 511 } 512 513 return fbody, end 514 } 515 516 // ---------------------------------------------------------------------------- 517 // Expressions 518 519 func (p *parser) parseSelector(x ast.Expr) ast.Expr { 520 period := p.skip() 521 522 sel := p.parseName() 523 524 return &ast.SelectorExpr{X: x, Period: period, Sel: sel} 525 } 526 527 func (p *parser) parseIndex(x ast.Expr) ast.Expr { 528 lbrack := p.skip() 529 530 index := p.parseRHS() 531 532 rbrack := p.expect(token.RBRACK) 533 534 return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: index, Rbrack: rbrack} 535 } 536 537 func (p *parser) parseCall(isMethod bool, x ast.Expr) ast.Expr { 538 colon := position.NoPos 539 var name *ast.Name 540 541 if isMethod { 542 colon = p.skip() 543 name = p.parseName() 544 } 545 546 tok := p.tok 547 548 switch tok.Type { 549 case token.LPAREN: 550 lparen := tok.Pos 551 p.next() 552 var args []ast.Expr 553 554 for p.tok.Type != token.RPAREN && p.tok.Type != token.EOF { 555 args = append(args, p.parseRHS()) 556 if !p.accept(token.COMMA) { 557 break 558 } 559 } 560 561 rparen := p.expect(token.RPAREN) 562 563 return &ast.CallExpr{X: x, Colon: colon, Name: name, Lparen: lparen, Args: args, Rparen: rparen} 564 case token.LBRACE: 565 y := p.parseTableLit() 566 567 return &ast.CallExpr{X: x, Colon: colon, Name: name, Args: []ast.Expr{y}} 568 case token.STRING: 569 y := &ast.BasicLit{Token: tok} 570 571 p.next() 572 573 return &ast.CallExpr{X: x, Colon: colon, Name: name, Args: []ast.Expr{y}} 574 } 575 576 // we have an error 577 p.errorExpected(tok, "callable") 578 579 // syncStmt(p) 580 581 return &ast.BadExpr{From: tok.Pos, To: p.tok.Pos} 582 } 583 584 func (p *parser) parseElement() ast.Expr { 585 lbrack := position.NoPos 586 rbrack := position.NoPos 587 588 var x ast.Expr 589 590 switch p.tok.Type { 591 case token.LBRACK: // [key] 592 lbrack = p.tok.Pos 593 594 p.next() 595 596 x = p.parseRHS() 597 598 rbrack = p.expect(token.RBRACK) 599 default: // key 600 x = p.parseBinaryExpr(true, token.LowestPrec) 601 } 602 603 if p.tok.Type == token.ASSIGN { 604 // key = value 605 606 eq := p.tok.Pos 607 608 p.next() 609 610 y := p.parseRHS() 611 612 return &ast.KeyValueExpr{Lbrack: lbrack, Key: x, Rbrack: rbrack, Equal: eq, Value: y} 613 } 614 615 // value 616 // p.markRHS(x) 617 618 return x 619 } 620 621 func (p *parser) parseElementList() (fields []ast.Expr) { 622 for p.tok.Type != token.RBRACE && p.tok.Type != token.EOF { 623 e := p.parseElement() 624 625 fields = append(fields, e) 626 627 if !p.accept(token.COMMA, token.SEMICOLON) { 628 break 629 } 630 } 631 632 return 633 } 634 635 func (p *parser) parseTableLit() *ast.TableLit { 636 lbrace := p.expect(token.LBRACE) 637 638 var fields []ast.Expr 639 if p.tok.Type != token.RBRACE { 640 fields = p.parseElementList() 641 } 642 643 rbrace := p.expect(token.RBRACE) 644 645 return &ast.TableLit{Lbrace: lbrace, Fields: fields, Rbrace: rbrace} 646 } 647 648 func (p *parser) parseFuncLit() *ast.FuncLit { 649 fn := p.expect(token.FUNCTION) 650 651 f, end := p.parseFuncBodyEnd() 652 653 return &ast.FuncLit{ 654 Func: fn, 655 Body: f, 656 EndPos: end, 657 } 658 } 659 660 // checkExpr checks that x is an expression. 661 func (p *parser) checkExpr(x ast.Expr) ast.Expr { 662 switch unparen(x).(type) { 663 case *ast.BadExpr: 664 case *ast.Name: 665 case *ast.Vararg: 666 case *ast.BasicLit: 667 case *ast.FuncLit: 668 case *ast.TableLit: 669 case *ast.ParenExpr: 670 panic("unreachable") 671 case *ast.SelectorExpr: 672 case *ast.IndexExpr: 673 case *ast.CallExpr: 674 case *ast.UnaryExpr: 675 case *ast.BinaryExpr: 676 default: 677 // all other nodes are not proper expressions 678 p.error(x.Pos(), fmt.Errorf("expected expression, found %T", x)) 679 680 x = &ast.BadExpr{From: x.Pos(), To: x.End()} 681 } 682 return x 683 } 684 685 // checkLHS checks that x is an LHS expression. 686 func (p *parser) checkLHS(x ast.Expr) ast.Expr { 687 // switch t := x.(type) { 688 switch x.(type) { 689 case *ast.Name: 690 // if !t.IsLHS { 691 // goto error 692 // } 693 case *ast.SelectorExpr: 694 // if !t.IsLHS { 695 // goto error 696 // } 697 case *ast.IndexExpr: 698 // if !t.IsLHS { 699 // goto error 700 // } 701 default: 702 goto error 703 } 704 705 return x 706 707 error: 708 // all other nodes are not proper expressions 709 p.error(x.Pos(), fmt.Errorf("expected LHS, found %T", x)) 710 711 x = &ast.BadExpr{From: x.Pos(), To: x.End()} 712 713 return x 714 } 715 716 // If x is of the form (T), unparen returns unparen(T), otherwise it returns x. 717 func unparen(x ast.Expr) ast.Expr { 718 if p, isParen := x.(*ast.ParenExpr); isParen { 719 x = unparen(p.X) 720 } 721 return x 722 } 723 724 func (p *parser) parsePrimaryExpr() ast.Expr { 725 tok := p.tok 726 727 switch tok.Type { 728 case token.NAME: 729 x := p.parseName() 730 // x.IsLHS = false 731 return x 732 case token.LPAREN: 733 lparen := tok.Pos 734 p.next() 735 x := p.parseRHS() 736 rparen := p.expect(token.RPAREN) 737 738 return &ast.ParenExpr{Lparen: lparen, X: x, Rparen: rparen} 739 } 740 741 // we have an error 742 p.errorExpected(tok, "NAME or '('") 743 744 // syncStmt(p) 745 746 return &ast.BadExpr{From: tok.Pos, To: p.tok.Pos} 747 } 748 749 func (p *parser) parseSuffixedExpr(isLHS bool) ast.Expr { 750 x := p.parsePrimaryExpr() 751 L: 752 for { 753 switch p.tok.Type { 754 case token.PERIOD: 755 x = p.parseSelector(p.checkExpr(x)) 756 case token.LBRACK: 757 x = p.parseIndex(p.checkExpr(x)) 758 case token.LPAREN, token.LBRACE, token.STRING: 759 x = p.parseCall(false, p.checkExpr(x)) 760 case token.COLON: 761 x = p.parseCall(true, p.checkExpr(x)) 762 default: 763 if isLHS { 764 // p.markLHS(x) 765 } 766 767 break L 768 } 769 } 770 771 return x 772 } 773 774 func (p *parser) parseSimpleExpr(isLHS bool) ast.Expr { 775 tok := p.tok 776 777 switch tok.Type { 778 case token.ELLIPSIS: 779 var x ast.Expr 780 781 if !p.allowEllipsis { 782 p.error(tok.Pos, errIllegalVararg) 783 784 p.next() 785 786 x = &ast.BadExpr{From: tok.Pos, To: p.tok.Pos} 787 788 return x 789 } 790 791 x = &ast.Vararg{Ellipsis: tok.Pos} 792 793 p.next() 794 795 return x 796 797 case token.INT, token.FLOAT, token.STRING: 798 x := &ast.BasicLit{Token: tok} 799 p.next() 800 return x 801 802 case token.FALSE, token.TRUE, token.NIL: 803 x := &ast.BasicLit{Token: tok} 804 p.next() 805 return x 806 807 case token.FUNCTION: 808 return p.parseFuncLit() 809 810 case token.LBRACE: 811 return p.parseTableLit() 812 default: 813 return p.parseSuffixedExpr(isLHS) 814 } 815 } 816 817 // If isLHS is set and the result is an name, it is not resolved. 818 func (p *parser) parseUnaryExpr(isLHS bool) ast.Expr { 819 tok := p.tok 820 821 switch tok.Type { 822 case token.UNM, token.BNOT, token.NOT, token.LEN: 823 p.next() 824 x := p.parseBinaryExpr(false, token.UnaryPrec) 825 return &ast.UnaryExpr{OpPos: tok.Pos, Op: tok.Type, X: p.checkExpr(x)} 826 } 827 828 return p.parseSimpleExpr(isLHS) 829 } 830 831 func (p *parser) tokPrec() (token.Type, int, int) { 832 tok := p.tok.Type 833 l, r := tok.Precedence() 834 return tok, l, r 835 } 836 837 // If isLHS is set and the result is an name, it is not resolved. 838 func (p *parser) parseBinaryExpr(isLHS bool, prec1 int) ast.Expr { 839 x := p.parseUnaryExpr(isLHS) 840 841 for { 842 op, lprec, rprec := p.tokPrec() 843 844 if lprec <= prec1 { 845 break 846 } 847 848 if isLHS { 849 // p.markRHS(x) 850 851 isLHS = false 852 } 853 854 olprec, orprec := lprec, rprec 855 856 for { 857 pos := p.expect(op) 858 859 y := p.parseBinaryExpr(false, orprec) 860 861 x = &ast.BinaryExpr{X: p.checkExpr(x), OpPos: pos, Op: op, Y: p.checkExpr(y)} 862 863 op, olprec, orprec = p.tokPrec() 864 865 if olprec < rprec { 866 break 867 } 868 } 869 } 870 871 return x 872 } 873 874 func (p *parser) parseLHS() ast.Expr { 875 return p.checkLHS(p.parseBinaryExpr(true, token.LowestPrec)) 876 } 877 878 func (p *parser) parseRHS() ast.Expr { 879 return p.checkExpr(p.parseBinaryExpr(false, token.LowestPrec)) 880 } 881 882 // ---------------------------------------------------------------------------- 883 // Statements 884 885 func (p *parser) parseAssign(LHS []ast.Expr) ast.Stmt { 886 eq := p.skip() 887 888 rhs := p.parseRHSList() 889 890 assign := &ast.AssignStmt{ 891 LHS: LHS, 892 Equal: eq, 893 RHS: rhs, 894 } 895 896 return assign 897 } 898 899 func (p *parser) parseLocalAssignStmt(local position.Position) ast.Stmt { 900 LHS := p.parseNameList() 901 902 var stmt ast.Stmt 903 904 if p.tok.Type == token.ASSIGN { 905 eq := p.tok.Pos 906 p.next() 907 908 rhs := p.parseRHSList() 909 910 stmt = &ast.LocalAssignStmt{ 911 Local: local, 912 LHS: LHS, 913 Equal: eq, 914 RHS: rhs, 915 } 916 } else { 917 stmt = &ast.LocalAssignStmt{ 918 Local: local, 919 LHS: LHS, 920 } 921 } 922 923 return stmt 924 } 925 926 func (p *parser) parseLocalStmt() ast.Stmt { 927 local := p.skip() 928 929 if p.tok.Type == token.FUNCTION { 930 fn := p.skip() 931 932 name := p.parseName() 933 934 f, end := p.parseFuncBodyEnd() 935 936 return &ast.LocalFuncStmt{ 937 Local: local, 938 Func: fn, 939 Name: name, 940 Body: f, 941 EndPos: end, 942 } 943 } 944 945 return p.parseLocalAssignStmt(local) 946 } 947 948 func (p *parser) parseFuncStmt() *ast.FuncStmt { 949 fn := p.skip() 950 951 var prefix []*ast.Name 952 var accessTok token.Type 953 var accessPos position.Position 954 var name *ast.Name 955 956 var list []*ast.Name 957 var periodPos position.Position 958 959 list = append(list, p.parseName()) 960 961 for p.tok.Type == token.PERIOD { 962 periodPos = p.tok.Pos 963 964 p.next() // make progress 965 966 list = append(list, p.parseName()) 967 } 968 969 if p.tok.Type == token.COLON { 970 accessTok = token.COLON 971 accessPos = p.tok.Pos 972 973 p.next() 974 975 name = p.parseName() 976 prefix = list 977 } else if len(list) == 1 { 978 name = list[0] 979 accessTok = token.ILLEGAL 980 accessPos = position.NoPos 981 } else { 982 name = list[len(list)-1] 983 prefix = list[:len(list)-1] 984 accessTok = token.PERIOD 985 accessPos = periodPos 986 } 987 988 f, end := p.parseFuncBodyEnd() 989 990 return &ast.FuncStmt{ 991 Func: fn, 992 PathList: prefix, 993 AccessTok: accessTok, 994 AccessPos: accessPos, 995 Name: name, 996 Body: f, 997 EndPos: end, 998 } 999 } 1000 1001 func (p *parser) parseExprOrAssignStmt() (stmt ast.Stmt) { 1002 tok := p.tok 1003 1004 expr, LHS := p.parseCallExprOrLHSList() 1005 if p.tok.Type == token.ASSIGN { // assign stmt 1006 if len(LHS) == 0 { 1007 p.errorExpected(tok, "LHS") 1008 1009 return &ast.BadStmt{From: tok.Pos, To: p.tok.Pos} 1010 } 1011 1012 stmt = p.parseAssign(LHS) 1013 } else { // expr stmt 1014 if expr == nil { 1015 p.errorExpected(tok, "callable") 1016 1017 return &ast.BadStmt{From: tok.Pos, To: p.tok.Pos} 1018 } 1019 1020 stmt = &ast.ExprStmt{expr} 1021 } 1022 1023 return 1024 } 1025 1026 func (p *parser) parseReturnStmt() *ast.ReturnStmt { 1027 ret := p.skip() 1028 semi := position.NoPos 1029 1030 if p.isEndOfBlock() { 1031 return &ast.ReturnStmt{ 1032 Return: ret, 1033 Semicolon: semi, 1034 } 1035 } 1036 1037 if p.tok.Type == token.SEMICOLON { 1038 semi = p.tok.Pos 1039 1040 p.next() 1041 1042 return &ast.ReturnStmt{ 1043 Return: ret, 1044 Semicolon: semi, 1045 } 1046 } 1047 1048 results := p.parseReturnList() 1049 1050 if p.tok.Type == token.SEMICOLON { 1051 semi = p.tok.Pos 1052 1053 p.next() 1054 } 1055 1056 return &ast.ReturnStmt{ 1057 Return: ret, 1058 Results: results, 1059 Semicolon: semi, 1060 } 1061 } 1062 1063 func (p *parser) parseLabelStmt() *ast.LabelStmt { 1064 label := p.skip() 1065 1066 name := p.parseName() 1067 1068 end := p.expect(token.LABEL) 1069 1070 return &ast.LabelStmt{ 1071 Label: label, 1072 Name: name, 1073 EndLabel: end, 1074 } 1075 } 1076 1077 func (p *parser) parseGotoStmt() *ast.GotoStmt { 1078 _goto := p.skip() 1079 1080 label := p.parseName() 1081 1082 return &ast.GotoStmt{Goto: _goto, Label: label} 1083 } 1084 1085 func (p *parser) parseBreak() ast.Stmt { 1086 if !p.allowBreak { 1087 from := p.tok.Pos 1088 p.error(from, errIllegalBreak) 1089 1090 // syncStmt(p) 1091 1092 return &ast.BadStmt{From: from, To: p.tok.Pos} 1093 } 1094 1095 brk := p.skip() 1096 1097 return &ast.BreakStmt{Break: brk} 1098 } 1099 1100 func (p *parser) parseDoStmt() *ast.DoStmt { 1101 do, body, end := p.parseDoBlockEnd() 1102 1103 return &ast.DoStmt{ 1104 Do: do, 1105 Body: body, 1106 EndPos: end, 1107 } 1108 } 1109 1110 func (p *parser) parseRepeatStmt() *ast.RepeatStmt { 1111 old := p.allowBreak 1112 1113 p.allowBreak = true 1114 1115 repeat, body, until := p.parseRepeatBlockUntil() 1116 1117 p.allowBreak = old 1118 1119 cond := p.parseRHS() 1120 1121 return &ast.RepeatStmt{ 1122 Repeat: repeat, 1123 Body: body, 1124 Until: until, 1125 Cond: cond, 1126 } 1127 } 1128 1129 func (p *parser) parseWhileStmt() *ast.WhileStmt { 1130 while := p.skip() 1131 1132 cond := p.parseRHS() 1133 1134 old := p.allowBreak 1135 1136 p.allowBreak = true 1137 1138 do, body, end := p.parseDoBlockEnd() 1139 1140 p.allowBreak = old 1141 1142 return &ast.WhileStmt{ 1143 While: while, 1144 Cond: cond, 1145 Do: do, 1146 Body: body, 1147 EndPos: end, 1148 } 1149 } 1150 1151 func (p *parser) parseIfStmt() *ast.IfStmt { 1152 _if := p.skip() 1153 1154 cond := p.parseRHS() 1155 1156 then, body := p.parseThenBlock() 1157 1158 stmt := &ast.IfStmt{ 1159 If: _if, 1160 Cond: cond, 1161 Then: then, 1162 Body: body, 1163 } 1164 1165 for { 1166 elseif := p.tok.Pos 1167 if !p.accept(token.ELSEIF) { 1168 break 1169 } 1170 1171 cond := p.parseRHS() 1172 then, body := p.parseThenBlock() 1173 1174 stmt.ElseIfList = append(stmt.ElseIfList, struct { 1175 If position.Position 1176 Cond ast.Expr 1177 Then position.Position 1178 Body *ast.Block 1179 }{ 1180 elseif, 1181 cond, 1182 then, 1183 body, 1184 }) 1185 } 1186 1187 if p.tok.Type == token.ELSE { 1188 stmt.Else = p.skip() 1189 stmt.ElseBody = p.parseBody(stmt.Else.Offset("else")) 1190 } 1191 1192 stmt.EndPos = p.expect(token.END) 1193 1194 return stmt 1195 } 1196 1197 func (p *parser) parseForStmt() ast.Stmt { 1198 _for := p.skip() 1199 1200 names := p.parseNameList() 1201 1202 var in, eq position.Position 1203 1204 if len(names) > 1 { 1205 in = p.expect(token.IN) 1206 goto foreach 1207 } 1208 1209 switch p.tok.Type { 1210 case token.ASSIGN: 1211 eq = p.tok.Pos 1212 p.next() 1213 case token.IN: 1214 in = p.tok.Pos 1215 p.next() 1216 goto foreach 1217 default: 1218 tok := p.tok 1219 1220 p.errorExpected(tok, "'=' or 'in'") 1221 1222 // syncStmt(p) 1223 1224 return &ast.BadStmt{From: tok.Pos, To: p.tok.Pos} 1225 } 1226 1227 // fornum 1228 { 1229 1230 start := p.parseRHS() 1231 1232 p.expect(token.COMMA) 1233 1234 finish := p.parseRHS() 1235 1236 var step ast.Expr 1237 1238 if p.accept(token.COMMA) { 1239 step = p.parseRHS() 1240 } 1241 1242 old := p.allowBreak 1243 1244 p.allowBreak = true 1245 1246 do, body, end := p.parseDoBlockEnd() 1247 1248 p.allowBreak = old 1249 1250 return &ast.ForStmt{ 1251 For: _for, 1252 Name: names[0], 1253 Equal: eq, 1254 Start: start, 1255 Finish: finish, 1256 Step: step, 1257 Do: do, 1258 Body: body, 1259 EndPos: end, 1260 } 1261 } 1262 1263 foreach: 1264 { 1265 exprs := p.parseRHSList() 1266 1267 old := p.allowBreak 1268 1269 p.allowBreak = true 1270 1271 do, body, end := p.parseDoBlockEnd() 1272 1273 p.allowBreak = old 1274 1275 return &ast.ForEachStmt{ 1276 For: _for, 1277 Names: names, 1278 In: in, 1279 Exprs: exprs, 1280 Do: do, 1281 Body: body, 1282 EndPos: end, 1283 } 1284 } 1285 } 1286 1287 func (p *parser) parseStmt() (s ast.Stmt) { 1288 switch p.tok.Type { 1289 case token.IF: 1290 s = p.parseIfStmt() 1291 case token.WHILE: 1292 s = p.parseWhileStmt() 1293 case token.DO: 1294 s = p.parseDoStmt() 1295 case token.FOR: 1296 s = p.parseForStmt() 1297 case token.REPEAT: 1298 s = p.parseRepeatStmt() 1299 case token.FUNCTION: 1300 s = p.parseFuncStmt() 1301 case token.LOCAL: 1302 s = p.parseLocalStmt() 1303 case token.SEMICOLON: 1304 s = &ast.EmptyStmt{Semicolon: p.tok.Pos} 1305 1306 p.next() 1307 case token.LABEL: 1308 s = p.parseLabelStmt() 1309 case token.RETURN: 1310 s = p.parseReturnStmt() 1311 case token.GOTO: 1312 s = p.parseGotoStmt() 1313 case token.BREAK: 1314 s = p.parseBreak() 1315 default: 1316 s = p.parseExprOrAssignStmt() 1317 } 1318 1319 return 1320 } 1321 1322 // ---------------------------------------------------------------------------- 1323 // Source files 1324 1325 func (p *parser) parseFile() *ast.File { 1326 chunk := p.parseChunk() 1327 1328 return &ast.File{ 1329 Filename: p.scanState.SourceName(), 1330 Shebang: p.scanState.Shebang(), 1331 Chunk: chunk, 1332 Comments: p.comments, 1333 } 1334 }