1use crate::engine::Paradigm;
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27pub enum SemanticClass {
28 Conjunction, Disjunction, Negation, Implication, Biconditional, ExclusiveOr, Verum, Falsum, Necessity, Possibility, Knows, Believes, CommonKnowledge, DistributedKnowledge, Obligatory, Permitted, Forbidden, Waived, Globally, Finally, Next, Until, Release, WeakUntil, MembershipDegree, FuzzyAnd, FuzzyOr, Probability, BothTrueAndFalse, NeitherTrueNorFalse,
71
72 Universal, Existential, UniqueExistential, ElementOf, NotElementOf, Subset, StrictSubset, Union, Intersection, EmptySet, Equals, NotEquals, LessThan, LessOrEqual, GreaterThan, GreaterOrEqual, Turnstile, DoubleTurnstile, Therefore, Because, Identifier,
102 NumericLiteral,
103 StringLiteral,
104 BooleanLiteral,
105 TimeLiteral,
106}
107
108impl SemanticClass {
109 pub fn paradigms(self) -> &'static [Paradigm] {
112 match self {
113 SemanticClass::Conjunction
114 | SemanticClass::Disjunction
115 | SemanticClass::Negation
116 | SemanticClass::Implication
117 | SemanticClass::Biconditional
118 | SemanticClass::ExclusiveOr
119 | SemanticClass::Verum
120 | SemanticClass::Falsum => &[Paradigm::Boolean],
121
122 SemanticClass::Necessity | SemanticClass::Possibility => {
123 &[Paradigm::Modal, Paradigm::Epistemic]
124 }
125
126 SemanticClass::Knows
127 | SemanticClass::Believes
128 | SemanticClass::CommonKnowledge
129 | SemanticClass::DistributedKnowledge => &[Paradigm::Epistemic],
130
131 SemanticClass::Obligatory
132 | SemanticClass::Permitted
133 | SemanticClass::Forbidden
134 | SemanticClass::Waived => &[Paradigm::Deontic],
135
136 SemanticClass::Globally
137 | SemanticClass::Finally
138 | SemanticClass::Next
139 | SemanticClass::Until
140 | SemanticClass::Release
141 | SemanticClass::WeakUntil => &[Paradigm::Temporal],
142
143 SemanticClass::MembershipDegree | SemanticClass::FuzzyAnd | SemanticClass::FuzzyOr => {
144 &[Paradigm::Fuzzy]
145 }
146
147 SemanticClass::Probability => &[Paradigm::Probabilistic],
148
149 SemanticClass::BothTrueAndFalse | SemanticClass::NeitherTrueNorFalse => {
150 &[Paradigm::Paraconsistent]
151 }
152
153 SemanticClass::Universal
154 | SemanticClass::Existential
155 | SemanticClass::UniqueExistential => &[Paradigm::Boolean, Paradigm::Modal],
156
157 _ => &[Paradigm::Boolean],
158 }
159 }
160}
161
162#[derive(Debug, Clone, Copy)]
164pub struct Symbol {
165 pub codepoint: u32,
167 pub keyword: Option<&'static str>,
169 pub name: &'static str,
171 pub class: SemanticClass,
173}
174
175pub struct UnicodeSemanticDictionary;
181
182impl UnicodeSemanticDictionary {
183 pub const ENTRIES: &'static [Symbol] = &[
185 Symbol {
187 codepoint: 0x2227,
188 keyword: Some("and"),
189 name: "Conjunction",
190 class: SemanticClass::Conjunction,
191 },
192 Symbol {
193 codepoint: 0x2228,
194 keyword: Some("or"),
195 name: "Disjunction",
196 class: SemanticClass::Disjunction,
197 },
198 Symbol {
199 codepoint: 0x00AC,
200 keyword: Some("not"),
201 name: "Negation",
202 class: SemanticClass::Negation,
203 },
204 Symbol {
205 codepoint: 0x2192,
206 keyword: Some("implies"),
207 name: "Implication",
208 class: SemanticClass::Implication,
209 },
210 Symbol {
211 codepoint: 0x2194,
212 keyword: Some("iff"),
213 name: "Biconditional",
214 class: SemanticClass::Biconditional,
215 },
216 Symbol {
217 codepoint: 0x2295,
218 keyword: Some("xor"),
219 name: "ExclusiveOr",
220 class: SemanticClass::ExclusiveOr,
221 },
222 Symbol {
223 codepoint: 0x22A4,
224 keyword: Some("true"),
225 name: "Verum",
226 class: SemanticClass::Verum,
227 },
228 Symbol {
229 codepoint: 0x22A5,
230 keyword: Some("false"),
231 name: "Falsum",
232 class: SemanticClass::Falsum,
233 },
234 Symbol {
236 codepoint: 0x25A1,
237 keyword: Some("necessarily"),
238 name: "Necessity",
239 class: SemanticClass::Necessity,
240 },
241 Symbol {
242 codepoint: 0x25C7,
243 keyword: Some("possibly"),
244 name: "Possibility",
245 class: SemanticClass::Possibility,
246 },
247 Symbol {
249 codepoint: 0x004B,
250 keyword: Some("knows"),
251 name: "Knows",
252 class: SemanticClass::Knows,
253 },
254 Symbol {
255 codepoint: 0x0042,
256 keyword: Some("believes"),
257 name: "Believes",
258 class: SemanticClass::Believes,
259 },
260 Symbol {
261 codepoint: 0x0043,
262 keyword: Some("common_knowledge"),
263 name: "CommonKnowledge",
264 class: SemanticClass::CommonKnowledge,
265 },
266 Symbol {
267 codepoint: 0x0044,
268 keyword: Some("distributed_knowledge"),
269 name: "DistributedKnowledge",
270 class: SemanticClass::DistributedKnowledge,
271 },
272 Symbol {
274 codepoint: 0x004F,
275 keyword: Some("must"),
276 name: "Obligatory",
277 class: SemanticClass::Obligatory,
278 },
279 Symbol {
280 codepoint: 0x0050,
281 keyword: Some("may"),
282 name: "Permitted",
283 class: SemanticClass::Permitted,
284 },
285 Symbol {
286 codepoint: 0x0046,
287 keyword: Some("must_not"),
288 name: "Forbidden",
289 class: SemanticClass::Forbidden,
290 },
291 Symbol {
292 codepoint: 0x0000,
293 keyword: Some("ought"),
294 name: "Obligatory",
295 class: SemanticClass::Obligatory,
296 },
297 Symbol {
298 codepoint: 0x0000,
299 keyword: Some("should"),
300 name: "Obligatory",
301 class: SemanticClass::Obligatory,
302 },
303 Symbol {
304 codepoint: 0x0000,
305 keyword: Some("prohibited"),
306 name: "Forbidden",
307 class: SemanticClass::Forbidden,
308 },
309 Symbol {
310 codepoint: 0x0000,
311 keyword: Some("permitted"),
312 name: "Permitted",
313 class: SemanticClass::Permitted,
314 },
315 Symbol {
316 codepoint: 0x0000,
317 keyword: Some("allowed"),
318 name: "Permitted",
319 class: SemanticClass::Permitted,
320 },
321 Symbol {
322 codepoint: 0x0000,
323 keyword: Some("forbidden"),
324 name: "Forbidden",
325 class: SemanticClass::Forbidden,
326 },
327 Symbol {
328 codepoint: 0x0000,
329 keyword: Some("waived"),
330 name: "Waived",
331 class: SemanticClass::Waived,
332 },
333 Symbol {
335 codepoint: 0x0047,
336 keyword: Some("always"),
337 name: "Globally",
338 class: SemanticClass::Globally,
339 },
340 Symbol {
341 codepoint: 0x0046,
342 keyword: Some("eventually"),
343 name: "Finally",
344 class: SemanticClass::Finally,
345 },
346 Symbol {
347 codepoint: 0x0058,
348 keyword: Some("next"),
349 name: "Next",
350 class: SemanticClass::Next,
351 },
352 Symbol {
353 codepoint: 0x0055,
354 keyword: Some("until"),
355 name: "Until",
356 class: SemanticClass::Until,
357 },
358 Symbol {
359 codepoint: 0x0052,
360 keyword: Some("release"),
361 name: "Release",
362 class: SemanticClass::Release,
363 },
364 Symbol {
365 codepoint: 0x0000,
366 keyword: Some("never"),
367 name: "Globally(¬)",
368 class: SemanticClass::Globally,
369 },
370 Symbol {
371 codepoint: 0x0000,
372 keyword: Some("within"),
373 name: "Finally",
374 class: SemanticClass::Finally,
375 },
376 Symbol {
377 codepoint: 0x0000,
378 keyword: Some("before"),
379 name: "Until",
380 class: SemanticClass::Until,
381 },
382 Symbol {
383 codepoint: 0x0000,
384 keyword: Some("after"),
385 name: "Finally",
386 class: SemanticClass::Finally,
387 },
388 Symbol {
389 codepoint: 0x0000,
390 keyword: Some("deadline"),
391 name: "Until",
392 class: SemanticClass::Until,
393 },
394 Symbol {
396 codepoint: 0x03BC,
397 keyword: Some("mu"),
398 name: "MembershipDegree",
399 class: SemanticClass::MembershipDegree,
400 },
401 Symbol {
402 codepoint: 0x2293,
403 keyword: Some("fuzzy_and"),
404 name: "FuzzyAnd",
405 class: SemanticClass::FuzzyAnd,
406 },
407 Symbol {
408 codepoint: 0x2294,
409 keyword: Some("fuzzy_or"),
410 name: "FuzzyOr",
411 class: SemanticClass::FuzzyOr,
412 },
413 Symbol {
414 codepoint: 0x0000,
415 keyword: Some("probability"),
416 name: "Probability",
417 class: SemanticClass::Probability,
418 },
419 Symbol {
420 codepoint: 0x0000,
421 keyword: Some("likely"),
422 name: "Probability",
423 class: SemanticClass::Probability,
424 },
425 Symbol {
426 codepoint: 0x0000,
427 keyword: Some("unlikely"),
428 name: "Probability",
429 class: SemanticClass::Probability,
430 },
431 Symbol {
433 codepoint: 0x2200,
434 keyword: Some("forall"),
435 name: "Universal",
436 class: SemanticClass::Universal,
437 },
438 Symbol {
439 codepoint: 0x2203,
440 keyword: Some("exists"),
441 name: "Existential",
442 class: SemanticClass::Existential,
443 },
444 Symbol {
445 codepoint: 0x2204,
446 keyword: Some("exists_unique"),
447 name: "UniqueExistential",
448 class: SemanticClass::UniqueExistential,
449 },
450 Symbol {
452 codepoint: 0x2208,
453 keyword: Some("in"),
454 name: "ElementOf",
455 class: SemanticClass::ElementOf,
456 },
457 Symbol {
458 codepoint: 0x2209,
459 keyword: Some("not_in"),
460 name: "NotElementOf",
461 class: SemanticClass::NotElementOf,
462 },
463 Symbol {
464 codepoint: 0x2286,
465 keyword: Some("subset"),
466 name: "Subset",
467 class: SemanticClass::Subset,
468 },
469 Symbol {
470 codepoint: 0x2282,
471 keyword: Some("strict_subset"),
472 name: "StrictSubset",
473 class: SemanticClass::StrictSubset,
474 },
475 Symbol {
476 codepoint: 0x222A,
477 keyword: Some("union"),
478 name: "Union",
479 class: SemanticClass::Union,
480 },
481 Symbol {
482 codepoint: 0x2229,
483 keyword: Some("intersect"),
484 name: "Intersection",
485 class: SemanticClass::Intersection,
486 },
487 Symbol {
488 codepoint: 0x2205,
489 keyword: Some("empty"),
490 name: "EmptySet",
491 class: SemanticClass::EmptySet,
492 },
493 Symbol {
495 codepoint: 0x003D,
496 keyword: Some("eq"),
497 name: "Equals",
498 class: SemanticClass::Equals,
499 },
500 Symbol {
501 codepoint: 0x2260,
502 keyword: Some("neq"),
503 name: "NotEquals",
504 class: SemanticClass::NotEquals,
505 },
506 Symbol {
507 codepoint: 0x003C,
508 keyword: Some("lt"),
509 name: "LessThan",
510 class: SemanticClass::LessThan,
511 },
512 Symbol {
513 codepoint: 0x2264,
514 keyword: Some("lte"),
515 name: "LessOrEqual",
516 class: SemanticClass::LessOrEqual,
517 },
518 Symbol {
519 codepoint: 0x003E,
520 keyword: Some("gt"),
521 name: "GreaterThan",
522 class: SemanticClass::GreaterThan,
523 },
524 Symbol {
525 codepoint: 0x2265,
526 keyword: Some("gte"),
527 name: "GreaterOrEqual",
528 class: SemanticClass::GreaterOrEqual,
529 },
530 Symbol {
532 codepoint: 0x22A2,
533 keyword: Some("proves"),
534 name: "Turnstile",
535 class: SemanticClass::Turnstile,
536 },
537 Symbol {
538 codepoint: 0x22A8,
539 keyword: Some("models"),
540 name: "DoubleTurnstile",
541 class: SemanticClass::DoubleTurnstile,
542 },
543 Symbol {
544 codepoint: 0x2234,
545 keyword: Some("therefore"),
546 name: "Therefore",
547 class: SemanticClass::Therefore,
548 },
549 Symbol {
550 codepoint: 0x2235,
551 keyword: Some("because"),
552 name: "Because",
553 class: SemanticClass::Because,
554 },
555 ];
556
557 pub fn lookup_codepoint(cp: u32) -> Option<&'static Symbol> {
559 Self::ENTRIES
560 .iter()
561 .find(|s| s.codepoint == cp && s.codepoint != 0)
562 }
563
564 pub fn lookup_keyword(kw: &str) -> Option<&'static Symbol> {
566 let mut buf = [0u8; 64];
568 let kw_bytes = kw.as_bytes();
569 let len = kw_bytes.len().min(64);
570 for (i, &b) in kw_bytes[..len].iter().enumerate() {
571 buf[i] = b.to_ascii_lowercase();
572 }
573 let lower = core::str::from_utf8(&buf[..len]).ok()?;
574 Self::ENTRIES.iter().find(|s| s.keyword == Some(lower))
575 }
576
577 pub fn detect_paradigms(classes: &[SemanticClass]) -> ParadigmSet {
580 let mut set = ParadigmSet::empty();
581 for cls in classes {
582 for &p in cls.paradigms() {
583 set.insert(p);
584 }
585 }
586 set.insert(Paradigm::Boolean);
588 set
589 }
590}
591
592#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
594#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
595pub struct ParadigmSet(u16);
596
597impl ParadigmSet {
598 pub const fn empty() -> Self {
599 Self(0)
600 }
601
602 pub fn insert(&mut self, p: Paradigm) {
603 self.0 |= 1 << (p as u8);
604 }
605
606 pub fn contains(&self, p: Paradigm) -> bool {
607 self.0 & (1 << (p as u8)) != 0
608 }
609
610 pub fn is_empty(&self) -> bool {
611 self.0 == 0
612 }
613
614 pub fn iter(&self) -> impl Iterator<Item = Paradigm> + '_ {
615 Paradigm::ALL.iter().copied().filter(|&p| self.contains(p))
616 }
617}