From e59ec59b027f921a6bfbe5014b15c2a802445ada Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Wed, 29 Nov 2023 16:01:41 +0100 Subject: pkg/ast: support expressions with ast.Type So far they have the following grammar: OP = "==", "!=", "&" value-expr = value-expr OP value-expr | factor factor = "(" and-expr ")" | integer | identifier | string Operators are left associative, e.g. A & B & C is the same as (A & B) & C. Further restrictions will be imposed in pkg/compiler. This will help implement conditionally included fields. --- pkg/ast/parser.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'pkg/ast/parser.go') diff --git a/pkg/ast/parser.go b/pkg/ast/parser.go index c87d43f5e..2f2e62055 100644 --- a/pkg/ast/parser.go +++ b/pkg/ast/parser.go @@ -433,7 +433,58 @@ func (p *parser) parseField(parseAttrs bool) *Field { return field } +type operatorInfo struct { + op Operator + prio int +} + +const maxOperatorPrio = 1 + +// The highest priority is 0. +var binaryOperators = map[token]operatorInfo{ + tokCmpEq: {op: OperatorCompareEq, prio: 0}, + tokCmpNeq: {op: OperatorCompareNeq, prio: 0}, + tokBinAnd: {op: OperatorBinaryAnd, prio: 1}, +} + +// Parse out a single Type object, which can either be a plain object or an expression. +// For now, only expressions constructed via '(', ')', "==", "!=", '&' are supported. func (p *parser) parseType() *Type { + return p.parseBinaryExpr(0) +} + +func (p *parser) parseBinaryExpr(expectPrio int) *Type { + if expectPrio > maxOperatorPrio { + return p.parseExprFactor() + } + lastPos := p.pos + curr := p.parseBinaryExpr(expectPrio + 1) + for { + info, ok := binaryOperators[p.tok] + if !ok || info.prio != expectPrio { + return curr + } + p.consume(p.tok) + curr = &Type{ + Pos: lastPos, + Expression: &BinaryExpression{ + Pos: p.pos, + Operator: info.op, + Left: curr, + Right: p.parseBinaryExpr(expectPrio + 1), + }, + } + lastPos = p.pos + } +} + +func (p *parser) parseExprFactor() *Type { + if p.tok == tokLParen { + p.consume(tokLParen) + ret := p.parseBinaryExpr(0) + p.consume(tokRParen) + return ret + } arg := &Type{ Pos: p.pos, } -- cgit mrf-deployment