github.com/myhau/pulumi/pkg/v3@v3.70.2-0.20221116134521-f2775972e587/codegen/hcl2/syntax/parser.go (about)

     1  // Copyright 2016-2020, Pulumi Corporation.
     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  
    15  package syntax
    16  
    17  import (
    18  	"io"
    19  	"io/ioutil"
    20  
    21  	"github.com/hashicorp/hcl/v2"
    22  	"github.com/hashicorp/hcl/v2/hclsyntax"
    23  )
    24  
    25  // File represents a single parsed HCL2 source file.
    26  type File struct {
    27  	Name   string          // The name of the file.
    28  	Body   *hclsyntax.Body // The body of the parsed file.
    29  	Bytes  []byte          // The raw bytes of the source file.
    30  	Tokens TokenMap        // A map from syntax nodes to token information.
    31  }
    32  
    33  // Parser is a parser for HCL2 source files.
    34  type Parser struct {
    35  	Files       []*File         // The parsed files.
    36  	Diagnostics hcl.Diagnostics // The diagnostics, if any, produced during parsing.
    37  	tokens      tokenMap        // A map from syntax nodes to token information.
    38  }
    39  
    40  // NewParser creates a new HCL2 parser.
    41  func NewParser() *Parser {
    42  	return &Parser{tokens: tokenMap{}}
    43  }
    44  
    45  // ParseFile attempts to parse the contents of the given io.Reader as HCL2. If parsing fails, any diagnostics generated
    46  // will be added to the parser's diagnostics.
    47  func (p *Parser) ParseFile(r io.Reader, filename string) error {
    48  	src, err := ioutil.ReadAll(r)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	hclFile, diags := hclsyntax.ParseConfig(src, filename, hcl.Pos{})
    54  	if !diags.HasErrors() {
    55  		tokens, _ := hclsyntax.LexConfig(src, filename, hcl.Pos{})
    56  		mapTokens(tokens, filename, hclFile.Body.(*hclsyntax.Body), hclFile.Bytes, p.tokens, hcl.Pos{})
    57  	}
    58  
    59  	p.Files = append(p.Files, &File{
    60  		Name:   filename,
    61  		Body:   hclFile.Body.(*hclsyntax.Body),
    62  		Bytes:  hclFile.Bytes,
    63  		Tokens: p.tokens,
    64  	})
    65  	p.Diagnostics = append(p.Diagnostics, diags...)
    66  	return nil
    67  }
    68  
    69  // NewDiagnosticWriter creates a new diagnostic writer for the files parsed by the parser.
    70  func (p *Parser) NewDiagnosticWriter(w io.Writer, width uint, color bool) hcl.DiagnosticWriter {
    71  	return NewDiagnosticWriter(w, p.Files, width, color)
    72  }
    73  
    74  // NewDiagnosticWriter creates a new diagnostic writer for the given list of HCL2 files.
    75  func NewDiagnosticWriter(w io.Writer, files []*File, width uint, color bool) hcl.DiagnosticWriter {
    76  	fileMap := map[string]*hcl.File{}
    77  	for _, f := range files {
    78  		fileMap[f.Name] = &hcl.File{Body: f.Body, Bytes: f.Bytes}
    79  	}
    80  	return hcl.NewDiagnosticTextWriter(w, fileMap, width, color)
    81  }
    82  
    83  // ParseExpression attempts to parse the given string as an HCL2 expression.
    84  func ParseExpression(expression, filename string, start hcl.Pos) (hclsyntax.Expression, TokenMap, hcl.Diagnostics) {
    85  	source := []byte(expression)
    86  	hclExpression, diagnostics := hclsyntax.ParseExpression(source, filename, start)
    87  	if diagnostics.HasErrors() {
    88  		return nil, nil, diagnostics
    89  	}
    90  	tokens := tokenMap{}
    91  	hclTokens, _ := hclsyntax.LexExpression(source, filename, start)
    92  	mapTokens(hclTokens, filename, hclExpression, source, tokens, start)
    93  	return hclExpression, tokens, diagnostics
    94  }