Skip to content

Commit 844c672

Browse files
Copilotfermga
andcommitted
Implement THOL recursive validation with depth tracking (WIP)
Co-authored-by: fermga <203334638+fermga@users.noreply.github.com>
1 parent 522b28b commit 844c672

File tree

1 file changed

+45
-42
lines changed

1 file changed

+45
-42
lines changed

src/tnfr/operators/grammar.py

Lines changed: 45 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -793,35 +793,45 @@ def _consume(self, token: str, index: int) -> None:
793793
if canonical == DISSONANCE:
794794
self._found_dissonance = True
795795

796-
# Track THOL state with recursive support
796+
# Track THOL state: Use balanced nesting to allow SILENCE/CONTRACTION inside THOL
797+
# TNFR Physical Principle: THOL applies as operator, bifurcates if d2_epi > tau
798+
# Empty THOL valid (no bifurcation), non-empty must be grammatically coherent
799+
# Closure: First SILENCE/CONTRACTION at nesting depth 0 closes THOL
797800
if canonical == SELF_ORGANIZATION:
798801
# THOL opening: push to stack and initialize subsequence
799802
self._thol_stack.append(index)
800803
self._thol_subsequences[index] = []
801804
self._open_thol = True
802-
elif self._open_thol and canonical in SELF_ORGANIZATION_CLOSURES:
803-
# THOL closure: validate subsequence recursively
804-
if not self._thol_stack:
805-
raise SequenceSyntaxError(
806-
index=index,
807-
token=token,
808-
message=f"{operator_display_name(canonical)} closure without corresponding {operator_display_name(SELF_ORGANIZATION)} opening"
809-
)
810-
811-
thol_start = self._thol_stack.pop()
812-
thol_subseq = self._thol_subsequences[thol_start]
805+
elif self._open_thol and self._thol_stack:
806+
current_thol = self._thol_stack[-1]
813807

814-
# Validate THOL subsequence recursively
815-
self._validate_thol_subsequence(thol_subseq, thol_start, index, token)
808+
# Check if this operator closes THOL BEFORE adding to subsequence
809+
# This allows SILENCE/CONTRACTION inside THOL as sequence operators
810+
if canonical in SELF_ORGANIZATION_CLOSURES:
811+
# Count nested THOL blocks to determine nesting depth
812+
subseq = self._thol_subsequences[current_thol]
813+
nested_thol_count = 0
814+
for op in subseq:
815+
if op == SELF_ORGANIZATION:
816+
nested_thol_count += 1
817+
elif op in SELF_ORGANIZATION_CLOSURES:
818+
nested_thol_count -= 1
819+
820+
# Close THOL if we're at depth 0 (no unclosed nested THOL)
821+
if nested_thol_count == 0:
822+
thol_start = self._thol_stack.pop()
823+
final_subseq = self._thol_subsequences[thol_start]
824+
825+
# Validate THOL subsequence
826+
# Empty THOL valid (no bifurcation), non-empty must be coherent
827+
self._validate_thol_subsequence(final_subseq, thol_start, index, token)
828+
829+
# Update _open_thol based on stack state (supports nested THOL)
830+
self._open_thol = bool(self._thol_stack)
831+
return # Don't add closure operator to subsequence
816832

817-
# Update _open_thol based on stack state (supports nested THOL)
818-
self._open_thol = bool(self._thol_stack)
819-
elif self._open_thol and self._thol_stack:
820-
# Track operators within THOL block (excluding nested THOL openings)
821-
# Nested THOL openings are handled separately, closures are part of inner subsequence
822-
if canonical != SELF_ORGANIZATION:
823-
current_thol = self._thol_stack[-1]
824-
self._thol_subsequences[current_thol].append(canonical)
833+
# Add operator to current THOL subsequence
834+
self._thol_subsequences[current_thol].append(canonical)
825835

826836
# Validate sequential compatibility if not first token
827837
# Only validate if both prev and current are known operators
@@ -1037,10 +1047,11 @@ def _validate_thol_subsequence(
10371047
) -> None:
10381048
"""Validate recursively the subsequence within THOL block.
10391049
1040-
TNFR Fractal Principle: THOL (self-organization) is a fractal operator
1041-
that encapsulates autonomous reorganization. The subsequence must:
1042-
1. Be non-empty (THOL without content is meaningless)
1043-
2. Respect all grammar rules R1-R6 (recursive coherence)
1050+
TNFR Physical Principle: THOL (self-organization) always applies as operator,
1051+
but only generates sub-EPIs (and thus subsequence) if ∂²EPI/∂t² > τ.
1052+
1053+
Empty THOL is physically valid - represents THOL application without bifurcation.
1054+
Non-empty subsequence represents sub-EPIs and must respect grammar rules (C1-C4).
10441055
10451056
Parameters
10461057
----------
@@ -1056,33 +1067,25 @@ def _validate_thol_subsequence(
10561067
Raises
10571068
------
10581069
SequenceSyntaxError
1059-
If subsequence is empty or invalid
1070+
If subsequence is invalid (when non-empty)
10601071
10611072
Notes
10621073
-----
10631074
From TNFR Manual §3.2.2 (Ontología fractal resonante):
10641075
"Los NFRs pueden anidarse jerárquicamente: un nodo puede contener
10651076
nodos internos coherentes, dando lugar a una estructura fractal."
10661077
1067-
This validation ensures THOL maintains operational fractality:
1068-
structures are coherent at all scales.
1078+
From operator implementation: THOL bifurcates only if d2_epi > tau.
1079+
This means THOL can appear without generating sub-EPIs (empty subsequence).
10691080
1070-
Autonomy is implicit: if the subsequence passes all grammar rules,
1071-
it is by definition autonomous (can function independently).
1081+
When bifurcation occurs (non-empty subsequence), structures must be
1082+
coherent at all scales - operational fractality is maintained.
10721083
"""
1073-
# Validation 1: Non-empty subsequence
1084+
# Empty THOL is valid: THOL applied but no bifurcation occurred
10741085
if not subsequence:
1075-
raise SequenceSyntaxError(
1076-
index=end_index,
1077-
token=end_token,
1078-
message=(
1079-
f"{operator_display_name(SELF_ORGANIZATION)} block is empty "
1080-
f"(opened at position {start_index}). Subsequence must contain "
1081-
f"at least one operator for autonomous reorganization."
1082-
)
1083-
)
1086+
return
10841087

1085-
# Validation 2: Recursive grammar validation
1088+
# Recursive grammar validation for non-empty subsequences
10861089
# Create new automaton to validate subsequence independently
10871090
try:
10881091
nested_automaton = _SequenceAutomaton()

0 commit comments

Comments
 (0)