Shaankar39's picture
Initial deploy: MLAF grammar engine
47b17cc verified
:- module(binding, [check_binding/3, classify_dp/3]).
:- use_module(lexicon).
%% ==========================================================================
%% MLAF Grammar Engine — Government & Binding Theory
%%
%% Implements Principles A, B, C:
%% Principle A: Anaphors must be bound in local domain
%% Principle B: Pronouns must be FREE in local domain
%% Principle C: R-expressions must be free everywhere
%%
%% Current 11-gesture vocabulary:
%% - Pronouns (I, You, He, We, They) -> Principle B
%% - R-expressions (food, water, book) -> Principle C
%% - Framework extensible for reflexives (Principle A)
%% ==========================================================================
%% --- classify_dp(+GestureID, -DPType, -Principle) ---
%% Classifies a DP node by its binding type.
classify_dp(GestureID, pronoun, principle_b) :-
lex(GestureID, _, _, Feats),
member(anaphor=no, Feats),
member(pronominal=yes, Feats),
!.
classify_dp(GestureID, r_expression, principle_c) :-
lex(GestureID, _, _, Feats),
member(anaphor=no, Feats),
member(pronominal=no, Feats),
!.
classify_dp(GestureID, anaphor, principle_a) :-
lex(GestureID, _, _, Feats),
member(anaphor=yes, Feats),
member(pronominal=no, Feats),
!.
classify_dp(_, unknown, none).
%% --- check_binding(+GestureIDs, +BindingDomain, -Violations) ---
%% GestureIDs: list of gesture IDs in the sentence
%% BindingDomain: local (clause-level) or global (discourse-level)
%% Violations: list of violation(Principle, ID, Message) or empty list
check_binding(GestureIDs, local, Violations) :-
findall(
violation(Principle, ID, Message),
(
member(ID, GestureIDs),
lex(ID, _, _, _),
binding_violation(ID, GestureIDs, local, Principle, Message)
),
Violations
).
check_binding(GestureIDs, global, Violations) :-
findall(
violation(Principle, ID, Message),
(
member(ID, GestureIDs),
lex(ID, _, _, _),
binding_violation(ID, GestureIDs, global, Principle, Message)
),
Violations
).
%% --- binding_violation(+ID, +AllIDs, +Domain, -Principle, -Message) ---
%% Checks if a specific DP violates binding principles.
%% Principle A: Anaphor must be bound in local domain
%% (no anaphors in current vocabulary, but framework ready)
binding_violation(ID, AllIDs, local, principle_a, Message) :-
classify_dp(ID, anaphor, principle_a),
%% Check if there's a c-commanding antecedent in the local domain
\+ has_local_antecedent(ID, AllIDs),
lex(ID, Form, _, _),
atomic_list_concat(['Anaphor ', Form, ' must be bound in its local domain'], Message).
%% Principle B: Pronoun must be FREE in local domain
%% In single-clause sentences with different referents, pronouns are fine.
%% Violation occurs if a pronoun is coindexed with a local c-commanding DP.
binding_violation(ID, AllIDs, local, principle_b, Message) :-
classify_dp(ID, pronoun, principle_b),
has_local_binder(ID, AllIDs),
lex(ID, Form, _, _),
atomic_list_concat(['Pronoun ', Form, ' must be free in its local domain'], Message).
%% Principle C: R-expression must be free everywhere
binding_violation(ID, AllIDs, _, principle_c, Message) :-
classify_dp(ID, r_expression, principle_c),
has_any_binder(ID, AllIDs),
lex(ID, Form, _, _),
atomic_list_concat(['R-expression ', Form, ' must not be bound'], Message).
%% --- Binding domain helpers ---
%% An anaphor has a local antecedent if another DP with matching features
%% appears before it (c-commands it) in the same clause.
has_local_antecedent(ID, AllIDs) :-
lex(ID, _, _, Feats),
member(person=P, Feats),
member(number=N, Feats),
member(OtherID, AllIDs),
OtherID \= ID,
lex(OtherID, _, _, OtherFeats),
member(person=P, OtherFeats),
member(number=N, OtherFeats),
%% Must appear before (c-command approximation via linear order)
appears_before(OtherID, ID, AllIDs).
%% A pronoun has a local binder if another DP with identical reference
%% c-commands it in the same clause (simplified: same person+number, appears before)
has_local_binder(ID, AllIDs) :-
lex(ID, _, _, Feats),
member(person=P, Feats),
member(number=N, Feats),
member(case=nom, Feats),
%% Subject pronoun bound by another subject = violation
member(OtherID, AllIDs),
OtherID \= ID,
lex(OtherID, _, _, OtherFeats),
member(person=P, OtherFeats),
member(number=N, OtherFeats),
member(case=nom, OtherFeats),
appears_before(OtherID, ID, AllIDs).
%% R-expression bound anywhere — requires explicit coreference.
%% In our vocabulary, binding violation only fires when the same gesture
%% ID appears twice (duplicate R-expression) or when a pronoun and
%% R-expression share the same referential index (future extension).
has_any_binder(ID, AllIDs) :-
%% Same gesture ID appearing more than once signals coreference
member(OtherID, AllIDs),
OtherID == ID,
appears_before(OtherID, ID, AllIDs).
%% --- Linear order helper ---
appears_before(X, Y, List) :-
nth0(IX, List, X),
nth0(IY, List, Y),
IX < IY.