1use crate::{
34 analysis, Arena, CompileOptions, drs, Interner, lambda, lexicon, Lexer, mwe,
35 OutputFormat, Parser, pragmatics, semantics, SymbolRegistry, ParseError, token,
36 arena_ctx::AstContext,
37 parser::{NegativeScopeMode, ModalPreference, QuantifierParsing},
38};
39
40pub const MAX_FOREST_READINGS: usize = 12;
43
44pub fn compile(input: &str) -> Result<String, ParseError> {
46 compile_with_options(input, CompileOptions::default())
47}
48
49pub fn compile_simple(input: &str) -> Result<String, ParseError> {
51 compile_with_options(input, CompileOptions {
52 format: OutputFormat::SimpleFOL,
53 })
54}
55
56pub fn compile_kripke(input: &str) -> Result<String, ParseError> {
59 compile_with_options(input, CompileOptions {
60 format: OutputFormat::Kripke,
61 })
62}
63
64pub fn compile_with_options(input: &str, options: CompileOptions) -> Result<String, ParseError> {
66 let mut interner = Interner::new();
67 let mut lexer = Lexer::new(input, &mut interner);
68 let tokens = lexer.tokenize();
69
70 let mwe_trie = mwe::build_mwe_trie();
72 let tokens = mwe::apply_mwe_pipeline(tokens, &mwe_trie, &mut interner);
73
74 let type_registry = {
76 let mut discovery = analysis::DiscoveryPass::new(&tokens, &mut interner);
77 discovery.run()
78 };
79
80 let expr_arena = Arena::new();
81 let term_arena = Arena::new();
82 let np_arena = Arena::new();
83 let sym_arena = Arena::new();
84 let role_arena = Arena::new();
85 let pp_arena = Arena::new();
86
87 let ctx = AstContext::new(
88 &expr_arena,
89 &term_arena,
90 &np_arena,
91 &sym_arena,
92 &role_arena,
93 &pp_arena,
94 );
95
96 let mut world_state = drs::WorldState::new();
98 let mut parser = Parser::new(tokens, &mut world_state, &mut interner, ctx, type_registry);
99 let ast = parser.parse()?;
100 let ast = semantics::apply_axioms(ast, ctx.exprs, ctx.terms, &mut interner);
101
102 let ast = if options.format == OutputFormat::Kripke {
104 semantics::apply_kripke_lowering(ast, ctx.exprs, ctx.terms, &mut interner)
105 } else {
106 ast
107 };
108
109 let ast = pragmatics::apply_pragmatics(ast, ctx.exprs, &interner);
110 let mut registry = SymbolRegistry::new();
111 let main_output = ast.transpile_discourse(&mut registry, &interner, options.format);
113
114 let constraints = world_state.time_constraints();
116 if constraints.is_empty() {
117 Ok(main_output)
118 } else {
119 let constraint_strs: Vec<String> = constraints.iter().map(|c| {
120 match c.relation {
121 drs::TimeRelation::Precedes => format!("Precedes({}, {})", c.left, c.right),
122 drs::TimeRelation::Equals => format!("{}={}", c.left, c.right),
123 }
124 }).collect();
125 Ok(format!("{} ∧ {}", main_output, constraint_strs.join(" ∧ ")))
126 }
127}
128
129pub fn compile_with_world_state(input: &str, world_state: &mut drs::WorldState) -> Result<String, ParseError> {
131 compile_with_world_state_options(input, world_state, CompileOptions::default())
132}
133
134pub fn compile_with_world_state_options(
136 input: &str,
137 world_state: &mut drs::WorldState,
138 options: CompileOptions,
139) -> Result<String, ParseError> {
140 let mut interner = Interner::new();
141 compile_with_world_state_interner_options(input, world_state, &mut interner, options)
142}
143
144pub fn compile_with_discourse(
147 input: &str,
148 world_state: &mut drs::WorldState,
149 interner: &mut Interner,
150) -> Result<String, ParseError> {
151 compile_with_world_state_interner_options(input, world_state, interner, CompileOptions::default())
152}
153
154pub fn compile_with_world_state_interner_options(
156 input: &str,
157 world_state: &mut drs::WorldState,
158 interner: &mut Interner,
159 options: CompileOptions,
160) -> Result<String, ParseError> {
161 let mut lexer = Lexer::new(input, interner);
162 let tokens = lexer.tokenize();
163
164 let mwe_trie = mwe::build_mwe_trie();
166 let tokens = mwe::apply_mwe_pipeline(tokens, &mwe_trie, interner);
167
168 let type_registry = {
170 let mut discovery = analysis::DiscoveryPass::new(&tokens, interner);
171 discovery.run()
172 };
173
174 let expr_arena = Arena::new();
175 let term_arena = Arena::new();
176 let np_arena = Arena::new();
177 let sym_arena = Arena::new();
178 let role_arena = Arena::new();
179 let pp_arena = Arena::new();
180
181 let ctx = AstContext::new(
182 &expr_arena,
183 &term_arena,
184 &np_arena,
185 &sym_arena,
186 &role_arena,
187 &pp_arena,
188 );
189
190 let mut parser = Parser::new(tokens, world_state, interner, ctx, type_registry);
191 parser.swap_drs_with_world_state();
193 let ast = parser.parse()?;
194 parser.swap_drs_with_world_state();
196 let ast = semantics::apply_axioms(ast, ctx.exprs, ctx.terms, interner);
197
198 world_state.end_sentence();
200
201 let ast = if options.format == OutputFormat::Kripke {
202 semantics::apply_kripke_lowering(ast, ctx.exprs, ctx.terms, interner)
203 } else {
204 ast
205 };
206
207 let ast = pragmatics::apply_pragmatics(ast, ctx.exprs, interner);
208 let mut registry = SymbolRegistry::new();
209 let main_output = ast.transpile_discourse(&mut registry, interner, options.format);
210
211 let constraints = world_state.time_constraints();
212 if constraints.is_empty() {
213 Ok(main_output)
214 } else {
215 let constraint_strs: Vec<String> = constraints.iter().map(|c| {
216 match c.relation {
217 drs::TimeRelation::Precedes => format!("Precedes({}, {})", c.left, c.right),
218 drs::TimeRelation::Equals => format!("{}={}", c.left, c.right),
219 }
220 }).collect();
221 Ok(format!("{} ∧ {}", main_output, constraint_strs.join(" ∧ ")))
222 }
223}
224
225pub fn compile_all_scopes(input: &str) -> Result<Vec<String>, ParseError> {
231 compile_all_scopes_with_options(input, CompileOptions::default())
232}
233
234pub fn compile_all_scopes_with_options(input: &str, options: CompileOptions) -> Result<Vec<String>, ParseError> {
236 let mut interner = Interner::new();
237 let mut lexer = Lexer::new(input, &mut interner);
238 let tokens = lexer.tokenize();
239
240 let mwe_trie = mwe::build_mwe_trie();
242 let tokens = mwe::apply_mwe_pipeline(tokens, &mwe_trie, &mut interner);
243
244 let type_registry = {
246 let mut discovery = analysis::DiscoveryPass::new(&tokens, &mut interner);
247 discovery.run()
248 };
249
250 let expr_arena = Arena::new();
251 let term_arena = Arena::new();
252 let np_arena = Arena::new();
253 let sym_arena = Arena::new();
254 let role_arena = Arena::new();
255 let pp_arena = Arena::new();
256
257 let ctx = AstContext::new(
258 &expr_arena,
259 &term_arena,
260 &np_arena,
261 &sym_arena,
262 &role_arena,
263 &pp_arena,
264 );
265
266 let mut world_state = drs::WorldState::new();
268 let mut parser = Parser::new(tokens, &mut world_state, &mut interner, ctx, type_registry);
269 let ast = parser.parse()?;
270
271 let scope_arena = Arena::new();
272 let scope_term_arena = Arena::new();
273 let scopings = lambda::enumerate_scopings(ast, &mut interner, &scope_arena, &scope_term_arena);
274
275 let intensional_arena = Arena::new();
276 let intensional_term_arena = Arena::new();
277 let intensional_role_arena: Arena<(crate::ast::ThematicRole, crate::ast::Term)> = Arena::new();
278
279 let mut results = Vec::new();
280 for scoped_expr in scopings {
281 let intensional_readings = lambda::enumerate_intensional_readings(
282 scoped_expr,
283 &mut interner,
284 &intensional_arena,
285 &intensional_term_arena,
286 &intensional_role_arena,
287 );
288 for reading in intensional_readings {
289 let reading = semantics::apply_axioms(reading, &intensional_arena, &intensional_term_arena, &mut interner);
290 let mut registry = SymbolRegistry::new();
291 results.push(reading.transpile(&mut registry, &interner, options.format));
292 }
293 }
294
295 Ok(results)
296}
297
298pub fn compile_forest(input: &str) -> Vec<String> {
305 compile_forest_with_options(input, CompileOptions::default())
306}
307
308pub fn compile_forest_with_options(input: &str, options: CompileOptions) -> Vec<String> {
310 let mut interner = Interner::new();
311 let mut lexer = Lexer::new(input, &mut interner);
312 let tokens = lexer.tokenize();
313
314 let mwe_trie = mwe::build_mwe_trie();
316 let tokens = mwe::apply_mwe_pipeline(tokens, &mwe_trie, &mut interner);
317
318 let type_registry = {
320 let mut discovery = analysis::DiscoveryPass::new(&tokens, &mut interner);
321 discovery.run()
322 };
323
324 let has_lexical_ambiguity = tokens.iter().any(|t| {
325 matches!(t.kind, token::TokenType::Ambiguous { .. })
326 });
327
328 let has_pp_ambiguity = tokens.iter().any(|t| {
329 if let token::TokenType::Preposition(sym) = &t.kind {
330 let prep = interner.resolve(*sym);
331 prep == "with" || prep == "by" || prep == "for"
332 } else {
333 false
334 }
335 });
336
337 let has_mixed_verb = tokens.iter().any(|t| {
339 if let token::TokenType::Verb { lemma, .. } = &t.kind {
340 Lexer::is_mixed_verb(interner.resolve(*lemma))
341 } else {
342 false
343 }
344 });
345
346 let has_collective_verb = tokens.iter().any(|t| {
348 if let token::TokenType::Verb { lemma, .. } = &t.kind {
349 Lexer::is_collective_verb(interner.resolve(*lemma))
350 } else {
351 false
352 }
353 });
354
355 let has_plural_subject = tokens.iter().any(|t| {
356 matches!(t.kind, token::TokenType::Cardinal(_))
357 || matches!(&t.kind, token::TokenType::Article(def) if matches!(def, lexicon::Definiteness::Definite))
358 });
359
360 let has_plurality_ambiguity = (has_mixed_verb || has_collective_verb) && has_plural_subject;
361
362 let has_event_adjective_ambiguity = {
364 let mut has_event_adj = false;
365 let mut has_agentive_noun = false;
366 for token in &tokens {
367 if let token::TokenType::Adjective(sym) = &token.kind {
368 if lexicon::is_event_modifier_adjective(interner.resolve(*sym)) {
369 has_event_adj = true;
370 }
371 }
372 if let token::TokenType::Noun(sym) = &token.kind {
373 if lexicon::lookup_agentive_noun(interner.resolve(*sym)).is_some() {
374 has_agentive_noun = true;
375 }
376 }
377 }
378 has_event_adj && has_agentive_noun
379 };
380
381 let has_negative_verb = tokens.iter().any(|t| {
383 if let token::TokenType::Verb { lemma, .. } = &t.kind {
384 lexicon::get_canonical_verb(&interner.resolve(*lemma).to_lowercase())
385 .map(|(_, is_neg)| is_neg)
386 .unwrap_or(false)
387 } else {
388 false
389 }
390 });
391
392 let has_may = tokens.iter().any(|t| matches!(t.kind, token::TokenType::May));
394 let has_can = tokens.iter().any(|t| matches!(t.kind, token::TokenType::Can));
395 let has_could = tokens.iter().any(|t| matches!(t.kind, token::TokenType::Could));
396
397 let mut results: Vec<String> = Vec::new();
398
399 {
401 let expr_arena = Arena::new();
402 let term_arena = Arena::new();
403 let np_arena = Arena::new();
404 let sym_arena = Arena::new();
405 let role_arena = Arena::new();
406 let pp_arena = Arena::new();
407
408 let ast_ctx = AstContext::new(
409 &expr_arena,
410 &term_arena,
411 &np_arena,
412 &sym_arena,
413 &role_arena,
414 &pp_arena,
415 );
416
417 let mut world_state = drs::WorldState::new();
418 let mut parser = Parser::new(tokens.clone(), &mut world_state, &mut interner, ast_ctx, type_registry.clone());
419 parser.set_noun_priority_mode(false);
420
421 if let Ok(ast) = parser.parse() {
422 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner);
423 let ast = if options.format == OutputFormat::Kripke {
424 semantics::apply_kripke_lowering(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner)
425 } else {
426 ast
427 };
428 let mut registry = SymbolRegistry::new();
429 results.push(ast.transpile_discourse(&mut registry, &interner, options.format));
430 }
431 }
432
433 if has_lexical_ambiguity {
435 let expr_arena = Arena::new();
436 let term_arena = Arena::new();
437 let np_arena = Arena::new();
438 let sym_arena = Arena::new();
439 let role_arena = Arena::new();
440 let pp_arena = Arena::new();
441
442 let ast_ctx = AstContext::new(
443 &expr_arena,
444 &term_arena,
445 &np_arena,
446 &sym_arena,
447 &role_arena,
448 &pp_arena,
449 );
450
451 let mut world_state = drs::WorldState::new();
452 let mut parser = Parser::new(tokens.clone(), &mut world_state, &mut interner, ast_ctx, type_registry.clone());
453 parser.set_noun_priority_mode(true);
454
455 if let Ok(ast) = parser.parse() {
456 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner);
457 let ast = if options.format == OutputFormat::Kripke {
458 semantics::apply_kripke_lowering(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner)
459 } else {
460 ast
461 };
462 let mut registry = SymbolRegistry::new();
463 let reading = ast.transpile_discourse(&mut registry, &interner, options.format);
464 if !results.contains(&reading) {
465 results.push(reading);
466 }
467 }
468 }
469
470 if has_pp_ambiguity {
472 let expr_arena = Arena::new();
473 let term_arena = Arena::new();
474 let np_arena = Arena::new();
475 let sym_arena = Arena::new();
476 let role_arena = Arena::new();
477 let pp_arena = Arena::new();
478
479 let ast_ctx = AstContext::new(
480 &expr_arena,
481 &term_arena,
482 &np_arena,
483 &sym_arena,
484 &role_arena,
485 &pp_arena,
486 );
487
488 let mut world_state = drs::WorldState::new();
489 let mut parser = Parser::new(tokens.clone(), &mut world_state, &mut interner, ast_ctx, type_registry.clone());
490 parser.set_pp_attachment_mode(true);
491
492 if let Ok(ast) = parser.parse() {
493 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner);
494 let ast = if options.format == OutputFormat::Kripke {
495 semantics::apply_kripke_lowering(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner)
496 } else {
497 ast
498 };
499 let mut registry = SymbolRegistry::new();
500 let reading = ast.transpile_discourse(&mut registry, &interner, options.format);
501 if !results.contains(&reading) {
502 results.push(reading);
503 }
504 }
505 }
506
507 if has_plurality_ambiguity {
509 let expr_arena = Arena::new();
510 let term_arena = Arena::new();
511 let np_arena = Arena::new();
512 let sym_arena = Arena::new();
513 let role_arena = Arena::new();
514 let pp_arena = Arena::new();
515
516 let ast_ctx = AstContext::new(
517 &expr_arena,
518 &term_arena,
519 &np_arena,
520 &sym_arena,
521 &role_arena,
522 &pp_arena,
523 );
524
525 let mut world_state = drs::WorldState::new();
526 let mut parser = Parser::new(tokens.clone(), &mut world_state, &mut interner, ast_ctx, type_registry.clone());
527 parser.set_collective_mode(true);
528
529 if let Ok(ast) = parser.parse() {
530 if let Ok(transformed) = parser.transform_cardinal_to_group(ast) {
531 let transformed = semantics::apply_axioms(transformed, ast_ctx.exprs, ast_ctx.terms, &mut interner);
532 let mut registry = SymbolRegistry::new();
533 let reading = transformed.transpile(&mut registry, &interner, options.format);
534 if !results.contains(&reading) {
535 results.push(reading);
536 }
537 }
538 }
539 }
540
541 if has_event_adjective_ambiguity {
543 let expr_arena = Arena::new();
544 let term_arena = Arena::new();
545 let np_arena = Arena::new();
546 let sym_arena = Arena::new();
547 let role_arena = Arena::new();
548 let pp_arena = Arena::new();
549
550 let ast_ctx = AstContext::new(
551 &expr_arena,
552 &term_arena,
553 &np_arena,
554 &sym_arena,
555 &role_arena,
556 &pp_arena,
557 );
558
559 let mut world_state = drs::WorldState::new();
560 let mut parser = Parser::new(tokens.clone(), &mut world_state, &mut interner, ast_ctx, type_registry.clone());
561 parser.set_event_reading_mode(true);
562
563 if let Ok(ast) = parser.parse() {
564 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner);
565 let ast = if options.format == OutputFormat::Kripke {
566 semantics::apply_kripke_lowering(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner)
567 } else {
568 ast
569 };
570 let mut registry = SymbolRegistry::new();
571 let reading = ast.transpile_discourse(&mut registry, &interner, options.format);
572 if !results.contains(&reading) {
573 results.push(reading);
574 }
575 }
576 }
577
578 if has_negative_verb {
580 let expr_arena = Arena::new();
581 let term_arena = Arena::new();
582 let np_arena = Arena::new();
583 let sym_arena = Arena::new();
584 let role_arena = Arena::new();
585 let pp_arena = Arena::new();
586
587 let ast_ctx = AstContext::new(
588 &expr_arena,
589 &term_arena,
590 &np_arena,
591 &sym_arena,
592 &role_arena,
593 &pp_arena,
594 );
595
596 let mut world_state = drs::WorldState::new();
597 let mut parser = Parser::new(tokens.clone(), &mut world_state, &mut interner, ast_ctx, type_registry.clone());
598 parser.set_negative_scope_mode(NegativeScopeMode::Wide);
599
600 if let Ok(ast) = parser.parse() {
601 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner);
602 let ast = if options.format == OutputFormat::Kripke {
603 semantics::apply_kripke_lowering(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner)
604 } else {
605 ast
606 };
607 let mut registry = SymbolRegistry::new();
608 let reading = ast.transpile_discourse(&mut registry, &interner, options.format);
609 if !results.contains(&reading) {
610 results.push(reading);
611 }
612 }
613 }
614
615 if has_may || has_could {
617 let expr_arena = Arena::new();
618 let term_arena = Arena::new();
619 let np_arena = Arena::new();
620 let sym_arena = Arena::new();
621 let role_arena = Arena::new();
622 let pp_arena = Arena::new();
623
624 let ast_ctx = AstContext::new(
625 &expr_arena,
626 &term_arena,
627 &np_arena,
628 &sym_arena,
629 &role_arena,
630 &pp_arena,
631 );
632
633 let mut world_state = drs::WorldState::new();
634 let mut parser = Parser::new(tokens.clone(), &mut world_state, &mut interner, ast_ctx, type_registry.clone());
635 parser.set_modal_preference(ModalPreference::Epistemic);
636
637 if let Ok(ast) = parser.parse() {
638 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner);
639 let ast = if options.format == OutputFormat::Kripke {
640 semantics::apply_kripke_lowering(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner)
641 } else {
642 ast
643 };
644 let mut registry = SymbolRegistry::new();
645 let reading = ast.transpile_discourse(&mut registry, &interner, options.format);
646 if !results.contains(&reading) {
647 results.push(reading);
648 }
649 }
650 }
651
652 if has_can {
654 let expr_arena = Arena::new();
655 let term_arena = Arena::new();
656 let np_arena = Arena::new();
657 let sym_arena = Arena::new();
658 let role_arena = Arena::new();
659 let pp_arena = Arena::new();
660
661 let ast_ctx = AstContext::new(
662 &expr_arena,
663 &term_arena,
664 &np_arena,
665 &sym_arena,
666 &role_arena,
667 &pp_arena,
668 );
669
670 let mut world_state = drs::WorldState::new();
671 let mut parser = Parser::new(tokens.clone(), &mut world_state, &mut interner, ast_ctx, type_registry.clone());
672 parser.set_modal_preference(ModalPreference::Deontic);
673
674 if let Ok(ast) = parser.parse() {
675 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner);
676 let ast = if options.format == OutputFormat::Kripke {
677 semantics::apply_kripke_lowering(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner)
678 } else {
679 ast
680 };
681 let mut registry = SymbolRegistry::new();
682 let reading = ast.transpile_discourse(&mut registry, &interner, options.format);
683 if !results.contains(&reading) {
684 results.push(reading);
685 }
686 }
687 }
688
689 if has_negative_verb && has_can {
691 let expr_arena = Arena::new();
692 let term_arena = Arena::new();
693 let np_arena = Arena::new();
694 let sym_arena = Arena::new();
695 let role_arena = Arena::new();
696 let pp_arena = Arena::new();
697
698 let ast_ctx = AstContext::new(
699 &expr_arena,
700 &term_arena,
701 &np_arena,
702 &sym_arena,
703 &role_arena,
704 &pp_arena,
705 );
706
707 let mut world_state = drs::WorldState::new();
708 let mut parser = Parser::new(tokens.clone(), &mut world_state, &mut interner, ast_ctx, type_registry);
709 parser.set_negative_scope_mode(NegativeScopeMode::Wide);
710 parser.set_modal_preference(ModalPreference::Deontic);
711
712 if let Ok(ast) = parser.parse() {
713 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner);
714 let ast = if options.format == OutputFormat::Kripke {
715 semantics::apply_kripke_lowering(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner)
716 } else {
717 ast
718 };
719 let mut registry = SymbolRegistry::new();
720 let reading = ast.transpile_discourse(&mut registry, &interner, options.format);
721 if !results.contains(&reading) {
722 results.push(reading);
723 }
724 }
725 }
726
727 results.truncate(MAX_FOREST_READINGS);
729
730 results
731}
732
733pub fn compile_discourse(sentences: &[&str]) -> Result<String, ParseError> {
739 compile_discourse_with_options(sentences, CompileOptions::default())
740}
741
742pub fn compile_discourse_with_options(sentences: &[&str], options: CompileOptions) -> Result<String, ParseError> {
744 let mut interner = Interner::new();
745 let mut world_state = drs::WorldState::new();
746 let mut results = Vec::new();
747 let mut registry = SymbolRegistry::new();
748 let mwe_trie = mwe::build_mwe_trie();
749
750 for sentence in sentences {
751 let event_var_name = world_state.next_event_var();
752 let event_var_symbol = interner.intern(&event_var_name);
753
754 let mut lexer = Lexer::new(sentence, &mut interner);
755 let tokens = lexer.tokenize();
756
757 let tokens = mwe::apply_mwe_pipeline(tokens, &mwe_trie, &mut interner);
759
760 let type_registry = {
762 let mut discovery = analysis::DiscoveryPass::new(&tokens, &mut interner);
763 discovery.run()
764 };
765
766 let expr_arena = Arena::new();
767 let term_arena = Arena::new();
768 let np_arena = Arena::new();
769 let sym_arena = Arena::new();
770 let role_arena = Arena::new();
771 let pp_arena = Arena::new();
772
773 let ast_ctx = AstContext::new(
774 &expr_arena,
775 &term_arena,
776 &np_arena,
777 &sym_arena,
778 &role_arena,
779 &pp_arena,
780 );
781
782 let mut parser = Parser::new(tokens, &mut world_state, &mut interner, ast_ctx, type_registry);
784 parser.set_discourse_event_var(event_var_symbol);
785 parser.swap_drs_with_world_state();
787 let ast = parser.parse()?;
788 parser.swap_drs_with_world_state();
790
791 world_state.end_sentence();
793
794 let ast = semantics::apply_axioms(ast, ast_ctx.exprs, ast_ctx.terms, &mut interner);
795 results.push(ast.transpile_discourse(&mut registry, &interner, options.format));
796 }
797
798 let event_history = world_state.event_history();
799 let mut precedes = Vec::new();
800 for i in 0..event_history.len().saturating_sub(1) {
801 precedes.push(format!("Precedes({}, {})", event_history[i], event_history[i + 1]));
802 }
803
804 if precedes.is_empty() {
805 Ok(results.join(" ∧ "))
806 } else {
807 Ok(format!("{} ∧ {}", results.join(" ∧ "), precedes.join(" ∧ ")))
808 }
809}
810
811pub fn compile_ambiguous(input: &str) -> Result<Vec<String>, ParseError> {
818 compile_ambiguous_with_options(input, CompileOptions::default())
819}
820
821pub fn compile_ambiguous_with_options(input: &str, options: CompileOptions) -> Result<Vec<String>, ParseError> {
823 let mut interner = Interner::new();
824 let mut lexer = Lexer::new(input, &mut interner);
825 let tokens = lexer.tokenize();
826
827 let mwe_trie = mwe::build_mwe_trie();
829 let tokens = mwe::apply_mwe_pipeline(tokens, &mwe_trie, &mut interner);
830
831 let type_registry = {
833 let mut discovery = analysis::DiscoveryPass::new(&tokens, &mut interner);
834 discovery.run()
835 };
836
837 let expr_arena = Arena::new();
838 let term_arena = Arena::new();
839 let np_arena = Arena::new();
840 let sym_arena = Arena::new();
841 let role_arena = Arena::new();
842 let pp_arena = Arena::new();
843
844 let ctx = AstContext::new(
845 &expr_arena,
846 &term_arena,
847 &np_arena,
848 &sym_arena,
849 &role_arena,
850 &pp_arena,
851 );
852
853 let mut world_state = drs::WorldState::new();
855 let mut parser = Parser::new(tokens.clone(), &mut world_state, &mut interner, ctx, type_registry.clone());
856 let ast = parser.parse()?;
857 let ast = semantics::apply_axioms(ast, ctx.exprs, ctx.terms, &mut interner);
858 let mut registry = SymbolRegistry::new();
859 let reading1 = ast.transpile(&mut registry, &interner, options.format);
860
861 let has_pp_ambiguity = tokens.iter().any(|t| {
862 if let token::TokenType::Preposition(sym) = &t.kind {
863 let prep = interner.resolve(*sym);
864 prep == "with" || prep == "by" || prep == "for"
865 } else {
866 false
867 }
868 });
869
870 if has_pp_ambiguity {
871 let expr_arena2 = Arena::new();
872 let term_arena2 = Arena::new();
873 let np_arena2 = Arena::new();
874 let sym_arena2 = Arena::new();
875 let role_arena2 = Arena::new();
876 let pp_arena2 = Arena::new();
877
878 let ctx2 = AstContext::new(
879 &expr_arena2,
880 &term_arena2,
881 &np_arena2,
882 &sym_arena2,
883 &role_arena2,
884 &pp_arena2,
885 );
886
887 let mut world_state2 = drs::WorldState::new();
888 let mut parser2 = Parser::new(tokens, &mut world_state2, &mut interner, ctx2, type_registry);
889 parser2.set_pp_attachment_mode(true);
890 let ast2 = parser2.parse()?;
891 let ast2 = semantics::apply_axioms(ast2, ctx2.exprs, ctx2.terms, &mut interner);
892 let mut registry2 = SymbolRegistry::new();
893 let reading2 = ast2.transpile(&mut registry2, &interner, options.format);
894
895 if reading1 != reading2 {
896 return Ok(vec![reading1, reading2]);
897 }
898 }
899
900 Ok(vec![reading1])
901}
902
903use crate::ast::{self, Stmt};
908use crate::token::Span;
909use crate::error::ParseErrorKind;
910use logicaffeine_proof::BackwardChainer;
911use crate::proof_convert::logic_expr_to_proof_expr;
912
913pub fn compile_theorem(input: &str) -> Result<String, ParseError> {
915 let mut interner = Interner::new();
916 let mut lexer = Lexer::new(input, &mut interner);
917 let tokens = lexer.tokenize();
918
919 let mwe_trie = mwe::build_mwe_trie();
921 let tokens = mwe::apply_mwe_pipeline(tokens, &mwe_trie, &mut interner);
922
923 let type_registry = {
925 let mut discovery = analysis::DiscoveryPass::new(&tokens, &mut interner);
926 discovery.run()
927 };
928
929 let expr_arena = Arena::new();
930 let term_arena = Arena::new();
931 let np_arena = Arena::new();
932 let sym_arena = Arena::new();
933 let role_arena = Arena::new();
934 let pp_arena = Arena::new();
935
936 let ctx = AstContext::new(
937 &expr_arena,
938 &term_arena,
939 &np_arena,
940 &sym_arena,
941 &role_arena,
942 &pp_arena,
943 );
944
945 let mut world_state = drs::WorldState::new();
947 let mut parser = Parser::new(tokens, &mut world_state, &mut interner, ctx, type_registry);
948 let statements = parser.parse_program()?;
949
950 let theorem = statements
952 .iter()
953 .find_map(|stmt| {
954 if let Stmt::Theorem(t) = stmt {
955 Some(t)
956 } else {
957 None
958 }
959 })
960 .ok_or_else(|| ParseError {
961 kind: ParseErrorKind::Custom("No theorem block found in input".to_string()),
962 span: Span::default(),
963 })?;
964
965 let mut engine = BackwardChainer::new();
967 for premise in &theorem.premises {
968 let proof_expr = logic_expr_to_proof_expr(premise, &interner);
969 engine.add_axiom(proof_expr);
970 }
971
972 let goal = logic_expr_to_proof_expr(theorem.goal, &interner);
974
975 match engine.prove(goal.clone()) {
977 Ok(derivation) => {
978 Ok(format!(
979 "Theorem '{}' Proved!\n{}",
980 theorem.name,
981 derivation.display_tree()
982 ))
983 }
984 Err(e) => {
985 Err(ParseError {
987 kind: ParseErrorKind::Custom(format!(
988 "Theorem '{}' failed.\n Goal: {}\n Premises: {}\n Error: {}",
989 theorem.name,
990 goal,
991 theorem.premises.len(),
992 e
993 )),
994 span: Span::default(),
995 })
996 }
997 }
998}
999
1000#[cfg(test)]
1001mod tests {
1002 use super::*;
1003
1004 #[test]
1005 fn test_compile_simple_sentence() {
1006 let result = compile("John runs.");
1007 assert!(result.is_ok());
1008 let output = result.unwrap();
1009 assert!(output.contains("Run"));
1010 assert!(output.contains("John"));
1011 }
1012
1013 #[test]
1014 fn test_compile_with_unicode_format() {
1015 let options = CompileOptions { format: OutputFormat::Unicode };
1016 let result = compile_with_options("Every dog barks.", options);
1017 assert!(result.is_ok());
1018 let output = result.unwrap();
1019 assert!(output.contains("∀") || output.contains("Forall"));
1020 }
1021
1022 #[test]
1023 fn test_compile_all_scopes() {
1024 let result = compile_all_scopes("Every woman loves a man.");
1025 assert!(result.is_ok());
1026 let readings = result.unwrap();
1027 assert!(readings.len() >= 1);
1028 }
1029}