]> gitweb.factorcode.org Git - factor.git/blob - basis/english/english.factor
Update actions, because Node.js 16 actions are deprecated, to Node.js 20
[factor.git] / basis / english / english.factor
1 ! Copyright (C) 2015, 2018 John Benediktsson
2 ! See http://factorcode.org/license.txt for BSD license
3 USING: accessors arrays assocs combinators help.markup kernel
4 literals math math.order math.parser sequences splitting unicode
5 words ;
6 IN: english
7
8 <PRIVATE
9
10 <<
11 ! Irregular pluralizations
12 CONSTANT: singular-to-plural H{
13
14     ! us -> i
15     { "alumnus" "alumni" }
16     { "cactus" "cacti" }
17     { "octopus" "octopi" }
18     { "focus" "foci" }
19     { "fungus" "fungi" }
20     { "nucleus" "nuclei" }
21     { "radius" "radii" }
22     { "stimulus" "stimuli" }
23
24     ! is -> es
25     { "analysis" "analyses" }
26     { "axis" "axes" }
27     { "basis" "bases" }
28     { "crisis" "crises" }
29     { "diagnosis" "diagnoses" }
30     { "ellipsis" "ellipses" }
31     { "hypothesis" "hypotheses" }
32     { "oasis" "oases" }
33     { "paralysis" "paralyses" }
34     { "parenthesis" "parentheses" }
35     { "synopsis" "synopses" }
36     { "synthesis" "syntheses" }
37     { "thesis" "theses" }
38
39     ! ix -> ices
40     { "appendix" "appendices" }
41     { "index" "indices" }
42     { "matrix" "matrices" }
43
44     ! eau -> eaux
45     { "beau" "beaux" }
46     { "bureau" "bureaus" }
47     { "tableau" "tableaux" }
48
49     ! ? -> en
50     { "child" "children" }
51     { "man" "men" }
52     { "ox" "oxen" }
53     { "woman" "women" }
54
55     ! ? -> a
56     { "bacterium" "bacteria" }
57     { "corpus" "corpora" }
58     { "criterion" "criteria" }
59     { "curriculum" "curricula" }
60     { "datum" "data" }
61     { "genus" "genera" }
62     { "medium" "media" }
63     { "memorandum" "memoranda" }
64     { "phenomenon" "phenomena" }
65     { "stratum" "strata" }
66
67     ! no change
68     { "bison" "bison" }
69     { "deer" "deer" }
70     { "fish" "fish" }
71     { "means" "means" }
72     { "moose" "moose" }
73     { "offspring" "offspring" }
74     { "series" "series" }
75     { "sheep" "sheep" }
76     { "species" "species" }
77     { "swine" "swine" }
78
79     ! oo -> ee
80     { "foot" "feet" }
81     { "goose" "geese" }
82     { "tooth" "teeth" }
83
84     ! a -> ae
85     { "antenna" "antennae" }
86     { "formula" "formulae" }
87     { "nebula" "nebulae" }
88     { "vertebra" "vertebrae" }
89     { "vita" "vitae" }
90
91     ! ouse -> ice
92     { "louse" "lice" }
93     { "mouse" "mice" }
94 }
95 >>
96
97 CONSTANT: plural-to-singular $[ singular-to-plural [ swap ] assoc-map ]
98
99 :: match-case ( master disciple -- master' )
100     {
101         { [ master >lower master = ] [ disciple >lower ] }
102         { [ master >upper master = ] [ disciple >upper ] }
103         { [ master >title master = ] [ disciple >title ] }
104         [ disciple ]
105     } cond ;
106
107 PRIVATE>
108
109 : singularize ( word -- singular )
110     dup >lower {
111         { [ dup empty? ] [ ] }
112         { [ dup singular-to-plural key? ] [ ] }
113         { [ plural-to-singular ?at ] [ ] }
114         { [ dup "s" tail? not ] [ ] }
115         {
116             [
117                 dup "ies" ?tail [
118                     last "aeiou" member? not
119                 ] [ drop f ] if
120             ] [ 3 head* "y" append ]
121         }
122         { [ dup "es" tail? ] [ 2 head* ] }
123         [ but-last ]
124     } cond match-case ;
125
126 : pluralize ( word -- plural )
127     dup >lower {
128         { [ dup empty? ] [ ] }
129         { [ dup plural-to-singular key? ] [ ] }
130         { [ singular-to-plural ?at ] [ ] }
131         {
132             [
133                 dup "y" ?tail [
134                     last "aeiou" member? not
135                 ] [ 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" "aeiou" ?
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 ;
177
178 : or-markup-example ( classes -- markup )
179     [
180         dup word? [
181             [ name>> ] keep \ $link
182         ] [
183             dup \ $snippet
184         ] if swap 2array [ a/an " " append ] dip 2array
185     ] map "or" comma-list ;
186
187 : $or-markup-example ( classes -- )
188     or-markup-example print-element ;