diff --git a/operator-fraction.go b/operator-fraction.go
new file mode 100644
index 0000000..34570e7
--- /dev/null
+++ b/operator-fraction.go
@@ -0,0 +1,57 @@
+// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
+// All rights reserved.
+
+// operand-fraction.go
+package expr
+
+import (
+	"fmt"
+	"strings"
+)
+
+type fraction struct {
+	num, den int64
+}
+
+func (f *fraction) ToString(opt FmtOpt) string {
+	var sb strings.Builder
+	sb.WriteString(fmt.Sprintf("%d|%d", f.num, f.den))
+	return sb.String()
+}
+
+// -------- fraction term
+func newFractionTerm(tk *Token) *term {
+	return &term{
+		tk:       *tk,
+		parent:   nil,
+		children: make([]*term, 0, 2),
+		position: posInfix,
+		priority: priFraction,
+		evalFunc: evalFraction,
+	}
+}
+
+// -------- eval func
+func evalFraction(ctx ExprContext, self *term) (v any, err error) {
+	var numValue, denValue any
+	var num, den int64
+	var ok bool
+
+	if numValue, denValue, err = self.evalInfix(ctx); err != nil {
+		return
+	}
+	if num, ok = numValue.(int64); !ok {
+		err = fmt.Errorf("numerator must be integer, got %T (%v)", numValue, numValue)
+	}
+	if den, ok = denValue.(int64); !ok {
+		err = fmt.Errorf("denominator must be integer, got %T (%v)", denValue, denValue)
+	}
+
+	v = &fraction{num, den}
+	return
+}
+
+// init
+func init() {
+	registerTermConstructor(SymVertBar, newFractionTerm)
+}