I haven't the time to explain Shen-YACC with types but SP users might like to experiment
with the following example of a Montague grammar. It will teach a lot.
Richard Montague developed this approach which compiles a source language (English) into an object language (logic) . There are basically two types - t (term) and f (formula). Montague's logic was complex and for this fragment of English we use a subset of Montague logic - function-free first-order logic without equality. The logical constants are ~ v & => <=> e! a!, the last two are the quantifiers.
Here is the type theory
(datatype t
if (not (element? t [~ v & => <=> e! a!]))
T : symbol;
________
T : t;
_______________
(gensym v) : t;)
(datatype f
F : t; T : (list t);
____________________
[F | T] : f;
(not (= F ~)) : verified;
F : t, T : t >> P;
___________________
[F T] : f >> P;
(not (element? C [v & => <=>])) : verified;
(not (element? F [e! a!])) : verified;
F : t, T1 : t, T2 : t >> P;
____________________________
[F T1 T2] : f >> P;
P : f;
==========
[~ P] : f;
if (element? C [v & => <=>])
P : f; Q : f;
=============
[P C Q] : f;
X : t; P : f;
=============
[e! X P] : f;
X : t; P : f;
=============
[a! X P] : f;)
Here is a Montague grammar in typed Shen-YACC.
(defcc <sent>
{(list t) ==> f}
<np> <vp> := (<np> <vp>);)
(defcc <np>
{(list t) ==> ((t --> f) --> f)}
Name := (/. P (P Name)) where (name? Name);
<det> <rcn> := (<det> <rcn>);
<det> <cn> := (<det> <cn>);)
(define name?
{t --> boolean}
Name -> (variable? Name))
(defcc <cn>
{(list t) ==> (t --> f)}
CN := (/. X [CN X]) where (common-noun? CN);)
(define common-noun?
{t --> boolean}
CN -> (element? CN [girl boy dog cat]))
(defcc <rcn>
{(list t) ==> (t --> f)}
<cn> that <vp> := (/. X [(<cn> X) & (<vp> X)]);
<cn> that <np> <trans> := (/. X [(<cn> X) & (<np> (/. Y (<trans> Y X)))]);)
(defcc <vp>
{(list t) ==> (t --> f)}
<intrans>;
<trans> <np> := (/. X (<np> (/. Y (<trans> X Y))));)
(defcc <intrans>
{(list t) ==> (t --> f)}
Intrans := (/. X [Intrans X]) where (intrans? Intrans);)
(define intrans?
{t --> boolean}
Intrans -> (element? Intrans [runs jumps walks]))
(defcc <trans>
{(list t) ==> (t --> t --> f)}
Trans := (/. X Y [Trans X Y]) where (trans? Trans);)
(define trans?
{t --> boolean}
Trans -> (element? Trans [likes greets admires]))
(defcc <det>
{(list t) ==> ((t --> f) --> ((t --> f) --> f))}
some := (let V (type (gensym v) t) (/. P Q [e! V [(P V) & (Q V)]]));
every := (let V (type (gensym v) t) (/. P Q [a! V [(P V) => (Q V)]]));
no := (let V (type (gensym v) t) (/. P Q [a! V [(P V) => [~ (Q V)]]]));)
Here it is in SP.
connecting to the web ...
Shen, copyright (C) 2010-2020 Mark Tarver
running under Common Lisp, implementation: SBCL
port 3 ported by Mark Tarver
commercially licensed to Mark Tarver
(0+) t#type : symbol
f#type : symbol
(fn <sent>) : ((list t) ==> f)
(fn <np>) : ((list t) ==> ((t --> f) --> f))
(fn name?) : (t --> boolean)
(fn <cn>) : ((list t) ==> (t --> f))
(fn common-noun?) : (t --> boolean)
(fn <rcn>) : ((list t) ==> (t --> f))
(fn <vp>) : ((list t) ==> (t --> f))
(fn <intrans>) : ((list t) ==> (t --> f))
(fn intrans?) : (t --> boolean)
(fn <trans>) : ((list t) ==> (t --> (t --> f)))
(fn trans?) : (t --> boolean)
(fn <det>) : ((list t) ==> ((t --> f) --> ((t --> f) --> f)))
run time: 0.5459995269775391 secs
typechecked in 10766 inferences
loaded
(0+) (compile (fn <sent>) [no girl likes a dog])
parse failure
(1+) (compile (fn <sent>) [no girl likes some dog])
[a! v12352 [[girl v12352] => [~ [e! v12354 [[dog v12354] & [likes v12352 v12354]
]]]]] : f
(2+) (compile (fn <sent>) [Mary likes John])
[likes Mary John] : f
(3+) (compile (fn <sent>) [every girl that jumps likes Bill])
[a! v12359 [[[girl v12359] & [jumps v12359]] => [likes v12359 Bill]]] : f
Mark