github.com/ladydascalie/elvish@v0.0.0-20170703214355-2964dd3ece7f/parse/parse.go (about) 1 // Package parse implements the elvish parser. 2 package parse 3 4 //go:generate ./boilerplate.py 5 //go:generate stringer -type=PrimaryType,RedirMode -output=string.go 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "unicode" 12 ) 13 14 // Parse parses Elvish source. If the error is not nil, it always has type 15 // ParseError. 16 func Parse(srcname, src string) (*Chunk, error) { 17 ps := NewParser(srcname, src) 18 n := ParseChunk(ps) 19 ps.Done() 20 return n, ps.Errors() 21 } 22 23 // Errors. 24 var ( 25 errUnexpectedRune = errors.New("unexpected rune") 26 errShouldBeForm = newError("", "form") 27 errBadLHS = errors.New("bad assignment LHS") 28 errDuplicateExitusRedir = newError("duplicate exitus redir") 29 errShouldBeThen = newError("", "then") 30 errShouldBeElifOrElseOrFi = newError("", "elif", "else", "fi") 31 errShouldBeFi = newError("", "fi") 32 errShouldBeTried = newError("", "tried") 33 errShouldBeDo = newError("", "do") 34 errShouldBeDone = newError("", "done") 35 errShouldBeIn = newError("", "in") 36 errShouldBePipelineSep = newError("", "';'", "newline") 37 errShouldBeEnd = newError("", "end") 38 errBadRedirSign = newError("bad redir sign", "'<'", "'>'", "'>>'", "'<>'") 39 errShouldBeFD = newError("", "a composite term representing fd") 40 errShouldBeFilename = newError("", "a composite term representing filename") 41 errShouldBeArray = newError("", "spaced") 42 errStringUnterminated = newError("string not terminated") 43 errInvalidEscape = newError("invalid escape sequence") 44 errInvalidEscapeOct = newError("invalid escape sequence", "octal digit") 45 errInvalidEscapeHex = newError("invalid escape sequence", "hex digit") 46 errInvalidEscapeControl = newError("invalid control sequence", "a rune between @ (0x40) and _(0x5F)") 47 errShouldBePrimary = newError("", 48 "single-quoted string", "double-quoted string", "bareword") 49 errShouldBeVariableName = newError("", "variable name") 50 errShouldBeRBracket = newError("", "']'") 51 errShouldBeRBrace = newError("", "'}'") 52 errShouldBeBraceSepOrRBracket = newError("", "','", "'}'") 53 errShouldBeRParen = newError("", "')'") 54 errShouldBeBackquoteOrLParen = newError("", "'`'", "'('") 55 errShouldBeBackquote = newError("", "'`'") 56 errShouldBeCompound = newError("", "compound") 57 errShouldBeEqual = newError("", "'='") 58 errArgListAllowNoSemicolon = newError("argument list doesn't allow semicolons") 59 ) 60 61 // Chunk = { PipelineSep | Space } { Pipeline { PipelineSep | Space } } 62 type Chunk struct { 63 node 64 Pipelines []*Pipeline 65 } 66 67 func (bn *Chunk) parse(ps *Parser) { 68 bn.parseSeps(ps) 69 for startsPipeline(ps.peek()) { 70 bn.addToPipelines(ParsePipeline(ps)) 71 if bn.parseSeps(ps) == 0 { 72 break 73 } 74 } 75 } 76 77 func isPipelineSep(r rune) bool { 78 return r == '\n' || r == ';' 79 } 80 81 // parseSeps parses pipeline separators along with whitespaces. It returns the 82 // number of pipeline separators parsed. 83 func (bn *Chunk) parseSeps(ps *Parser) int { 84 nseps := 0 85 for { 86 r := ps.peek() 87 if isPipelineSep(r) { 88 // parse as a Sep 89 parseSep(bn, ps, r) 90 nseps++ 91 } else if IsSpace(r) { 92 // parse a run of spaces as a Sep 93 parseSpaces(bn, ps) 94 } else if r == '#' { 95 // parse a comment as a Sep 96 for { 97 r := ps.peek() 98 if r == eof || r == '\n' { 99 break 100 } 101 ps.next() 102 } 103 addSep(bn, ps) 104 nseps++ 105 } else { 106 break 107 } 108 } 109 return nseps 110 } 111 112 // Pipeline = Form { '|' Form } 113 type Pipeline struct { 114 node 115 Forms []*Form 116 Background bool 117 } 118 119 func (pn *Pipeline) parse(ps *Parser) { 120 pn.addToForms(ParseForm(ps)) 121 for parseSep(pn, ps, '|') { 122 parseSpacesAndNewlines(pn, ps) 123 if !startsForm(ps.peek()) { 124 ps.error(errShouldBeForm) 125 return 126 } 127 pn.addToForms(ParseForm(ps)) 128 } 129 parseSpaces(pn, ps) 130 if ps.peek() == '&' { 131 ps.next() 132 addSep(pn, ps) 133 pn.Background = true 134 parseSpaces(pn, ps) 135 } 136 } 137 138 func startsPipeline(r rune) bool { 139 return startsForm(r) 140 } 141 142 // Form = { Space } { { Assignment } { Space } } 143 // { Compound } { Space } { ( Compound | MapPair | Redir | ExitusRedir ) { Space } } 144 type Form struct { 145 node 146 Assignments []*Assignment 147 Head *Compound 148 // Left-hand-sides for the spacey assignment. Right-hand-sides are in Args. 149 Vars []*Compound 150 Args []*Compound 151 Opts []*MapPair 152 Redirs []*Redir 153 ExitusRedir *ExitusRedir 154 } 155 156 func (fn *Form) parse(ps *Parser) { 157 parseSpaces(fn, ps) 158 for fn.tryAssignment(ps) { 159 parseSpaces(fn, ps) 160 } 161 162 // Parse head. 163 if !startsCompound(ps.peek(), true) { 164 if len(fn.Assignments) > 0 { 165 // Assignment-only form. 166 return 167 } 168 // Bad form. 169 ps.error(fmt.Errorf("bad rune at form head: %q", ps.peek())) 170 } 171 fn.setHead(ParseCompound(ps, true)) 172 parseSpaces(fn, ps) 173 174 for { 175 r := ps.peek() 176 switch { 177 case r == '&': 178 ps.next() 179 hasMapPair := startsCompound(ps.peek(), false) 180 ps.backup() 181 if !hasMapPair { 182 // background indicator 183 return 184 } 185 fn.addToOpts(ParseMapPair(ps)) 186 case startsCompound(r, false): 187 if ps.hasPrefix("?>") { 188 if fn.ExitusRedir != nil { 189 ps.error(errDuplicateExitusRedir) 190 // Parse the duplicate redir anyway. 191 addChild(fn, ParseExitusRedir(ps)) 192 } else { 193 fn.setExitusRedir(ParseExitusRedir(ps)) 194 } 195 continue 196 } 197 cn := ParseCompound(ps, false) 198 if isRedirSign(ps.peek()) { 199 // Redir 200 fn.addToRedirs(ParseRedir(ps, cn)) 201 } else if cn.sourceText == "=" { 202 // Spacey assignment. 203 // Turn the equal sign into a Sep. 204 addChild(fn, NewSep(ps.src, cn.begin, cn.end)) 205 // Turn the head and preceding arguments into LHSs. 206 addLHS := func(cn *Compound) { 207 if len(cn.Indexings) == 1 && checkVariableInAssignment(cn.Indexings[0].Head, ps) { 208 fn.Vars = append(fn.Vars, cn) 209 } else { 210 ps.errorp(cn.begin, cn.end, errBadLHS) 211 } 212 } 213 addLHS(fn.Head) 214 fn.Head = nil 215 for _, cn := range fn.Args { 216 addLHS(cn) 217 } 218 fn.Args = nil 219 } else { 220 fn.addToArgs(cn) 221 } 222 case isRedirSign(r): 223 fn.addToRedirs(ParseRedir(ps, nil)) 224 default: 225 return 226 } 227 parseSpaces(fn, ps) 228 } 229 } 230 231 // tryAssignment tries to parse an assignment. If succeeded, it adds the parsed 232 // assignment to fn.Assignments and returns true. Otherwise it rewinds the 233 // parser and returns false. 234 func (fn *Form) tryAssignment(ps *Parser) bool { 235 if !startsIndexing(ps.peek(), false) || ps.peek() == '=' { 236 return false 237 } 238 239 pos := ps.pos 240 errorEntries := ps.errors.Entries 241 an := ParseAssignment(ps) 242 // If errors were added, revert 243 if len(ps.errors.Entries) > len(errorEntries) { 244 ps.errors.Entries = errorEntries 245 ps.pos = pos 246 return false 247 } 248 fn.addToAssignments(an) 249 return true 250 } 251 252 func startsForm(r rune) bool { 253 return IsSpace(r) || startsCompound(r, true) 254 } 255 256 // Assignment = Indexing '=' Compound 257 type Assignment struct { 258 node 259 Left *Indexing 260 Right *Compound 261 } 262 263 func (an *Assignment) parse(ps *Parser) { 264 ps.cut('=') 265 an.setLeft(ParseIndexing(ps, false)) 266 head := an.Left.Head 267 if !checkVariableInAssignment(head, ps) { 268 ps.errorp(head.Begin(), head.End(), errShouldBeVariableName) 269 } 270 ps.uncut('=') 271 272 if !parseSep(an, ps, '=') { 273 ps.error(errShouldBeEqual) 274 } 275 an.setRight(ParseCompound(ps, false)) 276 } 277 278 func checkVariableInAssignment(p *Primary, ps *Parser) bool { 279 if p.Type == Braced { 280 // XXX don't check further inside braced expression 281 return true 282 } 283 if p.Type != Bareword && p.Type != SingleQuoted && p.Type != DoubleQuoted { 284 return false 285 } 286 if p.Value == "" { 287 return false 288 } 289 for _, r := range p.Value { 290 // XXX special case '&' and '@'. 291 if !allowedInVariableName(r) && r != '&' && r != '@' { 292 return false 293 } 294 } 295 return true 296 } 297 298 // ExitusRedir = '?' '>' { Space } Compound 299 type ExitusRedir struct { 300 node 301 Dest *Compound 302 } 303 304 func (ern *ExitusRedir) parse(ps *Parser) { 305 ps.next() 306 ps.next() 307 addSep(ern, ps) 308 parseSpaces(ern, ps) 309 ern.setDest(ParseCompound(ps, false)) 310 } 311 312 // Redir = { Compound } { '<'|'>'|'<>'|'>>' } { Space } ( '&'? Compound ) 313 type Redir struct { 314 node 315 Left *Compound 316 Mode RedirMode 317 RightIsFd bool 318 Right *Compound 319 } 320 321 func (rn *Redir) parse(ps *Parser, dest *Compound) { 322 // The parsing of the Left part is done in Form.parse. 323 if dest != nil { 324 rn.setLeft(dest) 325 rn.begin = dest.begin 326 } 327 328 begin := ps.pos 329 for isRedirSign(ps.peek()) { 330 ps.next() 331 } 332 sign := ps.src[begin:ps.pos] 333 switch sign { 334 case "<": 335 rn.Mode = Read 336 case ">": 337 rn.Mode = Write 338 case ">>": 339 rn.Mode = Append 340 case "<>": 341 rn.Mode = ReadWrite 342 default: 343 ps.error(errBadRedirSign) 344 } 345 addSep(rn, ps) 346 parseSpaces(rn, ps) 347 if parseSep(rn, ps, '&') { 348 rn.RightIsFd = true 349 } 350 rn.setRight(ParseCompound(ps, false)) 351 if len(rn.Right.Indexings) == 0 { 352 if rn.RightIsFd { 353 ps.error(errShouldBeFD) 354 } else { 355 ps.error(errShouldBeFilename) 356 } 357 return 358 } 359 } 360 361 func isRedirSign(r rune) bool { 362 return r == '<' || r == '>' 363 } 364 365 // RedirMode records the mode of an IO redirection. 366 type RedirMode int 367 368 // Possible values for RedirMode. 369 const ( 370 BadRedirMode RedirMode = iota 371 Read 372 Write 373 ReadWrite 374 Append 375 ) 376 377 // Compound = { Indexing } 378 type Compound struct { 379 node 380 Indexings []*Indexing 381 } 382 383 func (cn *Compound) parse(ps *Parser, head bool) { 384 cn.tilde(ps) 385 for startsIndexing(ps.peek(), head) { 386 cn.addToIndexings(ParseIndexing(ps, head)) 387 } 388 } 389 390 // tilde parses a tilde if there is one. It is implemented here instead of 391 // within Primary since a tilde can only appear as the first part of a 392 // Compound. Elsewhere tildes are barewords. 393 func (cn *Compound) tilde(ps *Parser) { 394 if ps.peek() == '~' { 395 ps.next() 396 base := node{nil, ps.pos - 1, ps.pos, "~", nil} 397 pn := &Primary{node: base, Type: Tilde, Value: "~"} 398 in := &Indexing{node: base} 399 in.setHead(pn) 400 cn.addToIndexings(in) 401 } 402 } 403 404 func startsCompound(r rune, head bool) bool { 405 return startsIndexing(r, head) 406 } 407 408 // Indexing = Primary { '[' Array ']' } 409 type Indexing struct { 410 node 411 Head *Primary 412 Indicies []*Array 413 } 414 415 func (in *Indexing) parse(ps *Parser, head bool) { 416 in.setHead(ParsePrimary(ps, head)) 417 for parseSep(in, ps, '[') { 418 if !startsArray(ps.peek()) { 419 ps.error(errShouldBeArray) 420 } 421 422 ps.pushCutset() 423 in.addToIndicies(ParseArray(ps, false)) 424 ps.popCutset() 425 426 if !parseSep(in, ps, ']') { 427 ps.error(errShouldBeRBracket) 428 return 429 } 430 } 431 } 432 433 func startsIndexing(r rune, head bool) bool { 434 return startsPrimary(r, head) 435 } 436 437 // Array = { Space | '\n' } { Compound { Space | '\n' } } 438 type Array struct { 439 node 440 Compounds []*Compound 441 // When non-empty, records the occurrences of semicolons by the indices of 442 // the compounds they appear before. For instance, [; ; a b; c d;] results 443 // in Semicolons={0 0 2 4}. 444 Semicolons []int 445 } 446 447 func (sn *Array) parse(ps *Parser, allowSemicolon bool) { 448 parseSep := func() { 449 parseSpacesAndNewlines(sn, ps) 450 if allowSemicolon { 451 for parseSep(sn, ps, ';') { 452 sn.Semicolons = append(sn.Semicolons, len(sn.Compounds)) 453 } 454 parseSpacesAndNewlines(sn, ps) 455 } 456 } 457 458 parseSep() 459 for startsCompound(ps.peek(), false) { 460 sn.addToCompounds(ParseCompound(ps, false)) 461 parseSep() 462 } 463 } 464 465 func IsSpace(r rune) bool { 466 return r == ' ' || r == '\t' 467 } 468 469 func startsArray(r rune) bool { 470 return IsSpaceOrNewline(r) || startsIndexing(r, false) 471 } 472 473 // Primary is the smallest expression unit. 474 type Primary struct { 475 node 476 Type PrimaryType 477 // The unquoted string value. Valid for Bareword, SingleQuoted, 478 // DoubleQuoted, Variable, Wildcard and Tilde. 479 Value string 480 List *Array // Valid for List and Lambda 481 Chunk *Chunk // Valid for OutputCapture, ExitusCapture and Lambda 482 MapPairs []*MapPair // Valid for Map 483 Braced []*Compound // Valid for Braced 484 IsRange []bool // Valid for Braced 485 } 486 487 // PrimaryType is the type of a Primary. 488 type PrimaryType int 489 490 // Possible values for PrimaryType. 491 const ( 492 BadPrimary PrimaryType = iota 493 Bareword 494 SingleQuoted 495 DoubleQuoted 496 Variable 497 Wildcard 498 Tilde 499 ExceptionCapture 500 OutputCapture 501 List 502 Lambda 503 Map 504 Braced 505 ) 506 507 func (pn *Primary) parse(ps *Parser, head bool) { 508 r := ps.peek() 509 if !startsPrimary(r, head) { 510 ps.error(errShouldBePrimary) 511 return 512 } 513 514 // Try bareword early, since it has precedence over wildcard on * 515 // when head is true. 516 if allowedInBareword(r, head) { 517 pn.bareword(ps, head) 518 return 519 } 520 521 switch r { 522 case '\'': 523 pn.singleQuoted(ps) 524 case '"': 525 pn.doubleQuoted(ps) 526 case '$': 527 pn.variable(ps) 528 case '*': 529 pn.wildcard(ps) 530 case '?': 531 if ps.hasPrefix("?(") { 532 pn.exitusCapture(ps) 533 } else { 534 pn.wildcard(ps) 535 } 536 case '(', '`': 537 pn.outputCapture(ps) 538 case '[': 539 pn.lbracket(ps) 540 case '{': 541 pn.lbrace(ps) 542 default: 543 // Parse an empty bareword. 544 pn.Type = Bareword 545 } 546 } 547 548 func (pn *Primary) singleQuoted(ps *Parser) { 549 pn.Type = SingleQuoted 550 ps.next() 551 var buf bytes.Buffer 552 defer func() { pn.Value = buf.String() }() 553 for { 554 switch r := ps.next(); r { 555 case eof: 556 ps.error(errStringUnterminated) 557 return 558 case '\'': 559 if ps.peek() == '\'' { 560 // Two consecutive single quotes 561 ps.next() 562 buf.WriteByte('\'') 563 } else { 564 // End of string 565 return 566 } 567 default: 568 buf.WriteRune(r) 569 } 570 } 571 } 572 573 func (pn *Primary) doubleQuoted(ps *Parser) { 574 pn.Type = DoubleQuoted 575 ps.next() 576 var buf bytes.Buffer 577 defer func() { pn.Value = buf.String() }() 578 for { 579 switch r := ps.next(); r { 580 case eof: 581 ps.error(errStringUnterminated) 582 return 583 case '"': 584 return 585 case '\\': 586 switch r := ps.next(); r { 587 case 'c', '^': 588 // Control sequence 589 r := ps.next() 590 if r < 0x40 || r >= 0x60 { 591 ps.backup() 592 ps.error(errInvalidEscapeControl) 593 ps.next() 594 } 595 buf.WriteByte(byte(r - 0x40)) 596 case 'x', 'u', 'U': 597 var n int 598 switch r { 599 case 'x': 600 n = 2 601 case 'u': 602 n = 4 603 case 'U': 604 n = 8 605 } 606 var rr rune 607 for i := 0; i < n; i++ { 608 d, ok := hexToDigit(ps.next()) 609 if !ok { 610 ps.backup() 611 ps.error(errInvalidEscapeHex) 612 break 613 } 614 rr = rr*16 + d 615 } 616 buf.WriteRune(rr) 617 case '0', '1', '2', '3', '4', '5', '6', '7': 618 // 2 more octal digits 619 rr := r - '0' 620 for i := 0; i < 2; i++ { 621 r := ps.next() 622 if r < '0' || r > '7' { 623 ps.backup() 624 ps.error(errInvalidEscapeOct) 625 break 626 } 627 rr = rr*8 + (r - '0') 628 } 629 buf.WriteRune(rr) 630 default: 631 if rr, ok := doubleEscape[r]; ok { 632 buf.WriteRune(rr) 633 } else { 634 ps.backup() 635 ps.error(errInvalidEscape) 636 ps.next() 637 } 638 } 639 default: 640 buf.WriteRune(r) 641 } 642 } 643 } 644 645 // a table for the simple double-quote escape sequences. 646 var doubleEscape = map[rune]rune{ 647 // same as golang 648 'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 649 't': '\t', 'v': '\v', '\\': '\\', '"': '"', 650 // additional 651 'e': '\033', 652 } 653 654 var doubleUnescape = map[rune]rune{} 655 656 func init() { 657 for k, v := range doubleEscape { 658 doubleUnescape[v] = k 659 } 660 } 661 662 func hexToDigit(r rune) (rune, bool) { 663 switch { 664 case '0' <= r && r <= '9': 665 return r - '0', true 666 case 'a' <= r && r <= 'f': 667 return r - 'a' + 10, true 668 case 'A' <= r && r <= 'F': 669 return r - 'A' + 10, true 670 default: 671 return -1, false 672 } 673 } 674 675 func (pn *Primary) variable(ps *Parser) { 676 pn.Type = Variable 677 defer func() { pn.Value = ps.src[pn.begin+1 : ps.pos] }() 678 ps.next() 679 // The character of the variable name can be anything. 680 if ps.next() == eof { 681 ps.backup() 682 ps.error(errShouldBeVariableName) 683 ps.next() 684 } 685 for allowedInVariableName(ps.peek()) { 686 ps.next() 687 } 688 } 689 690 // The following are allowed in variable names: 691 // * Anything beyond ASCII that is printable 692 // * Letters and numbers 693 // * The symbols "-_:&" 694 func allowedInVariableName(r rune) bool { 695 return (r >= 0x80 && unicode.IsPrint(r)) || 696 ('0' <= r && r <= '9') || 697 ('a' <= r && r <= 'z') || 698 ('A' <= r && r <= 'Z') || 699 r == '-' || r == '_' || r == ':' || r == '&' 700 } 701 702 func (pn *Primary) wildcard(ps *Parser) { 703 pn.Type = Wildcard 704 for isWildcard(ps.peek()) { 705 ps.next() 706 } 707 pn.Value = ps.src[pn.begin:ps.pos] 708 } 709 710 func isWildcard(r rune) bool { 711 return r == '*' || r == '?' 712 } 713 714 func (pn *Primary) exitusCapture(ps *Parser) { 715 ps.next() 716 ps.next() 717 addSep(pn, ps) 718 719 pn.Type = ExceptionCapture 720 721 ps.pushCutset() 722 pn.setChunk(ParseChunk(ps)) 723 ps.popCutset() 724 725 if !parseSep(pn, ps, ')') { 726 ps.error(errShouldBeRParen) 727 } 728 } 729 730 func (pn *Primary) outputCapture(ps *Parser) { 731 pn.Type = OutputCapture 732 733 var closer rune 734 var shouldBeCloser error 735 736 switch ps.next() { 737 case '(': 738 closer = ')' 739 shouldBeCloser = errShouldBeRParen 740 case '`': 741 closer = '`' 742 shouldBeCloser = errShouldBeBackquote 743 default: 744 ps.backup() 745 ps.error(errShouldBeBackquoteOrLParen) 746 ps.next() 747 return 748 } 749 addSep(pn, ps) 750 751 if closer == '`' { 752 ps.pushCutset(closer) 753 } else { 754 ps.pushCutset() 755 } 756 pn.setChunk(ParseChunk(ps)) 757 ps.popCutset() 758 759 if !parseSep(pn, ps, closer) { 760 ps.error(shouldBeCloser) 761 } 762 } 763 764 // List = '[' { Space } Array ']' 765 // Lambda = List '{' Chunk '}' 766 // Map = '[' { Space } '&' { Space } ']' 767 // = '[' { Space } { MapPair { Space } } ']' 768 769 func (pn *Primary) lbracket(ps *Parser) { 770 parseSep(pn, ps, '[') 771 parseSpacesAndNewlines(pn, ps) 772 773 r := ps.peek() 774 ps.pushCutset() 775 776 switch { 777 case r == '&': 778 pn.Type = Map 779 // parseSep(pn, ps, '&') 780 amp := ps.pos 781 ps.next() 782 r := ps.peek() 783 switch { 784 case IsSpace(r), r == ']', r == eof: 785 // '&' { Space } ']': '&' is a sep 786 addSep(pn, ps) 787 parseSpaces(pn, ps) 788 default: 789 // { MapPair { Space } } ']': Wind back 790 ps.pos = amp 791 for ps.peek() == '&' { 792 pn.addToMapPairs(ParseMapPair(ps)) 793 parseSpacesAndNewlines(pn, ps) 794 } 795 } 796 ps.popCutset() 797 if !parseSep(pn, ps, ']') { 798 ps.error(errShouldBeRBracket) 799 } 800 default: 801 pn.setList(ParseArray(ps, true)) 802 ps.popCutset() 803 804 if !parseSep(pn, ps, ']') { 805 ps.error(errShouldBeRBracket) 806 } 807 if parseSep(pn, ps, '{') { 808 if len(pn.List.Semicolons) > 0 { 809 ps.errorp(pn.List.Begin(), pn.List.End(), errArgListAllowNoSemicolon) 810 } 811 pn.lambda(ps) 812 } else { 813 pn.Type = List 814 } 815 } 816 } 817 818 // lambda parses a lambda expression. The opening brace has been seen. 819 func (pn *Primary) lambda(ps *Parser) { 820 pn.Type = Lambda 821 ps.pushCutset() 822 pn.setChunk(ParseChunk(ps)) 823 ps.popCutset() 824 if !parseSep(pn, ps, '}') { 825 ps.error(errShouldBeRBrace) 826 } 827 } 828 829 // Braced = '{' Compound { BracedSep Compounds } '}' 830 // BracedSep = { Space | '\n' } [ ',' ] { Space | '\n' } 831 func (pn *Primary) lbrace(ps *Parser) { 832 parseSep(pn, ps, '{') 833 834 if r := ps.peek(); r == ';' || r == '\n' || IsSpace(r) { 835 pn.lambda(ps) 836 return 837 } 838 839 pn.Type = Braced 840 841 ps.pushCutset() 842 defer ps.popCutset() 843 844 // XXX: The compound can be empty, which allows us to parse {,foo}. 845 // Allowing compounds to be empty can be fragile in other cases. 846 ps.cut(',') 847 pn.addToBraced(ParseCompound(ps, false)) 848 ps.uncut(',') 849 850 for isBracedSep(ps.peek()) { 851 parseSpacesAndNewlines(pn, ps) 852 // optional, so ignore the return value 853 parseSep(pn, ps, ',') 854 parseSpacesAndNewlines(pn, ps) 855 856 ps.cut(',') 857 pn.addToBraced(ParseCompound(ps, false)) 858 ps.uncut(',') 859 } 860 if !parseSep(pn, ps, '}') { 861 ps.error(errShouldBeBraceSepOrRBracket) 862 } 863 } 864 865 func isBracedSep(r rune) bool { 866 return r == ',' || IsSpaceOrNewline(r) 867 } 868 869 func (pn *Primary) bareword(ps *Parser, head bool) { 870 pn.Type = Bareword 871 defer func() { pn.Value = ps.src[pn.begin:ps.pos] }() 872 for allowedInBareword(ps.peek(), head) { 873 ps.next() 874 } 875 } 876 877 // The following are allowed in barewords: 878 // * Anything allowed in variable names, except & 879 // * The symbols "%+,./=@~!\" 880 // * The symbols "<>*^", if the bareword is in head 881 // 882 // The seemingly weird inclusion of \ is for easier path manipulation in 883 // Windows. 884 func allowedInBareword(r rune, head bool) bool { 885 return (r != '&' && allowedInVariableName(r)) || 886 r == '%' || r == '+' || r == ',' || r == '.' || 887 r == '/' || r == '=' || r == '@' || r == '~' || r == '!' || r == '\\' || 888 (head && (r == '<' || r == '>' || r == '*' || r == '^')) 889 } 890 891 func startsPrimary(r rune, head bool) bool { 892 return r == '\'' || r == '"' || r == '$' || allowedInBareword(r, head) || 893 r == '?' || r == '*' || r == '(' || r == '`' || r == '[' || r == '{' 894 } 895 896 // MapPair = '&' { Space } Compound { Space } Compound 897 type MapPair struct { 898 node 899 Key, Value *Compound 900 } 901 902 func (mpn *MapPair) parse(ps *Parser) { 903 parseSep(mpn, ps, '&') 904 905 // Parse key part, cutting on '='. 906 ps.cut('=') 907 mpn.setKey(ParseCompound(ps, false)) 908 if len(mpn.Key.Indexings) == 0 { 909 ps.error(errShouldBeCompound) 910 } 911 ps.uncut('=') 912 913 if parseSep(mpn, ps, '=') { 914 parseSpacesAndNewlines(mpn, ps) 915 // Parse value part. 916 mpn.setValue(ParseCompound(ps, false)) 917 // The value part can be empty. 918 } 919 } 920 921 // Sep is the catch-all node type for leaf nodes that lack internal structures 922 // and semantics, and serve solely for syntactic purposes. The parsing of 923 // separators depend on the Parent node; as such it lacks a genuine parse 924 // method. 925 type Sep struct { 926 node 927 } 928 929 func NewSep(src string, begin, end int) *Sep { 930 return &Sep{node{nil, begin, end, src[begin:end], nil}} 931 } 932 933 func addSep(n Node, ps *Parser) { 934 var begin int 935 ch := n.Children() 936 if len(ch) > 0 { 937 begin = ch[len(ch)-1].End() 938 } else { 939 begin = n.Begin() 940 } 941 addChild(n, NewSep(ps.src, begin, ps.pos)) 942 } 943 944 func parseSep(n Node, ps *Parser, sep rune) bool { 945 if ps.peek() == sep { 946 ps.next() 947 addSep(n, ps) 948 return true 949 } 950 return false 951 } 952 953 func parseSpaces(n Node, ps *Parser) { 954 if !IsSpace(ps.peek()) { 955 return 956 } 957 ps.next() 958 for IsSpace(ps.peek()) { 959 ps.next() 960 } 961 addSep(n, ps) 962 } 963 964 func parseSpacesAndNewlines(n Node, ps *Parser) { 965 // TODO parse comments here. 966 if !IsSpaceOrNewline(ps.peek()) { 967 return 968 } 969 ps.next() 970 for IsSpaceOrNewline(ps.peek()) { 971 ps.next() 972 } 973 addSep(n, ps) 974 } 975 976 func IsSpaceOrNewline(r rune) bool { 977 return IsSpace(r) || r == '\n' 978 } 979 980 func addChild(p Node, ch Node) { 981 p.n().children = append(p.n().children, ch) 982 ch.n().parent = p 983 }