diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2023-11-29 16:01:41 +0100 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2024-02-19 11:54:01 +0000 |
| commit | e59ec59b027f921a6bfbe5014b15c2a802445ada (patch) | |
| tree | 1c69d1db1b34e0b53d620f9fe272cf9f374b1400 /pkg/ast/format.go | |
| parent | 164800ebad7f26d05eefb0095d190462ed97bee0 (diff) | |
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.
Diffstat (limited to 'pkg/ast/format.go')
| -rw-r--r-- | pkg/ast/format.go | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/pkg/ast/format.go b/pkg/ast/format.go index 420eac916..4b54466c2 100644 --- a/pkg/ast/format.go +++ b/pkg/ast/format.go @@ -194,6 +194,12 @@ func (n *Type) serialize(w io.Writer) { } func fmtType(t *Type) string { + var sb strings.Builder + fmtExpressionRec(&sb, t, -1) + return sb.String() +} + +func fmtEndType(t *Type) string { v := "" switch { case t.Ident != "": @@ -247,6 +253,45 @@ func fmtInt(i *Int) string { } } +func fmtExpressionRec(sb *strings.Builder, t *Type, parentPrio int) { + if t.Expression == nil { + sb.WriteString(fmtEndType(t)) + return + } + be := t.Expression + myPrio := operatorPrio(be.Operator) + parentheses := myPrio < parentPrio + if parentheses { + sb.WriteByte('(') + } + fmtExpressionRec(sb, be.Left, myPrio) + sb.WriteByte(' ') + switch be.Operator { + case OperatorCompareEq: + sb.WriteString("==") + case OperatorCompareNeq: + sb.WriteString("!=") + case OperatorBinaryAnd: + sb.WriteString("&") + default: + panic(fmt.Sprintf("unknown operator %q", be.Operator)) + } + sb.WriteByte(' ') + fmtExpressionRec(sb, be.Right, myPrio) + if parentheses { + sb.WriteByte(')') + } +} + +func operatorPrio(op Operator) int { + for _, info := range binaryOperators { + if info.op == op { + return info.prio + } + } + panic(fmt.Sprintf("unknown operator %q", op)) +} + func comma(i int, or string) string { if i == 0 { return or |
