; ʞ / verb.scm
; (depends lisp-macro.scm struct.scm)
; a library by lexi hale
;
; macros, functions, and rules for conjugating verbs and
; generating verb phrases. this library rules was written
; specifically for english verbs and cannot be used as a
; "drop-in" library for other languages; however, the
; structured and functions used are sufficiently generic
; that it should be portable to other languages with
; minimal effort.
;;;; section i. generic functions & structures
; struct verb
; fields contain conjugation functions for the specified
; tense. ((v 'inf) object) will generate a verb phrase string
; with `object` as the direct object and in the bare form
; 'inf: bare infinitive / subjunctive / 1.PRS, 2.PRS, 3PL.PRS
; 'prs: 3SG.PRS
; 'ger: gerund (-ing form)
; 'pst: past (-ed form)
; 'ppl: past participle (often -ed or -en)
; * l10n note: the fields mentioned in the last line of the
; (verb-form) macro must always match the fields listed in
(define verb (struct 'inf 'prs 'ger 'adj 'pst 'ppl))
; takes a list of individual strings and joins them with
; spaces. occurrences of "a" are automatically replace by
; "an" if the word following them appears to start with a
; vowel. this can be forcibly induced by preceeding that
; word with the symbol 'vowel in the list
; TODO: make it handle initialisms. yes, everything about
; this is horrible. yes, this *is* the wrong way to do it.
; yes, i *am* ashamed. why do you ask
(define (word-append . body)
(define (vowel? c) (member c '("a" "e" "i" "o" "u")))
(define (vowel-onset? w)
(if (equal? w 'vowel) #t
(vowel? (substring w 0 1))))
(define (join acc lst)
(if (eq? lst '()) acc
(let ([word (car lst)]
[tail (cdr lst)])
(if (or (eq? word '()) (eq? word 'vowel)) (join acc tail)
(join (string-append acc (if (equal? acc "") "" " ")
(if (not (equal? word "a")) word
(if (eq? tail '()) "a"
(if (vowel-onset? (car tail)) "an" "a")))) tail)))))
(join "" body))
; make it easier to define repetitive verb forms
(define-macro (verb-form . body)
(define (make-id . body)
(string->symbol (apply string-append body)))
(define (finalize-rule r)
(define (finalize-sub-rule s)
(if (list? s) `(string-append ,@s) s))
(let* ([rule-name (car r)]
[rule-body (cdr r)])
`(define (,rule-name *o*)
(word-append ,@(map finalize-sub-rule rule-body)))))
(let* ([proc-def (car body)]
[proc-name (symbol->string (car proc-def))]
[proc-args (cdr proc-def)]
[defs (cdr body)])
`(define (,(make-id "verb:" proc-name) ,@proc-args)
,@(map finalize-rule defs) (verb inf prs ger adj pst ppl))))
; create a phrasal verb from a normal verb
; - vb: root verb
; - pp: preposition or pp phrase to append
(define (phrase vb pp)
(lambda (form)
(if (or (equal? form 'ppl) (equal? form 'adj))
(lambda (*o*)
(word-append (string-append ((vb form) '()) "-" pp) *o*))
(lambda (*o*)
(word-append ((vb form) *o*) pp)))))
; create a compound form a verb that already exists
; - prefix: prefix to append (e.g. up, out, over, un)
; - vb: final, "stem" verb
(define (compound prefix vb) (lambda (form) (lambda (*o*)
(word-append (string-append prefix ((vb form) *o*))))))
; create a verb where another string interposes between the
; root verb and the object. this can be used to implement
; object incorporation or prepositional verbs such as "get
; off on" (not to be confused with phrasal verbs)
; a phrasal verb.
; - vb: the root (leftmost) verb
; - pps: the preposition complex immediately following the
; verb.
(define (postpositive vb post) (lambda (form) (lambda (*o*)
(if (or (equal? form 'ppl) (equal? form 'adj))
(word-append
(string-append ((vb form) '()) "-" post)
*o*)
(word-append ((vb form) '()) post *o*)))))
;;; section ii. english-specific verb classes
(verb-form (weak stem)
; e.g. suck → sucking
(inf [stem] *o*)
(prs [stem "s"] *o*)
(ger [stem "ing"] *o*)
(adj [stem "ing"] *o*)
(pst [stem "ed"] *o*)
(ppl [stem "ed"] *o*))
(verb-form (es stem)
; e.g. suck → sucking
(inf [stem] *o*)
(prs [stem "es"] *o*)
(ger [stem "ing"] *o*)
(adj [stem "ing"] *o*)
(pst [stem "ed"] *o*)
(ppl [stem "ed"] *o*))
(verb-form (e stem)
; e.g. vape → vaping
(inf [stem "e"] *o*)
(prs [stem "es"] *o*)
(ger [stem "ing"] *o*)
(adj [stem "ing"] *o*)
(pst [stem "ed"] *o*)
(ppl [stem "ed"] *o*))
(verb-form (y stem)
; e.g. try → trying
(inf [stem "y"] *o*)
(prs [stem "ies"] *o*)
(ger [stem "ing"] *o*)
(adj [stem "ing"] *o*)
(pst [stem "ed"] *o*)
(ppl [stem "ed"] *o*))
(verb-form (heavy stem final)
; e.g. plug → plugging
(inf [stem] *o*)
(prs [stem "s"] *o*)
(ger [stem final "ing"] *o*)
(adj [stem final "ing"] *o*)
(pst [stem final "ed"] *o*)
(ppl [stem final "ed"] *o*))
(verb-form (strong stem ipst ippl)
; e.g. drink → drank
(inf [stem] *o*)
(prs [stem "s"] *o*)
(ger [stem "ing"] *o*)
(adj [stem "ing"] *o*)
(pst [ipst] *o*)
(ppl [ippl] *o*))
(verb-form (irregular iinf iprs iger ipst ippl)
; e.g. have → has → had
(inf [iinf] *o*)
(prs [iprs] *o*)
(ger [iger] *o*)
(adj [iger] *o*)
(pst [ipst] *o*)
(ppl [ippl] *o*))
(verb-form (strong! stem ipst)
; e.g. shoot → shot → shot
(inf [stem] *o*)
(prs [stem "s"] *o*)
(ger [stem "ing"] *o*)
(adj [stem "ing"] *o*)
(pst [ipst] *o*)
(ppl [ipst] *o*))