aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/ast/format.go
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-11-29 16:01:41 +0100
committerAleksandr Nogikh <nogikh@google.com>2024-02-19 11:54:01 +0000
commite59ec59b027f921a6bfbe5014b15c2a802445ada (patch)
tree1c69d1db1b34e0b53d620f9fe272cf9f374b1400 /pkg/ast/format.go
parent164800ebad7f26d05eefb0095d190462ed97bee0 (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.go45
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