mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-22 23:26:39 -08:00
fix(sbom): fix incompliant license format for spdx (#3335)
This commit is contained in:
102
pkg/licensing/expression/parser/parser.go
Normal file
102
pkg/licensing/expression/parser/parser.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/licensing/expression/lexer"
|
||||
"github.com/aquasecurity/trivy/pkg/licensing/expression/token"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidExpression = xerrors.New("invalid expression error")
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
lex *lexer.Lexer
|
||||
normalizeFn []NormalizeFunc
|
||||
}
|
||||
|
||||
type LicenseExpression struct {
|
||||
Node Node
|
||||
Operator string
|
||||
Next *LicenseExpression
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
License string
|
||||
LicenseExpression *LicenseExpression
|
||||
}
|
||||
|
||||
type NormalizeFunc func(n string) string
|
||||
|
||||
func New(lex *lexer.Lexer) *Parser {
|
||||
return &Parser{
|
||||
lex: lex,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) RegisterNormalizeFunc(fn ...NormalizeFunc) *Parser {
|
||||
p.normalizeFn = append(p.normalizeFn, fn...)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Parser) Parse() (*LicenseExpression, error) {
|
||||
root := &LicenseExpression{}
|
||||
cursor := root
|
||||
stack := Stack{}
|
||||
|
||||
for tok := p.lex.NextToken(); tok.Type != token.EOF; tok = p.lex.NextToken() {
|
||||
switch tok.Type {
|
||||
case token.IDENT:
|
||||
if cursor.Node.License == "" {
|
||||
cursor.Node = Node{License: tok.Literal}
|
||||
} else {
|
||||
cursor.Node.License = fmt.Sprintf("%s %s", cursor.Node.License, tok.Literal)
|
||||
}
|
||||
case token.AND, token.OR:
|
||||
cursor.Operator = string(tok.Type)
|
||||
cursor.Next = &LicenseExpression{}
|
||||
cursor = cursor.Next
|
||||
case token.LPAREN:
|
||||
p := Pair{root: root, cursor: cursor, bracket: tok.Type}
|
||||
stack.Push(p)
|
||||
root = &LicenseExpression{}
|
||||
cursor = root
|
||||
case token.RPAREN:
|
||||
e := stack.Pop()
|
||||
if e.bracket == token.LPAREN && tok.Type != token.RPAREN {
|
||||
return nil, ErrInvalidExpression
|
||||
}
|
||||
e.cursor.Node.LicenseExpression = root
|
||||
cursor = e.cursor
|
||||
root = e.root
|
||||
}
|
||||
}
|
||||
if !stack.IsEmpty() {
|
||||
return nil, ErrInvalidExpression
|
||||
}
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func (p *Parser) Normalize(l *LicenseExpression) string {
|
||||
cursor := l
|
||||
|
||||
var str string
|
||||
for ; cursor != nil; cursor = cursor.Next {
|
||||
str = strings.Join([]string{str, p.normalize(cursor.Node), cursor.Operator}, " ")
|
||||
}
|
||||
return strings.TrimSpace(str)
|
||||
}
|
||||
|
||||
func (p *Parser) normalize(n Node) string {
|
||||
if n.LicenseExpression != nil {
|
||||
return fmt.Sprintf("( %s )", p.Normalize(n.LicenseExpression))
|
||||
}
|
||||
for _, fn := range p.normalizeFn {
|
||||
n.License = fn(n.License)
|
||||
}
|
||||
return n.License
|
||||
}
|
||||
Reference in New Issue
Block a user