mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-22 23:26:39 -08:00
103 lines
2.2 KiB
Go
103 lines
2.2 KiB
Go
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
|
|
}
|