1// Package parser2v1 contains functions to read, load and parse 2// SPDX tag-value files. 3// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 4package parser2v1 5 6import ( 7 "fmt" 8 9 "github.com/spdx/tools-golang/spdx/common" 10 "github.com/spdx/tools-golang/spdx/v2_1" 11 "github.com/spdx/tools-golang/tvloader/reader" 12) 13 14// ParseTagValues takes a list of (tag, value) pairs, parses it and returns 15// a pointer to a parsed SPDX Document. 16func ParseTagValues(tvs []reader.TagValuePair) (*v2_1.Document, error) { 17 parser := tvParser2_1{} 18 for _, tv := range tvs { 19 err := parser.parsePair2_1(tv.Tag, tv.Value) 20 if err != nil { 21 return nil, err 22 } 23 } 24 if parser.file != nil && parser.file.FileSPDXIdentifier == nullSpdxElementId2_1 { 25 return nil, fmt.Errorf("file with FileName %s does not have SPDX identifier", parser.file.FileName) 26 } 27 if parser.pkg != nil && parser.pkg.PackageSPDXIdentifier == nullSpdxElementId2_1 { 28 return nil, fmt.Errorf("package with PackageName %s does not have SPDX identifier", parser.pkg.PackageName) 29 } 30 31 return parser.doc, nil 32} 33 34func (parser *tvParser2_1) parsePair2_1(tag string, value string) error { 35 switch parser.st { 36 case psStart2_1: 37 return parser.parsePairFromStart2_1(tag, value) 38 case psCreationInfo2_1: 39 return parser.parsePairFromCreationInfo2_1(tag, value) 40 case psPackage2_1: 41 return parser.parsePairFromPackage2_1(tag, value) 42 case psFile2_1: 43 return parser.parsePairFromFile2_1(tag, value) 44 case psSnippet2_1: 45 return parser.parsePairFromSnippet2_1(tag, value) 46 case psOtherLicense2_1: 47 return parser.parsePairFromOtherLicense2_1(tag, value) 48 case psReview2_1: 49 return parser.parsePairFromReview2_1(tag, value) 50 default: 51 return fmt.Errorf("parser state %v not recognized when parsing (%s, %s)", parser.st, tag, value) 52 } 53} 54 55func (parser *tvParser2_1) parsePairFromStart2_1(tag string, value string) error { 56 // fail if not in Start parser state 57 if parser.st != psStart2_1 { 58 return fmt.Errorf("got invalid state %v in parsePairFromStart2_1", parser.st) 59 } 60 61 // create an SPDX Document data struct if we don't have one already 62 if parser.doc == nil { 63 parser.doc = &v2_1.Document{ 64 ExternalDocumentReferences: []v2_1.ExternalDocumentRef{}, 65 } 66 } 67 68 switch tag { 69 case "SPDXVersion": 70 parser.doc.SPDXVersion = value 71 case "DataLicense": 72 parser.doc.DataLicense = value 73 case "SPDXID": 74 eID, err := extractElementID(value) 75 if err != nil { 76 return err 77 } 78 parser.doc.SPDXIdentifier = eID 79 case "DocumentName": 80 parser.doc.DocumentName = value 81 case "DocumentNamespace": 82 parser.doc.DocumentNamespace = value 83 case "ExternalDocumentRef": 84 documentRefID, uri, alg, checksum, err := extractExternalDocumentReference(value) 85 if err != nil { 86 return err 87 } 88 edr := v2_1.ExternalDocumentRef{ 89 DocumentRefID: documentRefID, 90 URI: uri, 91 Checksum: common.Checksum{Algorithm: common.ChecksumAlgorithm(alg), Value: checksum}, 92 } 93 parser.doc.ExternalDocumentReferences = append(parser.doc.ExternalDocumentReferences, edr) 94 case "DocumentComment": 95 parser.doc.DocumentComment = value 96 default: 97 // move to Creation Info parser state 98 parser.st = psCreationInfo2_1 99 return parser.parsePairFromCreationInfo2_1(tag, value) 100 } 101 102 return nil 103} 104