]> gitweb.factorcode.org Git - factor.git/blob - basis/english/english.factor
Switch to https urls
[factor.git] / basis / english / english.factor
1 ! Copyright (C) 2015, 2018 John Benediktsson
2 ! See https://factorcode.org/license.txt for BSD license
3 USING: arrays assocs combinators kernel literals math math.order
4 math.parser sequences splitting unicode ;
5 IN: english
6
7 <PRIVATE
8
9 <<
10 ! Irregular pluralizations
11 CONSTANT: singular-to-plural H{
12
13     ! us -> i
14     { "alumnus" "alumni" }
15     { "cactus" "cacti" }
16     { "octopus" "octopi" }
17     { "focus" "foci" }
18     { "fungus" "fungi" }
19     { "nucleus" "nuclei" }
20     { "radius" "radii" }
21     { "stimulus" "stimuli" }
22
23     ! is -> es
24     { "analysis" "analyses" }
25     { "axis" "axes" }
26     { "basis" "bases" }
27     { "crisis" "crises" }
28     { "diagnosis" "diagnoses" }
29     { "ellipsis" "ellipses" }
30     { "hypothesis" "hypotheses" }
31     { "oasis" "oases" }
32     { "paralysis" "paralyses" }
33     { "parenthesis" "parentheses" }
34     { "synopsis" "synopses" }
35     { "synthesis" "syntheses" }
36     { "thesis" "theses" }
37
38     ! ix -> ices
39     { "appendix" "appendices" }
40     { "index" "indices" }
41     { "matrix" "matrices" }
42
43     ! eau -> eaux
44     { "beau" "beaux" }
45     { "bureau" "bureaus" }
46     { "tableau" "tableaux" }
47
48     ! ? -> en
49     { "child" "children" }
50     { "man" "men" }
51     { "ox" "oxen" }
52     { "woman" "women" }
53
54     ! ? -> a
55     { "bacterium" "bacteria" }
56     { "corpus" "corpora" }
57     { "criterion" "criteria" }
58     { "curriculum" "curricula" }
59     { "datum" "data" }
60     { "genus" "genera" }
61     { "medium" "media" }
62     { "memorandum" "memoranda" }
63     { "phenomenon" "phenomena" }
64     { "stratum" "strata" }
65
66     ! no change
67     { "bison" "bison" }
68     { "deer" "deer" }
69     { "fish" "fish" }
70     { "means" "means" }
71     { "moose" "moose" }
72     { "offspring" "offspring" }
73     { "series" "series" }
74     { "sheep" "sheep" }
75     { "species" "species" }
76     { "swine" "swine" }
77
78     ! oo -> ee
79     { "foot" "feet" }
80     { "goose" "geese" }
81     { "tooth" "teeth" }
82
83     ! a -> ae
84     { "antenna" "antennae" }
85     { "formula" "formulae" }
86     { "nebula" "nebulae" }
87     { "vertebra" "vertebrae" }
88     { "vita" "vitae" }
89
90     ! ouse -> ice
91     { "louse" "lice" }
92     { "mouse" "mice" }
93 }
94 >>
95
96 CONSTANT: plural-to-singular $[ singular-to-plural [ swap ] assoc-map ]
97
98 :: match-case ( master disciple -- master' )
99     {
100         { [ master >lower master = ] [ disciple >lower ] }
101         { [ master >upper master = ] [ disciple >upper ] }
102         { [ master >title master = ] [ disciple >title ] }
103         [ disciple ]
104     } cond ;
105
106 PRIVATE>
107
108 CONSTANT: vowels "aeiou"
109
110 : vowel? ( ch -- ? )
111     vowels member? ; inline
112
113 : singularize ( word -- singular )
114     dup >lower {
115         { [ dup empty? ] [ ] }
116         { [ dup singular-to-plural key? ] [ ] }
117         { [ plural-to-singular ?at ] [ ] }
118         { [ dup "s" tail? not ] [ ] }
119         {
120             [
121                 dup "ies" ?tail [ last vowel? not ] [ drop f ] if
122             ] [ 3 head* "y" append ]
123         }
124         { [ dup "es" tail? ] [ 2 head* ] }
125         [ but-last ]
126     } cond match-case ;
127
128 : pluralize ( word -- plural )
129     dup >lower {
130         { [ dup empty? ] [ ] }
131         { [ dup plural-to-singular key? ] [ ] }
132         { [ singular-to-plural ?at ] [ ] }
133         {
134             [
135                 dup "y" ?tail [ last vowel? not ] [ drop f ] if
136             ] [ but-last "ies" append ]
137         }
138         {
139             [ dup { "s" "ch" "sh" } [ tail? ] with any? ]
140             [ dup "es" tail? [ "es" append ] unless ]
141         }
142         [ "s" append ]
143     } cond match-case ;
144
145 : singular? ( word -- ? )
146     [ singularize ] [ = ] bi ;
147
148 : plural? ( word -- ? )
149     [ singularize pluralize ] [ = ] bi ;
150
151 : ?pluralize ( count singular -- singular/plural )
152     swap 1 = [ pluralize ] unless ;
153
154 : count-of-things ( count word -- str )
155     dupd ?pluralize [ number>string ] dip " " glue ;
156
157 : a10n ( word -- numeronym )
158     dup length 3 > [
159         [ 1 head ] [ length 2 - number>string ] [ 1 tail* ] tri
160         3append
161     ] when ;
162
163 : a/an ( word -- article )
164     [ first ] [ length ] bi 1 = "afhilmnorsx" vowels ?
165     member? "an" "a" ? ;
166
167 : ?plural-article ( word -- article )
168     dup singular? [ a/an ] [ drop "the" ] if ;
169
170 : comma-list ( parts conjunction -- clause-seq )
171     [
172         [ length dup 1 [-] + ", " <array> ]
173         [ [ 2 * pick set-nth ] each-index ] bi
174     ] dip over length dup 3 >= [
175         [ 3 > ", " " " ? " " surround ] [ 2 - pick set-nth ] bi
176     ] [ 2drop ] if ;