diff --git a/matcher/matcher.go b/matcher/matcher.go
new file mode 100644
index 0000000..7542bdf
--- /dev/null
+++ b/matcher/matcher.go
@@ -0,0 +1,443 @@
+package matcher
+
+import (
+	"fmt"
+
+	"github.com/KorAP/KoralPipe-TermMapper2/ast"
+)
+
+// Matcher handles pattern matching and replacement in the AST
+type Matcher struct {
+	pattern     ast.Pattern
+	replacement ast.Replacement
+}
+
+// validateNode checks if a node is valid for pattern/replacement ASTs
+func validateNode(node ast.Node) error {
+	if node == nil {
+		return fmt.Errorf("nil node")
+	}
+
+	switch n := node.(type) {
+	case *ast.Token:
+		if n.Wrap != nil {
+			return validateNode(n.Wrap)
+		}
+		return nil
+	case *ast.Term:
+		return nil
+	case *ast.TermGroup:
+		if len(n.Operands) == 0 {
+			return fmt.Errorf("empty term group")
+		}
+		for _, op := range n.Operands {
+			if err := validateNode(op); err != nil {
+				return fmt.Errorf("invalid operand: %v", err)
+			}
+		}
+		return nil
+	case *ast.CatchallNode:
+		return fmt.Errorf("catchall nodes are not allowed in pattern/replacement ASTs")
+	default:
+		return fmt.Errorf("unknown node type: %T", node)
+	}
+}
+
+// NewMatcher creates a new Matcher with the given pattern and replacement
+func NewMatcher(pattern ast.Pattern, replacement ast.Replacement) (*Matcher, error) {
+	if err := validateNode(pattern.Root); err != nil {
+		return nil, fmt.Errorf("invalid pattern: %v", err)
+	}
+	if err := validateNode(replacement.Root); err != nil {
+		return nil, fmt.Errorf("invalid replacement: %v", err)
+	}
+	return &Matcher{
+		pattern:     pattern,
+		replacement: replacement,
+	}, nil
+}
+
+// Match checks if the given node matches the pattern
+func (m *Matcher) Match(node ast.Node) bool {
+	return m.matchNode(node, m.pattern.Root)
+}
+
+// Replace replaces all occurrences of the pattern in the given node with the replacement
+func (m *Matcher) Replace(node ast.Node) ast.Node {
+	// First step: Create complete structure with replacements
+	replaced := m.replaceNode(node)
+	// Second step: Simplify the structure
+	simplified := m.simplifyNode(replaced)
+	// If the input was a Token, ensure the output is also a Token
+	if _, isToken := node.(*ast.Token); isToken {
+		if _, isToken := simplified.(*ast.Token); !isToken {
+			return &ast.Token{Wrap: simplified}
+		}
+	}
+	return simplified
+}
+
+// replaceNode creates a complete structure with replacements
+func (m *Matcher) replaceNode(node ast.Node) ast.Node {
+	if node == nil {
+		return nil
+	}
+
+	// First handle Token nodes specially to preserve their structure
+	if token, ok := node.(*ast.Token); ok {
+		if token.Wrap == nil {
+			return token
+		}
+		// Process the wrapped node
+		wrap := m.replaceNode(token.Wrap)
+		return &ast.Token{Wrap: wrap}
+	}
+
+	// If this node matches the pattern
+	if m.Match(node) {
+		// For TermGroups that contain a matching Term, preserve unmatched operands
+		if tg, ok := node.(*ast.TermGroup); ok {
+			// Check if any operand matches the pattern exactly
+			hasExactMatch := false
+			for _, op := range tg.Operands {
+				if m.matchNode(op, m.pattern.Root) {
+					hasExactMatch = true
+					break
+				}
+			}
+
+			// If we have an exact match, replace matching operands
+			if hasExactMatch {
+				hasMatch := false
+				newOperands := make([]ast.Node, 0, len(tg.Operands))
+				for _, op := range tg.Operands {
+					if m.matchNode(op, m.pattern.Root) {
+						if !hasMatch {
+							newOperands = append(newOperands, m.cloneNode(m.replacement.Root))
+							hasMatch = true
+						} else {
+							newOperands = append(newOperands, m.replaceNode(op))
+						}
+					} else {
+						newOperands = append(newOperands, m.replaceNode(op))
+					}
+				}
+				return &ast.TermGroup{
+					Operands: newOperands,
+					Relation: tg.Relation,
+				}
+			}
+			// Otherwise, replace the entire TermGroup
+			return m.cloneNode(m.replacement.Root)
+		}
+		// For other nodes, return the replacement
+		return m.cloneNode(m.replacement.Root)
+	}
+
+	// Otherwise recursively process children
+	switch n := node.(type) {
+	case *ast.TermGroup:
+		// Check if any operand matches the pattern exactly
+		hasExactMatch := false
+		for _, op := range n.Operands {
+			if m.matchNode(op, m.pattern.Root) {
+				hasExactMatch = true
+				break
+			}
+		}
+
+		// If we have an exact match, replace matching operands
+		if hasExactMatch {
+			hasMatch := false
+			newOperands := make([]ast.Node, 0, len(n.Operands))
+			for _, op := range n.Operands {
+				if m.matchNode(op, m.pattern.Root) {
+					if !hasMatch {
+						newOperands = append(newOperands, m.cloneNode(m.replacement.Root))
+						hasMatch = true
+					} else {
+						newOperands = append(newOperands, m.replaceNode(op))
+					}
+				} else {
+					newOperands = append(newOperands, m.replaceNode(op))
+				}
+			}
+			return &ast.TermGroup{
+				Operands: newOperands,
+				Relation: n.Relation,
+			}
+		}
+		// Otherwise, recursively process operands
+		newOperands := make([]ast.Node, len(n.Operands))
+		for i, op := range n.Operands {
+			newOperands[i] = m.replaceNode(op)
+		}
+		return &ast.TermGroup{
+			Operands: newOperands,
+			Relation: n.Relation,
+		}
+
+	case *ast.CatchallNode:
+		newNode := &ast.CatchallNode{
+			NodeType:   n.NodeType,
+			RawContent: n.RawContent,
+		}
+		if n.Wrap != nil {
+			newNode.Wrap = m.replaceNode(n.Wrap)
+		}
+		if len(n.Operands) > 0 {
+			newNode.Operands = make([]ast.Node, len(n.Operands))
+			for i, op := range n.Operands {
+				newNode.Operands[i] = m.replaceNode(op)
+			}
+		}
+		return newNode
+
+	default:
+		return node
+	}
+}
+
+// simplifyNode removes unnecessary wrappers and empty nodes
+func (m *Matcher) simplifyNode(node ast.Node) ast.Node {
+	if node == nil {
+		return nil
+	}
+
+	switch n := node.(type) {
+	case *ast.Token:
+		if n.Wrap == nil {
+			return nil
+		}
+		simplified := m.simplifyNode(n.Wrap)
+		if simplified == nil {
+			return nil
+		}
+		return &ast.Token{Wrap: simplified}
+
+	case *ast.TermGroup:
+		// First simplify all operands
+		simplified := make([]ast.Node, 0, len(n.Operands))
+		for _, op := range n.Operands {
+			if s := m.simplifyNode(op); s != nil {
+				simplified = append(simplified, s)
+			}
+		}
+
+		// Handle special cases
+		if len(simplified) == 0 {
+			return nil
+		}
+		if len(simplified) == 1 {
+			// If we have a single operand, return it directly
+			// But only if we're not inside a Token
+			if _, isToken := node.(*ast.Token); !isToken {
+				return simplified[0]
+			}
+		}
+
+		return &ast.TermGroup{
+			Operands: simplified,
+			Relation: n.Relation,
+		}
+
+	case *ast.CatchallNode:
+		newNode := &ast.CatchallNode{
+			NodeType:   n.NodeType,
+			RawContent: n.RawContent,
+		}
+		if n.Wrap != nil {
+			newNode.Wrap = m.simplifyNode(n.Wrap)
+		}
+		if len(n.Operands) > 0 {
+			simplified := make([]ast.Node, 0, len(n.Operands))
+			for _, op := range n.Operands {
+				if s := m.simplifyNode(op); s != nil {
+					simplified = append(simplified, s)
+				}
+			}
+			if len(simplified) > 0 {
+				newNode.Operands = simplified
+			}
+		}
+		return newNode
+
+	default:
+		return node
+	}
+}
+
+// matchNode recursively checks if two nodes match
+func (m *Matcher) matchNode(node, pattern ast.Node) bool {
+	if pattern == nil {
+		return true
+	}
+	if node == nil {
+		return false
+	}
+
+	// Handle pattern being a Token
+	if pToken, ok := pattern.(*ast.Token); ok {
+		if nToken, ok := node.(*ast.Token); ok {
+			return m.matchNode(nToken.Wrap, pToken.Wrap)
+		}
+		return false
+	}
+
+	// Handle pattern being a Term
+	if pTerm, ok := pattern.(*ast.Term); ok {
+		// Direct term to term matching
+		if t, ok := node.(*ast.Term); ok {
+			return t.Foundry == pTerm.Foundry &&
+				t.Key == pTerm.Key &&
+				t.Layer == pTerm.Layer &&
+				t.Match == pTerm.Match &&
+				(pTerm.Value == "" || t.Value == pTerm.Value)
+		}
+		// If node is a Token, check its wrap
+		if tkn, ok := node.(*ast.Token); ok {
+			if tkn.Wrap == nil {
+				return false
+			}
+			return m.matchNode(tkn.Wrap, pattern)
+		}
+		// If node is a TermGroup, check its operands
+		if tg, ok := node.(*ast.TermGroup); ok {
+			for _, op := range tg.Operands {
+				if m.matchNode(op, pattern) {
+					return true
+				}
+			}
+			return false
+		}
+		// If node is a CatchallNode, check its wrap and operands
+		if c, ok := node.(*ast.CatchallNode); ok {
+			if c.Wrap != nil && m.matchNode(c.Wrap, pattern) {
+				return true
+			}
+			for _, op := range c.Operands {
+				if m.matchNode(op, pattern) {
+					return true
+				}
+			}
+			return false
+		}
+		return false
+	}
+
+	// Handle pattern being a TermGroup
+	if pGroup, ok := pattern.(*ast.TermGroup); ok {
+		// For OR relations, check if any operand matches the node
+		if pGroup.Relation == ast.OrRelation {
+			for _, pOp := range pGroup.Operands {
+				if m.matchNode(node, pOp) {
+					return true
+				}
+			}
+			return false
+		}
+
+		// For AND relations, node must be a TermGroup with matching relation
+		if tg, ok := node.(*ast.TermGroup); ok {
+			if tg.Relation != pGroup.Relation {
+				return false
+			}
+			// Check that all pattern operands match in any order
+			if len(tg.Operands) < len(pGroup.Operands) {
+				return false
+			}
+			matched := make([]bool, len(tg.Operands))
+			for _, pOp := range pGroup.Operands {
+				found := false
+				for j, tOp := range tg.Operands {
+					if !matched[j] && m.matchNode(tOp, pOp) {
+						matched[j] = true
+						found = true
+						break
+					}
+				}
+				if !found {
+					return false
+				}
+			}
+			return true
+		}
+
+		// If node is a Token, check its wrap
+		if tkn, ok := node.(*ast.Token); ok {
+			if tkn.Wrap == nil {
+				return false
+			}
+			return m.matchNode(tkn.Wrap, pattern)
+		}
+
+		// If node is a CatchallNode, check its wrap and operands
+		if c, ok := node.(*ast.CatchallNode); ok {
+			if c.Wrap != nil && m.matchNode(c.Wrap, pattern) {
+				return true
+			}
+			for _, op := range c.Operands {
+				if m.matchNode(op, pattern) {
+					return true
+				}
+			}
+			return false
+		}
+
+		return false
+	}
+
+	return false
+}
+
+// cloneNode creates a deep copy of a node
+func (m *Matcher) cloneNode(node ast.Node) ast.Node {
+	if node == nil {
+		return nil
+	}
+
+	switch n := node.(type) {
+	case *ast.Token:
+		return &ast.Token{
+			Wrap: m.cloneNode(n.Wrap),
+		}
+
+	case *ast.TermGroup:
+		operands := make([]ast.Node, len(n.Operands))
+		for i, op := range n.Operands {
+			operands[i] = m.cloneNode(op)
+		}
+		return &ast.TermGroup{
+			Operands: operands,
+			Relation: n.Relation,
+		}
+
+	case *ast.Term:
+		return &ast.Term{
+			Foundry: n.Foundry,
+			Key:     n.Key,
+			Layer:   n.Layer,
+			Match:   n.Match,
+			Value:   n.Value,
+		}
+
+	case *ast.CatchallNode:
+		newNode := &ast.CatchallNode{
+			NodeType:   n.NodeType,
+			RawContent: n.RawContent,
+		}
+		if n.Wrap != nil {
+			newNode.Wrap = m.cloneNode(n.Wrap)
+		}
+		if len(n.Operands) > 0 {
+			newNode.Operands = make([]ast.Node, len(n.Operands))
+			for i, op := range n.Operands {
+				newNode.Operands[i] = m.cloneNode(op)
+			}
+		}
+		return newNode
+
+	default:
+		return nil
+	}
+}
