Skip to main content

logicaffeine_lexicon/
types.rs

1//! Lexicon type definitions
2//!
3//! Core types used by the generated lexicon lookup functions.
4
5/// Article definiteness for noun phrases.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum Definiteness {
8    /// The referent is uniquely identifiable ("the").
9    Definite,
10    /// The referent is not uniquely identifiable ("a", "an").
11    Indefinite,
12    /// The referent is near the speaker ("this", "these").
13    Proximal,
14    /// The referent is far from the speaker ("that", "those").
15    Distal,
16}
17
18/// Temporal reference for verb tense.
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20pub enum Time {
21    /// Event occurred before speech time.
22    Past,
23    /// Event overlaps with speech time.
24    Present,
25    /// Event occurs after speech time.
26    Future,
27    /// No temporal specification (infinitives, bare stems).
28    None,
29}
30
31/// Grammatical aspect (viewpoint aspect).
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum Aspect {
34    /// Event viewed as a whole, completed action.
35    Simple,
36    /// Event viewed as ongoing, in progress.
37    Progressive,
38    /// Event completed with present relevance.
39    Perfect,
40}
41
42/// Vendler's Lexical Aspect Classes (Aktionsart)
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)]
44pub enum VerbClass {
45    /// +static, +durative, -telic: know, love, exist
46    State,
47    /// -static, +durative, -telic: run, swim, drive
48    #[default]
49    Activity,
50    /// -static, +durative, +telic: build, draw, write
51    Accomplishment,
52    /// -static, -durative, +telic: win, find, die
53    Achievement,
54    /// -static, -durative, -telic: knock, cough, blink
55    Semelfactive,
56}
57
58impl VerbClass {
59    /// Returns true if this is a stative verb class (no change of state).
60    ///
61    /// States denote properties or relations that hold without change: "know", "love", "exist".
62    pub fn is_stative(&self) -> bool {
63        matches!(self, VerbClass::State)
64    }
65
66    /// Returns true if this verb class denotes events with duration.
67    ///
68    /// Durative events: States, Activities, and Accomplishments all have temporal extent.
69    /// Non-durative: Achievements and Semelfactives are punctual.
70    pub fn is_durative(&self) -> bool {
71        matches!(
72            self,
73            VerbClass::State | VerbClass::Activity | VerbClass::Accomplishment
74        )
75    }
76
77    /// Returns true if this verb class has an inherent endpoint (telic).
78    ///
79    /// Telic events: Accomplishments and Achievements reach a natural endpoint.
80    /// Atelic events: States, Activities, and Semelfactives have no inherent endpoint.
81    pub fn is_telic(&self) -> bool {
82        matches!(self, VerbClass::Accomplishment | VerbClass::Achievement)
83    }
84}
85
86/// Semantic sorts for type checking.
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88pub enum Sort {
89    /// Top of the hierarchy; any individual.
90    Entity,
91    /// Concrete, spatially located objects.
92    Physical,
93    /// Living beings capable of self-motion.
94    Animate,
95    /// Persons with intentional agency.
96    Human,
97    /// Non-animal living organisms.
98    Plant,
99    /// Locations and regions.
100    Place,
101    /// Temporal intervals and points.
102    Time,
103    /// Non-physical, conceptual entities.
104    Abstract,
105    /// Propositional content and data.
106    Information,
107    /// Occurrences and happenings.
108    Event,
109    /// Stars, planets, and astronomical bodies.
110    Celestial,
111    /// Numeric or monetary amounts.
112    Value,
113    /// Hardware signals, wires, clocks, and buses.
114    Signal,
115    /// Collections of individuals.
116    Group,
117}
118
119impl Sort {
120    /// Check if this sort can be used where `other` is expected.
121    ///
122    /// Sort compatibility follows a subsumption hierarchy:
123    /// - Human ⊆ Animate ⊆ Physical ⊆ Entity
124    /// - Plant ⊆ Animate ⊆ Physical ⊆ Entity
125    /// - Everything ⊆ Entity
126    ///
127    /// For example, a Human noun can fill an Animate slot, but not vice versa.
128    pub fn is_compatible_with(self, other: Sort) -> bool {
129        if self == other {
130            return true;
131        }
132        match (self, other) {
133            (Sort::Human, Sort::Animate) => true,
134            (Sort::Plant, Sort::Animate) => true,
135            (Sort::Animate, Sort::Physical) => true,
136            (Sort::Human, Sort::Physical) => true,
137            (Sort::Plant, Sort::Physical) => true,
138            (_, Sort::Entity) => true,
139            _ => false,
140        }
141    }
142
143    /// Whether this sort denotes an OCCASION — an occurrence or happening whose
144    /// head noun behaves as a soft type. For occasion sorts, "the \[modifier\]
145    /// \[head\]" lets the modifier do the referring (the same event can be a
146    /// "trip", a "vacation", or a "holiday"), so two such definite descriptions
147    /// corefer when their modifier matches and their head sorts agree.
148    ///
149    /// Concrete physical objects (box, ball) are NOT occasions: "the red box"
150    /// and "the red ball" are distinct things even though both are `Physical`,
151    /// so they must never corefer through a shared modifier.
152    pub fn is_occasion(self) -> bool {
153        matches!(self, Sort::Event)
154    }
155}
156
157/// Grammatical number for nouns and agreement.
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
159pub enum Number {
160    /// Denotes a single individual.
161    Singular,
162    /// Denotes multiple individuals.
163    Plural,
164}
165
166/// Grammatical gender (for pronouns and agreement).
167#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
168pub enum Gender {
169    /// Masculine gender ("he", "him", "his").
170    Male,
171    /// Feminine gender ("she", "her", "hers").
172    Female,
173    /// Neuter gender ("it", "its").
174    Neuter,
175    /// Gender unspecified or indeterminate.
176    Unknown,
177}
178
179/// Grammatical case (for pronouns).
180#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
181pub enum Case {
182    /// Nominative case for subjects ("I", "he", "she").
183    Subject,
184    /// Accusative case for objects ("me", "him", "her").
185    Object,
186    /// Genitive case for possession ("my", "his", "her").
187    Possessive,
188}
189
190/// Lexical polarity for canonical mappings.
191#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
192pub enum Polarity {
193    /// Preserves the meaning (synonym mapping).
194    Positive,
195    /// Inverts the meaning (antonym mapping).
196    Negative,
197}
198
199/// Lexical features that encode grammatical and semantic properties of words.
200///
201/// Features are assigned to lexical entries in the lexicon database and control
202/// how words combine syntactically and what semantic representations they produce.
203/// The feature system follows the tradition of feature-based grammar formalisms
204/// like HPSG and LFG.
205#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
206pub enum Feature {
207    // -------------------------------------------------------------------------
208    // Verb Transitivity Features
209    // -------------------------------------------------------------------------
210
211    /// Verb requires a direct object (NP complement).
212    ///
213    /// Transitive verbs denote binary relations between an agent and a patient/theme.
214    /// In first-order logic, they translate to two-place predicates: `Verb(x, y)`.
215    ///
216    /// Examples: "see", "hit", "love", "build"
217    Transitive,
218
219    /// Verb takes no object (unary predicate).
220    ///
221    /// Intransitive verbs denote properties of a single argument (the subject).
222    /// They translate to one-place predicates: `Verb(x)`.
223    ///
224    /// Examples: "sleep", "arrive", "exist", "die"
225    Intransitive,
226
227    /// Verb takes two objects (direct + indirect).
228    ///
229    /// Ditransitive verbs denote ternary relations, typically involving transfer
230    /// of possession. They translate to three-place predicates: `Verb(x, y, z)`.
231    ///
232    /// Examples: "give", "tell", "show", "send"
233    Ditransitive,
234
235    // -------------------------------------------------------------------------
236    // Control Theory Features
237    // -------------------------------------------------------------------------
238
239    /// The subject of the matrix clause controls the PRO subject of the embedded clause.
240    ///
241    /// In "John promised Mary to leave", John (subject) is understood as the one leaving.
242    /// Formally: promise(j, m, leave(PRO_j)) where PRO is coindexed with the subject.
243    ///
244    /// Examples: "promise", "try", "want", "decide"
245    SubjectControl,
246
247    /// The object of the matrix clause controls the PRO subject of the embedded clause.
248    ///
249    /// In "John persuaded Mary to leave", Mary (object) is understood as the one leaving.
250    /// Formally: persuade(j, m, leave(PRO_m)) where PRO is coindexed with the object.
251    ///
252    /// Examples: "persuade", "force", "convince", "order"
253    ObjectControl,
254
255    /// Raising verb that does not assign a theta-role to its surface subject.
256    ///
257    /// In "John seems to be happy", "John" originates in the embedded clause and
258    /// raises to matrix subject position. No control relation; subject is shared.
259    /// Contrast with control: raising allows expletive subjects ("It seems that...").
260    ///
261    /// Examples: "seem", "appear", "happen", "tend"
262    Raising,
263
264    // -------------------------------------------------------------------------
265    // Semantic Features
266    // -------------------------------------------------------------------------
267
268    /// Creates an opaque (intensional) context blocking substitution of co-referential terms.
269    ///
270    /// In opaque contexts, Leibniz's Law fails: even if a=b, P(a) does not entail P(b).
271    /// "John believes Clark Kent is weak" does not entail "John believes Superman is weak"
272    /// even if Clark Kent = Superman. Requires possible-worlds semantics.
273    ///
274    /// Examples: "believe", "think", "want", "seek"
275    Opaque,
276
277    /// Presupposes the truth of its complement clause.
278    ///
279    /// Factive verbs entail the truth of their embedded proposition regardless of
280    /// the matrix clause's truth value. "John regrets that it rained" presupposes
281    /// that it rained, even under negation: "John doesn't regret that it rained."
282    ///
283    /// Examples: "know", "regret", "realize", "discover"
284    Factive,
285
286    /// Uttering the verb constitutes performing the action it describes.
287    ///
288    /// Performative verbs, when uttered in first person present, do not describe
289    /// an action but perform it. "I promise to come" is itself the act of promising.
290    /// Austin's speech act theory: saying is doing.
291    ///
292    /// Examples: "promise", "declare", "pronounce", "bet"
293    Performative,
294
295    /// Requires a plural or group subject; describes collective action.
296    ///
297    /// Collective predicates cannot distribute over atomic individuals.
298    /// "The students gathered" is true of the group, not of each student individually.
299    /// Contrast with distributive: "gathered" vs "slept".
300    ///
301    /// Examples: "gather", "meet", "disperse", "surround"
302    Collective,
303
304    /// Can be interpreted either collectively or distributively.
305    ///
306    /// Mixed predicates are ambiguous between collective and distributive readings.
307    /// "The students lifted the piano" can mean they lifted it together (collective)
308    /// or each lifted a piano (distributive). Context disambiguates.
309    ///
310    /// Examples: "lift", "carry", "build", "write"
311    Mixed,
312
313    /// Distributes over atomic individuals in a plurality.
314    ///
315    /// Distributive predicates apply to each member of a plural subject individually.
316    /// "The students slept" entails that each student slept. Formally: ∀x(student(x) → slept(x)).
317    ///
318    /// Examples: "sleep", "smile", "breathe", "think"
319    Distributive,
320
321    /// Impersonal verb describing meteorological phenomena; takes expletive subject.
322    ///
323    /// Weather verbs have no semantic subject; "it" in "it rains" is a dummy expletive.
324    /// In formal semantics, they are zero-place predicates or predicates of times/events.
325    ///
326    /// Examples: "rain", "snow", "thunder", "drizzle"
327    Weather,
328
329    /// Intransitive verb whose subject is a theme/patient, not an agent.
330    ///
331    /// Unaccusative verbs have an underlying object that surfaces as subject.
332    /// Evidence: auxiliary selection in Italian/German, participle agreement.
333    /// "The ice melted" - the ice undergoes melting, doesn't cause it.
334    ///
335    /// Examples: "arrive", "fall", "melt", "appear"
336    Unaccusative,
337
338    /// Takes a proposition and evaluates it relative to possible worlds.
339    ///
340    /// Intensional predicates don't just operate on truth values but on intensions
341    /// (functions from worlds to extensions). Required for modal and attitude reports.
342    /// "John believes it might rain" involves multiple world quantification.
343    ///
344    /// Examples: "believe", "know", "hope", "doubt"
345    IntensionalPredicate,
346
347    /// Causative change-of-state verb that licenses a RESULTATIVE secondary
348    /// predicate: the object's resulting state is brought about by the event.
349    /// "paint the door RED" (the door becomes red), "hammer the metal FLAT".
350    /// Verbs without this feature take a post-object AP as a DEPICTIVE instead
351    /// ("eat the meat RAW" — the meat is raw during, not caused by, the eating).
352    ///
353    /// Examples: "paint", "dye", "break", "flatten", "freeze"
354    Resultative,
355
356    /// Perception verb (see, hear, watch, …) taking a small-clause complement
357    /// "NP bare-VP" that denotes the PERCEIVED EVENT (§3.2): "Mary heard the bell
358    /// RING" → Hear(mary, ⟨Ring(bell)⟩).
359    ///
360    /// Examples: "see", "hear", "watch", "feel", "notice", "observe"
361    Perception,
362
363    /// Addressee-oriented attitude verb that, in an "if you V …" antecedent, marks a
364    /// BISCUIT / relevance conditional (§4.2): the consequent is asserted and the
365    /// if-clause restricts relevance, not truth ("If you WANT tea, the kettle is hot").
366    ///
367    /// Examples: "want", "need", "wonder", "care", "desire", "wish", "like"
368    Relevance,
369
370    // -------------------------------------------------------------------------
371    // Noun Features
372    // -------------------------------------------------------------------------
373
374    /// Noun can be counted; takes singular/plural marking and numerals directly.
375    ///
376    /// Count nouns denote atomic, individuated entities. They combine with numerals
377    /// and indefinite articles: "three cats", "a dog". Semantically, they have
378    /// natural atomic minimal parts.
379    ///
380    /// Examples: "cat", "idea", "student", "book"
381    Count,
382
383    /// Noun denotes stuff without natural units; requires measure phrases for counting.
384    ///
385    /// Mass nouns are cumulative and divisive: any part of water is water, and
386    /// water plus water is water. Cannot directly combine with numerals;
387    /// require classifiers: "three glasses of water", not "three waters".
388    ///
389    /// Examples: "water", "rice", "information", "furniture"
390    Mass,
391
392    /// Noun is a proper name denoting a specific individual.
393    ///
394    /// Proper nouns are rigid designators that refer to the same individual in
395    /// all possible worlds. They typically lack articles and don't take plural
396    /// marking. Semantically, they denote individuals directly, not sets.
397    ///
398    /// Examples: "Socrates", "Paris", "Microsoft", "Monday"
399    Proper,
400
401    // -------------------------------------------------------------------------
402    // Gender Features
403    // -------------------------------------------------------------------------
404
405    /// Grammatically masculine; triggers masculine agreement on dependents.
406    ///
407    /// In languages with grammatical gender, masculine nouns control agreement
408    /// on articles, adjectives, and pronouns. In English, primarily affects
409    /// pronoun selection for animate referents.
410    ///
411    /// Examples: "man", "king", "actor", "waiter"
412    Masculine,
413
414    /// Grammatically feminine; triggers feminine agreement on dependents.
415    ///
416    /// Feminine nouns control feminine agreement patterns. In English, primarily
417    /// relevant for pronoun selection with human referents.
418    ///
419    /// Examples: "woman", "queen", "actress", "waitress"
420    Feminine,
421
422    /// Grammatically neuter; triggers neuter agreement on dependents.
423    ///
424    /// Neuter is the default for inanimate objects in English. Used for entities
425    /// where natural gender is absent or unknown. "It" is the neuter pronoun.
426    ///
427    /// Examples: "table", "rock", "system", "idea"
428    Neuter,
429
430    // -------------------------------------------------------------------------
431    // Animacy Features
432    // -------------------------------------------------------------------------
433
434    /// Denotes an entity capable of self-initiated action or sentience.
435    ///
436    /// Animacy is a semantic feature affecting argument realization. Animate
437    /// entities can be agents, experiencers, recipients. Affects pronoun choice
438    /// ("who" vs "what") and relative clause formation.
439    ///
440    /// Examples: "dog", "person", "bird", "robot" (ambiguous)
441    Animate,
442
443    /// Denotes a non-sentient entity incapable of self-initiated action.
444    ///
445    /// Inanimate entities typically serve as themes, patients, or instruments.
446    /// Cannot be agents in the semantic sense. "What" rather than "who".
447    ///
448    /// Examples: "rock", "table", "water", "idea"
449    Inanimate,
450
451    // -------------------------------------------------------------------------
452    // Adjective Features
453    // -------------------------------------------------------------------------
454
455    /// Adjective meaning combines by set intersection with noun meaning.
456    ///
457    /// For intersective adjectives, "A N" denotes things that are both A and N.
458    /// "Red ball" means {x : red(x) ∧ ball(x)}. The adjective has a context-independent
459    /// extension that intersects with the noun's extension.
460    ///
461    /// Examples: "red", "round", "wooden", "French"
462    Intersective,
463
464    /// Adjective meaning cannot be computed by simple intersection.
465    ///
466    /// Non-intersective adjectives require the noun to determine their extension.
467    /// "Fake gun" is not a gun at all, so fake(x) ∧ gun(x) gives wrong results.
468    /// Includes privative ("fake", "former") and modal ("alleged", "potential").
469    ///
470    /// Examples: "fake", "alleged", "former", "potential"
471    NonIntersective,
472
473    /// Adjective picks out a subset of the noun denotation relative to a comparison class.
474    ///
475    /// Subsective adjectives entail the noun: a "skillful surgeon" is a surgeon.
476    /// But "skillful" is relative: skillful for a surgeon, not skillful absolutely.
477    /// "Small elephant" is large for an animal but small for an elephant.
478    ///
479    /// Examples: "skillful", "good", "large", "small"
480    Subsective,
481
482    /// Adjective has a degree argument and supports comparison morphology.
483    ///
484    /// Gradable adjectives place entities on a scale with a contextual standard.
485    /// "Tall" means exceeding some contextual standard of height. Supports
486    /// comparatives ("taller"), superlatives ("tallest"), and degree modification.
487    ///
488    /// Examples: "tall", "expensive", "heavy", "smart"
489    Gradable,
490
491    /// Adjective that modifies the event denoted by the verb, not the noun.
492    ///
493    /// Event-modifying adjectives (when used adverbially) characterize manner or
494    /// other event properties. "Careful surgeon" suggests careful in operating,
495    /// not careful as a person. Related to adverb formation.
496    ///
497    /// Examples: "careful", "slow", "quick", "deliberate"
498    EventModifier,
499
500    /// Denominal, non-predicating adjective denoting a relation to a base noun.
501    ///
502    /// Relational (pertainymic) adjectives — "dental" ← tooth, "coastal" ← coast,
503    /// "nuclear" ← nucleus — are NOT intersective: "a dental procedure" is not
504    /// {dental things} ∩ {procedures}; the adjective relates the procedure to
505    /// teeth. They are predicates of KINDS (McNally & Boleda 2004), modeled as
506    /// `Noun(x) ∧ Rel(x, ^Base)` (kind-level, default) or
507    /// `Noun(x) ∧ ∃y(Base(y) ∧ Rel(x, y))` (instance-level override).
508    ///
509    /// Examples: "dental", "coastal", "nuclear", "marine", "postal", "solar"
510    Relational,
511
512    /// Gradable adjective with borderline cases and sorites behavior (§8.5): the
513    /// threshold has a PENUMBRA (a vague region θ_low < d < θ_high), not a sharp
514    /// cutoff. Implies a degree-standard reading plus a borderline marker.
515    ///
516    /// Examples: "bald", "tall", "heavy", "rich", "old", "big"
517    Vague,
518
519    /// Negative-pole (decreasing) gradable adjective: the comparative denotes a
520    /// SMALLER value on the canonical measured scale, so an arithmetic comparative
521    /// subtracts rather than adds ("narrower" → less wingspan, "lighter" → less
522    /// weight). The unmarked positive pole ("wide", "long", "heavy") increases.
523    ///
524    /// Examples: "narrow", "short", "small", "light", "cheap", "slow", "young"
525    Decreasing,
526}
527
528impl Feature {
529    /// Parses a feature name from a string.
530    ///
531    /// Returns `Some(Feature)` if the string matches a known feature name (case-sensitive),
532    /// or `None` if unrecognized.
533    pub fn from_str(s: &str) -> Option<Feature> {
534        match s {
535            "Transitive" => Some(Feature::Transitive),
536            "Intransitive" => Some(Feature::Intransitive),
537            "Ditransitive" => Some(Feature::Ditransitive),
538            "SubjectControl" => Some(Feature::SubjectControl),
539            "ObjectControl" => Some(Feature::ObjectControl),
540            "Raising" => Some(Feature::Raising),
541            "Opaque" => Some(Feature::Opaque),
542            "Factive" => Some(Feature::Factive),
543            "Performative" => Some(Feature::Performative),
544            "Collective" => Some(Feature::Collective),
545            "Mixed" => Some(Feature::Mixed),
546            "Distributive" => Some(Feature::Distributive),
547            "Weather" => Some(Feature::Weather),
548            "Unaccusative" => Some(Feature::Unaccusative),
549            "IntensionalPredicate" => Some(Feature::IntensionalPredicate),
550            "Resultative" => Some(Feature::Resultative),
551            "Perception" => Some(Feature::Perception),
552            "Relevance" => Some(Feature::Relevance),
553            "Count" => Some(Feature::Count),
554            "Mass" => Some(Feature::Mass),
555            "Proper" => Some(Feature::Proper),
556            "Masculine" => Some(Feature::Masculine),
557            "Feminine" => Some(Feature::Feminine),
558            "Neuter" => Some(Feature::Neuter),
559            "Animate" => Some(Feature::Animate),
560            "Inanimate" => Some(Feature::Inanimate),
561            "Intersective" => Some(Feature::Intersective),
562            "NonIntersective" => Some(Feature::NonIntersective),
563            "Subsective" => Some(Feature::Subsective),
564            "Gradable" => Some(Feature::Gradable),
565            "EventModifier" => Some(Feature::EventModifier),
566            "Relational" => Some(Feature::Relational),
567            "Vague" => Some(Feature::Vague),
568            "Decreasing" => Some(Feature::Decreasing),
569            _ => None,
570        }
571    }
572}
573
574/// Verb entry returned from irregular verb lookup.
575///
576/// This owned struct is returned when looking up inflected verb forms
577/// (e.g., "ran" → run, "went" → go). Contains the resolved morphological
578/// information needed for semantic processing.
579#[derive(Debug, Clone, PartialEq, Eq)]
580pub struct VerbEntry {
581    /// The dictionary form (infinitive) of the verb.
582    /// Example: "run" for input "ran", "go" for input "went".
583    pub lemma: String,
584
585    /// The temporal reference encoded by the inflection.
586    /// Example: Past for "ran", Present for "runs".
587    pub time: Time,
588
589    /// The grammatical aspect of the inflected form.
590    /// Example: Progressive for "running", Perfect for "run" (in "has run").
591    pub aspect: Aspect,
592
593    /// The Vendler aspectual class (Aktionsart) of the verb.
594    /// Determines compatibility with temporal adverbials and aspect markers.
595    pub class: VerbClass,
596}
597
598/// Static verb metadata from the lexicon database.
599///
600/// This borrowed struct provides zero-copy access to verb information
601/// stored in the generated lexicon. Used for verbs looked up by lemma
602/// rather than inflected form.
603#[derive(Debug, Clone, Copy, PartialEq, Eq)]
604pub struct VerbMetadata {
605    /// The dictionary form (infinitive) of the verb.
606    pub lemma: &'static str,
607
608    /// The Vendler aspectual class determining temporal behavior.
609    pub class: VerbClass,
610
611    /// The default temporal reference (usually [`Time::None`] for infinitives).
612    pub time: Time,
613
614    /// The default grammatical aspect (usually [`Aspect::Simple`]).
615    pub aspect: Aspect,
616
617    /// Lexical features controlling syntax and semantics.
618    /// See [`Feature`] for the full list of possible features.
619    pub features: &'static [Feature],
620}
621
622/// Static noun metadata from the lexicon database.
623///
624/// Provides lexical information for noun lookup including number
625/// and semantic features. Nouns are keyed by their surface form,
626/// with separate entries for singular and plural.
627#[derive(Debug, Clone, Copy, PartialEq, Eq)]
628pub struct NounMetadata {
629    /// The canonical form of the noun (usually singular).
630    pub lemma: &'static str,
631
632    /// The grammatical number of this surface form.
633    /// "cat" → Singular, "cats" → Plural.
634    pub number: Number,
635
636    /// Semantic features including count/mass, animacy, and gender.
637    pub features: &'static [Feature],
638}
639
640/// Static adjective metadata from the lexicon database.
641///
642/// Adjectives carry features that determine their semantic behavior
643/// when combined with nouns (intersective, subsective, etc.) and
644/// whether they support gradability and comparison.
645#[derive(Debug, Clone, Copy, PartialEq, Eq)]
646pub struct AdjectiveMetadata {
647    /// The base form of the adjective (positive degree).
648    pub lemma: &'static str,
649
650    /// Semantic features controlling modification behavior.
651    /// See [`Feature::Intersective`], [`Feature::Subsective`], etc.
652    pub features: &'static [Feature],
653}
654
655/// Canonical mapping for verb synonyms and antonyms.
656///
657/// Maps a verb to its canonical form for semantic normalization.
658/// Antonyms are mapped with negative polarity, synonyms with positive.
659/// Example: "despise" → ("hate", Positive), "love" → ("hate", Negative).
660#[derive(Debug, Clone, Copy, PartialEq, Eq)]
661pub struct CanonicalMapping {
662    /// The canonical verb lemma this word maps to.
663    pub lemma: &'static str,
664
665    /// Whether the mapping preserves (Positive) or inverts (Negative) polarity.
666    pub polarity: Polarity,
667}
668
669/// Morphological rule for derivational morphology.
670///
671/// Defines how suffixes transform words between categories.
672/// Used for productive morphological patterns like "-ness" (adj → noun)
673/// or "-ly" (adj → adv).
674#[derive(Debug, Clone, Copy, PartialEq, Eq)]
675pub struct MorphologicalRule {
676    /// The suffix that triggers this rule (e.g., "-ness", "-ly").
677    pub suffix: &'static str,
678
679    /// The part of speech or category produced (e.g., "noun", "adverb").
680    pub produces: &'static str,
681}