1// Copyright 2014 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package parser 16 17import ( 18 "errors" 19 "fmt" 20 "io" 21 "sort" 22 "strconv" 23 "strings" 24 "text/scanner" 25) 26 27var errTooManyErrors = errors.New("too many errors") 28 29const maxErrors = 1 30 31const default_select_branch_name = "__soong_conditions_default__" 32const any_select_branch_name = "__soong_conditions_any__" 33 34type ParseError struct { 35 Err error 36 Pos scanner.Position 37} 38 39func (e *ParseError) Error() string { 40 return fmt.Sprintf("%s: %s", e.Pos, e.Err) 41} 42 43type File struct { 44 Name string 45 Defs []Definition 46 Comments []*CommentGroup 47} 48 49func parse(p *parser) (file *File, errs []error) { 50 defer func() { 51 if r := recover(); r != nil { 52 if r == errTooManyErrors { 53 errs = p.errors 54 return 55 } 56 panic(r) 57 } 58 }() 59 60 p.next() 61 defs := p.parseDefinitions() 62 p.accept(scanner.EOF) 63 errs = p.errors 64 comments := p.comments 65 66 return &File{ 67 Name: p.scanner.Filename, 68 Defs: defs, 69 Comments: comments, 70 }, errs 71 72} 73 74func ParseAndEval(filename string, r io.Reader, scope *Scope) (file *File, errs []error) { 75 file, errs = Parse(filename, r) 76 if len(errs) > 0 { 77 return nil, errs 78 } 79 80 // evaluate all module properties 81 var newDefs []Definition 82 for _, def := range file.Defs { 83 switch d := def.(type) { 84 case *Module: 85 for _, prop := range d.Map.Properties { 86 newval, err := prop.Value.Eval(scope) 87 if err != nil { 88 return nil, []error{err} 89 } 90 switch newval.(type) { 91 case *String, *Bool, *Int64, *Select, *Map, *List: 92 // ok 93 default: 94 panic(fmt.Sprintf("Evaled but got %#v\n", newval)) 95 } 96 prop.Value = newval 97 } 98 newDefs = append(newDefs, d) 99 case *Assignment: 100 if err := scope.HandleAssignment(d); err != nil { 101 return nil, []error{err} 102 } 103 } 104 } 105 106 // This is not strictly necessary, but removing the assignments from 107 // the result makes it clearer that this is an evaluated file. 108 // We could also consider adding a "EvaluatedFile" type to return. 109 file.Defs = newDefs 110 111 return file, nil 112} 113 114func Parse(filename string, r io.Reader) (file *File, errs []error) { 115 p := newParser(r) 116 p.scanner.Filename = filename 117 118 return parse(p) 119} 120 121func ParseExpression(r io.Reader) (value Expression, errs []error) { 122 p := newParser(r) 123 p.next() 124 value = p.parseExpression() 125 p.accept(scanner.EOF) 126 errs = p.errors 127 return 128} 129 130type parser struct { 131 scanner scanner.Scanner 132 tok rune 133 errors []error 134 comments []*CommentGroup 135} 136 137func newParser(r io.Reader) *parser { 138 p := &parser{} 139 p.scanner.Init(r) 140 p.scanner.Error = func(sc *scanner.Scanner, msg string) { 141 p.errorf(msg) 142 } 143 p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings | 144 scanner.ScanRawStrings | scanner.ScanComments 145 return p 146} 147 148func (p *parser) error(err error) { 149 pos := p.scanner.Position 150 if !pos.IsValid() { 151 pos = p.scanner.Pos() 152 } 153 err = &ParseError{ 154 Err: err, 155 Pos: pos, 156 } 157 p.errors = append(p.errors, err) 158 if len(p.errors) >= maxErrors { 159 panic(errTooManyErrors) 160 } 161} 162 163func (p *parser) errorf(format string, args ...interface{}) { 164 p.error(fmt.Errorf(format, args...)) 165} 166 167func (p *parser) accept(toks ...rune) bool { 168 for _, tok := range toks { 169 if p.tok != tok { 170 p.errorf("expected %s, found %s", scanner.TokenString(tok), 171 scanner.TokenString(p.tok)) 172 return false 173 } 174 p.next() 175 } 176 return true 177} 178 179func (p *parser) next() { 180 if p.tok != scanner.EOF { 181 p.tok = p.scanner.Scan() 182 if p.tok == scanner.Comment { 183 var comments []*Comment 184 for p.tok == scanner.Comment { 185 lines := strings.Split(p.scanner.TokenText(), "\n") 186 if len(comments) > 0 && p.scanner.Position.Line > comments[len(comments)-1].End().Line+1 { 187 p.comments = append(p.comments, &CommentGroup{Comments: comments}) 188 comments = nil 189 } 190 comments = append(comments, &Comment{lines, p.scanner.Position}) 191 p.tok = p.scanner.Scan() 192 } 193 p.comments = append(p.comments, &CommentGroup{Comments: comments}) 194 } 195 } 196} 197 198func (p *parser) parseDefinitions() (defs []Definition) { 199 for { 200 switch p.tok { 201 case scanner.Ident: 202 ident := p.scanner.TokenText() 203 pos := p.scanner.Position 204 205 p.accept(scanner.Ident) 206 207 switch p.tok { 208 case '+': 209 p.accept('+') 210 defs = append(defs, p.parseAssignment(ident, pos, "+=")) 211 case '=': 212 defs = append(defs, p.parseAssignment(ident, pos, "=")) 213 case '{', '(': 214 defs = append(defs, p.parseModule(ident, pos)) 215 default: 216 p.errorf("expected \"=\" or \"+=\" or \"{\" or \"(\", found %s", 217 scanner.TokenString(p.tok)) 218 } 219 case scanner.EOF: 220 return 221 default: 222 p.errorf("expected assignment or module definition, found %s", 223 scanner.TokenString(p.tok)) 224 return 225 } 226 } 227} 228 229func (p *parser) parseAssignment(name string, namePos scanner.Position, 230 assigner string) (assignment *Assignment) { 231 232 // These are used as keywords in select statements, prevent making variables 233 // with the same name to avoid any confusion. 234 switch name { 235 case "default", "unset": 236 p.errorf("'default' and 'unset' are reserved keywords, and cannot be used as variable names") 237 return nil 238 } 239 240 assignment = new(Assignment) 241 242 pos := p.scanner.Position 243 if !p.accept('=') { 244 return 245 } 246 value := p.parseExpression() 247 248 assignment.Name = name 249 assignment.NamePos = namePos 250 assignment.Value = value 251 assignment.EqualsPos = pos 252 assignment.Assigner = assigner 253 254 return 255} 256 257func (p *parser) parseModule(typ string, typPos scanner.Position) *Module { 258 259 compat := false 260 lbracePos := p.scanner.Position 261 if p.tok == '{' { 262 compat = true 263 } 264 265 if !p.accept(p.tok) { 266 return nil 267 } 268 properties := p.parsePropertyList(true, compat) 269 rbracePos := p.scanner.Position 270 if !compat { 271 p.accept(')') 272 } else { 273 p.accept('}') 274 } 275 276 return &Module{ 277 Type: typ, 278 TypePos: typPos, 279 Map: Map{ 280 Properties: properties, 281 LBracePos: lbracePos, 282 RBracePos: rbracePos, 283 }, 284 } 285} 286 287func (p *parser) parsePropertyList(isModule, compat bool) (properties []*Property) { 288 for p.tok == scanner.Ident { 289 properties = append(properties, p.parseProperty(isModule, compat)) 290 291 if p.tok != ',' { 292 // There was no comma, so the list is done. 293 break 294 } 295 296 p.accept(',') 297 } 298 299 return 300} 301 302func (p *parser) parseProperty(isModule, compat bool) (property *Property) { 303 property = new(Property) 304 305 name := p.scanner.TokenText() 306 namePos := p.scanner.Position 307 p.accept(scanner.Ident) 308 pos := p.scanner.Position 309 310 if isModule { 311 if compat { 312 if !p.accept(':') { 313 return 314 } 315 } else { 316 if !p.accept('=') { 317 return 318 } 319 } 320 } else { 321 if !p.accept(':') { 322 return 323 } 324 } 325 326 value := p.parseExpression() 327 328 property.Name = name 329 property.NamePos = namePos 330 property.Value = value 331 property.ColonPos = pos 332 333 return 334} 335 336func (p *parser) parseExpression() (value Expression) { 337 value = p.parseValue() 338 switch p.tok { 339 case '+': 340 return p.parseOperator(value) 341 case '-': 342 p.errorf("subtraction not supported: %s", p.scanner.String()) 343 return value 344 default: 345 return value 346 } 347} 348 349func (p *parser) parseOperator(value1 Expression) Expression { 350 operator := p.tok 351 pos := p.scanner.Position 352 p.accept(operator) 353 354 value2 := p.parseExpression() 355 356 return &Operator{ 357 Args: [2]Expression{value1, value2}, 358 Operator: operator, 359 OperatorPos: pos, 360 } 361} 362 363func (p *parser) parseValue() (value Expression) { 364 switch p.tok { 365 case scanner.Ident: 366 switch text := p.scanner.TokenText(); text { 367 case "true", "false": 368 return p.parseBoolean() 369 case "select": 370 return p.parseSelect() 371 default: 372 return p.parseVariable() 373 } 374 case '-', scanner.Int: // Integer might have '-' sign ahead ('+' is only treated as operator now) 375 return p.parseIntValue() 376 case scanner.String, scanner.RawString: 377 return p.parseStringValue() 378 case '[': 379 return p.parseListValue() 380 case '{': 381 return p.parseMapValue() 382 default: 383 p.errorf("expected bool, list, or string value; found %s", 384 scanner.TokenString(p.tok)) 385 return 386 } 387} 388 389func (p *parser) parseBoolean() Expression { 390 switch text := p.scanner.TokenText(); text { 391 case "true", "false": 392 result := &Bool{ 393 LiteralPos: p.scanner.Position, 394 Value: text == "true", 395 Token: text, 396 } 397 p.accept(scanner.Ident) 398 return result 399 default: 400 p.errorf("Expected true/false, got %q", text) 401 return nil 402 } 403} 404 405func (p *parser) parseVariable() Expression { 406 var value Expression 407 408 text := p.scanner.TokenText() 409 value = &Variable{ 410 Name: text, 411 NamePos: p.scanner.Position, 412 } 413 414 p.accept(scanner.Ident) 415 return value 416} 417 418func (p *parser) parseSelect() Expression { 419 result := &Select{ 420 KeywordPos: p.scanner.Position, 421 } 422 // Read the "select(" 423 p.accept(scanner.Ident) 424 if !p.accept('(') { 425 return nil 426 } 427 428 // If we see another '(', there's probably multiple conditions and there must 429 // be a ')' after. Set the multipleConditions variable to remind us to check for 430 // the ')' after. 431 multipleConditions := false 432 if p.tok == '(' { 433 multipleConditions = true 434 p.accept('(') 435 } 436 437 // Read all individual conditions 438 conditions := []ConfigurableCondition{} 439 for first := true; first || multipleConditions; first = false { 440 condition := ConfigurableCondition{ 441 position: p.scanner.Position, 442 FunctionName: p.scanner.TokenText(), 443 } 444 if !p.accept(scanner.Ident) { 445 return nil 446 } 447 if !p.accept('(') { 448 return nil 449 } 450 451 for p.tok != ')' { 452 if s := p.parseStringValue(); s != nil { 453 condition.Args = append(condition.Args, *s) 454 } else { 455 return nil 456 } 457 if p.tok == ')' { 458 break 459 } 460 if !p.accept(',') { 461 return nil 462 } 463 } 464 p.accept(')') 465 466 for _, c := range conditions { 467 if c.Equals(condition) { 468 p.errorf("Duplicate select condition found: %s", c.String()) 469 } 470 } 471 472 conditions = append(conditions, condition) 473 474 if multipleConditions { 475 if p.tok == ')' { 476 p.next() 477 break 478 } 479 if !p.accept(',') { 480 return nil 481 } 482 // Retry the closing parent to allow for a trailing comma 483 if p.tok == ')' { 484 p.next() 485 break 486 } 487 } 488 } 489 490 if multipleConditions && len(conditions) < 2 { 491 p.errorf("Expected multiple select conditions due to the extra parenthesis, but only found 1. Please remove the extra parenthesis.") 492 return nil 493 } 494 495 result.Conditions = conditions 496 497 if !p.accept(',') { 498 return nil 499 } 500 501 result.LBracePos = p.scanner.Position 502 if !p.accept('{') { 503 return nil 504 } 505 506 maybeParseBinding := func() (Variable, bool) { 507 if p.scanner.TokenText() != "@" { 508 return Variable{}, false 509 } 510 p.next() 511 value := Variable{ 512 Name: p.scanner.TokenText(), 513 NamePos: p.scanner.Position, 514 } 515 p.accept(scanner.Ident) 516 return value, true 517 } 518 519 parseOnePattern := func() SelectPattern { 520 var result SelectPattern 521 switch p.tok { 522 case scanner.Ident: 523 switch p.scanner.TokenText() { 524 case "any": 525 result.Value = &String{ 526 LiteralPos: p.scanner.Position, 527 Value: any_select_branch_name, 528 } 529 p.next() 530 if binding, exists := maybeParseBinding(); exists { 531 result.Binding = binding 532 } 533 return result 534 case "default": 535 result.Value = &String{ 536 LiteralPos: p.scanner.Position, 537 Value: default_select_branch_name, 538 } 539 p.next() 540 return result 541 case "true": 542 result.Value = &Bool{ 543 LiteralPos: p.scanner.Position, 544 Value: true, 545 } 546 p.next() 547 return result 548 case "false": 549 result.Value = &Bool{ 550 LiteralPos: p.scanner.Position, 551 Value: false, 552 } 553 p.next() 554 return result 555 default: 556 p.errorf("Expected a string, true, false, or default, got %s", p.scanner.TokenText()) 557 } 558 case scanner.String: 559 if s := p.parseStringValue(); s != nil { 560 if strings.HasPrefix(s.Value, "__soong") { 561 p.errorf("select branch patterns starting with __soong are reserved for internal use") 562 return result 563 } 564 result.Value = s 565 return result 566 } 567 fallthrough 568 default: 569 p.errorf("Expected a string, true, false, or default, got %s", p.scanner.TokenText()) 570 } 571 return result 572 } 573 574 hasNonUnsetValue := false 575 for p.tok != '}' { 576 c := &SelectCase{} 577 578 if multipleConditions { 579 if !p.accept('(') { 580 return nil 581 } 582 for i := 0; i < len(conditions); i++ { 583 c.Patterns = append(c.Patterns, parseOnePattern()) 584 if i < len(conditions)-1 { 585 if !p.accept(',') { 586 return nil 587 } 588 } else if p.tok == ',' { 589 // allow optional trailing comma 590 p.next() 591 } 592 } 593 if !p.accept(')') { 594 return nil 595 } 596 } else { 597 c.Patterns = append(c.Patterns, parseOnePattern()) 598 } 599 c.ColonPos = p.scanner.Position 600 if !p.accept(':') { 601 return nil 602 } 603 if p.tok == scanner.Ident && p.scanner.TokenText() == "unset" { 604 c.Value = &UnsetProperty{Position: p.scanner.Position} 605 p.accept(scanner.Ident) 606 } else { 607 hasNonUnsetValue = true 608 c.Value = p.parseExpression() 609 } 610 // allow trailing comma, require it if not seeing a } 611 if p.tok != '}' { 612 if !p.accept(',') { 613 return nil 614 } 615 } 616 result.Cases = append(result.Cases, c) 617 } 618 619 // If all branches have the value "unset", then this is equivalent 620 // to an empty select. 621 if !hasNonUnsetValue { 622 p.errorf("This select statement is empty, remove it") 623 return nil 624 } 625 626 patternsEqual := func(a, b SelectPattern) bool { 627 // We can ignore the bindings, they don't affect which pattern is matched 628 switch a2 := a.Value.(type) { 629 case *String: 630 if b2, ok := b.Value.(*String); ok { 631 return a2.Value == b2.Value 632 } else { 633 return false 634 } 635 case *Bool: 636 if b2, ok := b.Value.(*Bool); ok { 637 return a2.Value == b2.Value 638 } else { 639 return false 640 } 641 default: 642 // true so that we produce an error in this unexpected scenario 643 return true 644 } 645 } 646 647 patternListsEqual := func(a, b []SelectPattern) bool { 648 if len(a) != len(b) { 649 return false 650 } 651 for i := range a { 652 if !patternsEqual(a[i], b[i]) { 653 return false 654 } 655 } 656 return true 657 } 658 659 for i, c := range result.Cases { 660 // Check for duplicate patterns across different branches 661 for _, d := range result.Cases[i+1:] { 662 if patternListsEqual(c.Patterns, d.Patterns) { 663 p.errorf("Found duplicate select patterns: %v", c.Patterns) 664 return nil 665 } 666 } 667 // check for duplicate bindings within this branch 668 for i := range c.Patterns { 669 if c.Patterns[i].Binding.Name != "" { 670 for j := i + 1; j < len(c.Patterns); j++ { 671 if c.Patterns[i].Binding.Name == c.Patterns[j].Binding.Name { 672 p.errorf("Found duplicate select pattern binding: %s", c.Patterns[i].Binding.Name) 673 return nil 674 } 675 } 676 } 677 } 678 // Check that the only all-default cases is the last one 679 if i < len(result.Cases)-1 { 680 isAllDefault := true 681 for _, x := range c.Patterns { 682 if x2, ok := x.Value.(*String); !ok || x2.Value != default_select_branch_name { 683 isAllDefault = false 684 break 685 } 686 } 687 if isAllDefault { 688 p.errorf("Found a default select branch at index %d, expected it to be last (index %d)", i, len(result.Cases)-1) 689 return nil 690 } 691 } 692 } 693 694 result.RBracePos = p.scanner.Position 695 if !p.accept('}') { 696 return nil 697 } 698 if !p.accept(')') { 699 return nil 700 } 701 return result 702} 703 704func (p *parser) parseStringValue() *String { 705 str, err := strconv.Unquote(p.scanner.TokenText()) 706 if err != nil { 707 p.errorf("couldn't parse string: %s", err) 708 return nil 709 } 710 711 value := &String{ 712 LiteralPos: p.scanner.Position, 713 Value: str, 714 } 715 p.accept(p.tok) 716 return value 717} 718 719func (p *parser) parseIntValue() *Int64 { 720 var str string 721 literalPos := p.scanner.Position 722 if p.tok == '-' { 723 str += string(p.tok) 724 p.accept(p.tok) 725 if p.tok != scanner.Int { 726 p.errorf("expected int; found %s", scanner.TokenString(p.tok)) 727 return nil 728 } 729 } 730 str += p.scanner.TokenText() 731 i, err := strconv.ParseInt(str, 10, 64) 732 if err != nil { 733 p.errorf("couldn't parse int: %s", err) 734 return nil 735 } 736 737 value := &Int64{ 738 LiteralPos: literalPos, 739 Value: i, 740 Token: str, 741 } 742 p.accept(scanner.Int) 743 return value 744} 745 746func (p *parser) parseListValue() *List { 747 lBracePos := p.scanner.Position 748 if !p.accept('[') { 749 return nil 750 } 751 752 var elements []Expression 753 for p.tok != ']' { 754 element := p.parseExpression() 755 elements = append(elements, element) 756 757 if p.tok != ',' { 758 // There was no comma, so the list is done. 759 break 760 } 761 762 p.accept(',') 763 } 764 765 rBracePos := p.scanner.Position 766 p.accept(']') 767 768 return &List{ 769 LBracePos: lBracePos, 770 RBracePos: rBracePos, 771 Values: elements, 772 } 773} 774 775func (p *parser) parseMapValue() *Map { 776 lBracePos := p.scanner.Position 777 if !p.accept('{') { 778 return nil 779 } 780 781 properties := p.parsePropertyList(false, false) 782 783 rBracePos := p.scanner.Position 784 p.accept('}') 785 786 return &Map{ 787 LBracePos: lBracePos, 788 RBracePos: rBracePos, 789 Properties: properties, 790 } 791} 792 793type Scope struct { 794 vars map[string]*Assignment 795 preventInheriting map[string]bool 796 parentScope *Scope 797} 798 799func NewScope(s *Scope) *Scope { 800 return &Scope{ 801 vars: make(map[string]*Assignment), 802 preventInheriting: make(map[string]bool), 803 parentScope: s, 804 } 805} 806 807func (s *Scope) HandleAssignment(assignment *Assignment) error { 808 switch assignment.Assigner { 809 case "+=": 810 if !s.preventInheriting[assignment.Name] && s.parentScope.Get(assignment.Name) != nil { 811 return fmt.Errorf("modified non-local variable %q with +=", assignment.Name) 812 } 813 if old, ok := s.vars[assignment.Name]; !ok { 814 return fmt.Errorf("modified non-existent variable %q with +=", assignment.Name) 815 } else if old.Referenced { 816 return fmt.Errorf("modified variable %q with += after referencing", assignment.Name) 817 } else { 818 newValue, err := evaluateOperator(s, '+', old.Value, assignment.Value) 819 if err != nil { 820 return err 821 } 822 old.Value = newValue 823 } 824 case "=": 825 if old, ok := s.vars[assignment.Name]; ok { 826 return fmt.Errorf("variable already set, previous assignment: %s", old) 827 } 828 829 if old := s.parentScope.Get(assignment.Name); old != nil && !s.preventInheriting[assignment.Name] { 830 return fmt.Errorf("variable already set in inherited scope, previous assignment: %s", old) 831 } 832 833 if newValue, err := assignment.Value.Eval(s); err != nil { 834 return err 835 } else { 836 assignment.Value = newValue 837 } 838 s.vars[assignment.Name] = assignment 839 default: 840 return fmt.Errorf("Unknown assigner '%s'", assignment.Assigner) 841 } 842 return nil 843} 844 845func (s *Scope) Get(name string) *Assignment { 846 if s == nil { 847 return nil 848 } 849 if a, ok := s.vars[name]; ok { 850 return a 851 } 852 if s.preventInheriting[name] { 853 return nil 854 } 855 return s.parentScope.Get(name) 856} 857 858func (s *Scope) GetLocal(name string) *Assignment { 859 if s == nil { 860 return nil 861 } 862 if a, ok := s.vars[name]; ok { 863 return a 864 } 865 return nil 866} 867 868// DontInherit prevents this scope from inheriting the given variable from its 869// parent scope. 870func (s *Scope) DontInherit(name string) { 871 s.preventInheriting[name] = true 872} 873 874func (s *Scope) String() string { 875 var sb strings.Builder 876 s.stringInner(&sb) 877 return sb.String() 878} 879 880func (s *Scope) stringInner(sb *strings.Builder) { 881 if s == nil { 882 return 883 } 884 vars := make([]string, 0, len(s.vars)) 885 for k := range s.vars { 886 vars = append(vars, k) 887 } 888 889 sort.Strings(vars) 890 891 for _, v := range vars { 892 sb.WriteString(s.vars[v].String()) 893 sb.WriteRune('\n') 894 } 895 896 s.parentScope.stringInner(sb) 897} 898