sign := *top* & 
[ ORTH *dlist*,
  HEAD pos,
  SPR *list*,
  COMPS *list*, 
  SEM semantics,
  GAP *dlist*,
  ARGS *list* ].

agr := *top*.

sg := agr.

pl := agr.

pos := *top* & [ MOD *list* ].

nominal := pos & [ NUMAGR agr ].

noun := nominal & [MOD <>].
verb := pos & [MOD <>].
det := nominal & [MOD <>].
prep := pos & [MOD < [ SPR < sign >] >].

semantics := *top* &
[ INDEX index,
  RELS *dlist* ].

index := *top* & [ INSTLOC string ].

event := index.
object := index.

relation := *top* &
[ PRED string,
  ARG0 index ].

arg1-relation := relation & [ ARG1 index ].
arg1-2-relation := arg1-relation & [ ARG2 index ].
arg1-2-3-relation := arg1-2-relation & [ ARG3 index ].

phrase := sign &
[ COMPS <> ].

unary-rule := phrase &
[ ORTH #orth,
  SEM #cont,
  ARGS < [ ORTH #orth, SEM #cont ] > ].

unary-rule-passgap := unary-rule &
[ GAP #gap,
  ARGS < [ GAP #gap ] > ].

binary-rule := phrase &
[ ORTH [LIST #ofront, LAST #otail],
  SEM.RELS [LIST #cfront, LAST #ctail ],
  ARGS < [ ORTH [LIST #ofront, LAST #omiddle ],
           SEM.RELS [LIST #cfront, LAST #cmiddle ] ],
         [ ORTH [LIST #omiddle, LAST #otail ],
           SEM.RELS [LIST #cmiddle, LAST #ctail ] ] > ].

binary-rule-passgap := binary-rule &
[ GAP [LIST #gfront, LAST #gtail ],
  ARGS < [ GAP [LIST #gfront, LAST #gmiddle ] ],
         [ GAP [LIST #gmiddle, LAST #gtail ] ] > ].

ternary-rule := phrase &
[ ORTH [LIST #ofront, LAST #otail],
  SEM.RELS [LIST #cfront, LAST #ctail ],
  ARGS < [ ORTH [LIST #ofront, LAST #omiddle1 ],
           SEM.RELS [LIST #cfront, LAST #cmiddle1 ] ],
         [ ORTH [LIST #omiddle1, LAST #omiddle2 ],
           SEM.RELS [LIST #cmiddle1, LAST #cmiddle2 ] ],
         [ ORTH [LIST #omiddle2, LAST #otail ],
           SEM.RELS [LIST #cmiddle2, LAST #ctail ] ] > ].

ternary-rule-passgap := ternary-rule &
[ GAP [LIST #gfront, LAST #gtail ],
  ARGS < [ GAP [LIST #gfront, LAST #gmiddle1 ] ],
         [ GAP [LIST #gmiddle1, LAST #gmiddle2 ] ],
         [ GAP [LIST #gmiddle2, LAST #gtail ] ] > ].

head-initial := phrase &
[ HEAD #head,
  SEM [ INDEX #index ],
  ARGS < [ HEAD #head,
           SEM [ INDEX #index ] ], ... > ].

unary-head-initial := unary-rule-passgap & head-initial.
unary-head-initial-startgap := unary-rule & head-initial &
[ GAP <! sign !>,
  ARGS < [ GAP <! !> ] > ].
binary-head-initial := binary-rule-passgap & head-initial.
binary-head-initial-startgap := binary-rule & head-initial &
[ GAP <! sign !>,
  ARGS < [ GAP <! !> ], [ GAP <! !> ] > ].
ternary-head-initial := ternary-rule-passgap & head-initial.

binary-head-second := binary-rule &
[ HEAD #head,
  SEM [ INDEX #index ],
  ARGS < sign, [ HEAD #head,
                      SEM [ INDEX #index ] ] > ].

binary-head-second-passgap := binary-head-second & binary-rule-passgap.

lex-item := sign &
[ ORTH [ LIST [ REST #rest ], LAST #rest ],
   GAP <! !> ]. 

lexeme := lex-item &
[ SEM [ INDEX #index,
        RELS <! [ARG0 #index] !> ] ].

const-lxm := lexeme.

word := lex-item &
[ HEAD #head,
  SPR #spr,
  COMPS #comps,
  SEM #cont,
  ARGS < lexeme &
         [ HEAD #head,
           SPR #spr,
           COMPS #comps,
           SEM #cont ] > ].

det-lxm := const-lxm &
[ HEAD det,
  SPR < >,
  COMPS < >,
  SEM [ INDEX object ] ].

sg-det-lxm := det-lxm &
[ HEAD [ NUMAGR sg ]].

pl-det-lxm := det-lxm &
[ HEAD [ NUMAGR pl ]].

noun-lxm := lexeme &
[ HEAD noun & [NUMAGR #agr],
  SPR < [HEAD det & [NUMAGR #agr],
         SEM.INDEX #index ] >,
  COMPS < >,
  SEM [ INDEX object & #index ] ].

noun-form := word &
 [ ARGS < noun-lxm > ].

sing-noun := noun-form &
[ HEAD.NUMAGR sg ].

plur-noun := noun-form &
[ HEAD.NUMAGR pl ].

verb-lxm := lexeme &
[ HEAD verb,
  SPR < phrase & [HEAD noun, SPR <>] >,
  SEM [ INDEX event ] ].

verb-form := word &
 [ ARGS < verb-lxm > ].

past-verb := verb-form.

sing-verb := verb-form &
[ SPR < [HEAD.NUMAGR sg ] > ].

plur-verb := verb-form &
[ SPR < [HEAD.NUMAGR pl ] > ].

intrans-verb := verb-lxm &
[ SPR < [SEM.INDEX #arg1] >,
  COMPS <>,
  SEM.RELS <! arg1-relation 
              & [ARG1 #arg1] !> ].

trans-verb := verb-lxm &
[ SPR < [SEM.INDEX #arg1] >,
  COMPS < phrase & [HEAD noun, SPR <>, SEM.INDEX #arg2] >,
  SEM.RELS <! arg1-2-relation & [ARG1 #arg1, ARG2 #arg2] !> ].

ditranspp-verb := verb-lxm &
[ SPR < [SEM.INDEX #arg1] >,
  COMPS < phrase & [HEAD noun, SPR <>, SEM.INDEX #arg2],
          phrase & [HEAD prep, SPR <>, SEM.INDEX #arg3] >,
  SEM.RELS <! arg1-2-3-relation & [ARG1 #arg1, ARG2 #arg2, ARG3 #arg3] !>].

ditransnp-verb := verb-lxm &
[ SPR < [SEM.INDEX #arg1] >,
  COMPS < phrase & [HEAD noun, SPR <>, SEM.INDEX #arg2],
          phrase & [HEAD noun, SPR <>, SEM.INDEX #arg3] >,
  SEM.RELS <! arg1-2-3-relation & [ARG1 #arg1, ARG2 #arg2, ARG3 #arg3] !>].

prep-lxm := const-lxm &
[ HEAD prep & [MOD < [SEM.INDEX #index] > ],
  SPR <>,
  COMPS < phrase & [HEAD noun, SPR <>, SEM.INDEX #arg1] >,
  SEM [INDEX #index, RELS <! arg1-relation & [ARG1 #arg1] !> ]].

;;;
;;; standard types
;;;

string := *top*.

*list* := *top*.

*ne-list* := *list* &
 [ FIRST *top*,
   REST *list* ].

*null* := *list*.

*dlist* := *top* &
[ LIST *list*,
  LAST *list* ].

*null-dlist* := *dlist* &
[ LIST #last,
  LAST #last ].

*ne-dlist* := *dlist* &
[LIST *ne-list* ].