Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/blueprint/parser/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 12 kB image not shown  

Quelle  printer.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package parser

import (
 "fmt"
 "strconv"
 "strings"
 "text/scanner"
 "unicode"
)

var noPos scanner.Position

type printer struct {
 defs     []Definition
 comments []*CommentGroup

 curComment int

 pos scanner.Position

 pendingSpace   bool
 pendingNewline int

 output []byte

 indentList []int
 wsBuf      []byte

 skippedComments []*CommentGroup
}

func newPrinter(file *File) *printer {
 return &printer{
  defs:       file.Defs,
  comments:   file.Comments,
  indentList: []int{0},

  // pendingNewLine is initialized to -1 to eat initial spaces if the first token is a comment
  pendingNewline: -1,

  pos: scanner.Position{
   Line: 1,
  },
 }
}

func Print(file *File) ([]byte, error) {
 p := newPrinter(file)

 for _, def := range p.defs {
  p.printDef(def)
 }
 p.flush()
 return p.output, nil
}

func PrintExpression(expression Expression) ([]byte, error) {
 dummyFile := &File{}
 p := newPrinter(dummyFile)
 p.printExpression(expression)
 p.flush()
 return p.output, nil
}

func (p *printer) Print() ([]byte, error) {
 for _, def := range p.defs {
  p.printDef(def)
 }
 p.flush()
 return p.output, nil
}

func (p *printer) printDef(def Definition) {
 if assignment, ok := def.(*Assignment); ok {
  p.printAssignment(assignment)
 } else if module, ok := def.(*Module); ok {
  p.printModule(module)
 } else {
  panic("Unknown definition")
 }
}

func (p *printer) printAssignment(assignment *Assignment) {
 p.printToken(assignment.Name, assignment.NamePos)
 p.requestSpace()
 p.printToken(assignment.Assigner, assignment.EqualsPos)
 p.requestSpace()
 p.printExpression(assignment.Value)
 p.requestNewline()
}

func (p *printer) printModule(module *Module) {
 p.printToken(module.Type, module.TypePos)
 p.printMap(&module.Map)
 p.requestDoubleNewline()
}

func (p *printer) printExpression(value Expression) {
 switch v := value.(type) {
 case *Variable:
  p.printToken(v.Name, v.NamePos)
 case *Operator:
  p.printOperator(v)
 case *Bool:
  var s string
  if v.Value {
   s = "true"
  } else {
   s = "false"
  }
  p.printToken(s, v.LiteralPos)
 case *Int64:
  p.printToken(strconv.FormatInt(v.Value, 10), v.LiteralPos)
 case *String:
  p.printToken(strconv.Quote(v.Value), v.LiteralPos)
 case *List:
  p.printList(v.Values, v.LBracePos, v.RBracePos)
 case *Map:
  p.printMap(v)
 case *Select:
  p.printSelect(v)
 default:
  panic(fmt.Errorf("bad property type: %v", value))
 }
}

func (p *printer) printSelect(s *Select) {
 print_append := func() {
  if s.Append != nil {
   p.requestSpace()
   p.printToken("+", s.RBracePos)
   p.requestSpace()
   p.printExpression(s.Append)
  }
 }
 if len(s.Cases) == 0 {
  print_append()
  return
 }
 if len(s.Cases) == 1 && len(s.Cases[0].Patterns) == 1 {
  if str, ok := s.Cases[0].Patterns[0].Value.(*String); ok && str.Value == default_select_branch_name {
   p.printExpression(s.Cases[0].Value)
   p.pos = s.RBracePos
   print_append()
   return
  }
 }
 if len(s.Cases) == 1 && len(s.Cases[0].Patterns) == 0 {
  p.printExpression(s.Cases[0].Value)
  p.pos = s.RBracePos
  print_append()
  return
 }
 p.requestSpace()
 p.printToken("select(", s.KeywordPos)
 multilineConditions := false
 if len(s.Conditions) > 1 {
  p.printToken("(", s.KeywordPos)
  if s.Conditions[len(s.Conditions)-1].position.Line > s.KeywordPos.Line {
   multilineConditions = true
   p.requestNewline()
   p.indent(p.curIndent() + 4)
  }
 }
 for i, c := range s.Conditions {
  p.printToken(c.FunctionName, c.position)
  p.printToken("(", c.position)
  for i, arg := range c.Args {
   p.printToken(strconv.Quote(arg.Value), arg.LiteralPos)
   if i < len(c.Args)-1 {
    p.printToken(",", arg.LiteralPos)
    p.requestSpace()
   }
  }
  p.printToken(")", p.pos)
  if len(s.Conditions) > 1 {
   if multilineConditions {
    p.printToken(",", p.pos)
    p.requestNewline()
   } else if i < len(s.Conditions)-1 {
    p.printToken(",", p.pos)
    p.requestSpace()
   }
  }
 }
 if len(s.Conditions) > 1 {
  if multilineConditions {
   p.unindent(p.pos)
  }
  p.printToken(")", p.pos)
 }
 p.printToken(", {", s.LBracePos)
 p.requestNewline()
 p.indent(p.curIndent() + 4)
 for _, c := range s.Cases {
  p.requestNewline()
  if len(c.Patterns) > 1 {
   p.printToken("(", p.pos)
  }
  for i, pat := range c.Patterns {
   p.printSelectPattern(pat)
   if i < len(c.Patterns)-1 {
    p.printToken(",", p.pos)
    p.requestSpace()
   }
  }
  if len(c.Patterns) > 1 {
   p.printToken(")", p.pos)
  }
  p.printToken(":", c.ColonPos)
  p.requestSpace()
  if unset, ok := c.Value.(*UnsetProperty); ok {
   p.printToken(unset.String(), unset.Pos())
  } else {
   p.printExpression(c.Value)
  }
  p.printToken(",", c.Value.End())
 }
 p.requestNewline()
 p.unindent(s.RBracePos)
 p.printToken("})", s.RBracePos)
 print_append()
}

func (p *printer) printSelectPattern(pat SelectPattern) {
 switch pat := pat.Value.(type) {
 case *String:
  if pat.Value == default_select_branch_name {
   p.printToken("default", pat.LiteralPos)
  } else if pat.Value == any_select_branch_name {
   p.printToken("any", pat.LiteralPos)
  } else {
   p.printToken(strconv.Quote(pat.Value), pat.LiteralPos)
  }
 case *Bool:
  s := "false"
  if pat.Value {
   s = "true"
  }
  p.printToken(s, pat.LiteralPos)
 default:
  panic("Unhandled case")
 }
 if pat.Binding.Name != "" {
  p.requestSpace()
  p.printToken("@", pat.Binding.Pos())
  p.requestSpace()
  p.printExpression(&pat.Binding)
 }
}

func (p *printer) printList(list []Expression, pos, endPos scanner.Position) {
 p.requestSpace()
 p.printToken("[", pos)
 if len(list) > 1 || pos.Line != endPos.Line || listHasMap(list) {
  p.requestNewline()
  p.indent(p.curIndent() + 4)
  for _, value := range list {
   if sv, ok := value.(*String); ok && sv.Deleted {
    p.pos = sv.LiteralPos
    continue
   }
   p.printExpression(value)
   p.printToken(",", noPos)
   p.requestNewline()
  }
  p.unindent(endPos)
 } else {
  for _, value := range list {
   if sv, ok := value.(*String); ok && sv.Deleted {
    p.pos = sv.LiteralPos
    continue
   }
   p.printExpression(value)
  }
 }
 p.printToken("]", endPos)
}

func (p *printer) printMap(m *Map) {
 p.requestSpace()
 p.printToken("{", m.LBracePos)
 if len(m.Properties) > 0 || m.LBracePos.Line != m.RBracePos.Line {
  p.requestNewline()
  p.indent(p.curIndent() + 4)
  for _, prop := range m.Properties {
   if prop.Deleted {
    p.pos = prop.End()
    continue
   }
   p.printProperty(prop)
   p.printToken(",", noPos)
   p.requestNewline()
  }
  p.unindent(m.RBracePos)
 }
 p.printToken("}", m.RBracePos)
}

func (p *printer) printOperator(operator *Operator) {
 p.printOperatorInternal(operator, true)
}

func (p *printer) printOperatorInternal(operator *Operator, allowIndent bool) {
 p.printExpression(operator.Args[0])
 p.requestSpace()
 p.printToken(string(operator.Operator), operator.OperatorPos)

 indented := false
 if operator.Args[0].End().Line == operator.Args[1].Pos().Line {
  p.requestSpace()
 } else {
  if allowIndent {
   indented = true
   p.indent(p.curIndent() + 4)
  }
  p.requestNewline()
 }

 if op, isOp := operator.Args[1].(*Operator); isOp {
  p.printOperatorInternal(op, false)
 } else {
  p.printExpression(operator.Args[1])
 }

 if indented {
  p.unindent(p.pos)
 }
}

func (p *printer) printProperty(property *Property) {
 p.printToken(property.Name, property.NamePos)
 p.printToken(":", property.ColonPos)
 p.requestSpace()
 p.printExpression(property.Value)
}

// Print a single token, including any necessary comments or whitespace between
// this token and the previously printed token
func (p *printer) printToken(s string, pos scanner.Position) {
 newline := p.pendingNewline != 0

 if pos == noPos {
  pos = p.pos
 }

 if newline {
  p.printEndOfLineCommentsBefore(pos)
  p.requestNewlinesForPos(pos)
 }

 p.printInLineCommentsBefore(pos)

 p.flushSpace()

 p.output = append(p.output, s...)

 p.pos = pos
}

// Print any in-line (single line /* */) comments that appear _before_ pos
func (p *printer) printInLineCommentsBefore(pos scanner.Position) {
 for p.curComment < len(p.comments) && p.comments[p.curComment].Pos().Offset < pos.Offset {
  c := p.comments[p.curComment]
  if c.Comments[0].Comment[0][0:2] == "//" || len(c.Comments[0].Comment) > 1 {
   p.skippedComments = append(p.skippedComments, c)
  } else {
   p.printComment(c)
   p.requestSpace()
  }
  p.curComment++
 }
}

// Print any comments, including end of line comments, that appear _before_ the line specified
// by pos
func (p *printer) printEndOfLineCommentsBefore(pos scanner.Position) {
 if len(p.skippedComments) > 0 {
  for _, c := range p.skippedComments {
   p.printComment(c)
   p._requestNewline()
  }
  p.skippedComments = nil
 }
 for p.curComment < len(p.comments) && p.comments[p.curComment].Pos().Line < pos.Line {
  c := p.comments[p.curComment]
  p.printComment(c)
  p._requestNewline()
  p.curComment++
 }
}

// Compare the line numbers of the previous and current positions to determine whether extra
// newlines should be inserted.  A second newline is allowed anywhere requestNewline() is called.
func (p *printer) requestNewlinesForPos(pos scanner.Position) bool {
 if pos.Line > p.pos.Line {
  p._requestNewline()
  if pos.Line > p.pos.Line+1 {
   p.pendingNewline = 2
  }
  return true
 }

 return false
}

func (p *printer) requestSpace() {
 p.pendingSpace = true
}

// Ask for a newline to be inserted before the next token, but do not insert any comments.  Used
// by the comment printers.
func (p *printer) _requestNewline() {
 if p.pendingNewline == 0 {
  p.pendingNewline = 1
 }
}

// Ask for a newline to be inserted before the next token.  Also inserts any end-of line comments
// for the current line
func (p *printer) requestNewline() {
 pos := p.pos
 pos.Line++
 p.printEndOfLineCommentsBefore(pos)
 p._requestNewline()
}

// Ask for two newlines to be inserted before the next token.  Also inserts any end-of line comments
// for the current line
func (p *printer) requestDoubleNewline() {
 p.requestNewline()
 p.pendingNewline = 2
}

// Flush any pending whitespace, ignoring pending spaces if there is a pending newline
func (p *printer) flushSpace() {
 if p.pendingNewline == 1 {
  p.output = append(p.output, '\n')
  p.pad(p.curIndent())
 } else if p.pendingNewline == 2 {
  p.output = append(p.output, "\n\n"...)
  p.pad(p.curIndent())
 } else if p.pendingSpace == true && p.pendingNewline != -1 {
  p.output = append(p.output, ' ')
 }

 p.pendingSpace = false
 p.pendingNewline = 0
}

// Print a single comment, which may be a multi-line comment
func (p *printer) printComment(cg *CommentGroup) {
 for _, comment := range cg.Comments {
  if !p.requestNewlinesForPos(comment.Pos()) {
   p.requestSpace()
  }
  for i, line := range comment.Comment {
   line = strings.TrimRightFunc(line, unicode.IsSpace)
   p.flushSpace()
   if i != 0 {
    lineIndent := strings.IndexFunc(line, func(r rune) bool { return !unicode.IsSpace(r) })
    lineIndent = max(lineIndent, p.curIndent())
    p.pad(lineIndent - p.curIndent())
   }
   p.output = append(p.output, strings.TrimSpace(line)...)
   if i < len(comment.Comment)-1 {
    p._requestNewline()
   }
  }
  if p.pos.Offset < comment.End().Offset {
   p.pos = comment.End()
  }
 }
}

// Print any comments that occur after the last token, and a trailing newline
func (p *printer) flush() {
 for _, c := range p.skippedComments {
  if !p.requestNewlinesForPos(c.Pos()) {
   p.requestSpace()
  }
  p.printComment(c)
 }
 for p.curComment < len(p.comments) {
  p.printComment(p.comments[p.curComment])
  p.curComment++
 }
 p.output = append(p.output, '\n')
}

// Print whitespace to pad from column l to column max
func (p *printer) pad(l int) {
 if l > len(p.wsBuf) {
  p.wsBuf = make([]byte, l)
  for i := range p.wsBuf {
   p.wsBuf[i] = ' '
  }
 }
 p.output = append(p.output, p.wsBuf[0:l]...)
}

func (p *printer) indent(i int) {
 p.indentList = append(p.indentList, i)
}

func (p *printer) unindent(pos scanner.Position) {
 p.printEndOfLineCommentsBefore(pos)
 p.indentList = p.indentList[0 : len(p.indentList)-1]
}

func (p *printer) curIndent() int {
 return p.indentList[len(p.indentList)-1]
}

func max(a, b int) int {
 if a > b {
  return a
 } else {
  return b
 }
}

func listHasMap(list []Expression) bool {
 for _, value := range list {
  if _, ok := value.(*Map); ok {
   return true
  }
 }
 return false
}

[Dauer der Verarbeitung: 0.20 Sekunden, vorverarbeitet 2026-06-28]