├── .gitignore ├── CHANGES.md ├── LICENSE.txt ├── Makefile ├── README.md ├── ape.pl ├── examples ├── README.md ├── ace_to_ace.pl ├── ace_to_owl.pl ├── output_tests.pl ├── paraphrase_roundtrip.pl └── the_lol_policy.ace.txt ├── get_ape_results.pl ├── java ├── README.md ├── install-jpl.sh ├── pom.xml └── src │ ├── main │ └── java │ │ ├── ch │ │ └── uzh │ │ │ └── ifi │ │ │ └── attempto │ │ │ └── ape │ │ │ ├── ACEParser.java │ │ │ ├── ACEParserException.java │ │ │ ├── ACEParserResult.java │ │ │ ├── ACEText.java │ │ │ ├── ACEUtils.java │ │ │ ├── APELocal.java │ │ │ ├── APESocket.java │ │ │ ├── APEWebservice.java │ │ │ ├── FunctionWords.java │ │ │ ├── Gender.java │ │ │ ├── Lexicon.java │ │ │ ├── LexiconEntry.java │ │ │ ├── Message.java │ │ │ ├── MessageContainer.java │ │ │ ├── OutputType.java │ │ │ ├── PrologUtils.java │ │ │ ├── SyntaxBoxes.java │ │ │ └── package-info.java │ │ └── overview.html │ └── test │ └── java │ └── ch │ └── uzh │ └── ifi │ └── attempto │ └── ape │ ├── APELocalTest.java │ ├── APESocketTest.java │ ├── APEWebserviceTest.java │ ├── LexiconEntryTest.java │ └── Testcase.java ├── make_exe.bat ├── pack.pl ├── prolog ├── ape.pl ├── lexicon │ ├── chars.pl │ ├── clex.pl │ ├── clex_lexicon.pl │ ├── functionwords.pl │ ├── illegalwords.pl │ ├── is_in_lexicon.pl │ ├── lexicon_interface.pl │ ├── spellcheck.pl │ └── ulex.pl ├── logger │ └── error_logger.pl ├── parser │ ├── .gitignore │ ├── ace_to_drs.pl │ ├── ape_utils.pl │ ├── compile.sh │ ├── fit_to_plp.pl │ ├── grammar.fit │ ├── grammar_contentwords.fit │ ├── grammar_functionwords.fit │ ├── grammar_words.pl │ ├── make_syntax_report.perl │ ├── prologfeatures.pl │ ├── refres.pl │ ├── sentence_failure.pl │ ├── sorts.fit │ ├── tokenizer.pl │ └── tokens_to_sentences.pl └── utils │ ├── ace_niceace.pl │ ├── are_equivalent.pl │ ├── drs_ops.pl │ ├── drs_reverse.pl │ ├── drs_to_ace.pl │ ├── drs_to_ascii.pl │ ├── drs_to_coreace.pl │ ├── drs_to_drslist.pl │ ├── drs_to_fol_to_prenex.pl │ ├── drs_to_html.pl │ ├── drs_to_npace.pl │ ├── drs_to_ruleml.pl │ ├── drs_to_sdrs.pl │ ├── drs_to_tptp.pl │ ├── drs_to_xml.pl │ ├── drs_utils.pl │ ├── implication_turn.pl │ ├── is_wellformed.pl │ ├── morphgen.pl │ ├── owlswrl │ ├── README.md │ ├── drs_to_owldrs.pl │ ├── drs_to_owlswrl.pl │ ├── drs_to_owlswrl_core.pl │ ├── get_owl_output.pl │ ├── illegal_conditions.pl │ ├── implication_to_swrl.pl │ ├── owlfss_owlrdfxml.pl │ ├── owlswrl_iri.pl │ ├── owlswrl_to_fss.pl │ ├── owlswrl_to_xml.pl │ ├── simplify_axiom.pl │ └── transform_anonymous.pl │ ├── serialize_term.pl │ ├── tree_utils.pl │ ├── trees_to_ascii.pl │ └── xmlterm_to_xmlatom.pl ├── run.sh ├── runape.pl ├── tests ├── .gitignore ├── README.md ├── acetexts.pl ├── bugs_and_requests.pl ├── downloader.pl ├── make_acetext_drs.pl ├── rtest.bash ├── test_ape.pl ├── test_apeexe.sh ├── test_drace.pl ├── test_drs_to_x.pl ├── test_duration.pl ├── test_everything.sh ├── test_owlswrl.pl ├── test_ruleml.sh └── testruns │ ├── .gitignore │ ├── README.drace │ ├── drace_test_results.txt │ ├── dracenp_test_results.txt │ ├── owlswrl_test_results.txt │ ├── sum.perl │ └── test_drs_to_tptp_out.txt └── tools ├── create_zip.sh ├── extract_words.perl └── search.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /ape.exe 2 | /ape-*.zip 3 | /packages 4 | *~ 5 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | APE Change Log 2 | ============== 3 | 4 | Version 6.7-180714 5 | ------------------ 6 | 7 | - Package APE as a [SWI-Prolog extension package](http://www.swi-prolog.org/howto/Pack.txt) 8 | (Thanks to @fnogatz, see more at https://github.com/Attempto/APE/pull/24) 9 | - Small fixes to improve compatibility with dependencies 10 | 11 | Version 6.7-131003 12 | ------------------ 13 | 14 | This release implements two new ACE features and brings minor improvements. 15 | 16 | - New in ACE 6.7: Support for the exponentiation operator ^ in arithmetical expressions, 17 | e.g. "2^3^4", which is parsed as (2^3)^4. 18 | - New in ACE 6.7: Support for how many/how much queries, which ask for numbers of 19 | countable nouns or for amounts of mass or measurement nouns, 20 | e.g. "How many beaches have how much sand?" 21 | - APE can now translate ACE texts into the RuleML format. 22 | - The coverage of the ACE-to-OWL translator has been improved. 23 | - The dependencies of the Java Interface for APE on external libraries are now managed using Maven. 24 | - The large Clex lexicon (~100,000 entries) was migrated to a separate repository [Attempto/Clex](https://github.com/Attempto/Clex). 25 | As before, the APE source distribution contains a reduced (~2000 entries) version of this lexicon. 26 | 27 | 28 | Version 6.6-110816 29 | ------------------ 30 | 31 | This is a bugfix release that brings minor changes and updates: 32 | 33 | - ACE to DRS translation: 34 | - fixed: sentences like "For every woman of who everybody waits." now correctly fail 35 | - fixed: a bug that in rare cases generated a DRS with duplicate referents 36 | - fixed: duplicate DRS conditions are now always suppressed 37 | - fixed: misguiding error message for imperatives 38 | - deprecated: the construct "the ... of which/who" 39 | - DRS to FOL translation: 40 | - fixed: disjunctions related by anaphoric references (e.g. the DRS of "A man sleeps or the man 41 | waits.") are now correctly mapped to FOL 42 | - DRS to ACE translation: 43 | - improved: handling of disjuntions, e.g. "Every dog barks or a cat sleeps." is now paraphrased 44 | as "A cat sleeps or if there is a dog X1 then the dog X1 barks." 45 | - restored: support for 0, e.g. "There are 0 men." 46 | - DRS to OWL/SWRL translation: 47 | - the pretty-printed output (owlfsspp) now conforms to the OWL Functional-Style Syntax (and can 48 | be parsed by the OWL-API) 49 | - avoid including redundant owl:Thing in intersections 50 | - now supported: the DRS of "John does not see what?" 51 | - fixed: sentences like "There is X. If X is a fireman then X is a man." now map to OWL (instead 52 | of SWRL as before) 53 | - improved: the SWRL-mapping now supports formula/3 with =<, >=, \= 54 | - fixed: "Peter owns 3 kg of apples." now correctly fails 55 | - Attempto Java Packages: 56 | - updated the Apache HTTP libraries to httpcore-4.1.1.jar and httpclient-4.1.1.jar 57 | - removed the OWL Verbalizer Webservice interface, this is now available at 58 | owlverbalizer.googlecode.com 59 | - updated enum OutputType: removed OWLRDF, added TPTP 60 | - The APE regression test set (~3500 small ACE texts with their corresponding DRSs) is now included 61 | (see ape/acetext_drs.pl) 62 | - Several improvements to the documentation of ACE, DRS and the APE source code. 63 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Tested only on Ubuntu Linux. 2 | # For Windows builds use make_exe.bat 3 | 4 | SHELL=/bin/bash 5 | 6 | swipl = swipl 7 | version = 6.7 8 | 9 | text1 = "John likes Mary." 10 | text2 = "Every man likes a car." 11 | text3 = "1 / 2 ^ 3 ^ 4 = 1/8." 12 | text4 = "If John likes Mary then 1 / 2 ^ 3 = 1/8." 13 | text5 = "1 / 2 * 3 - 4 = 1/8." 14 | 15 | all: help 16 | 17 | help: 18 | @echo Targets: 19 | @echo 20 | @echo " plp: compiles fit-files into plp-files" 21 | @echo "install: builds ape.exe" 22 | @echo " build: (deprecated: use install)" 23 | @echo " doc: generates documentation" 24 | @echo " clean: deletes automatically generatable files" 25 | @echo " test: runs some tests" 26 | @echo 27 | 28 | 29 | build: 30 | $(swipl) -O -F none -g "working_directory(_, 'prolog/parser'), [fit_to_plp], halt." -t halt ; $(swipl) -O -f ape.pl -g "qsave_program('ape.exe', [goal(ape), toplevel(halt)])." -t halt 31 | 32 | plp: 33 | $(swipl) -O -F none -g "working_directory(_, 'prolog/parser'), [fit_to_plp], halt." -t halt 34 | 35 | install: plp 36 | $(swipl) -O -f ape.pl -g "qsave_program('ape.exe', [goal(ape), toplevel(halt)])." -t halt 37 | 38 | check: 39 | 40 | clean: 41 | rm -f *.exe *.toc prolog/parser/*.{plp,html,toc} 42 | 43 | doc: 44 | cat prolog/parser/{grammar,grammar_functionwords,grammar_contentwords}.fit | perl prolog/parser/make_syntax_report.perl 45 | cat prolog/parser/{grammar,grammar_functionwords,grammar_contentwords}.fit | perl prolog/parser/make_syntax_report.perl --number $(version) > syntax_report.html 46 | 47 | test: 48 | ./ape.exe -text $(text1) -cdrspp -cparaphrase -cowlfsspp -csyntax -csyntaxpp -csyntaxd -csyntaxdpp 49 | ./ape.exe -text $(text2) -cdrspp -cparaphrase -cowlfsspp 50 | ./ape.exe -text $(text3) -cdrspp -cparaphrase 51 | ./ape.exe -text $(text4) -solo owlfsspp 52 | ./ape.exe -text $(text5) -cdrspp -cparaphrase -cowlfsspp -csyntax -csyntaxpp -csyntaxd -csyntaxdpp 53 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | Examples 2 | ======== 3 | 4 | Introduction 5 | ------------ 6 | 7 | Some examples of using ACE->DRS, DRS->ACE, and ACE->OWL programmatically. 8 | 9 | 10 | Usage 11 | ----- 12 | 13 | Examples of calling the scripts from the command line: 14 | 15 | $ swipl -s ace_to_ace.pl -g "t('Every man is a human.')" -t halt 16 | 17 | $ swipl -s ace_to_owl.pl -g "t('Every man is a human.')" -t halt 18 | 19 | $ swipl -s paraphrase_roundtrip.pl -g paraphrase_roundtrip -t halt 20 | -------------------------------------------------------------------------------- /examples/ace_to_ace.pl: -------------------------------------------------------------------------------- 1 | /** 2 | This is an example that shows how to paraphrase ACE sentences as 3 | (syntactically different) ACE sentences. 4 | A simple Prolog commandline interface ('cli') is provided. 5 | 6 | @author Kaarel Kaljurand 7 | @version 2011-11-26 8 | 9 | Usage examples: 10 | 11 | == 12 | ?- t("Every man waits."). 13 | [If there is a man X1 then the man X1 waits.] 14 | 15 | ?- t("Every man waits.", CoreAce). 16 | CoreAce = ['If there is a man X1 then the man X1 waits.']. 17 | 18 | ?- tnp("Every man waits.", NpAce). 19 | NpAce = ['Every man waits.']. 20 | 21 | ?- cli. 22 | ACE to ACE> Every man waits. 23 | [If there is a man X1 then the man X1 waits.] 24 | == 25 | 26 | */ 27 | 28 | % We point to the directory where APE modules and the lexicons are located. 29 | :- assert(user:file_search_path(ape, '../prolog')). 30 | 31 | :- use_module(ape('parser/ace_to_drs'), [ 32 | acetext_to_drs/5 33 | ]). 34 | 35 | :- use_module(ape('logger/error_logger'), [ 36 | clear_messages/0 37 | ]). 38 | 39 | :- use_module(ape('utils/drs_to_coreace'), [ 40 | drs_to_coreace/2 41 | ]). 42 | 43 | :- use_module(ape('utils/drs_to_npace'), [ 44 | drs_to_npace/2 45 | ]). 46 | 47 | % Import the lexicons 48 | :- style_check(-singleton). 49 | :- style_check(-discontiguous). 50 | :- use_module(ape('lexicon/clex')). 51 | :- use_module(ape('lexicon/ulex')). 52 | :- style_check(+discontiguous). 53 | :- style_check(+singleton). 54 | 55 | 56 | %% t(+AceText:atom) is det. 57 | %% t(+AceText:atom, -Paraphrase:list) is det. 58 | % 59 | % @param AceText is an ACE text (as an atom) 60 | % @param Paraphrase is a paraphrase of ACE text (as a list of sentences) 61 | % 62 | t(AceText) :- 63 | t(AceText, Paraphrase), 64 | format("~w~n", [Paraphrase]). 65 | 66 | t(AceText, Paraphrase) :- 67 | acetext_to_drs(AceText, _, _, Drs, _), 68 | drs_to_coreace(Drs, Paraphrase). 69 | 70 | tnp(AceText, Paraphrase) :- 71 | acetext_to_drs(AceText, _, _, Drs, _), 72 | drs_to_npace(Drs, Paraphrase). 73 | 74 | % Commandline interface 75 | cli :- 76 | clear_messages, 77 | prompt(Old, 'ACE to ACE> '), 78 | read_text_from_commandline(AceText), 79 | prompt(_, Old), 80 | t(AceText), 81 | cli. 82 | 83 | read_text_from_commandline([C | R]) :- 84 | get0(C), 85 | line_continues(C), 86 | !, 87 | read_text_from_commandline(R). 88 | 89 | read_text_from_commandline([]). 90 | 91 | 92 | multiline(false). 93 | line_continues(C) :- C \== 10, C \== -1, !. 94 | line_continues(C) :- multiline(true), C \== -1. 95 | -------------------------------------------------------------------------------- /examples/ace_to_owl.pl: -------------------------------------------------------------------------------- 1 | /** 2 | This is an example that shows how to convert ACE sentences into OWL/SWRL. 3 | A simple Prolog commandline interface ('cli') is provided. 4 | 5 | @author Kaarel Kaljurand 6 | @version 2010-11-14 7 | 8 | */ 9 | 10 | % We point to the directory where APE modules and the lexicons are located. 11 | :- assert(user:file_search_path(ape, '../prolog')). 12 | 13 | :- use_module(ape('parser/ace_to_drs'), [ 14 | acetext_to_drs/5 15 | ]). 16 | 17 | :- use_module(ape('utils/drs_to_ascii'), [ 18 | drs_to_ascii/2 19 | ]). 20 | 21 | :- use_module(ape('utils/owlswrl/drs_to_owlswrl'), [ 22 | drs_to_owlswrl/4 23 | ]). 24 | 25 | % Import the lexicons 26 | :- style_check(-singleton). 27 | :- style_check(-discontiguous). 28 | :- use_module(ape('lexicon/clex')). 29 | :- use_module(ape('lexicon/ulex')). 30 | :- style_check(+discontiguous). 31 | :- style_check(+singleton). 32 | 33 | :- use_module(ape('logger/error_logger'), [ 34 | clear_messages/0, 35 | get_messages/1 36 | ]). 37 | 38 | :- use_module(ape('utils/owlswrl/owlswrl_to_fss'), [ 39 | owlswrl_to_fss/1 40 | ]). 41 | 42 | :- use_module(ape('utils/owlswrl/owlswrl_to_xml'), [ 43 | owlswrl_to_xml/2 44 | ]). 45 | 46 | 47 | 48 | t(AceText, Owl) :- 49 | clear_messages, 50 | acetext_to_drs(AceText, _, _, Drs, _), 51 | drs_to_owlswrl(Drs, test, 'Ontology from an ACE text.', Owl). 52 | 53 | t(AceText) :- 54 | clear_messages, 55 | acetext_to_drs(AceText, _, _, Drs, _), 56 | drs_to_ascii(Drs, DrsAscii), 57 | format("~w~n", [DrsAscii]), 58 | drs_to_owlswrl(Drs, test, 'Ontology from an ACE text.', Owl), 59 | get_messages(Messages), 60 | format("Messages: ~w~n~n", [Messages]), 61 | owlswrl_to_fss(Owl), nl, 62 | owlswrl_to_xml(Owl, XML), 63 | xml_write(user, XML, [layout(true), indent(0), header(false), net(true)]), 64 | format("~n~n"), 65 | !. 66 | 67 | t(_) :- 68 | format("Something failed.~n~n"). 69 | 70 | 71 | % Commandline interface 72 | cli :- 73 | clear_messages, 74 | prompt(Old, 'ACE to OWL> '), 75 | read_text_from_commandline(AceText), 76 | prompt(_, Old), 77 | t(AceText), 78 | cli. 79 | 80 | read_text_from_commandline([C | R]) :- 81 | get0(C), 82 | line_continues(C), 83 | !, 84 | read_text_from_commandline(R). 85 | 86 | read_text_from_commandline([]). 87 | 88 | 89 | multiline(false). 90 | line_continues(C) :- C \== 10, C \== -1, !. 91 | line_continues(C) :- multiline(true), C \== -1. 92 | -------------------------------------------------------------------------------- /examples/output_tests.pl: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | This script outputs the APE regression test set positive testcases 4 | separated by newlines. Each testcase is normalized first: 5 | 6 | - the testcase is tokenized with the APE tokenizer 7 | - the first character of every sentence is lowercased if it belongs to a function word 8 | - tokens like `every-' and `thing' are glued 9 | - the Saxon Genitive marker is glued to the previous token 10 | 11 | TODO: 12 | 13 | - handle paragraph breaks somehow 14 | 15 | @author Kaarel Kaljurand 16 | @version 2012-01-04 17 | 18 | Usage example: 19 | 20 | == 21 | swipl -s output_tests.pl -t halt -g main 22 | == 23 | 24 | */ 25 | 26 | % We point to the directory where APE modules and the lexicons are located. 27 | :- assert(user:file_search_path(ape, '../prolog')). 28 | 29 | :- use_module(ape('parser/tokenizer'), [ 30 | tokenize/2 31 | ]). 32 | 33 | :- use_module(ape('parser/tokens_to_sentences'), [ 34 | tokens_to_sentences/2 35 | ]). 36 | 37 | :- use_module(ape('utils/ace_niceace'), [ 38 | atom_capitalize/2, 39 | pronoun_split/3 40 | ]). 41 | 42 | :- assert(user:file_search_path(ape, '..')). 43 | 44 | :- consult(ape('tests/acetexts')). 45 | 46 | 47 | main :- 48 | get_test(Text), 49 | text_to_sentences(Text, Sentences), 50 | process(Sentences, SentencesN), 51 | concat(SentencesN, Formatted), 52 | writeln(Formatted), 53 | fail ; true. 54 | 55 | 56 | process --> 57 | maplist(sentence_lowercase), 58 | maplist(merge_some_tokens), 59 | maplist(concat). 60 | 61 | 62 | %% text_to_sentences is det. 63 | % 64 | text_to_sentences(Text, Sentences) :- 65 | tokenize(Text, Tokens), 66 | tokens_to_sentences(Tokens, Sentences). 67 | 68 | 69 | %% get_test 70 | % 71 | % Picks a test case that correctly (0) produces a non-empty DRS ([_ | _]). 72 | % 73 | get_test(Test) :- 74 | text_drs_eval(0, _Id, Test, drs(_, [_ | _]), _Syntax, _Date, _User, _Comment). 75 | 76 | 77 | %% sentence_lowercase 78 | % 79 | sentence_lowercase([^, Upper | Rest], [Lower | Rest]) :- 80 | atom_capitalize(Lower, Upper). 81 | 82 | 83 | %% merge_some_tokens 84 | % 85 | merge_some_tokens([], []). 86 | 87 | merge_some_tokens([T, '\'', s | Rest], [Atom | RestMerged]) :- 88 | !, 89 | atomic_list_concat([T, '\'', s], Atom), 90 | merge_some_tokens(Rest, RestMerged). 91 | 92 | merge_some_tokens([T, '\'' | Rest], [Atom | RestMerged]) :- 93 | !, 94 | atomic_list_concat([T, '\''], Atom), 95 | merge_some_tokens(Rest, RestMerged). 96 | 97 | merge_some_tokens([T1, T2 | Rest], [Atom | RestMerged]) :- 98 | pronoun_split(Atom, lower, (T1, T2)), 99 | !, 100 | merge_some_tokens(Rest, RestMerged). 101 | 102 | merge_some_tokens([H | Rest], [H | RestMerged]) :- 103 | merge_some_tokens(Rest, RestMerged). 104 | 105 | 106 | %% concat 107 | % 108 | concat(Tokens, Atom) :- 109 | atomic_list_concat(Tokens, ' ', Atom). 110 | -------------------------------------------------------------------------------- /examples/paraphrase_roundtrip.pl: -------------------------------------------------------------------------------- 1 | /** 2 | This is an example that shows how to 3 | 4 | 1. Translate an ACE file into a DRS 5 | 2. Verbalize this DRS (effectively paraphrasing the ACE text (in this case in Core ACE)) 6 | 3. Translate the resulting paraphrase into a new DRS 7 | 4. Test if the original DRS is structurally equivalent to the new DRS 8 | 9 | @author Kaarel Kaljurand 10 | @version 2009-06-16 11 | 12 | */ 13 | 14 | % We point to the directory where APE modules and the lexicons are located. 15 | :- assert(user:file_search_path(ape, '../prolog')). 16 | 17 | % We import the needed modules. 18 | :- use_module(ape(parser/ace_to_drs), [acetext_to_drs/8]). 19 | 20 | :- style_check(-discontiguous). 21 | :- use_module(ape(lexicon/clex)). 22 | :- use_module(ape(lexicon/ulex)). 23 | :- style_check(+discontiguous). 24 | 25 | % Various modules that deal with the DRSs are located in ape/utils/. 26 | 27 | :- use_module(ape(utils/drs_to_ascii), [drs_to_ascii/2]). 28 | 29 | :- use_module(ape(utils/drs_to_coreace), [bigdrs_to_coreace/2]). 30 | 31 | :- use_module(ape(utils/are_equivalent), [are_equivalent/3]). 32 | 33 | % Various modules that deal with ACE texts (e.g. pretty-printing) are located in ape/utils/. 34 | 35 | :- use_module(ape(utils/morphgen), [acesentencelist_pp/2]). 36 | 37 | 38 | % This example uses the ACE version of the LOL policy. 39 | acetext('the_lol_policy.ace.txt'). 40 | 41 | paraphrase_roundtrip :- 42 | acetext(AceText), 43 | % We load the file into character codes. 44 | read_file_to_codes(AceText, AceTextCodes, [encoding(utf8)]), 45 | format("ACE text = ~n~s~n", [AceTextCodes]), 46 | % We call APE with guessing turned "on". 47 | % The input is the character codes. 48 | % The output that interests us is the DRS and possible error/warning messages. 49 | acetext_to_drs(AceTextCodes, on, off, _Sentences1, _SyntaxTrees1, Drs1, Messages1, _DurationList1), 50 | % We pretty-print the DRS. 51 | drs_to_ascii(Drs1, DrsAscii1), 52 | format("DRS1 = ~n~w~n", [DrsAscii1]), 53 | format("Messages1 = ~n~w~n", [Messages1]), 54 | % We verbalize the DRS in Core ACE (the verbalizer expects untyped DRSs as input). 55 | bigdrs_to_coreace(Drs1, Paraphrase), 56 | % The verbalization results in a list of sentences where each sentence is a Prolog atom. 57 | % We convert the list structure into an atom. 58 | acesentencelist_pp(Paraphrase, ParaphrasePp), 59 | format("Paraphrase = ~n~w~n", [ParaphrasePp]), 60 | % We call APE again. This time on the paraphrase. 61 | % Note that the input is given now as an atom, not in character codes like before, 62 | % APE accepts both types of inputs. 63 | acetext_to_drs(ParaphrasePp, on, off, _Sentences2, _SyntaxTrees2, Drs2, Messages2, _DurationList2), 64 | ( 65 | % We now test if the DRSs are structurally equivalent. 66 | % We ignore the sentence IDs while checking for equivalence. 67 | are_equivalent(Drs1, Drs2, [ignore_sid(true)]) 68 | -> 69 | % If the DRSs were equivalent then the roundtrip finished where it started. 70 | format("Roundtrip worked: ACE -> DRS -> Core ACE -> DRS~n", []) 71 | ; 72 | % If the DRSs were not equivalent then the roundtrip did not take place. 73 | % This means that a bug was encountered in either the verbalizer 74 | % or in APE. We show the new DRS in this case, along with possible messages. 75 | format("Roundtrip did not work: ACE -> DRS1 -> Core ACE -> DRS2~n", []), 76 | drs_to_ascii(Drs2, DrsAscii2), 77 | format("DRS2 = ~n~w~n", [DrsAscii2]), 78 | format("Messages2 = ~n~w~n", [Messages2]) 79 | ). 80 | -------------------------------------------------------------------------------- /examples/the_lol_policy.ace.txt: -------------------------------------------------------------------------------- 1 | /** 2 | @title The LOL policy 3 | @author Kaarel Kaljurand 4 | @version 2008-01-30 5 | 6 | This is based on the if-then sentences 7 | in Appendix A 8 | in "Further Notes. Draft of December 19, 2007" 9 | by Juri Luca De Coi. 10 | 11 | The idea has been to convert Juri's if-then sentences into every-sentences 12 | to see if they come out more readable than the if-then sentences, 13 | and also to test the Core ACE paraphraser which would translate the 14 | every-sentences back into if-then sentences. This way we will have 3 sets 15 | of sentences: Juri's original sentences, Kaarel's "everyfication", 16 | DRACE Core's paraphrases. We should make sure that APE really converts them 17 | into equivalent DRSs. We should also make sure that Protune users 18 | accept those 3 sets as equivalent. 19 | 20 | Note: the sentences below can be parsed with guessing on. 21 | On 2007-12-30, the roundtrip ACE1->DRS->ACE2->DRS worked, where 22 | ACE1 is this file, 23 | DRS is its DRS-translation, 24 | ACE2 is the Core ACE paraphrase of ACE1, and 25 | DRS (i.e. the same DRS as before) is its DRS-translation. 26 | */ 27 | 28 | /* r1 */ 29 | Every user 30 | can browse "index". 31 | 32 | 33 | /* r2 */ 34 | Every resource that is public 35 | can be downloaded by every user. 36 | 37 | 38 | /* r3 */ 39 | Every user who is authenticated 40 | and who has a subscription that is available-for a resource 41 | can download the resource. 42 | 43 | 44 | /* r4 */ 45 | Every user who is authenticated 46 | and who buys a resource 47 | can download the resource. 48 | 49 | 50 | /* r5 */ 51 | Every user 52 | can log all information. 53 | 54 | 55 | /* r6 */ 56 | Every user who sends a credential 57 | that is an identifier 58 | and whose name is the user's name 59 | and whose public key is challenged by "System" 60 | is authenticated. 61 | 62 | 63 | /* r7 */ 64 | Every user who provides a declaration 65 | whose username is the user's name 66 | and whose password is the user's password 67 | is authenticated. 68 | 69 | 70 | /* r8 */ 71 | Every user who registers at "http://lol.com/register.php" 72 | is authenticated. 73 | 74 | 75 | /* r9 */ 76 | Every credential whose type is an id 77 | and whose issuer is trusted-for the type 78 | is an identifier. 79 | 80 | 81 | /* r10 */ 82 | "id" is an id. 83 | 84 | 85 | /* r11 */ 86 | "ssn" is an id. 87 | 88 | 89 | /* r12 */ 90 | "passport" is an id. 91 | 92 | 93 | /* r13 */ 94 | "driving_license" is an id. 95 | 96 | 97 | /* r14 */ 98 | Every user who pays the price of a resource with "fastPay" 99 | buys the resource. 100 | 101 | 102 | /* r15 */ 103 | Every user who pays the price of a resource with "creditCard" 104 | buys the resource. 105 | 106 | 107 | /* r16 */ 108 | Every user who provides a declaration 109 | and who sends a credential that is valid 110 | and whose type is "fastPay" 111 | and on which a price is charged with a pin of the declaration 112 | pays the price with "fastPay". 113 | 114 | 115 | /* r17 */ 116 | Every user who sends a credential that is valid 117 | and whose type is "creditCard" 118 | and whose owner is authenticated 119 | and on which a price is charged 120 | pays the price with "creditCard". 121 | 122 | 123 | /* r18 */ 124 | Every credential that is verified by "System" with a public key of an issuer of the credential 125 | is valid. 126 | -------------------------------------------------------------------------------- /get_ape_results.pl: -------------------------------------------------------------------------------- 1 | :- module(get_ape_results, []). 2 | :- reexport('prolog/ape'). 3 | -------------------------------------------------------------------------------- /java/README.md: -------------------------------------------------------------------------------- 1 | Java Interface for APE 2 | ====================== 3 | 4 | The Java Interface for APE is part of the Attempto Parsing Engine (APE). 5 | Copyright 2008-2013, Attempto Group, University of Zurich (http://attempto.ifi.uzh.ch). 6 | 7 | 8 | Content 9 | ------- 10 | 11 | To simplify calling APE from Java programs, we provide the `ACEParser` interface which 12 | is effectively a Java-style front-end to querying the predicate `get_ape_results/2`. 13 | `ACEParser` is implemented by the following classes: 14 | 15 | - `APELocal` accesses APE via JPL, the bidirectional Prolog/Java interface, which is included in the SWI-Prolog installation; 16 | - `APESocket` accesses APE via its socket server; 17 | - `APEWebservice` accesses APE via its HTTP server. 18 | 19 | 20 | Building with Maven 21 | ------------------- 22 | 23 | The Java Interface for APE can be compiled into a single jar-file `attempto-ape.jar`. 24 | 25 | First install SWI-Prolog's JPL into your local Maven repository. 26 | See [install-jpl.sh](install-jpl.sh) for an example on how do it. 27 | You might also need to update the JPL version number in `pom.xml` to match your version 28 | of SWI-Prolog. 29 | 30 | Building the jar-file. 31 | 32 | mvn package -DskipTests 33 | 34 | Building the documentation, licenses, etc. 35 | 36 | mvn site 37 | 38 | 39 | Testing 40 | ------- 41 | 42 | In order to run the unit tests (`mvn test`), first compile `ape.exe`. 43 | 44 | For the `APELocal` tests to succeed, place `ape.exe` into the APE root directory 45 | and execute (in any directory): 46 | 47 | eval `swipl -dump-runtime-variables` 48 | export LD_PRELOAD=$PLBASE/lib/$PLARCH/libjpl.so:$PLBASE/lib/$PLARCH/libswipl.so 49 | 50 | For the `APESocket` tests to succeed, start the APE socket server: 51 | 52 | ape.exe -server -port 5000 53 | 54 | For the `APEWebservice` tests to succeed, start the APE HTTP server: 55 | 56 | ape.exe -httpserver -port 8000 57 | 58 | Now run 59 | 60 | mvn test 61 | -------------------------------------------------------------------------------- /java/install-jpl.sh: -------------------------------------------------------------------------------- 1 | mvn install:install-file \ 2 | -Dfile=/usr/lib/swi-prolog/lib/jpl.jar \ 3 | -DgroupId=jpl \ 4 | -DartifactId=jpl \ 5 | -Dversion=7.6.4 \ 6 | -Dpackaging=jar \ 7 | -DgeneratePom=true 8 | -------------------------------------------------------------------------------- /java/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | ch.uzh.ifi.attempto.ape 5 | attempto-ape 6 | jar 7 | 1.0.3 8 | Java Interface for APE 9 | Java Interface for APE 10 | http://attempto.ifi.uzh.ch/ 11 | 12 | GitHub 13 | https://github.com/Attempto/APE/issues?labels=java 14 | 15 | 16 | 17 | LGPL 3.0 license 18 | http://www.opensource.org/licenses/lgpl-3.0.html 19 | 20 | 21 | 22 | 23 | Kaarel Kaljurand 24 | kaljurand@gmail.com 25 | +1 26 | 27 | 28 | Tobias Kuhn 29 | kuhntobias@gmail.com 30 | +1 31 | 32 | 33 | 34 | UTF-8 35 | 36 | 37 | 38 | jpl 39 | jpl 40 | 7.6.4 41 | 42 | 43 | junit 44 | junit 45 | 4.5 46 | test 47 | 48 | 49 | org.apache.httpcomponents 50 | httpclient 51 | 4.3.6 52 | 53 | 54 | com.sun.phobos 55 | jdom 56 | 1.0 57 | 58 | 59 | 60 | 61 | 62 | org.apache.maven.plugins 63 | maven-javadoc-plugin 64 | 2.9 65 | 66 | 67 | 68 | 69 | 70 | 71 | org.apache.maven.plugins 72 | maven-compiler-plugin 73 | 2.0.2 74 | 75 | 1.6 76 | 1.6 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/ACEParserException.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | import org.jdom.Element; 18 | 19 | /** 20 | * This exception is used by the ACE parser when used in solo mode. It contains the error 21 | * messages of the parser. 22 | * 23 | * @author Tobias Kuhn 24 | */ 25 | public class ACEParserException extends Exception { 26 | 27 | private static final long serialVersionUID = 5759137566239371054L; 28 | 29 | private MessageContainer messageContainer; 30 | 31 | 32 | ACEParserException(Element xmlElement) { 33 | messageContainer = new MessageContainer(xmlElement); 34 | } 35 | 36 | /** 37 | * Returns the message container with the error messages. 38 | * 39 | * @return The message container. 40 | */ 41 | public MessageContainer getMessageContainer() { 42 | return messageContainer; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/ACEParserResult.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | import java.io.StringReader; 18 | 19 | import org.jdom.Document; 20 | import org.jdom.Element; 21 | import org.jdom.input.SAXBuilder; 22 | 23 | /** 24 | * This class represents the output that is returned by the ACEParser class. 25 | * 26 | * @author Tobias Kuhn 27 | */ 28 | public class ACEParserResult { 29 | 30 | private Element result; 31 | private MessageContainer messageContainer = new MessageContainer(); 32 | 33 | 34 | ACEParserResult(String xmlString) { 35 | try { 36 | SAXBuilder sb = new SAXBuilder(); 37 | sb.setValidation(false); 38 | Document xml = sb.build(new StringReader(xmlString)); 39 | result = xml.getRootElement(); 40 | messageContainer = new MessageContainer(result.getChild("messages")); 41 | } catch (Exception ex) { 42 | ex.printStackTrace(); 43 | } 44 | } 45 | 46 | /** 47 | * Returns the specified output as a string. If the requested output is not available (because 48 | * it has not been requested) then null is returned. 49 | * 50 | * @param outputType The output to be returned. 51 | * @return The output as a string. 52 | */ 53 | public String get(OutputType outputType) { 54 | try { 55 | Element element = result.getChild(outputType.toString().toLowerCase()); 56 | return element.getText(); 57 | } catch (Exception ex) { 58 | return null; 59 | } 60 | } 61 | 62 | /** 63 | * Returns the message container that contains the error and warning messages of the parsing 64 | * procedure. 65 | * 66 | * @return The message container. 67 | */ 68 | public MessageContainer getMessageContainer() { 69 | return messageContainer; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/ACEText.java: -------------------------------------------------------------------------------- 1 | package ch.uzh.ifi.attempto.ape; 2 | 3 | /** 4 | * WARNING: This class is experimental and is incomplete (i.e. covers only a subset of the lexicon entries). 5 | *

6 | * This class reflects the fact that an ACE text is really a combination of 7 | * a string and a lexicon. The lexicon is used to interpret the content words 8 | * in the string: assign them word classes, features (e.g. gender) and map them 9 | * to logical symbols. 10 | *

11 | * We experiment with a representation where the string and the lexicon are 12 | * packaged into a single string: 13 | *

14 | * John|pn_sg|John_PN|masc buys|tv_finsg|buy_V2 everything that isn't a present|noun_sg|present_N|neutr . 15 | * 16 | * @author Kaarel Kaljurand 17 | */ 18 | public class ACEText { 19 | 20 | public static final String WORDCLASS_PN_SG = "pn_sg"; 21 | public static final String WORDCLASS_PNDEF_SG = "pndef_sg"; 22 | public static final String WORDCLASS_PNDEF_PL = "pndef_pl"; 23 | public static final String WORDCLASS_NOUN_SG = "noun_sg"; 24 | public static final String WORDCLASS_NOUN_PL = "noun_pl"; 25 | public static final String WORDCLASS_TV_FINSG = "tv_finsg"; 26 | public static final String WORDCLASS_TV_INFPL = "tv_infpl"; 27 | public static final String WORDCLASS_TV_PP = "tv_pp"; 28 | public static final String WORDCLASS_ADJ_TR = "adj_tr"; 29 | 30 | private final StringBuilder mText = new StringBuilder(); 31 | private final Lexicon mLexicon = new Lexicon(); 32 | 33 | public ACEText(String text) { 34 | tokenize(text); 35 | } 36 | 37 | public String getText() { 38 | return mText.toString(); 39 | } 40 | 41 | public Lexicon getLexicon() { 42 | return mLexicon; 43 | } 44 | 45 | 46 | /** 47 | * Tokenizes that given string assuming that tokens are separated by sequences of spaces. 48 | * Each token is split by a vertical bar (|). If this splitting results in at least 3 units, 49 | * then they are assumed to be: word form, word class identifier, logical symbol. With nouns 50 | * a gender argument can also follow, but this is optional and by default the UNDEF gender is assumed. 51 | * If the word class does not match a known ACE word class then we assume that the token 52 | * is a regular ACE token. 53 | *

54 | * TODO: currently only AceWiki word classes are covered 55 | * TODO: correctly handle ACE quoted strings (which contain the vertical bar character) 56 | */ 57 | private void tokenize(String str) { 58 | for (String tok : str.split("\\s+")) { 59 | String[] splits = tok.split("\\|"); 60 | 61 | if (splits.length <= 2) { 62 | mText.append(' '); 63 | mText.append(tok); 64 | continue; 65 | } 66 | 67 | String wordForm = splits[0]; 68 | String wordClass = splits[1]; 69 | String logicalSymbol = splits[2]; 70 | 71 | if (WORDCLASS_PN_SG.equals(wordClass)) { 72 | if (splits.length > 3) { 73 | add(wordForm, LexiconEntry.createPropernameSgEntry(wordForm, logicalSymbol, Gender.create(splits[3]))); 74 | } else { 75 | add(wordForm, LexiconEntry.createPropernameSgEntry(wordForm, logicalSymbol, Gender.UNDEF)); 76 | } 77 | } else if (WORDCLASS_PNDEF_SG.equals(wordClass)) { 78 | if (splits.length > 3) { 79 | add(wordForm, LexiconEntry.createPropernameDefSgEntry(wordForm, logicalSymbol, Gender.create(splits[3]))); 80 | } else { 81 | add(wordForm, LexiconEntry.createPropernameDefSgEntry(wordForm, logicalSymbol, Gender.UNDEF)); 82 | } 83 | } else if (WORDCLASS_PNDEF_PL.equals(wordClass)) { 84 | if (splits.length > 3) { 85 | add(wordForm, LexiconEntry.createPropernameDefPlEntry(wordForm, logicalSymbol, Gender.create(splits[3]))); 86 | } else { 87 | add(wordForm, LexiconEntry.createPropernameDefPlEntry(wordForm, logicalSymbol, Gender.UNDEF)); 88 | } 89 | } else if (WORDCLASS_NOUN_SG.equals(wordClass)) { 90 | if (splits.length > 3) { 91 | add(wordForm, LexiconEntry.createNounSgEntry(wordForm, logicalSymbol, Gender.create(splits[3]))); 92 | } else { 93 | add(wordForm, LexiconEntry.createNounSgEntry(wordForm, logicalSymbol, Gender.UNDEF)); 94 | } 95 | } else if (WORDCLASS_NOUN_PL.equals(wordClass)) { 96 | if (splits.length > 3) { 97 | add(wordForm, LexiconEntry.createNounPlEntry(wordForm, logicalSymbol, Gender.create(splits[3]))); 98 | } else { 99 | add(wordForm, LexiconEntry.createNounPlEntry(wordForm, logicalSymbol, Gender.UNDEF)); 100 | } 101 | } else if (WORDCLASS_TV_FINSG.equals(wordClass)) { 102 | add(wordForm, LexiconEntry.createTrVerbThirdEntry(wordForm, logicalSymbol)); 103 | } else if (WORDCLASS_TV_INFPL.equals(wordClass)) { 104 | add(wordForm, LexiconEntry.createTrVerbInfEntry(wordForm, logicalSymbol)); 105 | } else if (WORDCLASS_TV_PP.equals(wordClass)) { 106 | add(wordForm, LexiconEntry.createTrVerbPPEntry(wordForm, logicalSymbol)); 107 | } else if (WORDCLASS_ADJ_TR.equals(wordClass)) { 108 | // Note that the preposition is used as an independent token only in comparative constructs, e.g. 109 | // "Mary is more fond-of Bill than of John.". 110 | // For the simple ADJ_TR we could also ignore it. 111 | String prep = addPrep(splits); 112 | add(wordForm, LexiconEntry.createTrAdjEntry(wordForm, logicalSymbol, prep)); 113 | } else { 114 | mText.append(' '); 115 | mText.append(tok); 116 | } 117 | } 118 | } 119 | 120 | 121 | private void add(String tok, LexiconEntry le) { 122 | mLexicon.addEntry(le); 123 | mText.append(' '); 124 | mText.append("`"); 125 | mText.append(tok); 126 | mText.append("`"); 127 | } 128 | 129 | 130 | private String addPrep(String[] splits) { 131 | if (splits.length > 3) { 132 | String prep = splits[3]; 133 | if (prep.length() > 0) { 134 | mLexicon.addEntry(LexiconEntry.createPrepEntry(prep, prep)); 135 | } 136 | return prep; 137 | } 138 | return ""; 139 | } 140 | } -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/ACEUtils.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | /** 18 | * This class contains ACE-related utility methods. 19 | * 20 | * @author Tobias Kuhn 21 | */ 22 | public class ACEUtils { 23 | 24 | private ACEUtils() {} // no instances allowed 25 | 26 | /** 27 | * This method can be used to determine whether an indefinite article has the form "a" or 28 | * "an" if it is followed by the given word. Heuristics are used and the result might not 29 | * be correct in 100% of the cases. 30 | * 31 | * @param word The word that immediately follows the indefinite article. 32 | * @return true if "an" should be used; false for "a". 33 | */ 34 | public static boolean useIndefiniteArticleAn(String word) { 35 | if (word == null || word.equals("")) return false; 36 | boolean an = false; 37 | word = word.toLowerCase(); 38 | if (word.matches("[aeiou].*")) an = true; 39 | if (word.matches("[fhlmnrsx]")) an = true; 40 | if (word.matches("[fhlmnrsx]-.*")) an = true; 41 | if (word.equals("u")) an = false; 42 | if (word.matches("u-.*")) an = false; 43 | if (word.matches("u[rtn]i.*")) an = false; 44 | if (word.matches("use.*")) an = false; 45 | if (word.matches("uk.*")) an = false; 46 | return an; 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/APESocket.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | import java.io.BufferedReader; 18 | import java.io.IOException; 19 | import java.io.InputStreamReader; 20 | import java.io.PrintWriter; 21 | import java.net.Socket; 22 | import java.net.UnknownHostException; 23 | 24 | /** 25 | * This class provides an interface to the Attempto Parsing Engine (APE) socket server. 26 | * The socket server implementation is provided by ape.exe. To start 27 | * a server, execute for example: 28 | * 29 | *

 30 |  * ./ape.exe -server -port 2766
 31 |  * 
32 | * 33 | * @author Kaarel Kaljurand 34 | */ 35 | public class APESocket extends ACEParser { 36 | 37 | private String host; 38 | private int port; 39 | 40 | /** 41 | * Constructs a new parser object based on the hostname and the port number 42 | * of the APE socket server. 43 | * 44 | * @param host The hostname of the socket server. 45 | * @param port The port number of the socket server. 46 | */ 47 | public APESocket(String host, int port) { 48 | this.host = host; 49 | this.port = port; 50 | } 51 | 52 | /** 53 | * Constructs a new parser object based on the APE socket server running on "localhost". 54 | * 55 | * @param port The port number of the socket server. 56 | */ 57 | public APESocket(int port) { 58 | this("localhost", port); 59 | } 60 | 61 | public ACEParserResult getMultiOutput(String text, Lexicon lexicon, OutputType... outputTypes) { 62 | String ulexStr = ""; 63 | if (lexicon != null) { 64 | ulexStr = ",ulextext=" + PrologUtils.escape(lexicon.toString()); 65 | } 66 | String paramList = "text=" + PrologUtils.escape(text) + ulexStr + getOptions(); 67 | for (OutputType t : outputTypes) { 68 | paramList = paramList + "," + t.toMultiFlag() + "=on"; 69 | } 70 | return new ACEParserResult(getParserResponseAsString(paramList)); 71 | } 72 | 73 | public String getSoloOutput(String text, Lexicon lexicon, OutputType outputType) throws ACEParserException { 74 | String ulexStr = ""; 75 | if (lexicon != null) { 76 | ulexStr = ",ulextext=" + PrologUtils.escape(lexicon.toString()); 77 | } 78 | String paramList = "text=" + PrologUtils.escape(text) + ulexStr + ",solo=" + outputType.toSoloFlag() + getOptions(); 79 | return checkForErrors(getParserResponseAsString(paramList)); 80 | } 81 | 82 | 83 | private String getParserResponseAsString(String paramList) { 84 | Socket client; 85 | try { 86 | client = new Socket(host, port); 87 | } catch (UnknownHostException e) { 88 | throw new RuntimeException("Accessing APE socket failed: " + e.getMessage()); 89 | } catch (IOException e) { 90 | throw new RuntimeException("Accessing APE socket failed: " + e.getMessage()); 91 | } 92 | 93 | 94 | BufferedReader fromServer; 95 | 96 | try { 97 | fromServer = new BufferedReader(new InputStreamReader(client.getInputStream())); 98 | } catch (IOException e) { 99 | throw new RuntimeException("Accessing APE socket failed: " + e.getMessage()); 100 | } 101 | 102 | 103 | PrintWriter toServer; 104 | try { 105 | toServer = new PrintWriter(client.getOutputStream(), true); 106 | } catch (IOException e) { 107 | throw new RuntimeException("Accessing APE socket failed: " + e.getMessage()); 108 | } 109 | 110 | toServer.println("get([" + paramList + "])."); 111 | 112 | String allLines = ""; 113 | String responseLine; 114 | try { 115 | while ((responseLine = fromServer.readLine()) != null) { 116 | if (responseLine.equals("APESERVERSTREAMEND")) { 117 | break; 118 | } 119 | // TODO: not sure if we should replace "\n" with a platform independent method call 120 | allLines = allLines + responseLine + "\n"; 121 | } 122 | } catch (IOException e) { 123 | throw new RuntimeException("Accessing APE socket failed: " + e.getMessage()); 124 | } 125 | try { 126 | toServer.close(); 127 | fromServer.close(); 128 | client.close(); 129 | } catch (IOException e) { 130 | throw new RuntimeException("Accessing APE socket failed: " + e.getMessage()); 131 | } 132 | return allLines; 133 | } 134 | } -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/FunctionWords.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | import java.util.Arrays; 18 | import java.util.HashSet; 19 | import java.util.Set; 20 | 21 | /** 22 | * This class contains the function words of ACE. These words have a predefined meaning and cannot 23 | * be used in the lexicon. Function words like "can" or "true", which can be used in the lexicon, 24 | * are not covered by this class. 25 | * 26 | * @author Tobias Kuhn 27 | */ 28 | public class FunctionWords { 29 | 30 | private static HashSet functionWords = new HashSet(Arrays.asList(new String[] { 31 | "null", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", 32 | "twelve", "dozen", "there", "and", "or", "not", "that", "than", "of", "if", "then", "such", "be", "provably", 33 | "more", "most", "are", "is", "the", "a", "an", "some", "no", "every", "all", "each", "which", "its", "his", 34 | "her", "their", "whose", "it", "he", "she", "they", "him", "them", "itself", "himself", "herself", 35 | "themselves", "someone", "somebody", "something", "nobody", "nothing", "everyone", "everybody", "everything", 36 | "what", "who", "how", "where", "when", "by", "Null", "Zero", "One", "Two", "Three", "Four", "Five", "Six", 37 | "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Dozen", "There", "If", "Are", "Is", "The", "A", "An", 38 | "Some", "No", "Every", "All", "Each", "Which", "Its", "His", "Her", "Their", "Whose", "It", "He", "She", 39 | "They", "Someone", "Somebody", "Something", "Nobody", "Nothing", "Everyone", "Everybody", "Everything", 40 | "What", "Who", "How", "Where", "When" 41 | })); 42 | 43 | private FunctionWords() {} // no instances allowed 44 | 45 | /** 46 | * Checks whether a certain string represents a function word. 47 | * 48 | * @param s The string to be checked. 49 | * @return true if the string represents a function word. 50 | */ 51 | public static boolean isFunctionWord(String s) { 52 | return functionWords.contains(s); 53 | } 54 | 55 | /** 56 | * Returns a set that contains all function words. 57 | * 58 | * @return A list containing all function words. 59 | */ 60 | public static Set getFunctionWords() { 61 | return new HashSet(functionWords); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/Gender.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | /** 18 | * This enumeration lists the possible gender types for nouns and proper names. 19 | * 20 | * @author Tobias Kuhn 21 | * @author Kaarel Kaljurand 22 | */ 23 | public enum Gender { 24 | 25 | /** 26 | * Undefined gender. 27 | */ 28 | UNDEF, 29 | 30 | /** 31 | * Neutral gender. 32 | */ 33 | NEUTRAL, 34 | 35 | /** 36 | * Human gender. 37 | */ 38 | HUMAN, 39 | 40 | /** 41 | * Masculine gender. 42 | */ 43 | MASCULINE, 44 | 45 | /** 46 | * Feminine gender. 47 | */ 48 | FEMININE; 49 | 50 | /** 51 | * Returns the Prolog atom representation of the type of gender. 52 | */ 53 | public String toString() { 54 | switch (this) { 55 | case UNDEF: return "undef"; 56 | case NEUTRAL: return "neutr"; 57 | case HUMAN: return "human"; 58 | case MASCULINE: return "masc"; 59 | case FEMININE: return "fem"; 60 | } 61 | return null; 62 | } 63 | 64 | 65 | /** 66 | * Returns the gender that corresponds to the given Prolog atom. 67 | */ 68 | public static Gender create(String str) { 69 | if ("neutr".equals(str)) return NEUTRAL; 70 | if ("human".equals(str)) return HUMAN; 71 | if ("masc".equals(str)) return MASCULINE; 72 | if ("fem".equals(str)) return FEMININE; 73 | return UNDEF; 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/Lexicon.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Collection; 19 | import java.util.List; 20 | 21 | /** 22 | * This class represents a lexicon which consists of a set of lexicon entries. 23 | * 24 | * @author Tobias Kuhn 25 | */ 26 | public class Lexicon { 27 | 28 | private List entries = new ArrayList(); 29 | 30 | 31 | /** 32 | * Creates an empty lexicon. 33 | */ 34 | public Lexicon() { 35 | } 36 | 37 | /** 38 | * Adds a lexicon entry to this lexicon. 39 | * 40 | * @param entry The lexicon entry to be added. 41 | */ 42 | public void addEntry(LexiconEntry entry) { 43 | if (!entries.contains(entry)) { 44 | entries.add(entry); 45 | } 46 | } 47 | 48 | /** 49 | * Adds a collection of lexicon entries to this lexicon. 50 | * 51 | * @param entries The lexicon entries to be added. 52 | */ 53 | public void addEntries(Collection entries) { 54 | for (LexiconEntry entry : entries) { 55 | addEntry(entry); 56 | } 57 | } 58 | 59 | /** 60 | * Removes the lexicon entry from this lexicon. 61 | * 62 | * @param entry The lexicon entry to be removed. 63 | */ 64 | public void removeEntry(LexiconEntry entry) { 65 | entries.remove(entry); 66 | } 67 | 68 | /** 69 | * Removes all entries from this lexicon. 70 | */ 71 | public void removeAllEntries() { 72 | entries.clear(); 73 | } 74 | 75 | /** 76 | * Returns a list of all lexicon entries that are contained in this lexicon. 77 | * 78 | * @return A list of all lexicon entries. 79 | */ 80 | public List getEntries() { 81 | return new ArrayList(entries); 82 | } 83 | 84 | /** 85 | * Returns the lexicon as a serialized Prolog list. 86 | * 87 | * @return The lexicon as a serialized Prolog list. 88 | */ 89 | public String toList() { 90 | StringBuilder sb = new StringBuilder(); 91 | for (LexiconEntry entry : entries) { 92 | sb.append(entry.toString()); 93 | sb.append(", "); 94 | } 95 | if (sb.length() > 0) { 96 | sb.substring(0, sb.length()-2); 97 | } 98 | return "[" + sb.toString() + "]"; 99 | } 100 | 101 | /** 102 | * Returns this lexicon as a contents of an APE lexicon file, i.e. 103 | * each entry is followed by a dot ('.') and a space (' '). 104 | */ 105 | @Override 106 | public String toString() { 107 | StringBuilder sb = new StringBuilder(); 108 | for (LexiconEntry entry : entries) { 109 | sb.append(entry.toString()); 110 | sb.append(". "); 111 | } 112 | return sb.toString(); 113 | } 114 | 115 | } -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/Message.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | import org.jdom.Element; 18 | 19 | /** 20 | * This class represents a warning or error message of the ACE parser. 21 | * 22 | * @author Tobias Kuhn 23 | * @author Kaarel Kaljurand 24 | */ 25 | public class Message { 26 | 27 | private boolean isError; 28 | private String type, value, repair; 29 | private Integer sentenceId, tokenId; 30 | 31 | /** 32 | * Creates a new Message object. All the relevant information for the 33 | * message must be passed as arguments to this constructor. 34 | * 35 | * @param importance The importance of the message, e.g. "error", "warning" 36 | * @param type The type of the message, e.g. "sentence", "token" 37 | * @param sentenceId The number of the problematic sentence, or null if unknown 38 | * @param tokenId The number of the problematic token, or null if unknown 39 | * @param value The value of the message (e.g. a misspelled word) 40 | * @param repair The description that helps to resolve the error or warning 41 | */ 42 | public Message(String importance, String type, Integer sentenceId, Integer tokenId, String value, String repair) { 43 | this.isError = importance.equals("error"); 44 | this.type = type; 45 | this.sentenceId = sentenceId; 46 | this.tokenId = tokenId; 47 | this.value = value; 48 | this.repair = repair; 49 | } 50 | 51 | 52 | Message(Element xmlElement) { 53 | isError = (xmlElement.getAttribute("importance").getValue().equals("error")); 54 | type = xmlElement.getAttribute("type").getValue(); 55 | value = xmlElement.getAttribute("value").getValue(); 56 | repair = xmlElement.getAttribute("repair").getValue(); 57 | try { 58 | sentenceId = new Integer(xmlElement.getAttribute("sentence").getValue()); 59 | } catch (NumberFormatException ex) {} 60 | try { 61 | tokenId = new Integer(xmlElement.getAttribute("token").getValue()); 62 | } catch (NumberFormatException ex) {} 63 | } 64 | 65 | /** 66 | * Returns true if this message is an error message, or false if it is only a warning 67 | * message. 68 | * 69 | * @return true if this is an error message. 70 | */ 71 | public boolean isError() { 72 | return isError; 73 | } 74 | 75 | /** 76 | * Returns the type of the error/warning message. 77 | * 78 | * @return The type of the message. 79 | */ 80 | public String getType() { 81 | return type; 82 | } 83 | 84 | /** 85 | * Returns the sentence number that locates the reason for the error/warning message. 86 | * In some cases, this can be null. 87 | * 88 | * @return The sentence number. 89 | */ 90 | public Integer getSentenceId() { 91 | return sentenceId; 92 | } 93 | 94 | /** 95 | * Returns the token number that locates the reason for the error/warning message. 96 | * In some cases, this can be null. 97 | * 98 | * @return The token number. 99 | */ 100 | public Integer getTokenId() { 101 | return tokenId; 102 | } 103 | 104 | /** 105 | * Returns the value of the error/warning message. This is for example the word that 106 | * caused the error or warning. 107 | * 108 | * @return The value of the message. 109 | */ 110 | public String getValue() { 111 | return value; 112 | } 113 | 114 | /** 115 | * Returns an suggestion how to react on the error or warning. 116 | * 117 | * @return Suggestion how to react on the error/warning. 118 | */ 119 | public String getRepair() { 120 | return repair; 121 | } 122 | 123 | /** 124 | * Returns a pretty-printed error/warning message. 125 | */ 126 | public String toString() { 127 | return (isError ? "ERROR: [" : "WARNING: [") + type + "] at " + (sentenceId == null ? "?" : sentenceId) + "-" + (tokenId == null ? "?" : tokenId) + ": '" + value + "'. " + repair; 128 | } 129 | } -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/MessageContainer.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | import org.jdom.Element; 21 | 22 | /** 23 | * This class is a container for error and warning messages. 24 | * 25 | * @author Tobias Kuhn 26 | */ 27 | public class MessageContainer { 28 | 29 | private List messages = new ArrayList(); 30 | 31 | MessageContainer() { 32 | } 33 | 34 | MessageContainer(Element xmlElement) { 35 | if (xmlElement == null) return; 36 | for (Object o : xmlElement.getChildren("message")) { 37 | if (!(o instanceof Element)) continue; 38 | messages.add(new Message((Element) o)); 39 | } 40 | } 41 | 42 | /** 43 | * Returns a list that contains all messages. 44 | * 45 | * @return A list of all messages. 46 | */ 47 | public List getMessages() { 48 | return new ArrayList(messages); 49 | } 50 | 51 | /** 52 | * Returns a list that contains all error messages. 53 | * 54 | * @return A list of all error messages. 55 | */ 56 | public List getErrorMessages() { 57 | List list = new ArrayList(); 58 | for (Message m : messages) { 59 | if (m.isError()) list.add(m); 60 | } 61 | return list; 62 | } 63 | 64 | /** 65 | * Returns a list that contains all warning messages. 66 | * 67 | * @return A list of all warning messages. 68 | */ 69 | public List getWarningMessages() { 70 | List list = new ArrayList(); 71 | for (Message m : messages) { 72 | if (!m.isError()) list.add(m); 73 | } 74 | return list; 75 | } 76 | 77 | /** 78 | * Returns a list that contains all messages of a given type. 79 | * 80 | * @param type The type of the messages to be returned. 81 | * @return A list of all messages with the given type. 82 | */ 83 | public List getMessages(String type) { 84 | List list = new ArrayList(); 85 | for (Message m : messages) { 86 | if (m.getType().equals(type)) list.add(m); 87 | } 88 | return list; 89 | } 90 | 91 | /** 92 | * Returns a list that contains all error messages of a given type. 93 | * 94 | * @param type The type of the error messages to be returned. 95 | * @return A list of all error messages with the given type. 96 | */ 97 | public List getErrorMessages(String type) { 98 | List list = new ArrayList(); 99 | for (Message m : messages) { 100 | if (m.isError() && m.getType().equals(type)) list.add(m); 101 | } 102 | return list; 103 | } 104 | 105 | /** 106 | * Returns a list that contains all warning messages of a given type. 107 | * 108 | * @param type The type of the warning message to be returned. 109 | * @return A list of all warning messages with the given type. 110 | */ 111 | public List getWarningMessages(String type) { 112 | List list = new ArrayList(); 113 | for (Message m : messages) { 114 | if (!m.isError() && m.getType().equals(type)) list.add(m); 115 | } 116 | return list; 117 | } 118 | 119 | public String toString() { 120 | String s = ""; 121 | for (Message m : messages) { 122 | s += m; 123 | } 124 | return s; 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/OutputType.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | /** 18 | * This enumeration lists all the possible outputs of the ACE parser. 19 | * 20 | * @author Tobias Kuhn 21 | */ 22 | public enum OutputType { 23 | 24 | /** 25 | * The discourse representation structure (DRS) as a Prolog term. 26 | */ 27 | DRS, 28 | 29 | /** 30 | * The DRS in XML. 31 | */ 32 | DRSXML, 33 | 34 | /** 35 | * The DRS in pretty-printed form in plain text. 36 | */ 37 | DRSPP, 38 | 39 | /** 40 | * The DRS in pretty-printed form in HTML. 41 | */ 42 | DRSHTML, 43 | 44 | /** 45 | * A paraphrase which is a "best-effort" combination of PARAPHRASE1 and PARAPHRASE2. 46 | */ 47 | PARAPHRASE, 48 | 49 | /** 50 | * A paraphrase which uses full sentences instead of relative clauses. 51 | */ 52 | PARAPHRASE1, 53 | 54 | /** 55 | * A paraphrase which uses relative clauses instead of full sentences. 56 | */ 57 | PARAPHRASE2, 58 | 59 | /** 60 | * Tokens as a Prolog list of lists. 61 | */ 62 | TOKENS, 63 | 64 | /** 65 | * Sentences as a Prolog list. 66 | */ 67 | SENTENCES, 68 | 69 | /** 70 | * Simplified syntax trees as a Prolog list. 71 | */ 72 | SYNTAX, 73 | 74 | /** 75 | * Simplified syntax trees in pretty-printed form. 76 | */ 77 | SYNTAXPP, 78 | 79 | /** 80 | * Plain syntax trees as a Prolog list (for debugging). 81 | */ 82 | SYNTAXD, 83 | 84 | /** 85 | * Plain syntax trees in pretty-printed form (for debugging). 86 | */ 87 | SYNTAXDPP, 88 | 89 | /** 90 | * OWL/SWRL in the Functional-Style Syntax representation as a Prolog term. 91 | */ 92 | OWLFSS, 93 | 94 | /** 95 | * OWL/SWRL in the Functional-Style Syntax representation in a pretty-printed form. 96 | */ 97 | OWLFSSPP, 98 | 99 | /** 100 | * OWL/SWRL in the XML representation. 101 | */ 102 | OWLXML, 103 | 104 | /** 105 | * RuleML representation of the DRS. 106 | */ 107 | RULEML, 108 | 109 | /** 110 | * Standard first-order logic representation (default form) of the DRS as a Prolog term. 111 | */ 112 | FOL, 113 | 114 | /** 115 | * Standard first-order logic representation (prenex normal form) of the DRS as a Prolog term. 116 | */ 117 | PNF, 118 | 119 | /** 120 | * TPTP representation of the DRS. 121 | */ 122 | TPTP; 123 | 124 | /** 125 | * 126 | * @return flag used to pass the parameter to the parser in the solo-mode (e.g. "fol") 127 | */ 128 | public String toSoloFlag() { 129 | return toString().toLowerCase(); 130 | } 131 | 132 | /** 133 | * 134 | * @return flag used to pass the parameter to the parser in the multi-mode (e.g. "cfol") 135 | */ 136 | public String toMultiFlag() { 137 | return "c" + toSoloFlag(); 138 | } 139 | } -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/PrologUtils.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | /** 18 | * This class contains Prolog-related utility methods. 19 | * 20 | * @author Tobias Kuhn 21 | */ 22 | public class PrologUtils { 23 | 24 | private PrologUtils() {} // no instances allowed 25 | 26 | /** 27 | * Escapes the string according to Prolog escaping rules and puts it into single quotes. 28 | * 29 | * @param s The string to be escaped. 30 | * @return The escaped string. 31 | */ 32 | public static String escape(String s) { 33 | if (s == null) { 34 | return "''"; 35 | } 36 | return "'" + s.replace("\\", "\\\\").replace("'", "\\'") + "'"; 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/SyntaxBoxes.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2012, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | package ch.uzh.ifi.attempto.ape; 16 | 17 | import java.util.Stack; 18 | 19 | /** 20 | * This class generates the colored syntax boxes in HTML notation on the basis of the syntax tree 21 | * of an ACE sentence. Noun phrases are represented by blue boxes, verb phrases by yellow boxes, 22 | * and (subordinated) sentences by gray boxes. 23 | * 24 | * @author Tobias Kuhn 25 | */ 26 | public class SyntaxBoxes { 27 | 28 | private static final String[] sNodes = new String[] {"s", "cond_s", "neg_s", "s_coord", "top_s", "question", "command"}; 29 | private static final String[] vpNodes = new String[] {"vp", "vp_coord", "neg_vp"}; 30 | private static final String[] npNodes = new String[] {"np"}; 31 | 32 | private final boolean showS, showVP, showNP; 33 | private Stack stack = new Stack(); 34 | 35 | private SyntaxBoxes(boolean showS, boolean showVP, boolean showNP) { 36 | this.showS = showS; 37 | this.showVP = showVP; 38 | this.showNP = showNP; 39 | } 40 | 41 | /** 42 | * This method takes the syntax tree of a parsing result and generates the HTML representation of the 43 | * syntax boxes showing all three types of boxes. 44 | * 45 | * @param parserResult The parsing result. 46 | * @return The HTML representation of the syntax boxes. 47 | */ 48 | public static String getBoxesHtml(ACEParserResult parserResult) { 49 | return getBoxesHtml(parserResult, true, true, true); 50 | } 51 | 52 | /** 53 | * This method takes the syntax tree of a parsing result and generates the HTML representation of the 54 | * syntax boxes. The three types of boxes can individually be switched on or off. 55 | * 56 | * @param parserResult The parsing result. 57 | * @param showS true if the gray boxes for (subordinated) sentences should be shown. 58 | * @param showVP true if the yellow boxes for verb phrases should be shown. 59 | * @param showNP true if the blue boxes for noun phrases should be shown. 60 | * @return The HTML representation of the syntax boxes. 61 | */ 62 | public static String getBoxesHtml(ACEParserResult parserResult, boolean showS, boolean showVP, boolean showNP) { 63 | String s = new SyntaxBoxes(showS, showVP, showNP).createBoxes(parserResult.get(OutputType.SYNTAX)); 64 | String c = s.replace("'", "").replace("{", "").replace("}", "").replace("_that_", "that"); 65 | String r = 66 | "\n" + 67 | "\n\n" + 72 | "\n" + 73 | c + 74 | "\n" + 75 | "
"; 76 | // This style-element is actually not allowed at this position, but it works in all tested browsers. 77 | 78 | return r; 79 | } 80 | 81 | private String createBoxes(String p) { 82 | if (p.length() == 0) { 83 | return ""; 84 | } else if (p.startsWith(" ")) { 85 | return createBoxes(p.substring(1)); 86 | } else if (p.startsWith(",")) { 87 | return createBoxes(p.substring(1)); 88 | } else if (p.startsWith("[[")) { 89 | stack.push(""); 90 | return createBoxes(p.substring(1)); 91 | } else if (p.startsWith("[]")) { 92 | return createBoxes(p.substring(2)); 93 | } else if (p.startsWith("[")) { 94 | if (showS) { 95 | for (String s : sNodes) { 96 | if (p.startsWith("[" + s + ",")) { 97 | stack.push(""); 98 | return "" + createBoxes(p.substring(s.length()+2)); 99 | } 100 | } 101 | } 102 | if (showVP) { 103 | for (String s : vpNodes) { 104 | if (p.startsWith("[" + s + ",")) { 105 | stack.push("
"); 106 | return "" + createBoxes(p.substring(s.length()+2)); 107 | } 108 | } 109 | } 110 | if (showNP) { 111 | for (String s : npNodes) { 112 | if (p.startsWith("[" + s + ",")) { 113 | stack.push("
"); 114 | return "" + createBoxes(p.substring(s.length()+2)); 115 | } 116 | } 117 | } 118 | if (p.indexOf(",") > 0) { 119 | stack.push(""); 120 | return createBoxes(p.substring(p.indexOf(",")+1)); 121 | } 122 | } else if (p.startsWith("]")) { 123 | String t = stack.pop(); 124 | return t + createBoxes(p.substring(1)); 125 | } else if (p.indexOf("]") > 0) { 126 | int ci = p.indexOf(","); 127 | int bi = p.indexOf("]"); 128 | int i = bi; 129 | if (ci > 0 && ci < bi) i = ci; 130 | String a = p.substring(0, i); 131 | String b = p.substring(i); 132 | return " " + createBoxes(b); 133 | } 134 | return " ERROR(" + p + ")ERROR "; 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /java/src/main/java/ch/uzh/ifi/attempto/ape/package-info.java: -------------------------------------------------------------------------------- 1 | // This file is part of the Attempto Parsing Engine (APE). 2 | // Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | // 4 | // The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | // under the terms of the GNU Lesser General Public License as published by the Free Software 6 | // Foundation, either version 3 of the License, or (at your option) any later version. 7 | // 8 | // The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | // PURPOSE. See the GNU Lesser General Public License for more details. 11 | // 12 | // You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | // Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | /** 16 | * This package provides interfaces to the Attempto Parsing Engine (APE). 17 | * 18 | * 19 | * @author Kaarel Kaljurand 20 | * @author Tobias Kuhn 21 | */ 22 | package ch.uzh.ifi.attempto.ape; 23 | -------------------------------------------------------------------------------- /java/src/main/java/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Java Interface for APE 6 | 7 | 8 | 9 | The Java Interface for APE contains interfaces to the Attempto Parsing Engine (APE) 10 | developed within the Attempto project. 11 | The Java Interface for APE is free software licensed under the 12 | GNU Lesser General Public Licence 13 | (LGPL). It is hosted on GitHub. 14 | 15 | 16 | -------------------------------------------------------------------------------- /java/src/test/java/ch/uzh/ifi/attempto/ape/APELocalTest.java: -------------------------------------------------------------------------------- 1 | package ch.uzh.ifi.attempto.ape; 2 | 3 | import org.junit.BeforeClass; 4 | import org.junit.Test; 5 | 6 | import static org.junit.Assert.assertEquals; 7 | 8 | public class APELocalTest extends Testcase { 9 | 10 | private static ACEParser parser; 11 | 12 | @BeforeClass public static void setUp() { 13 | parser = getApeLocal(); 14 | } 15 | 16 | private static APELocal getApeLocal() { 17 | APELocal.init("../ape.exe", true); 18 | return APELocal.getInstance(); 19 | } 20 | 21 | @Test 22 | public void testDRS() throws ACEParserException { 23 | APELocal apeLocal = getApeLocal(); 24 | apeLocal.setGuessingEnabled(true); 25 | String drs = apeLocal.getSoloOutput(ACETEXT, OutputType.DRS); 26 | assertEquals("DRS mismatch", ACETEXT_DRS, drs); 27 | } 28 | 29 | @Test 30 | public final void testGetSoloOutput() throws ACEParserException { 31 | parser.setGuessingEnabled(false); 32 | String response = null; 33 | response = parser.getSoloOutput(Testcase.ACETEXT1, OutputType.PARAPHRASE1); 34 | 35 | assertEquals(Testcase.ACETEXT1_CORE_ACE, response.trim()); 36 | } 37 | @Test 38 | public final void testGetMultiOutput() { 39 | ACEParserResult result = parser.getMultiOutput(Testcase.ACETEXT, OutputType.DRS, OutputType.TPTP); 40 | assertEquals(Testcase.ACETEXT_DRS, result.get(OutputType.DRS)); 41 | assertEquals(Testcase.ACETEXT_TPTP, result.get(OutputType.TPTP)); 42 | } 43 | @Test 44 | public final void testGetMultiOutput3() { 45 | parser.setGuessingEnabled(true); 46 | ACEParserResult response = parser.getMultiOutput(Testcase.ACETEXT, OutputType.DRSPP); 47 | assertEquals(Testcase.ACETEXT_DRSPP, response.get(OutputType.DRSPP).trim()); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /java/src/test/java/ch/uzh/ifi/attempto/ape/APESocketTest.java: -------------------------------------------------------------------------------- 1 | package ch.uzh.ifi.attempto.ape; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | public class APESocketTest { 8 | private static final ACEParser parser = new APESocket(5000); 9 | 10 | @Test 11 | public final void testGetSoloOutput() { 12 | parser.setGuessingEnabled(false); 13 | String response = null; 14 | try { 15 | response = parser.getSoloOutput(Testcase.ACETEXT1, OutputType.PARAPHRASE1); 16 | } catch (ACEParserException e) { 17 | fail(e.getMessageContainer().toString()); 18 | } 19 | assertEquals(Testcase.ACETEXT1_CORE_ACE, response.trim()); 20 | } 21 | 22 | 23 | @Test 24 | public final void testGetMultiOutput() { 25 | //Lexicon lexicon = new Lexicon(); 26 | //lexicon.addEntry(LexiconEntry.createNounSgEntry("dooog", "DOOOG", Gender.NEUTRAL)); 27 | parser.setGuessingEnabled(true); 28 | ACEParserResult response = parser.getMultiOutput(Testcase.ACETEXT2, OutputType.PARAPHRASE1); 29 | assertEquals(Testcase.ACETEXT2_CORE_ACE, response.get(OutputType.PARAPHRASE1).trim()); 30 | } 31 | 32 | 33 | @Test 34 | public final void testGetMultiOutput3() { 35 | parser.setGuessingEnabled(true); 36 | ACEParserResult response = parser.getMultiOutput(Testcase.ACETEXT, OutputType.DRSPP); 37 | assertEquals(Testcase.ACETEXT_DRSPP, response.get(OutputType.DRSPP).trim()); 38 | } 39 | } -------------------------------------------------------------------------------- /java/src/test/java/ch/uzh/ifi/attempto/ape/LexiconEntryTest.java: -------------------------------------------------------------------------------- 1 | package ch.uzh.ifi.attempto.ape; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | public class LexiconEntryTest { 8 | 9 | @Test 10 | public final void testCreateAdvEntry() { 11 | LexiconEntry le = LexiconEntry.createAdvEntry(Testcase.WORD, Testcase.SYMBOL); 12 | assertEquals(le.toString(), Testcase.ENTRY); 13 | } 14 | 15 | @Test 16 | public final void testCreateAdvEntryEquals() { 17 | LexiconEntry le1 = LexiconEntry.createAdvEntry(Testcase.WORD, Testcase.SYMBOL); 18 | LexiconEntry le2 = LexiconEntry.createAdvEntry(Testcase.WORD, Testcase.SYMBOL); 19 | assertEquals(le1, le2); 20 | } 21 | 22 | @Test 23 | public final void testCreateAdvEntryHashCode() { 24 | LexiconEntry le1 = LexiconEntry.createAdvEntry(Testcase.WORD, Testcase.SYMBOL); 25 | LexiconEntry le2 = LexiconEntry.createAdvEntry(Testcase.WORD, Testcase.SYMBOL); 26 | assertEquals(le1.hashCode(), le2.hashCode()); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /java/src/test/java/ch/uzh/ifi/attempto/ape/Testcase.java: -------------------------------------------------------------------------------- 1 | package ch.uzh.ifi.attempto.ape; 2 | 3 | public class Testcase { 4 | 5 | public static final String ACETEXT = "John waits."; 6 | public static final String ACETEXT_DRSPP = "[A]\npredicate(A,wait,named(John))-1/2"; 7 | public static final String ACETEXT_DRS = "drs([A],[predicate(A,wait,named('John'))-1/2])"; 8 | public static final String ACETEXT_TPTP = "fof(f1, axiom, (\n? [A] : (predicate1(A,wait,'John'))))."; 9 | 10 | public static final String ACETEXT1 = "Every dog's friend is an animal."; 11 | public static final String ACETEXT1_CORE_ACE = "If there is a friend X1 of a dog then the friend X1 is an animal."; 12 | 13 | public static final String ACETEXT2 = "Every dooog's friend is an animal."; 14 | public static final String ACETEXT2_CORE_ACE = "If there is a friend X1 of a n:dooog then the friend X1 is an animal."; 15 | 16 | public static final String ACETEXT3 = "John|pn_sg|John_PN| |tv_finsg|buy_V2 everything that | isn't a present|noun_sg|present_N ."; 17 | public static final String ACETEXT3_OWLFSS = "'Ontology'(test,['SubClassOf'('ObjectComplementOf'('':present_N),'ObjectSomeValuesFrom'('ObjectInverseOf'('':buy_V2),'ObjectOneOf'(['':'John_PN'])))])"; 18 | 19 | public static final String ACETEXT4 = 20 | "the Åland_islands|pndef_pl|Åland_islands_PN|neutr are larger-than|adj_tr|larger-than_A2|than the Black_Forest|pndef_sg|Black_Forest_PN|neutr ."; 21 | public static final String ACETEXT4_OWLFSS = 22 | "'Ontology'(test,['ObjectPropertyAssertion'('':'larger-than_A2','':'Åland_islands_PN','':'Black_Forest_PN')])"; 23 | 24 | public static final String WORD = "multi word"; 25 | public static final String ENTRY= "adv('multi word', 'sym(multi word)')"; 26 | public static final String SYMBOL = "sym(multi word)"; 27 | 28 | } -------------------------------------------------------------------------------- /make_exe.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | del ape.exe 3 | swipl -O -F none -g "working_directory(_, 'prolog/parser'), [fit_to_plp], halt." -t halt & swipl -O -f ape.pl -g "qsave_program('ape.exe', [goal(ape), toplevel(halt)])." -t halt 4 | if exist ape.exe goto success 5 | echo Could not find the SWI Prolog command. 6 | echo Make sure that the location of the SWI Prolog binaries is in the PATH variable. 7 | goto end 8 | :success 9 | echo ape.exe created. 10 | :end 11 | -------------------------------------------------------------------------------- /pack.pl: -------------------------------------------------------------------------------- 1 | name(ape). 2 | version('6.7.180715'). 3 | 4 | % see http://www.swi-prolog.org/howto/PackInfo.html 5 | 6 | download('https://github.com/Attempto/APE/releases/*.zip'). 7 | 8 | title('Parser for Attempto Controlled English (ACE)'). 9 | author('Kaarel Kaljurand','kaljurand@gmail.com'). 10 | author('Norbert E. Fuchs','fuchs@ifi.uzh.ch'). 11 | author('Tobias Kuhn','kuhntobias@gmail.com'). 12 | 13 | home('https://github.com/Attempto/APE'). 14 | -------------------------------------------------------------------------------- /prolog/lexicon/chars.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(chars, [ 17 | is_digit/1, 18 | is_capitalized/1, 19 | to_lowercase/2, 20 | is_lowercase/1, 21 | is_uppercase/1, 22 | is_letter/1, 23 | is_unused/1, 24 | is_sentence_end_symbol/1 25 | ]). 26 | 27 | /** Characters 28 | 29 | @author Kaarel Kaljurand 30 | @author Tobias Kuhn 31 | @version 2009-04-29 32 | 33 | Note: SWI has char_type/2 which could be used instead of the predicates defined 34 | in this module. But Sicstus does not seem to have anything similar. 35 | Note also: char_type/2 does not seem to be good because it does not handle anything 36 | beyond ASCII-7. 37 | */ 38 | 39 | 40 | %% is_capitalized(+Token:atom) is semidet. 41 | % 42 | % Succeeds if Token starts with an uppercase letter. 43 | % 44 | % @param Token is an ACE token 45 | % 46 | is_capitalized(Token) :- 47 | atom(Token), 48 | atom_codes(Token, [Code | _]), 49 | is_uppercase(Code). 50 | 51 | 52 | %% to_lower_case(+TokenIn, -TokenOut) 53 | % 54 | % Transforms the first character into a lowercase character. The same token is returned if the first 55 | % character is not an uppercase character. 56 | % 57 | to_lowercase(TokenIn, TokenOut) :- 58 | atom(TokenIn), 59 | atom_codes(TokenIn, [Code|CodesRest]), 60 | is_uppercase(Code), 61 | !, 62 | NewCode is Code + 32, 63 | atom_codes(TokenOut, [NewCode|CodesRest]). 64 | 65 | to_lowercase(Token, Token). 66 | 67 | 68 | %% is_digit(+Code:integer) is semidet. 69 | % 70 | % Succeeds if Code corresponds to an ASCII-7 digit symbol. 71 | % 72 | % @param Code is a character code 73 | % 74 | is_digit(Code) :- 75 | 48 =< Code, Code =< 57. 76 | 77 | 78 | %% is_lowercase(+Code:integer) is semidet. 79 | % 80 | % Succeeds iff Code corresponds to a lowercase letter. 81 | % 82 | % @param Code is a character code 83 | % 84 | % We also test lowercase letters from the upper half of latin1. 85 | 86 | % 0x61 -- 0x7a (a..z) 87 | is_lowercase(Code) :- 88 | 97 =< Code, Code =< 122. 89 | 90 | % 0xdf -- 0xf6 91 | is_lowercase(Code) :- 92 | 223 =< Code, Code =< 246. 93 | 94 | % 0xf8 -- 0xff 95 | is_lowercase(Code) :- 96 | 248 =< Code, Code =< 255. 97 | 98 | 99 | %% is_uppercase(+Code:integer) is semidet. 100 | % 101 | % Succeeds iff Code corresponds to an uppercase letter. 102 | % 103 | % @param Code is a character code 104 | % 105 | % We also test uppercase letters from the upper half of latin1. 106 | 107 | % 0x41 -- 0x5a (A..Z) 108 | is_uppercase(Code) :- 109 | 65 =< Code, Code =< 90. 110 | 111 | % 0xc0 -- 0xd6 112 | is_uppercase(Code) :- 113 | 192 =< Code, Code =< 214. 114 | 115 | % 0xd8 -- 0xde 116 | is_uppercase(Code) :- 117 | 216 =< Code, Code =< 222. 118 | 119 | 120 | %% is_letter(+Code:integer) is semidet. 121 | % 122 | % Succeeds iff Code corresponds to a lower- or uppercase letter. 123 | % 124 | % @param Code is a character code 125 | % 126 | is_letter(Code) :- 127 | is_lowercase(Code). 128 | 129 | is_letter(Code) :- 130 | is_uppercase(Code). 131 | 132 | 133 | %% is_unused(+Code:integer) is semidet. 134 | % 135 | % Succeeds iff Code corresponds to an unused character according to 136 | % http://www.w3.org/MarkUp/html3/latin1.html 137 | % In addition: tab, linefeed. 138 | % 139 | % @param Code is a character code 140 | % 141 | is_unused(Code) :- 142 | Code =< 31. 143 | 144 | is_unused(Code) :- 145 | 127 =< Code, Code =< 160. 146 | 147 | 148 | %% is_sentence_end_symbol(?Token:atom) is semidet. 149 | % 150 | % Tests if Token is an ACE sentence end symbol. 151 | % 152 | % @param Token is a token. 153 | % 154 | is_sentence_end_symbol('.'). 155 | is_sentence_end_symbol('?'). 156 | is_sentence_end_symbol('!'). 157 | -------------------------------------------------------------------------------- /prolog/lexicon/clex.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(clex, [ 17 | clex_switch/1, % ?Switch 18 | set_clex_switch/1 % +Switch 19 | ]). 20 | :- use_module(library(error)). 21 | 22 | /** Common Lexicon Interface 23 | 24 | This module contains the predicates for the management of the common lexicon that is compiled into 25 | the executable. 26 | 27 | @author Tobias Kuhn 28 | @version 2008-07-17 29 | */ 30 | 31 | 32 | %% clex_file(-ClexFile) 33 | % 34 | % This predicate defines the clex-file that is loaded and compiled into the executable. In order to 35 | % change this, you have to edit the source code and recompile. 36 | 37 | clex_file(clex_lexicon). 38 | %clex_file(clex_lexicon_small). 39 | %clex_file(''). 40 | 41 | 42 | % The predicates for the lexicon entries are declared dynamic. In this way, they don't fail if 43 | % no entry exists. 44 | 45 | :- dynamic adv/2. 46 | :- dynamic adv_comp/2. 47 | :- dynamic adv_sup/2. 48 | :- dynamic adj_itr/2. 49 | :- dynamic adj_itr_comp/2. 50 | :- dynamic adj_itr_sup/2. 51 | :- dynamic adj_tr/3. 52 | :- dynamic adj_tr_comp/3. 53 | :- dynamic adj_tr_sup/3. 54 | :- dynamic noun_sg/3. 55 | :- dynamic noun_pl/3. 56 | :- dynamic noun_mass/3. 57 | :- dynamic mn_sg/2. 58 | :- dynamic mn_pl/2. 59 | :- dynamic pn_sg/3. 60 | :- dynamic pn_pl/3. 61 | :- dynamic pndef_sg/3. 62 | :- dynamic pndef_pl/3. 63 | :- dynamic iv_finsg/2. 64 | :- dynamic iv_infpl/2. 65 | :- dynamic tv_finsg/2. 66 | :- dynamic tv_infpl/2. 67 | :- dynamic tv_pp/2. 68 | :- dynamic dv_finsg/3. 69 | :- dynamic dv_infpl/3. 70 | :- dynamic dv_pp/3. 71 | :- dynamic prep/2. 72 | 73 | 74 | % Load the clex-file 75 | :- style_check(-discontiguous). 76 | :- clex_file(ClexFile), ( ClexFile == '' ; load_files(ClexFile, [encoding(utf8)]) ). 77 | :- style_check(+discontiguous). 78 | 79 | 80 | %% clex_switch(?Switch) 81 | % 82 | % This predicate returns 'on' if clex is switched on, or 'off' otherwise. 83 | 84 | :- dynamic(clex_switch/1). 85 | 86 | clex_switch(on). 87 | 88 | 89 | %% set_clex_switch(+Switch) 90 | % 91 | % This predicate switches clex on (Switch='on') or off (Switch='off'). 92 | 93 | set_clex_switch(Switch) :- 94 | must_be(oneof([on,off]), Switch), 95 | retractall(clex_switch(_)), 96 | assert(clex_switch(Switch)). 97 | -------------------------------------------------------------------------------- /prolog/lexicon/illegalwords.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(illegalwords, [ 17 | is_illegalword/2 % +IllegalWord:atom, -ErrorMessage 18 | ]). 19 | 20 | 21 | %% is_illegalword(+IllegalWord:atom, -ErrorMessage) is semidet. 22 | % 23 | % @param IllegalWord is a word that is not allowed in ACE 24 | % @param ErrorMessage is an error message explaning how to act 25 | % 26 | % This is a simple list of (function) words that are not allowed in ACE. 27 | % BUG: The question remains if one could be allowed to define such words as 28 | % content words and use them anyway. In this case, the error message would be misleading. 29 | % Should we in ACE define a set of words that are not ACE function words and that can not 30 | % be ACE content words either. 31 | % 32 | is_illegalword(any, 'The word \'any\' is not allowed. Did you mean \'every\', \'some\', or \'a\'?'). 33 | is_illegalword('Any', 'The word \'Any\' is not allowed. Did you mean \'Every\', \'Some\', or \'A\'?'). 34 | is_illegalword(anybody, 'The word \'anybody\' is not allowed. Did you mean \'everybody\' or \'somebody\'?'). 35 | is_illegalword('Anybody', 'The word \'Anybody\' is not allowed. Did you mean \'Everybody\' or \'Somebody\'?'). 36 | is_illegalword(anything, 'The word \'anything\' is not allowed. Did you mean \'everything\' or \'something\'?'). 37 | is_illegalword('Anything', 'The word \'Anything\' is not allowed. Did you mean \'Everything\' or \'Something\'?'). 38 | 39 | is_illegalword(this, 'The word \'this\' is not allowed. Did you mean \'the\'?'). 40 | is_illegalword('This', 'The word \'This\' is not allowed. Did you mean \'The\'?'). 41 | is_illegalword(these, 'The word \'these\' is not allowed. Did you mean \'the\'?'). 42 | is_illegalword('These', 'The word \'These\' is not allowed. Did you mean \'The\'?'). 43 | 44 | is_illegalword(Pronoun, ErrorText) :- 45 | is_illegal_pronoun(Pronoun), 46 | with_output_to(atom(ErrorText), format("The pronoun \'~w\' is not allowed. Use only third person singular or plural.", [Pronoun])). 47 | 48 | 49 | %% is_illegal_pronoun(+Pronoun:atom) is semidet. 50 | % 51 | % @param Pronoun is an English pronoun 52 | % 53 | % Succeeds if Pronoun is not allowed in ACE. 54 | % 55 | is_illegal_pronoun('I'). 56 | is_illegal_pronoun(me). 57 | is_illegal_pronoun('Me'). 58 | is_illegal_pronoun(my). 59 | is_illegal_pronoun('My'). 60 | is_illegal_pronoun(mine). 61 | is_illegal_pronoun('Mine'). 62 | is_illegal_pronoun(yours). 63 | is_illegal_pronoun('Yours'). 64 | is_illegal_pronoun(we). 65 | is_illegal_pronoun('We'). 66 | is_illegal_pronoun(us). 67 | is_illegal_pronoun('Us'). 68 | is_illegal_pronoun(our). 69 | is_illegal_pronoun('Our'). 70 | is_illegal_pronoun(ours). 71 | is_illegal_pronoun('Ours'). 72 | is_illegal_pronoun('Theirs'). 73 | -------------------------------------------------------------------------------- /prolog/lexicon/is_in_lexicon.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(is_in_lexicon, [ 17 | is_in_lexicon/1, 18 | is_functionword/1, 19 | is_contentword/1 20 | ]). 21 | 22 | 23 | /** Is a token in the lexicon? 24 | 25 | @author Kaarel Kaljurand 26 | @author Tobias Kuhn 27 | @version 2007-12-06 28 | 29 | */ 30 | 31 | :- use_module(functionwords). 32 | :- use_module(lexicon_interface). 33 | :- use_module(illegalwords). 34 | :- use_module(chars). 35 | 36 | 37 | %% is_in_lexicon(+WordForm:atom) is semidet. 38 | % 39 | % @param WordForm is an ACE wordform 40 | % 41 | % Succeeds if WordForm is among the ACE words, possibly 42 | % one of the illegal words like `any' or `this'. 43 | % 44 | is_in_lexicon(WordForm) :- 45 | ( 46 | is_functionword(WordForm) 47 | ; 48 | is_contentword(WordForm) 49 | ; 50 | is_illegalword(WordForm, _) 51 | ). 52 | 53 | 54 | %% is_functionword(+WordForm:atom) is nondet. 55 | % 56 | % @param WordForm is an ACE wordform 57 | % 58 | % Succeeds if WordForm is among the ACE function words. 59 | % 60 | is_functionword(WordForm) :- 61 | ( 62 | functionwords:rawnumber_number(WordForm, _) 63 | ; 64 | functionwords:functionword(WordForm) 65 | ; 66 | functionwords:variable(WordForm) 67 | ). 68 | 69 | 70 | %% is_contentword(+WordForm:atom) is nondet. 71 | % 72 | % @param WordForm is an ACE wordform 73 | % 74 | % Succeeds if WordForm is in the content word lexicon. 75 | % 76 | is_contentword(WordForm) :- 77 | ( 78 | adv(WordForm, _) 79 | ; 80 | adv_comp(WordForm, _) 81 | ; 82 | adv_sup(WordForm, _) 83 | ; 84 | adj_itr(WordForm, _) 85 | ; 86 | adj_itr_comp(WordForm, _) 87 | ; 88 | adj_itr_sup(WordForm, _) 89 | ; 90 | adj_tr(WordForm, _, _) 91 | ; 92 | adj_tr_comp(WordForm, _, _) 93 | ; 94 | adj_tr_sup(WordForm, _, _) 95 | ; 96 | noun_sg(WordForm, _, _) 97 | ; 98 | noun_pl(WordForm, _, _) 99 | ; 100 | noun_mass(WordForm, _, _) 101 | ; 102 | mn_sg(WordForm, _) 103 | ; 104 | mn_pl(WordForm, _) 105 | ; 106 | pn_sg(WordForm, _, _) 107 | ; 108 | pn_pl(WordForm, _, _) 109 | ; 110 | pndef_sg(WordForm, _, _) 111 | ; 112 | pndef_pl(WordForm, _, _) 113 | ; 114 | iv_finsg(WordForm, _) 115 | ; 116 | iv_infpl(WordForm, _) 117 | ; 118 | tv_finsg(WordForm, _) 119 | ; 120 | tv_infpl(WordForm, _) 121 | ; 122 | tv_pp(WordForm, _) 123 | ; 124 | dv_finsg(WordForm, _, _) 125 | ; 126 | dv_infpl(WordForm, _, _) 127 | ; 128 | dv_pp(WordForm, _, _) 129 | ; 130 | ( chars:to_lowercase(WordForm, WordFormL), prep(WordFormL, _) ) 131 | ). 132 | -------------------------------------------------------------------------------- /prolog/parser/.gitignore: -------------------------------------------------------------------------------- 1 | /*.plp 2 | -------------------------------------------------------------------------------- /prolog/parser/compile.sh: -------------------------------------------------------------------------------- 1 | 2 | swipl -g "[fit_to_plp], halt." 3 | -------------------------------------------------------------------------------- /prolog/parser/fit_to_plp.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | %============================================================================== 17 | % Convert fit (i.e. ProFIT) files into plp (i.e. Prolog). 18 | % Kaarel Kaljurand 19 | % Tobias Kuhn 20 | % 2008-03-13 21 | %============================================================================== 22 | % Notes: 23 | % * No interactivity is needed, so you can run it on the commandline, e.g. 24 | % swipl -g "[fit_to_plp], halt." 25 | %============================================================================== 26 | 27 | :- op(400, fy, -). 28 | :- op(400, fy, ~). 29 | :- op(500, xfx, =>). 30 | :- op(500, xfx, v). 31 | 32 | 33 | :- [prologfeatures]. 34 | 35 | :- resolve_features([sorts, grammar, grammar_functionwords, grammar_contentwords]). 36 | -------------------------------------------------------------------------------- /prolog/parser/sentence_failure.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(sentence_failure, [ 17 | get_all_sentence_errors/2, % +SentenceTokens, -ErrorTextList 18 | get_sentence_error_text/2 % +SentenceTokens, -ErrorText 19 | ]). 20 | 21 | :- use_module('../lexicon/lexicon_interface'). 22 | 23 | :- use_module('../lexicon/chars', [ 24 | is_capitalized/1 25 | ]). 26 | 27 | :- use_module('../lexicon/is_in_lexicon', [ 28 | is_functionword/1 29 | ]). 30 | 31 | :- use_module('../lexicon/illegalwords'). 32 | 33 | :- style_check(-singleton). 34 | :- style_check(-discontiguous). 35 | :- use_module('grammar.plp'). 36 | :- style_check(+discontiguous). 37 | :- style_check(+singleton). 38 | 39 | /** Sentence Failure 40 | 41 | @author Norbert E. Fuchs 42 | @author Tobias Kuhn 43 | @author Kaarel Kaljurand 44 | @version 2011-07-18 45 | */ 46 | 47 | %% get_all_sentence_errors(+SentenceTokens:list, -ErrorTextList:list) is det. 48 | % 49 | % @param SentenceTokens is a list of tokens in the sentence 50 | % @param ErrorTextList is a list of error messages 51 | % 52 | get_all_sentence_errors(SentenceTokens, ErrorTextList) :- 53 | findall(ErrorText, get_sentence_error_text(SentenceTokens, ErrorText), ErrorTextListIntermediate), 54 | % remove duplicate messages 55 | list_to_set(ErrorTextListIntermediate, ErrorTextList). 56 | 57 | 58 | %% get_sentence_error_text(+SentenceTokens:list, -ErrorText:atom) is nondet. 59 | % 60 | % @param SentenceTokens is a list of tokens in the sentence 61 | % @param ErrorText is an error message 62 | % 63 | 64 | % check for illegal words 65 | get_sentence_error_text(SentenceTokens, ErrorText) :- 66 | member(IllegalWord, SentenceTokens), 67 | % BUG: add: \+ is_contentword(IllegalWord) 68 | % because maybe the user defined `any' as a contentword 69 | is_illegalword(IllegalWord, ErrorText). 70 | 71 | % check for repetitions of tokens 72 | get_sentence_error_text(SentenceTokens, ErrorText) :- 73 | append(_, [Token, '<>', Token|_], SentenceTokens), 74 | \+ is_repeatable(Token), 75 | with_output_to(atom(ErrorText), format("Token \'~w\' repeated.", [Token])). 76 | 77 | % check for `there is' + proper name 78 | get_sentence_error_text(SentenceTokens, ErrorText) :- 79 | append(_, [There, is, Token, '<>' | _], SentenceTokens), 80 | ( 81 | There = there 82 | ; 83 | There = 'There' 84 | ), 85 | ( 86 | Token = the 87 | ; 88 | is_capitalized(Token) 89 | ; 90 | pn_sg(Token, _, _) 91 | ), 92 | with_output_to(atom(ErrorText), format("The construct \'there is\' + \'~w\' is not allowed.", [Token])). 93 | 94 | % check for `there are' + proper name 95 | get_sentence_error_text(SentenceTokens, ErrorText) :- 96 | append(_, [There, are, Token, '<>' | _], SentenceTokens), 97 | ( 98 | There = there 99 | ; 100 | There = 'There' 101 | ), 102 | ( 103 | Token = the 104 | ; 105 | is_capitalized(Token) 106 | ; 107 | pn_pl(Token, _, _) 108 | ), 109 | with_output_to(atom(ErrorText), format("The construct \'there are\' + \'~w\' is not allowed.", [Token])). 110 | 111 | % check for intransitive verb followed by that-subordination 112 | % Example: John appears that Mary waits. (`appear' is an intransitive verb that is not transitive) 113 | get_sentence_error_text(SentenceTokens, ErrorText) :- 114 | append(_, [Wordform, '<>', that | _], SentenceTokens), 115 | ( 116 | iv_finsg(Wordform, Verb) 117 | ; 118 | iv_infpl(Wordform, Verb) 119 | ), 120 | with_output_to(atom(ErrorText), format("The intransitive verb \'~w\' cannot be followed by that-subordination. Use a transitive verb.", [Verb])). 121 | 122 | get_sentence_error_text(SentenceTokens, 'The sentence contains \'then\' but not \'if\'.') :- 123 | member(then, SentenceTokens), 124 | \+ member(if, SentenceTokens), 125 | \+ member('If', SentenceTokens). 126 | 127 | get_sentence_error_text(SentenceTokens, 'The sentence contains \'if\' but not \'then\'.') :- 128 | ( 129 | member(if, SentenceTokens) 130 | ; 131 | member('If', SentenceTokens) 132 | ), 133 | \+ member(then, SentenceTokens). 134 | 135 | 136 | % check for illegal use of commas 137 | % Note that this rule does not find all illegal uses of commas, e.g.: 138 | % [...] ... , ... [...] 139 | % {...} ... , ... {...} 140 | % ,! 141 | get_sentence_error_text(SentenceTokens, 'Commas must be immediately followed by \'and\' or \'or\', or must occur at specified positions in lists, sets and commands.') :- 142 | append(Front, [',', NextToken | Tail], SentenceTokens), 143 | % comma not immediately followed by 'and' 144 | NextToken \= and, 145 | % comma not immediately followed by 'or' 146 | NextToken \= or, 147 | % comma not followed by an exclamation mark (command) 148 | \+ member('!', Tail), 149 | % comma not between [ and ] (list) 150 | \+ (member('[', Front), member(']', Tail)), 151 | % comma not between { and } (set) 152 | \+ (member('{', Front), member('}', Tail)). 153 | 154 | 155 | get_sentence_error_text(_, 'This is the first sentence that was not ACE. The sign <> indicates the position where parsing failed.'). 156 | 157 | 158 | %% is_repeatable(?Token) is nondet. 159 | % 160 | % @param Token is an ACE token that can be repeated 161 | % 162 | % Example: ((1+2)-3) = 0. 163 | % 164 | is_repeatable('{'). 165 | is_repeatable('}'). 166 | is_repeatable('('). 167 | is_repeatable(')'). 168 | is_repeatable('['). 169 | is_repeatable(']'). 170 | is_repeatable('"'). 171 | -------------------------------------------------------------------------------- /prolog/parser/tokens_to_sentences.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(tokens_to_sentences, [ 17 | tokens_to_sentences/2, 18 | tokens_to_paragraphs/2 19 | ]). 20 | 21 | 22 | :- use_module('../lexicon/chars', [ 23 | is_sentence_end_symbol/1 24 | ]). 25 | 26 | 27 | /** APE Sentence splitter 28 | 29 | Converts a flat list of tokens into a list of sentences, 30 | each of which is a list of tokens. Sentences end with 31 | one of the three symbols: '.', '?', and '!'. 32 | 33 | For example, the following list of tokens: 34 | 35 | == 36 | [John, likes, Mary, ., Every, man, owns, a, car, .] 37 | == 38 | 39 | is converted into the following list of sentences 40 | 41 | == 42 | [[John, likes, Mary, .], [Every, man, owns, a, car, .]] 43 | == 44 | 45 | @author Kaarel Kaljurand 46 | @author Tobias Kuhn 47 | @version 2009-05-21 48 | 49 | @bug should we generate error messages here (if token list does not end with ./?/!) 50 | 51 | */ 52 | 53 | 54 | %% tokens_to_sentences(+Tokens:list, -Sentences:list) is semidet. 55 | % 56 | % Succeeds if Tokens is a list of ACE sentences, in this case 57 | % the sentences are returned. To succeed the token list must either 58 | % be empty or end with a sentence end symbol. E.g. the following 59 | % token list would cause a failure: 60 | % 61 | %== 62 | %[a, b, c] 63 | %== 64 | % 65 | % @param Tokens is a list of ACE tokens 66 | % @param Sentences is a list of sentences (where a sentence is a list of ACE tokens) 67 | % 68 | tokens_to_sentences([], []). 69 | 70 | tokens_to_sentences(Tokens, [[^|Sentence]|Sentences]) :- 71 | first_sentence(Tokens, Sentence, RestTokens), 72 | tokens_to_sentences(RestTokens, Sentences). 73 | 74 | 75 | %% first_sentence(+Tokens:list, -Sentence:list, -RestTokens:list) is det. 76 | % 77 | % Note that the token list can contain variables (added by the guesser 78 | % to match prefixed in the parser). Thus we have to make sure that a variable 79 | % is not "mistaken" for a sentence end symbol. 80 | % 81 | % @param Tokens is a list of ACE tokens 82 | % @param Sentence is an ACE sentence (a list of ACE tokens) 83 | % @param RestTokens is a list of ACE tokens 84 | % 85 | first_sentence([SentenceEndSymbol | RestTokens], [SentenceEndSymbol], RestTokens) :- 86 | nonvar(SentenceEndSymbol), 87 | is_sentence_end_symbol(SentenceEndSymbol), 88 | !. 89 | 90 | first_sentence([Token | RestTokens], RestSentence, RestTokens2) :- 91 | Token == '

', 92 | !, 93 | first_sentence(RestTokens, RestSentence, RestTokens2). 94 | 95 | first_sentence([Token | RestTokens], [Token | RestSentence], RestTokens2) :- 96 | first_sentence(RestTokens, RestSentence, RestTokens2). 97 | 98 | 99 | %% tokens_to_paragraphs(+Tokens, -Paragraphs). 100 | 101 | tokens_to_paragraphs([], []). 102 | 103 | tokens_to_paragraphs(Tokens, [Paragraph|Paragraphs]) :- 104 | first_paragraph(Tokens, Paragraph, RestTokens), 105 | tokens_to_paragraphs(RestTokens, Paragraphs). 106 | 107 | 108 | %% first_paragraph(+Tokens, -Paragraph, -RestTokens). 109 | 110 | first_paragraph([Token | RestTokens], [], RestTokens) :- 111 | Token == '

', 112 | !. 113 | 114 | first_paragraph([Token | RestTokens], [Token | RestParagraph], RestTokens2) :- 115 | first_paragraph(RestTokens, RestParagraph, RestTokens2). 116 | 117 | first_paragraph([], [], []). 118 | -------------------------------------------------------------------------------- /prolog/utils/drs_ops.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(drs_ops, [ 17 | drs_operator/1, 18 | unary_drs_operator/1, 19 | binary_drs_operator/1 20 | ]). 21 | 22 | /** DRS Operators 23 | 24 | @author Tobias Kuhn 25 | */ 26 | 27 | 28 | %% drs_operator(?DRSOperator) 29 | 30 | drs_operator(DRSOperator) :- 31 | ( 32 | unary_drs_operator(DRSOperator) 33 | ; 34 | binary_drs_operator(DRSOperator) 35 | ). 36 | 37 | 38 | %% unary_drs_operator(?DRSOperator) 39 | 40 | unary_drs_operator(-). 41 | unary_drs_operator(~). 42 | unary_drs_operator(can). 43 | unary_drs_operator(must). 44 | unary_drs_operator(should). 45 | unary_drs_operator(may). 46 | unary_drs_operator(question). 47 | unary_drs_operator(command). 48 | 49 | 50 | %% binary_drs_operator(?DRSOperator) 51 | 52 | binary_drs_operator(=>). 53 | binary_drs_operator(v). 54 | 55 | -------------------------------------------------------------------------------- /prolog/utils/drs_reverse.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(drs_reverse, [drs_reverse/2]). 17 | 18 | :- use_module(drs_ops). 19 | 20 | /** Reverse a DRS 21 | 22 | @author Kaarel Kaljurand 23 | @author Tobias Kuhn 24 | @version 2008-05-13 25 | 26 | */ 27 | 28 | 29 | %% drs_reverse(+Drs:term, -DrsReversed:term) is det. 30 | % 31 | % Reverses all domains (lists of referents) and condition lists 32 | % of the input DRS. 33 | % 34 | % @param Drs is an Attempto DRS 35 | % @param DrsReversed is the DRS with its domain and conditions reversed 36 | % 37 | drs_reverse(drs([], []), drs([], [])) :- !. 38 | 39 | drs_reverse(drs(Dom, Conds), drs(DomR, CondsR)) :- 40 | reverse(Dom, DomR), 41 | reverse(Conds, Conds1), 42 | conds_reverse(Conds1, CondsR). 43 | 44 | 45 | %% conds_reverse(+Conditions:list, -ConditionsReversed:list) is det. 46 | % 47 | % Reverses each condition in a list of conditions. 48 | % 49 | % @param Conditions is a list of conditions 50 | % @param ConditionsReversed is a list of conditions reversed 51 | % 52 | conds_reverse([], []). 53 | 54 | conds_reverse([First | Conds], [FirstR | CondsR]) :- 55 | condition_reverse(First, FirstR), 56 | conds_reverse(Conds, CondsR). 57 | 58 | 59 | %% condition_reverse(+Condition:term, -ConditionReversed:term) is det. 60 | % 61 | % If the input is a complex condition then reverses its component DRSs. 62 | % If the input is an atomic condition then does nothing. 63 | % 64 | % @param Condition is a DRS condition 65 | % @param ConditionReversed is the condition reversed 66 | % 67 | condition_reverse(Drs, DrsR) :- 68 | Drs =.. [Op, SubDrs], 69 | unary_drs_operator(Op), 70 | drs_reverse(SubDrs, SubDrsR), 71 | !, 72 | DrsR =.. [Op, SubDrsR]. 73 | 74 | condition_reverse(Drs, DrsR) :- 75 | Drs =.. [Op, SubDrs1, SubDrs2], 76 | binary_drs_operator(Op), 77 | drs_reverse(SubDrs1, SubDrs1R), 78 | drs_reverse(SubDrs2, SubDrs2R), 79 | !, 80 | DrsR =.. [Op, SubDrs1R, SubDrs2R]. 81 | 82 | condition_reverse([H|T], R) :- 83 | reverse([H|T], R1), 84 | conds_reverse(R1, R), 85 | !. 86 | 87 | condition_reverse(Label:Drs, Label:DrsR) :- 88 | drs_reverse(Drs, DrsR), 89 | !. 90 | 91 | condition_reverse(Cond, Cond). 92 | -------------------------------------------------------------------------------- /prolog/utils/drs_to_ace.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(drs_to_ace, [drs_to_ace/2]). 17 | 18 | :- use_module(drs_to_drslist, [ 19 | drs_to_drslist/2 20 | ]). 21 | 22 | :- use_module(drs_to_coreace). 23 | 24 | :- use_module(drs_to_npace). 25 | 26 | /** DRS to ACE verbalizer 27 | 28 | Translate an Attempto DRS into Attempto Controlled English (ACE). 29 | The result is either in Core ACE or in NP ACE. 30 | 31 | @author Kaarel Kaljurand 32 | @version 2009-06-03 33 | */ 34 | 35 | 36 | %% drs_to_ace(+Drs:drs, -Ace:list) is det. 37 | % 38 | % Splits the given DRS into a list of (smaller) DRSs, 39 | % and verbalizes each split in either Core ACE or NP ACE. 40 | % 41 | % @param Drs is an Attempto DRS (untyped) 42 | % @param Ace is a list of ACE sentences 43 | % 44 | drs_to_ace(Drs, Ace) :- 45 | drs_to_drslist(Drs, DrsList), 46 | drslist_to_ace(DrsList, Ace). 47 | 48 | 49 | %% drslist_to_ace 50 | % 51 | % 52 | drslist_to_ace([], []). 53 | 54 | drslist_to_ace([Drs | DrsList], [Ace | AceList]) :- 55 | drs_to_ace_x(Drs, Ace), 56 | drslist_to_ace(DrsList, AceList). 57 | 58 | 59 | % BUG: As Drace NP might take very long (due to a bug?) we add 60 | % a timeout to fail if it takes longer than, say, 0.5 seconds. 61 | drs_to_ace_x(Drs, Ace) :- 62 | catch( 63 | call_with_time_limit( 64 | 0.5, 65 | drs_to_npace:drs_to_npace(Drs, Ace) 66 | ), 67 | time_limit_exceeded, 68 | fail 69 | ), 70 | Ace \= [], 71 | \+ member('ERROR', Ace), 72 | !. 73 | 74 | drs_to_ace_x(Drs, Ace) :- 75 | drs_to_coreace:drs_to_coreace(Drs, Ace). 76 | -------------------------------------------------------------------------------- /prolog/utils/drs_to_ascii.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(drs_to_ascii, [ 17 | drs_to_ascii/2, % +Drs, -DrsAscii 18 | display_drs/1 % +Drs 19 | ]). 20 | 21 | 22 | /** DRS Pretty-printer 23 | 24 | Creates a pretty print representation of a DRS. 25 | 26 | @author Kaarel Kaljurand 27 | @version 2008-03-14 28 | */ 29 | 30 | 31 | :- op(400, fx, -). 32 | :- op(400, fx, ~). 33 | :- op(500, xfx, =>). 34 | :- op(500, xfx, v). 35 | 36 | 37 | %% drs_to_ascii(+Drs:term, -DrsAscii:atom) is det. 38 | % 39 | % @param Drs is an Attempto DRS 40 | % @param DrsAscii is an ASCII-graphics representation of the DRS 41 | % 42 | drs_to_ascii(Drs, DrsAscii) :- 43 | drs_to_drspp(Drs, PP), 44 | with_output_to(atom(DrsAscii), pp_to_ascii(PP)). 45 | 46 | 47 | %% display_drs(+DRS) 48 | % 49 | % Makes a pretty print of a DRS and writes it out on the screen. 50 | % 51 | display_drs(Drs):- 52 | drs_to_drspp(Drs, PP), 53 | pp_to_ascii(PP). 54 | 55 | 56 | %% drs_to_drspp(+Drs:term, -DrsPP:list) is det. 57 | % 58 | % @param Drs is an Attempto DRS 59 | % @param DrsPP is the DRS with indentation information 60 | % 61 | drs_to_drspp(Drs, PP) :- 62 | copy_term(Drs, DrsCopy), 63 | numbervars(DrsCopy, 0, _), 64 | write_drs(DrsCopy, 0, PP). 65 | 66 | 67 | %% pp_to_ascii(+PP:term) is det. 68 | % 69 | pp_to_ascii([]). 70 | 71 | pp_to_ascii([(Indent, Term) | Rest]) :- 72 | with_output_to(atom(AtomTerm), format('~W', [Term, [numbervars(true)]])), 73 | PrettyIndent is Indent * 3, 74 | writef('%r%w\n', [' ', PrettyIndent, AtomTerm]), 75 | pp_to_ascii(Rest). 76 | 77 | 78 | %% write_drs(+DRS, +Indent, -PP) 79 | % 80 | % Creates a DRS in pretty print and indents it 81 | % according to the value of Indent 82 | % 83 | write_drs(drs(Dom,[]), Indent, [(Indent,'No conditions') | PP]):- 84 | write_dom(Dom, Indent, PP), 85 | !. 86 | 87 | write_drs(drs(Dom,Conds),Indent,PP):- 88 | write_dom(Dom,Indent,PP1), 89 | write_conds(Conds,Indent,PP2), 90 | append(PP1,PP2,PP), 91 | !. 92 | 93 | write_drs(_Term,Indent,[(Indent,'ERROR')]). 94 | 95 | 96 | %% write_dom(+Dom:list, +Indent:integer, -PP:list) is det. 97 | % 98 | % 99 | write_dom(Dom, Indent, [(Indent, Dom)]). 100 | 101 | 102 | %% write_conds(+ConditionsList,+Indent) 103 | % 104 | % 105 | write_conds([],_Indent,[]). 106 | 107 | write_conds([F|R],Indent,PP):- 108 | write_cond(F,Indent,PP1), 109 | write_conds(R,Indent,PP2), 110 | append(PP1,PP2,PP). 111 | 112 | 113 | %% write_cond(+Condition,+Indent) 114 | % 115 | % 116 | write_cond(Restr => Scope,Indent,PP):- 117 | !, 118 | NewIndent is Indent+1, 119 | write_drs(Restr,NewIndent,PP1), 120 | write_drs(Scope,NewIndent,PP2), 121 | append(PP1,[(NewIndent,=>)|PP2],PP). 122 | 123 | write_cond(Restr v Scope,Indent,PP):- 124 | !, 125 | NewIndent is Indent+1, 126 | write_drs(Restr,NewIndent,PP1), 127 | write_drs(Scope,NewIndent,PP2), 128 | append(PP1,[(NewIndent,v)|PP2],PP). 129 | 130 | write_cond([FirstCond|Conds], Indent, PP) :- 131 | !, 132 | NewIndent is Indent+1, 133 | write_conds([FirstCond|Conds], NewIndent, PP). 134 | 135 | write_cond(-DRS, Indent, [(NewIndent,'NOT') | PP]) :- 136 | !, 137 | NewIndent is Indent+1, 138 | write_drs(DRS,NewIndent,PP). 139 | 140 | write_cond(~DRS, Indent, [(NewIndent,'NAF') | PP]) :- 141 | !, 142 | NewIndent is Indent+1, 143 | write_drs(DRS, NewIndent, PP). 144 | 145 | write_cond(can(DRS), Indent, [(NewIndent, 'CAN') | PP]) :- 146 | !, 147 | NewIndent is Indent+1, 148 | write_drs(DRS, NewIndent, PP). 149 | 150 | write_cond(must(DRS), Indent, [(NewIndent, 'MUST') | PP]) :- 151 | !, 152 | NewIndent is Indent+1, 153 | write_drs(DRS, NewIndent, PP). 154 | 155 | write_cond(should(DRS), Indent, [(NewIndent, 'SHOULD') | PP]) :- 156 | !, 157 | NewIndent is Indent+1, 158 | write_drs(DRS, NewIndent, PP). 159 | 160 | write_cond(may(DRS), Indent, [(NewIndent, 'MAY') | PP]) :- 161 | !, 162 | NewIndent is Indent+1, 163 | write_drs(DRS, NewIndent, PP). 164 | 165 | write_cond(question(DRS), Indent, [(NewIndent, 'QUESTION') | PP]) :- 166 | !, 167 | NewIndent is Indent+1, 168 | write_drs(DRS, NewIndent, PP). 169 | 170 | write_cond(command(DRS), Indent, [(NewIndent, 'COMMAND') | PP]) :- 171 | !, 172 | NewIndent is Indent+1, 173 | write_drs(DRS, NewIndent, PP). 174 | 175 | write_cond(Label:DRS, Indent, [(NewIndent, Label) | PP]) :- 176 | !, 177 | NewIndent is Indent+1, 178 | write_drs(DRS, NewIndent, PP). 179 | 180 | write_cond(drs(Dom,Cond),Indent,PP):- 181 | !, 182 | NewIndent is Indent+1, 183 | write_drs(drs(Dom,Cond),NewIndent,PP). 184 | 185 | write_cond(Cond, Indent, [(Indent,Cond)]). 186 | -------------------------------------------------------------------------------- /prolog/utils/drs_to_drslist.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | :- module(drs_to_drslist, [ 16 | drs_to_drslist/2 17 | ]). 18 | 19 | 20 | :- use_module(drs_ops, [ 21 | drs_operator/1 22 | ]). 23 | 24 | /** DRS to DRS lists converter 25 | 26 | This module provides predicates to split a given DRS into 27 | a list of DRSs, such that if the elements of the resulting list 28 | are merged (by concatenating the domains and the condition lists 29 | of its DRSs), 30 | then the resulting DRS is structurally equivalent to the original. 31 | The DRSs in the resulting list do not share discourse referents. 32 | 33 | @author Kaarel Kaljurand 34 | @version 2009-06-03 35 | 36 | */ 37 | 38 | 39 | %% drs_to_drslist(+Drs:drs, -DrsList:list) is det. 40 | % 41 | % @param Drs is an Attempto DRS 42 | % @param DrsList is a list of Attempto DRSs 43 | % 44 | 45 | drs_to_drslist(drs(_, CondList), DrsListSorted) :- 46 | termlist_to_termlistlist(CondList, CondListList), 47 | maplist(condlist_to_drs, CondListList, DrsList), 48 | sort_drslist(DrsList, DrsListSorted). 49 | 50 | 51 | condlist_to_drs(CondList, drs(Dom, CondList)) :- 52 | get_toplevel_conds(CondList, ToplevelCondList), 53 | term_variables(ToplevelCondList, Dom). 54 | 55 | 56 | %% get_toplevel_conds(+CondsIn:list, -CondsOut:list) 57 | % 58 | % Extracts from the given list of DRS conditions only 59 | % those conditions that contribute discourse referents 60 | % to the toplevel domain. Such conditions are simple 61 | % toplevel conditions, but also simple conditions in the lists. 62 | % For example, in the DRS of the sentence 63 | % 64 | % Less than 3 dogs hate less than 3 cats. 65 | % 66 | % all discourse referents are toplevel. 67 | % 68 | get_toplevel_conds([], []). 69 | 70 | get_toplevel_conds([Cond-Id | Conds], [Cond-Id | SelectedConds]) :- 71 | !, 72 | get_toplevel_conds(Conds, SelectedConds). 73 | 74 | get_toplevel_conds([[H | T] | Conds], SelectedConds) :- 75 | !, 76 | get_toplevel_conds([H | T], SelectedConds1), 77 | get_toplevel_conds(Conds, SelectedConds2), 78 | append(SelectedConds1, SelectedConds2, SelectedConds). 79 | 80 | get_toplevel_conds([_ComplexCond | Conds], SelectedConds) :- 81 | get_toplevel_conds(Conds, SelectedConds). 82 | 83 | 84 | termlist_to_termlistlist(TermList, TermListList) :- 85 | termlist_to_termlistlist(TermList, [], TermListList). 86 | 87 | termlist_to_termlistlist([], Out, Out). 88 | 89 | termlist_to_termlistlist([Term | TermList], TermListList, Out) :- 90 | ( 91 | term_and_termlist_share_variables(Term, TermListList, Included, Excluded) 92 | -> 93 | termlist_to_termlistlist(TermList, [[Term | Included] | Excluded], Out) 94 | ; 95 | termlist_to_termlistlist(TermList, [[Term] | TermListList], Out) 96 | ). 97 | 98 | 99 | term_and_termlist_share_variables(Term, TermListList, IncludedFlat, Excluded) :- 100 | partition(terms_share_variables(Term), TermListList, Included, Excluded), 101 | append(Included, IncludedFlat). 102 | 103 | terms_share_variables(Term1, Term2) :- 104 | term_variables(Term1, List1), 105 | term_variables(Term2, List2), 106 | exists_intersection(List1, List2). 107 | 108 | exists_intersection(List1, List2) :- 109 | member(El1, List1), 110 | member(El2, List2), 111 | El1 == El2, 112 | !. 113 | 114 | 115 | %% sort_drslist(+DrsList:list, -DrsListSorted:list) is det. 116 | % 117 | % Sorts the list of DRSs. Sorting is done by keysort/2, and 118 | % the keys are assigned by assign_key/2. See the definition 119 | % of assign_key/2 to find out how the soring order is determined. 120 | % 121 | % 122 | sort_drslist([], []) :- !. 123 | 124 | sort_drslist([Drs], [Drs]) :- !. 125 | 126 | sort_drslist(DrsList, DrsListSorted) :- 127 | maplist(assign_key, DrsList, DrsListWithKeys), 128 | keysort(DrsListWithKeys, DrsListWithKeysSorted), 129 | maplist(remove_key, DrsListWithKeysSorted, DrsListSorted). 130 | 131 | 132 | %% remove_key(+DrsWithKey:term, -Drs:term) 133 | % 134 | remove_key(_-Drs, Drs). 135 | 136 | 137 | %% assign_key(+Drs:term, -DrsWithKey:term) 138 | % 139 | % The key of a DRS is the smallest (in the standard order of terms) 140 | % sentence ID and token ID combination (SId/TId) of a DRS condition. 141 | % The SId/TId of a complex condition is determined recursively. 142 | % Note that we do not check the 2nd DRS of complex binary conditions 143 | % (e.g. the then-part of an implication), as there the keys are known 144 | % to be larger. 145 | % 146 | assign_key(drs(Dom, Conds), Key-drs(Dom, Conds)) :- 147 | assign_key_to_conds(Conds, Key). 148 | 149 | 150 | assign_key_to_conds(Conds, Key) :- 151 | maplist(get_key, Conds, Keys), 152 | sort(Keys, [Key | _]). 153 | 154 | 155 | get_key(_-Key, Key) :- !. 156 | 157 | get_key(Cond, Key) :- 158 | functor(Cond, Op, _), 159 | drs_operator(Op), 160 | arg(1, Cond, Drs), 161 | assign_key(Drs, Key-_). 162 | 163 | get_key(_Label:Drs, Key) :- 164 | assign_key(Drs, Key-_). 165 | 166 | get_key([H | T], Key) :- 167 | assign_key_to_conds([H | T], Key). 168 | -------------------------------------------------------------------------------- /prolog/utils/drs_to_ruleml.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(drs_to_ruleml, [ 17 | drs_to_ruleml/2 18 | ]). 19 | 20 | /** Attempto DRS to RuleML/folog converter 21 | 22 | This module converts the Attempto DRS into RuleML/folog as 23 | specified by David Hirtle in his thesis. 24 | 25 | @author Kaarel Kaljurand 26 | @author Tobias Kuhn 27 | @version 2012-08-23 28 | @see http://www.ruleml.org/translator/ 29 | 30 | @bug Test RuleML validity. 31 | @bug Test correspondence to Hirtle's specification. E.g. DRSs resulting from 32 | query sentences are currently incorrectly supported. (Note that Hirtle just 33 | rejects such DRSs.) 34 | @bug Support ACE 5/5.5/6 extensions (e.g. RuleML supports NAF). 35 | */ 36 | 37 | 38 | % The following operators are used in the DRS. 39 | :- op(400, fx, -). 40 | :- op(500, xfx, =>). 41 | :- op(500, xfx, v). 42 | 43 | 44 | %% drs_to_ruleml(+Drs:drs, -RuleML:functor) is det. 45 | % 46 | % Turn the DRS into RuleML/folog (in SWI Prolog's internal XML format) 47 | % as specified in David Hirtle's thesis. 48 | 49 | drs_to_ruleml( 50 | DRS, 51 | element('RuleML', [], [ 52 | element('Assert', [], Elements) 53 | ]) 54 | ) :- 55 | existdrs_els(DRS, Elements). 56 | 57 | 58 | %% conds_and(+Conds:list, -Element:functor) is det. 59 | % 60 | % Converts a list of DRS conditions into a RuleML and-element. 61 | 62 | conds_and(Conds, ElementsOut) :- 63 | conds_elements(Conds, Elements), 64 | conds_and_x(Elements, ElementsOut). 65 | 66 | conds_and_x([Element], Element) :- 67 | !. 68 | 69 | conds_and_x(Elements, element('And', [], Elements)). 70 | 71 | 72 | %% conds_elements(+Conds:list, -Elements:list) is det. 73 | % 74 | % Converts a list of DRS conditions into RuleML elements. 75 | 76 | conds_elements([], []). 77 | 78 | conds_elements([Cond | Tail], [SCond | STail]) :- 79 | cond_element(Cond, SCond), 80 | conds_elements(Tail, STail). 81 | 82 | 83 | %% cond_element(+Condition:functor, -Element:functor) is det. 84 | % 85 | % Converts a DRS condition into a RuleML element. 86 | % 87 | % As the structure of the DRS doesn't match exactly to the structure 88 | % of the RuleML element (as specified by Hirtle), 89 | % we have to do some ugly appending. 90 | 91 | cond_element(drs(Dom1, Conds1) => DRS2, 92 | element('Forall', [], SubElements0) 93 | ) :- 94 | args_els(Dom1, VarElements1), 95 | conds_and(Conds1, Element1), 96 | existdrs_els(DRS2, SubElements2), 97 | append([Element1], SubElements2, SubElements1), 98 | append(VarElements1, [element('Implies', [], SubElements1)], SubElements0). 99 | 100 | 101 | cond_element(DRS1 v DRS2, 102 | element('Or', [], SubElements0) 103 | ) :- 104 | existdrs_els(DRS1, SubElements1), 105 | existdrs_els(DRS2, SubElements2), 106 | append(SubElements1, SubElements2, SubElements0). 107 | 108 | 109 | cond_element(-DRS, element('Neg', [], SubElements)) :- 110 | existdrs_els(DRS, SubElements). 111 | 112 | 113 | cond_element(Conds, Element) :- 114 | is_list(Conds), 115 | conds_and(Conds, Element). 116 | 117 | 118 | cond_element(Condition-_, element('Atom', [], [element('Rel', [], [Functor]) | Els])) :- 119 | Condition =.. [Functor | Args], 120 | args_els(Args, Els). 121 | 122 | 123 | %% args_els(+List:list, -Elements:list) is det. 124 | % 125 | % Converts the arguments of a DRS condition into RuleML elements. 126 | % 127 | % Note that all terms (e.g. variables and numbers) must be converted into atoms 128 | % to be compatible with the way how SWI represents XML 129 | % documents internally. 130 | 131 | args_els([], []). 132 | 133 | args_els([H | T], [element('Var', [], [HH]) | ElsTail]) :- 134 | var(H), 135 | !, 136 | term_to_atom(H, HH), 137 | args_els(T, ElsTail). 138 | 139 | args_els([H | T], [element('Data', [], [HH]) | ElsTail]) :- 140 | number(H), 141 | !, 142 | term_to_atom(H, HH), % alternatively: atom_number(HH, H) 143 | args_els(T, ElsTail). 144 | 145 | args_els([H | T], [element('Ind', [], [H]) | ElsTail]) :- 146 | args_els(T, ElsTail). 147 | 148 | 149 | %% existdrs_els(+Drs:drs, -Elements:list) is det. 150 | % 151 | % Converts an existential DRS box into RuleML elements. 152 | 153 | existdrs_els(drs([],Conds), [Element]) :- 154 | !, 155 | conds_and(Conds, Element). 156 | 157 | existdrs_els(drs(Dom,Conds), [element('Exists', [], Elements)]) :- 158 | args_els(Dom, DomElements), 159 | conds_and(Conds, Element), 160 | append(DomElements, [Element], Elements). 161 | 162 | 163 | %% to_xml(+Elements:list, -Xml:atom) is det. 164 | % 165 | % @param Elements is a list of XML elements 166 | % @param Xml is an XML document as an atom 167 | % 168 | % @deprecated use SWI's xml_write/3 instead 169 | % 170 | % Converts SWI Prolog's XML represenation into an XML atom. 171 | % Something like xml_write/3 but very simple. 172 | 173 | to_xml([], ''). 174 | 175 | to_xml([element(Name, _, Elements) | T], Xml) :- 176 | to_xml(Elements, ElXml), 177 | to_xml(T, TXml), 178 | format(atom(Xml), '<~w>~w~n~w', [Name, ElXml, Name, TXml]). 179 | 180 | to_xml([Text | T], Xml) :- 181 | atom(Text), 182 | to_xml(T, TXml), 183 | format(atom(Xml), '~w~w', [Text, TXml]). 184 | -------------------------------------------------------------------------------- /prolog/utils/drs_to_sdrs.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(drs_to_sdrs, [drs_to_sdrs/2]). 17 | 18 | :- use_module(drs_ops). 19 | 20 | /** DRS simplifier 21 | 22 | Converts the DRS into a simplified form where every 23 | DRS-box is represented as a list of conditions, i.e. 24 | 25 | == 26 | drs(Dom, Conds) --> Conds 27 | == 28 | 29 | where Conds is a list of conditions (with sentence IDs). 30 | 31 | @author Kaarel Kaljurand 32 | @author Tobias Kuhn 33 | @version 2009-05-13 34 | 35 | */ 36 | 37 | 38 | %% drs_to_sdrs(+Drs:drs, -SDrs:sdrs) is det. 39 | % 40 | % Removes the domain-argument from all the (non-atomic) DRS conditions, 41 | % including the embedded ones. 42 | % 43 | % @param Drs is an Attempto DRS 44 | % @param SDrs is an Attempto DRS with the domain-arguments removed 45 | 46 | drs_to_sdrs(drs(_, Conds), SConds) :- 47 | conds_sconds(Conds, SConds). 48 | 49 | 50 | conds_sconds([], []). 51 | 52 | conds_sconds([Cond | Tail], [SCond | STail]) :- 53 | simplify(Cond, SCond), 54 | !, 55 | conds_sconds(Tail, STail). 56 | 57 | 58 | simplify(DRS, SDRS) :- 59 | DRS =.. [Op, drs(_, Conds)], 60 | unary_drs_operator(Op), 61 | conds_sconds(Conds, SConds), 62 | SDRS =.. [Op, SConds]. 63 | 64 | simplify(DRS, SDRS) :- 65 | DRS =.. [Op, drs(_, Conds1), drs(_, Conds2)], 66 | binary_drs_operator(Op), 67 | conds_sconds(Conds1, SConds1), 68 | conds_sconds(Conds2, SConds2), 69 | SDRS =.. [Op, SConds1, SConds2]. 70 | 71 | simplify(Conds, (SConds)) :- 72 | is_list(Conds), 73 | conds_sconds(Conds, SConds). 74 | 75 | simplify(Label:drs(_, Conds), Label:SConds) :- 76 | conds_sconds(Conds, SConds). 77 | 78 | simplify(Cond, Cond). 79 | -------------------------------------------------------------------------------- /prolog/utils/drs_utils.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(drs_utils, [ 17 | get_toplevel_object_referents/2 18 | ]). 19 | 20 | /** Attempto DRS utils 21 | 22 | @author Kaarel Kaljurand 23 | @version 2009-04-08 24 | 25 | */ 26 | 27 | %% get_toplevel_object_referents(+ConditionList:list, -Toplevel:term) is det. 28 | % 29 | % Returns a term toplevel(ReferentList, SubjectList, ObjectList, NamedList) where 30 | % 31 | % * ReferentList is a list of top-level object-referents 32 | % * SubjectList is a list of top-level object-referents that are used as subjects 33 | % * ObjectList is a list of top-level object-referents that are used as objects 34 | % * NamedList is a list of top-level object-referents that correspond to proper names (Type = named) 35 | % 36 | % @param ConditionList is a list of DRS conditions 37 | % @param Toplevel is a term containing top-level DRS discourse referents 38 | % 39 | get_toplevel_object_referents(ConditionList, toplevel(ReferentList, SubjectList, ObjectList, NamedList)) :- 40 | get_toplevel_object_referents_x( 41 | ConditionList, 42 | toplevel( 43 | -([], ReferentList), 44 | -([], SubjectList), 45 | -([], ObjectList), 46 | -([], NamedList) 47 | ) 48 | ). 49 | 50 | 51 | %% get_toplevel_object_referents_x(+ConditionList:list, -Toplevel:term) is det. 52 | % 53 | % @param ConditionList is a list of DRS conditions 54 | % @param Toplevel is a term containing top-level DRS discourse referents 55 | % 56 | get_toplevel_object_referents_x([], toplevel(R-R, S-S, O-O, N-N)). 57 | 58 | get_toplevel_object_referents_x([Condition | ConditionList], toplevel(R1-R2, S1-S2, O1-O2, N1-N2)) :- 59 | condition_referents(Condition, toplevel(R1-RT, S1-ST, O1-OT, N1-NT)), 60 | get_toplevel_object_referents_x(ConditionList, toplevel(RT-R2, ST-S2, OT-O2, NT-N2)). 61 | 62 | 63 | %% condition_referents(+Condition:term) is det. 64 | % 65 | % Note: the referents of plural objects, mass-objects, query-objects, and objects in the relation-condition 66 | % are considered as named-objects, i.e. they will not be verbalized by "there is/are". 67 | % BUG: This is a hack, and it is DRACE specific. 68 | % 69 | % @param Condition is a DRS condition 70 | % 71 | 72 | % BUG: ??? 73 | condition_referents(object(Ref, Noun, Type, _, _Eq, na)-_, toplevel(R-[Ref | R], S-S, O-O, N-N)) :- 74 | Noun \= na, 75 | Type \= named, 76 | Type \= mass, 77 | !. 78 | 79 | % Plural objects (i.e. NP conjunction). BUG: we consider them named-objects for the time being. 80 | condition_referents(object(Ref, na, _, _, _, _)-_, toplevel(R-[Ref | R], S-S, O-O, N1-[Ref | N1])) :- !. 81 | 82 | % Mass objects. BUG: we consider them objects as named-objects for the time being. 83 | condition_referents(object(Ref, _, mass, _, _, _)-_, toplevel(R-[Ref | R], S-S, O-O, N1-[Ref | N1])) :- !. 84 | 85 | % Parts of plural objects. BUG: we consider them named-objects for the time being. 86 | condition_referents(has_part(_, Ref)-_, toplevel(R-R, S-S, O-O, N1-[Ref | N1])) :- !. 87 | 88 | % Relation object. BUG: we consider them named-objects for the time being. 89 | condition_referents(relation(Ref1, of, Ref2)-_, toplevel(R-R, S-S, O-O, N-[Ref1, Ref2 | N])) :- !. 90 | 91 | % Query objects. BUG: we consider them named-objects for the time being. 92 | condition_referents(query(Ref, _)-_, toplevel(R-[Ref | R], S-S, O-O, N1-[Ref | N1])) :- !. 93 | 94 | /* BUG: is the var/nonvar stuff really necessary? */ 95 | 96 | condition_referents(predicate(_, _, Ref)-_, toplevel(R-R, S-[Ref | S], O-O, N-N)) :- 97 | var(Ref), 98 | !. 99 | 100 | condition_referents(predicate(_, _, Ref, O1)-_, toplevel(R-R, S-[Ref | S], O-[O1 | O], N-N)) :- 101 | var(Ref), var(O1), 102 | !. 103 | 104 | condition_referents(predicate(_, _, Ref, O1)-_, toplevel(R-R, S-[Ref | S], O-O, N-N)) :- 105 | var(Ref), nonvar(O1), 106 | !. 107 | 108 | condition_referents(predicate(_, _, Ref, O1)-_, toplevel(R-R, S-S, O-[O1 | O], N-N)) :- 109 | nonvar(Ref), var(O1), 110 | !. 111 | 112 | condition_referents(predicate(_, _, Ref, O1, O2)-_, toplevel(R-R, S-[Ref | S], O-[O1, O2 | O], N-N)) :- 113 | var(Ref), var(O1), var(O2), 114 | !. 115 | 116 | condition_referents(predicate(_, _, Ref, O1, O2)-_, toplevel(R-R, S-S, O-[O1, O2 | O], N-N)) :- 117 | nonvar(Ref), var(O1), var(O2), 118 | !. 119 | 120 | condition_referents(predicate(_, _, Ref, O1, O2)-_, toplevel(R-R, S-[Ref | S], O-[O2 | O], N-N)) :- 121 | var(Ref), nonvar(O1), var(O2), 122 | !. 123 | 124 | condition_referents(predicate(_, _, Ref, O1, O2)-_, toplevel(R-R, S-[Ref | S], O-[O1 | O], N-N)) :- 125 | var(Ref), var(O1), nonvar(O2), 126 | !. 127 | 128 | condition_referents(predicate(_, _, Ref, O1, O2)-_, toplevel(R-R, S-S, O-[O2 | O], N-N)) :- 129 | nonvar(Ref), nonvar(O1), var(O2), 130 | !. 131 | 132 | condition_referents(predicate(_, _, Ref, O1, O2)-_, toplevel(R-R, S-S, O-[O1 | O], N-N)) :- 133 | nonvar(Ref), var(O1), nonvar(O2), 134 | !. 135 | 136 | condition_referents(predicate(_, _, Ref, O1, O2)-_, toplevel(R-R, S-[Ref | S], O-O, N-N)) :- 137 | var(Ref), nonvar(O1), nonvar(O2), 138 | !. 139 | 140 | condition_referents(_, toplevel(R-R, S-S, O-O, N-N)). 141 | -------------------------------------------------------------------------------- /prolog/utils/owlswrl/README.md: -------------------------------------------------------------------------------- 1 | Translating Attempto DRS into OWL and SWRL 2 | ========================================== 3 | 4 | Introduction 5 | ------------ 6 | 7 | Translating an Attempto DRS into Web Ontology Language (OWL 2), 8 | or if this fails then to Semantic Web Rule Language (SWRL). 9 | Various serializations are provided by: 10 | 11 | - `owlfss`: Prolog term based on [OWL 2 Web Ontology Language Structural Specification and Functional-Style Syntax](http://www.w3.org/TR/2009/REC-owl2-syntax-20091027/), e.g. OWL lists and sets are denoted by Prolog lists 12 | - `owlxml`: [OWL 2 Web Ontology Language XML Serialization](http://www.w3.org/TR/2009/REC-owl2-xml-serialization-20091027/) 13 | - `owlfsspp`: [OWL 2 Web Ontology Language Structural Specification and Functional-Style Syntax](http://www.w3.org/TR/2009/REC-owl2-syntax-20091027/), useful for pretty-printing, but also understood by e.g. the Manchester OWL API 14 | 15 | For SWRL rules we use the functional and XML-based syntaxes that are described in 16 | . 17 | 18 | 19 | Documentation 20 | ------------- 21 | 22 | For the documentation see: 23 | 24 | > Kaarel Kaljurand. 25 | > Attempto Controlled English as a Semantic Web Language. 26 | > PhD thesis, Faculty of Mathematics and Computer Science, University of Tartu, 2007. 27 | > 28 | > (Printable version: ) 29 | 30 | Note that this thesis uses the label "OWL 1.1" to discuss OWL 2. 31 | This is because OWL 1.1 used to be the name of OWL 2 until April 2008. 32 | 33 | Also, see the PlDoc documentation inside the translator files. 34 | 35 | Some examples of sentences that the OWL/SWRL translator supports are available at 36 | . 37 | 38 | 39 | Usage 40 | ----- 41 | 42 | Processing an ACE sentence `Every man likes Mary.` using the APE commandline: 43 | 44 | ape.exe \ 45 | -uri "http://www.example.com/default" \ 46 | -noclex \ 47 | -ulextext "pn_sg('Mary', iri('http://www.example.com/names#Mary'), fem). noun_sg(man, man, masc). tv_finsg(likes, like)." \ 48 | -text "Every man likes Mary." \ 49 | -solo owlfsspp 50 | 51 | results in: 52 | 53 | Prefix(:=) 54 | Ontology( 55 | SubClassOf( 56 | :man 57 | ObjectSomeValuesFrom( 58 | :like 59 | ObjectOneOf( 60 | 61 | ) 62 | ) 63 | ) 64 | ) 65 | 66 | Note that by using the `iri`-term in the lexicon one can assign the complete 67 | IRI to the surface word. Otherwise, the default namespace is assumed. 68 | -------------------------------------------------------------------------------- /prolog/utils/owlswrl/get_owl_output.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2010, Kaarel Kaljurand . 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(get_owl_output, [ 17 | get_owl_output/6 18 | ]). 19 | 20 | 21 | /** Interface for the OWL outputs 22 | 23 | @author Kaarel Kaljurand 24 | @version 2010-11-26 25 | 26 | */ 27 | 28 | :- use_module(drs_to_owlswrl). 29 | :- use_module(owlfss_owlrdfxml). 30 | :- use_module(owlswrl_to_xml). 31 | :- use_module(owlswrl_to_fss). 32 | :- use_module('../../logger/error_logger'). 33 | 34 | :- use_module('../xmlterm_to_xmlatom', [ 35 | xmlterm_to_xmlatom/2 36 | ]). 37 | 38 | :- use_module('../serialize_term', [ 39 | serialize_term_into_atom/2 40 | ]). 41 | 42 | 43 | %% get_owl_output(+OwlOutputType:atom, +Comment:atom, +Drs:term, +Uri:atom, -ContentType:atom, -Output:atom) is det. 44 | % 45 | % @param OwlOutputType is one of {owlfss, owlfsspp, owlxml} 46 | % @param Comment is a comment to be included in the ontology (currently ignored) 47 | % @param Drs is an Attempto DRS 48 | % @param Uri is the name of the ontology to be created 49 | % @param ContentType is the content type of the result, one of {text/xml, text/plain} 50 | % @param Output is the output of the conversion to OWL 51 | % 52 | get_owl_output(owlrdf, Comment, Drs, Uri, 'text/xml', Output) :- 53 | ignore(drs_to_owlswrl:drs_to_owlswrl(Drs, Uri, Comment, OwlFss)), 54 | ( 55 | get_messages_with_type(owl, []) 56 | -> 57 | owlfss_owlrdfxml:owlfss_owlrdfxml(OwlFss, OwlRdfxml), 58 | xmlterm_to_xmlatom(OwlRdfxml, Output) 59 | ; 60 | Output = '' 61 | ). 62 | 63 | get_owl_output(owlfss, Comment, Drs, Uri, 'text/plain', Output) :- 64 | ignore(drs_to_owlswrl:drs_to_owlswrl(Drs, Uri, Comment, OwlFss)), 65 | ( 66 | get_messages_with_type(owl, []) 67 | -> 68 | serialize_term_into_atom(OwlFss, Output) 69 | ; 70 | Output = '' 71 | ). 72 | 73 | get_owl_output(owlfsspp, Comment, Drs, Uri, 'text/plain', Output) :- 74 | ignore(drs_to_owlswrl:drs_to_owlswrl(Drs, Uri, Comment, OwlFss)), 75 | ( 76 | get_messages_with_type(owl, []) 77 | -> 78 | owlswrl_to_fss:owlswrl_to_fss(OwlFss, Output) 79 | ; 80 | Output = '' 81 | ). 82 | 83 | get_owl_output(owlxml, Comment, Drs, Uri, 'text/xml', Output) :- 84 | ignore(drs_to_owlswrl:drs_to_owlswrl(Drs, Uri, Comment, OwlFss)), 85 | ( 86 | get_messages_with_type(owl, []) 87 | -> 88 | owlswrl_to_xml:owlswrl_to_xml(OwlFss, OwlXml), 89 | xmlterm_to_xmlatom(OwlXml, Output) 90 | ; 91 | Output = '' 92 | ). 93 | -------------------------------------------------------------------------------- /prolog/utils/owlswrl/illegal_conditions.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2010, Kaarel Kaljurand . 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | :- module(illegal_conditions, [ 16 | illegal_conditions/1, 17 | illegal_condition/1 18 | ]). 19 | 20 | /** DRS checker for DRS-to-OWL/SWRL 21 | 22 | Setting some error messages for conditions which ACE->OWL/SWRL cannot handle. 23 | 24 | @author Kaarel Kaljurand 25 | @version 2010-12-14 26 | 27 | TODO 28 | 29 | * add more detailed messages in case of property/[4,5,7] 30 | 31 | * paraphrase the DRS to deliver a nicer error message. 32 | DRS->ACE needs to support this though (i.e. the situation when the 33 | the DRS contains referents which are defined on the upper level). 34 | 35 | * Should error messages be given on the ACE level or on the DRS level? 36 | For the end user the ACE level is better, but on the other hand the input 37 | to ACE->OWL is the DRS (i.e. the module is actually doing DRS->OWL). 38 | 39 | */ 40 | 41 | :- use_module(ape('logger/error_logger'), [ 42 | add_error_message/4 43 | ]). 44 | 45 | :- use_module(ape('utils/drs_ops'), [ 46 | unary_drs_operator/1, 47 | binary_drs_operator/1 48 | ]). 49 | 50 | 51 | % Operators used in the DRS. 52 | :- op(400, fx, -). 53 | :- op(500, xfx, v). 54 | :- op(500, xfx, =>). 55 | 56 | 57 | %% illegal_conditions(+Conditions:list) is det. 58 | % 59 | % 60 | illegal_conditions([]). 61 | 62 | illegal_conditions([Cond | CondList]) :- 63 | illegal_condition(Cond), 64 | !, 65 | illegal_conditions(CondList). 66 | 67 | 68 | %% illegal_condition(BoxId, Cond, NewCond) is det. 69 | % 70 | % 71 | 72 | illegal_condition(relation(_, of, _)-SId/TId) :- 73 | add_error_message(owl, SId-TId, of, 'Possessive constructions not supported (in this particular case).'). 74 | 75 | illegal_condition(modifier_adv(_, Adverb, _)-SId/TId) :- 76 | add_error_message(owl, SId-TId, Adverb, 'Adverbs not supported.'). 77 | 78 | illegal_condition(modifier_pp(_, Preposition, _)-SId/TId) :- 79 | add_error_message(owl, SId-TId, Preposition, 'Prepositional phrases not supported.'). 80 | 81 | % property/4 (comp adjective) 82 | illegal_condition(property(_, Adjective, comp)-SId/TId) :- 83 | add_error_message(owl, SId-TId, Adjective, 'Comparative adjective not supported.'). 84 | 85 | % property/4 (sup adjective) 86 | illegal_condition(property(_, Adjective, sup)-SId/TId) :- 87 | add_error_message(owl, SId-TId, Adjective, 'Superlative adjective not supported.'). 88 | 89 | % property/5 (comp_than adjective) 90 | illegal_condition(property(_, Adjective, _, _)-SId/TId) :- 91 | add_error_message(owl, SId-TId, Adjective, 'Adjective not supported.'). 92 | 93 | % property/7 (comp_than + subj/obj adjective) 94 | illegal_condition(property(_, Adjective, _, _, _, _)-SId/TId) :- 95 | add_error_message(owl, SId-TId, Adjective, 'Adjective not supported.'). 96 | 97 | illegal_condition(query(_, QueryWord)-SId/TId) :- 98 | add_error_message(owl, SId-TId, QueryWord, 'Query not supported.'). 99 | 100 | illegal_condition(predicate(_, Verb, _)-SId/TId) :- 101 | add_error_message(owl, SId-TId, Verb, 'Intransitive verbs not supported.'). 102 | 103 | illegal_condition(predicate(_, Verb, _, _, _)-SId/TId) :- 104 | add_error_message(owl, SId-TId, Verb, 'Ditransitive verbs not supported.'). 105 | 106 | illegal_condition(must(Drs)) :- 107 | conds_sid(Drs, SId), 108 | add_error_message(owl, SId, 'must/1', 'Necessity not supported.'). 109 | 110 | illegal_condition(can(Drs)) :- 111 | conds_sid(Drs, SId), 112 | add_error_message(owl, SId, 'can/1', 'Possibility not supported.'). 113 | 114 | illegal_condition(_:Drs) :- 115 | conds_sid(Drs, SId), 116 | add_error_message(owl, SId, ':/2', 'Sentence subordination not supported.'). 117 | 118 | illegal_condition('~'(Drs)) :- 119 | conds_sid(Drs, SId), 120 | add_error_message(owl, SId, '~/1', 'Negation-as-failure not supported.'). 121 | 122 | illegal_condition(should(Drs)) :- 123 | conds_sid(Drs, SId), 124 | add_error_message(owl, SId, 'should/1', 'Recommendation not supported.'). 125 | 126 | illegal_condition(may(Drs)) :- 127 | conds_sid(Drs, SId), 128 | add_error_message(owl, SId, 'may/1', 'Admissibility not supported.'). 129 | 130 | % Note: do not do anything, NP conjunction ('na' as 2nd argument) is handled by the object-rule 131 | illegal_condition(has_part(_, _)-_). 132 | 133 | illegal_condition(predicate(_, Value, _, _)-SId/TId) :- 134 | add_error_message(owl, SId-TId, Value, 'Subject or object of this verb makes an illegal reference.'). 135 | 136 | illegal_condition(object(_, na, _, na, _, _)-SId/TId) :- 137 | !, 138 | add_error_message(owl, SId-TId, and, 'Noun phrase conjunctions not supported.'). 139 | 140 | illegal_condition(object(_, Value, _, na, _, _)-SId/TId) :- 141 | Value \= na, 142 | !, 143 | add_error_message(owl, SId-TId, Value, 'A reference to this noun either does not exist or is illegal.'). 144 | 145 | illegal_condition(object(_, _, _, Unit, _, _)-SId/TId) :- 146 | Unit \= na, 147 | add_error_message(owl, SId-TId, Unit, 'Measurement nouns are not supported.'). 148 | 149 | 150 | %% conds_sid(+Conditions:list, -SentenceId:integer) is det. 151 | % 152 | % Finds the shared sentence ID of the conditions. 153 | % 154 | conds_sid([], _). 155 | 156 | conds_sid([_-SId/_TId | _], SId) :- !. 157 | 158 | conds_sid([C | Cs], SId) :- 159 | cond_sid(C, SId), 160 | conds_sid(Cs, SId). 161 | 162 | 163 | cond_sid(Cond, SId) :- 164 | functor(Cond, F, 1), 165 | unary_drs_operator(F), 166 | !, 167 | arg(1, Cond, Drs), 168 | conds_id(Drs, SId). 169 | 170 | cond_id(_Label:Drs, SId) :- 171 | !, 172 | conds_id(Drs, SId). 173 | 174 | cond_id(Drs1 v Drs2, SId) :- 175 | !, 176 | conds_id(Drs1, SId), 177 | conds_id(Drs2, SId). 178 | 179 | cond_id(Drs1 => Drs2, SId) :- 180 | !, 181 | conds_id(Drs1, SId), 182 | conds_id(Drs2, SId). 183 | -------------------------------------------------------------------------------- /prolog/utils/owlswrl/owlswrl_iri.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2013, Kaarel Kaljurand . 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | :- module(owlswrl_iri, [ 16 | iri_to_prefix/2, 17 | builtin_iri/2 18 | ]). 19 | 20 | /** Some helper predicates related to IRIs 21 | 22 | @author Kaarel Kaljurand 23 | @version 2013-06-03 24 | 25 | */ 26 | 27 | 28 | %% iri_to_prefix(+Iri:atom, -Prefix:atom) is det. 29 | % 30 | % Attaches the #-character to the given IRI, unless 31 | % it already has it. 32 | % 33 | iri_to_prefix(Iri, Iri) :- 34 | sub_atom(Iri, _, 1, 0, '#'), 35 | !. 36 | 37 | iri_to_prefix(Iri, Prefix) :- 38 | atom_concat(Iri, '#', Prefix). 39 | 40 | 41 | %% builtin_iri 42 | % 43 | % Lists all the builtin / hardcoded IRI prefixes, 44 | % and their abbreviations. 45 | % 46 | builtin_iri(ace, 'http://attempto.ifi.uzh.ch/ace#'). 47 | -------------------------------------------------------------------------------- /prolog/utils/owlswrl/owlswrl_to_fss.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Kaarel Kaljurand . 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | :- module(owlswrl_to_fss, [ 16 | owlswrl_to_fss/1, 17 | owlswrl_to_fss/2 18 | ]). 19 | 20 | :- use_module(owlswrl_iri, [ 21 | iri_to_prefix/2, 22 | builtin_iri/2 23 | ]). 24 | 25 | 26 | /** OWL/SWRL serializer into OWL/SWRL Functional-Style Syntax 27 | 28 | @author Kaarel Kaljurand 29 | @version 2013-06-03 30 | 31 | @tbd Escaping 32 | 33 | @tbd Test on the regression test set if OWL-API can load the output produced here 34 | 35 | */ 36 | 37 | %% owlswrl_to_fss(+Ontology) 38 | %% owlswrl_to_fss(+Ontology, -Atom) 39 | % 40 | % Writes the OWL/SWRL ontology in Functional-Style Syntax into the current stream. 41 | % 42 | owlswrl_to_fss('Ontology'(OntologyIri, Axioms)) :- 43 | iri_to_prefix(OntologyIri, Prefix), 44 | format("Prefix(:=<~w>)~n", [Prefix]), 45 | forall( 46 | builtin_iri(Abbr, IriPrefix), 47 | format("Prefix(~w:=<~w>)~n", [Abbr, IriPrefix]) 48 | ), 49 | format("Ontology(<~w>~n", [OntologyIri]), 50 | print_list(Axioms, 1), 51 | format(")~n"). 52 | 53 | % 54 | owlswrl_to_fss(Ontology, OntologyFss) :- 55 | with_output_to(atom(OntologyFss), owlswrl_to_fss(Ontology)). 56 | 57 | 58 | %% print_compound 59 | % 60 | % 61 | print_compound(OwlFss, Level) :- 62 | OwlFss =.. [Name | Args], 63 | PrettyIndent is Level * 3, 64 | writef('%r%w(\n', [' ', PrettyIndent, Name]), 65 | NewLevel is Level + 1, 66 | print_list(Args, NewLevel), 67 | writef('%r)\n', [' ', PrettyIndent]). 68 | 69 | 70 | %% print_list 71 | % 72 | % Don't change the order, e.g. an empty list should 73 | % not be "mistaken" for an atom. 74 | % 75 | print_list([], _). 76 | 77 | print_list([Head | Tail], Level) :- 78 | is_list(Head), 79 | !, 80 | print_list(Head, Level), 81 | print_list(Tail, Level). 82 | 83 | print_list([Expression | Tail], Level) :- 84 | print_terminal(Expression, Level), 85 | !, 86 | print_list(Tail, Level). 87 | 88 | print_list([Head | Tail], Level) :- 89 | compound(Head), 90 | !, 91 | print_compound(Head, Level), 92 | print_list(Tail, Level). 93 | 94 | 95 | %% print_terminal 96 | % 97 | % 98 | print_terminal(Number, Level) :- 99 | number(Number), 100 | !, 101 | PrettyIndent is Level * 3, 102 | writef('%r%w\n', [' ', PrettyIndent, Number]). 103 | 104 | print_terminal(Iri, Level) :- 105 | atom(Iri), 106 | !, 107 | PrettyIndent is Level * 3, 108 | writef('%r<%w>\n', [' ', PrettyIndent, Iri]). 109 | 110 | print_terminal('Variable'(Iri), Level) :- 111 | PrettyIndent is Level * 3, 112 | writef('%rVariable(<%w>)\n', [' ', PrettyIndent, Iri]). 113 | 114 | print_terminal('BuiltInAtom'(Iri, DArgList), Level) :- 115 | PrettyIndent is Level * 3, 116 | writef('%rBuiltInAtom(<%w>\n', [' ', PrettyIndent, Iri]), 117 | NewLevel is Level + 1, 118 | print_list(DArgList, NewLevel), 119 | writef('%r)\n', [' ', PrettyIndent]). 120 | 121 | print_terminal('^^'(DataValue, DataType), Level) :- 122 | PrettyIndent is Level * 3, 123 | writef('%r"%w"^^<%w>\n', [' ', PrettyIndent, DataValue, DataType]). 124 | 125 | print_terminal(Terminal, Level) :- 126 | pretty_print(Terminal, PrettyExpression), 127 | !, 128 | PrettyIndent is Level * 3, 129 | writef('%r%w\n', [' ', PrettyIndent, PrettyExpression]). 130 | 131 | 132 | pretty_print(nodeID(Number), '_':Number). 133 | pretty_print(NS:Name, NS:Name). 134 | -------------------------------------------------------------------------------- /prolog/utils/owlswrl/simplify_axiom.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Kaarel Kaljurand . 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(simplify_axiom, [ 17 | simplify_axiom/2 18 | ]). 19 | 20 | 21 | /** Maps the given axiom to a syntactically simpler form 22 | 23 | The given axiom is mapped to a syntactically simpler form 24 | in order to achieve better compatibility with OWL tools 25 | and OWL fragments (which are defined based on syntax). 26 | In most cases the axiom is preserved as it is, we only target the 27 | following forms: 28 | 29 | - ObjectPropertyDomain 30 | - ObjectPropertyRange 31 | - DisjointClasses 32 | 33 | @author Kaarel Kaljurand 34 | @version 2013-04-07 35 | @license LGPLv3 36 | 37 | */ 38 | 39 | 40 | %% simplify_axiom(+Axiom:term, -SimplerAxiom:term) is det. 41 | % 42 | % Note: rule order is important 43 | % 44 | % @param Axiom is an OWL axiom 45 | % @param SimplerAxiom is the same axiom possibly in a simpler form 46 | % 47 | 48 | % object property assertion 49 | simplify_axiom( 50 | 'ClassAssertion'('ObjectSomeValuesFrom'(OPE, 'ObjectOneOf'([I2])), I1), 51 | 'ObjectPropertyAssertion'(OPE, I1, I2) 52 | ) :- !. 53 | 54 | % data property assertion 55 | simplify_axiom( 56 | 'ClassAssertion'('DataHasValue'(DPE, Data), I1), 57 | 'DataPropertyAssertion'(DPE, I1, Data) 58 | ) :- !. 59 | 60 | % same individual 61 | simplify_axiom( 62 | 'ClassAssertion'('ObjectOneOf'([I2]), I1), 63 | 'SameIndividual'([I1, I2]) 64 | ) :- !. 65 | 66 | % disjoint classes 67 | simplify_axiom( 68 | 'SubClassOf'(CE1, 'ObjectComplementOf'(CE2)), 69 | 'DisjointClasses'([CE1, CE2]) 70 | ) :- !. 71 | 72 | % range 73 | simplify_axiom( 74 | 'SubClassOf'('ObjectIntersectionOf'([owl:'Thing', 'ObjectSomeValuesFrom'('ObjectInverseOf'(OPE), owl:'Thing')]), CE), 75 | 'ObjectPropertyRange'(OPE, CE) 76 | ) :- !. 77 | 78 | simplify_axiom( 79 | 'SubClassOf'('ObjectSomeValuesFrom'('ObjectInverseOf'(OPE), owl:'Thing'), CE), 80 | 'ObjectPropertyRange'(OPE, CE) 81 | ) :- !. 82 | 83 | % domain 84 | simplify_axiom( 85 | 'SubClassOf'('ObjectIntersectionOf'([owl:'Thing', 'ObjectSomeValuesFrom'(OPE, owl:'Thing')]), CE), 86 | 'ObjectPropertyDomain'(OPE, CE) 87 | ) :- !. 88 | 89 | simplify_axiom( 90 | 'SubClassOf'('ObjectSomeValuesFrom'(OPE, owl:'Thing'), CE), 91 | 'ObjectPropertyDomain'(OPE, CE) 92 | ) :- !. 93 | 94 | % Converts OWL 2 property axioms into a semantically equivalent yet 95 | % syntactically simplified form, so that the resulting axiom is more 96 | % backwards compatible with OWL 1. E.g. in case a property chain stands 97 | % for a transitivity then we represent it with the TransitiveObjectProperty-axiom. 98 | simplify_axiom( 99 | 'SubObjectPropertyOf'('ObjectPropertyChain'(['ObjectInverseOf'(R)]), 'ObjectInverseOf'(S)), 100 | 'SubObjectPropertyOf'(R, S) 101 | ) :- !. 102 | 103 | simplify_axiom( 104 | 'SubObjectPropertyOf'('ObjectPropertyChain'(['ObjectInverseOf'(R)]), S), 105 | 'SubObjectPropertyOf'(R, 'ObjectInverseOf'(S)) 106 | ) :- !. 107 | 108 | simplify_axiom( 109 | 'SubObjectPropertyOf'('ObjectPropertyChain'([R]), S), 110 | 'SubObjectPropertyOf'(R, S) 111 | ) :- !. 112 | 113 | simplify_axiom( 114 | 'SubObjectPropertyOf'('ObjectPropertyChain'([R, R]), R), 115 | 'TransitiveObjectProperty'(R) 116 | ) :- !. 117 | 118 | 119 | % no change 120 | simplify_axiom(Axiom, Axiom). 121 | -------------------------------------------------------------------------------- /prolog/utils/owlswrl/transform_anonymous.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(transform_anonymous, [ 17 | transform_anonymous/2 % +TermIn, -TermOut 18 | ]). 19 | 20 | /** Transform Anonymous Individuals 21 | 22 | @author Tobias Kuhn 23 | @version 2007-10-29 24 | */ 25 | 26 | 27 | %% transform_anonymous(+TermIn, -TermOut) 28 | 29 | transform_anonymous(TermIn, TermOut) :- 30 | transform_anonymous(TermIn, TermOut, [], _). 31 | 32 | 33 | transform_anonymous(Var, Var, Map, Map) :- 34 | var(Var), 35 | !. 36 | 37 | transform_anonymous(nodeID('$VAR'(LocalID)), nodeID(GlobalID), MapIn, MapOut) :- 38 | !, 39 | ( member((LocalID, GID), MapIn) -> 40 | GlobalID = GID, 41 | MapOut = MapIn 42 | ; 43 | GlobalID is random(1000000000000000000), 44 | MapOut = [(LocalID, GlobalID)|MapIn] 45 | ). 46 | 47 | transform_anonymous([], [], Map, Map) :- 48 | !. 49 | 50 | transform_anonymous([H1|T1], [H2|T2], MapIn, MapOut) :- 51 | !, 52 | transform_anonymous(H1, H2, MapIn, MapTemp), 53 | transform_anonymous(T1, T2, MapTemp, MapOut). 54 | 55 | transform_anonymous(Term, Term, Map, Map) :- 56 | Term =.. [Term], 57 | !. 58 | 59 | transform_anonymous(Term1, Term2, MapIn, MapOut) :- 60 | !, 61 | Term1 =.. List1, 62 | transform_anonymous(List1, List2, MapIn, MapOut), 63 | Term2 =.. List2. 64 | -------------------------------------------------------------------------------- /prolog/utils/serialize_term.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(serialize_term, [ 17 | serialize_term/1, % +Term 18 | serialize_term/2, % +Stream, +Term 19 | serialize_term_into_atom/2 % +Term, -Atom 20 | ]). 21 | 22 | /** Term serializer 23 | 24 | The purpose of this module is to provide a single official 25 | predicate for serializing Prolog terms that the Attempto 26 | tools produce (DRSs, token lists, OWL FSS, etc.). 27 | 28 | Serialized terms can be stored in files, sent over HTTP, etc., 29 | so that they can be later read back into the exact same term. 30 | 31 | Essentially we provide a customized version of Prolog built-ins 32 | like write_canonical/[1,2] and writeq/[1,2]. 33 | 34 | @author Kaarel Kaljurand 35 | @version 2009-03-20 36 | 37 | TODO: 38 | 39 | * test how \= (ACE non-equality) is serialized, maybe check character_escapes(bool, changeable) 40 | * find a way to print terms which contain variables so that the output 41 | has nice variable names (A vs _G123) but without the detour of numbervars, 42 | maybe check: print, portray 43 | * should we serialize singletons as '_' 44 | * we make an extra effort to locally undefine some operators, there must be a cleaner way 45 | 46 | */ 47 | 48 | %% serialize_term(+Stream:stream, +Term:term) is det. 49 | %% serialize_term(+Term:term) is det. 50 | % 51 | % @param Stream is the output stream 52 | % @param Term is a term to be serialized 53 | % 54 | serialize_term(Stream, Term) :- 55 | numbervars(Term, 0, _), 56 | op(0, fy, -), 57 | op(0, fy, ~), 58 | op(0, xfx, =>), 59 | op(0, xfx, v), 60 | op(0, xfx, &), 61 | write_term(Stream, Term, [numbervars(true), quoted(true)]), 62 | fail ; true. 63 | 64 | 65 | serialize_term(Term) :- 66 | numbervars(Term, 0, _), 67 | op(0, fy, -), 68 | op(0, fy, ~), 69 | op(0, xfx, =>), 70 | op(0, xfx, v), 71 | op(0, xfx, &), 72 | write_term(Term, [numbervars(true), quoted(true)]), 73 | fail ; true. 74 | 75 | 76 | %% serialize_term_into_atom(+Term:term, -SerializedTerm:atom) is det. 77 | % 78 | % @param Term is a term to be serialized 79 | % @param SerializedTerm is the term serialized as an atom 80 | % 81 | serialize_term_into_atom(Term, SerializedTerm) :- 82 | with_output_to(atom(SerializedTerm), serialize_term(Term)). 83 | -------------------------------------------------------------------------------- /prolog/utils/tree_utils.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(tree_utils, [ 17 | unsplit_pronouns_in_tree/2, % +TreeIn, -TreeOut 18 | remove_gaps_in_tree/2, % +TreeIn, -TreeOut 19 | unify_coords_in_tree/2 % +TreeIn, -TreeOut 20 | ]). 21 | 22 | /** Tree Utils 23 | 24 | @author Tobias Kuhn 25 | */ 26 | 27 | :- use_module(ace_niceace, [ 28 | pronoun_split/2 29 | ]). 30 | 31 | 32 | %% unsplit_pronouns_in_tree(+TreeIn, -TreeOut) 33 | 34 | unsplit_pronouns_in_tree([], []). 35 | 36 | unsplit_pronouns_in_tree([np, [det, T1], [nbar, [n, T2]|RestIn]], [np, [pn, T]|RestOut]) :- 37 | pronoun_split(T, (T1, T2)), 38 | !, 39 | unsplit_pronouns_in_tree(RestIn, RestOut). 40 | 41 | unsplit_pronouns_in_tree([HeadIn|TailIn], [HeadOut|TailOut]) :- 42 | !, 43 | unsplit_pronouns_in_tree(HeadIn, HeadOut), 44 | unsplit_pronouns_in_tree(TailIn, TailOut). 45 | 46 | unsplit_pronouns_in_tree(Term, Term). 47 | 48 | 49 | %% remove_gaps_in_tree(+TreeIn, -TreeOut) 50 | 51 | remove_gaps_in_tree([], []). 52 | 53 | remove_gaps_in_tree([HeadIn|TailIn], TailOut) :- 54 | empty_branch(HeadIn), 55 | !, 56 | remove_gaps_in_tree(TailIn, TailOut). 57 | 58 | remove_gaps_in_tree([HeadIn|TailIn], [HeadOut|TailOut]) :- 59 | !, 60 | remove_gaps_in_tree(HeadIn, HeadOut), 61 | remove_gaps_in_tree(TailIn, TailOut). 62 | 63 | remove_gaps_in_tree(Term, Term). 64 | 65 | 66 | %% empty_branch(+Branch) 67 | 68 | empty_branch([]). 69 | 70 | empty_branch([_|Tail]) :- 71 | empty_branches(Tail). 72 | 73 | 74 | %% empty_branches(+BranchList) 75 | 76 | empty_branches([]). 77 | 78 | empty_branches([Head|Tail]) :- 79 | empty_branch(Head), 80 | empty_branches(Tail). 81 | 82 | 83 | %% unify_coords_in_tree(TreeIn, -TreeOut) 84 | 85 | unify_coords_in_tree(Leaf, Leaf) :- 86 | atomic(Leaf). 87 | 88 | unify_coords_in_tree(TreeIn, TreeOut) :- 89 | TreeIn = [Node, VP1, Coord, [Node|VP2Rest]], 90 | member(Node, [np_coord, vp_coord, s_coord, ap_coord]), 91 | !, 92 | unify_coords_in_tree(VP1, VP1T), 93 | unify_coords_in_tree([Node|VP2Rest], [Node|VP2RestT]), 94 | TreeOut = [Node, VP1T, Coord|VP2RestT]. 95 | 96 | unify_coords_in_tree([Node|ChildrenIn], [Node|ChildrenOut]) :- 97 | atom(Node), 98 | !, 99 | unify_coords_in_tree(ChildrenIn, ChildrenOut). 100 | 101 | unify_coords_in_tree([FirstIn|RestIn], [FirstOut|RestOut]) :- 102 | unify_coords_in_tree(FirstIn, FirstOut), 103 | unify_coords_in_tree(RestIn, RestOut). 104 | -------------------------------------------------------------------------------- /prolog/utils/trees_to_ascii.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(trees_to_ascii, [ 17 | trees_to_ascii/2 % +SyntaxLists, -Ascii 18 | ]). 19 | 20 | /** ASCII trees 21 | 22 | This module creates ASCII graphics for syntax trees. 23 | 24 | @author Tobias Kuhn 25 | @version 2008-03-17 26 | */ 27 | 28 | 29 | %% trees_to_ascii(+SyntaxLists, -Ascii) 30 | % 31 | % Returns the trees described by the syntax list as an atom (ASCII graphics). 32 | 33 | trees_to_ascii([], ''). 34 | 35 | trees_to_ascii([FirstAndOnly], Ascii) :- 36 | tree_to_ascii(FirstAndOnly, Ascii), 37 | !. 38 | 39 | trees_to_ascii([First | Rest], Ascii) :- 40 | tree_to_ascii(First, AsciiFirst), 41 | trees_to_ascii(Rest, AsciiRest), 42 | format(atom(Ascii), '~w~n~w', [AsciiFirst, AsciiRest]). 43 | 44 | 45 | %% tree_to_ascii(+SyntaxList, -Ascii) 46 | 47 | tree_to_ascii(Tree, Ascii) :- 48 | retractall(char(_,_,_)), 49 | retractall(final_line(_)), 50 | depth(Tree, Depth), 51 | FinalLine is Depth * 2, 52 | assert(final_line(FinalLine)), 53 | draw_tree(Tree, 0, 0, _, _), 54 | get_ascii(0, Ascii). 55 | 56 | 57 | %% char(+Line, +Pos, -Char) 58 | 59 | :- dynamic(char/3). 60 | 61 | 62 | %% final_line(-FinalLine) 63 | 64 | :- dynamic(final_line/1). 65 | 66 | 67 | %% get_ascii(+Line, -Ascii) 68 | 69 | get_ascii(Line, Ascii) :- 70 | setof(P, C^char(Line,P,C), Ps), 71 | !, 72 | last(Ps, MaxPos), 73 | get_line(Line, 0, MaxPos, Atom), 74 | NewLine is Line + 1, 75 | get_ascii(NewLine, AsciiRest), 76 | atom_concat(Atom, '\n', AtomT), 77 | atom_concat(AtomT, AsciiRest, Ascii). 78 | 79 | get_ascii(_, ''). 80 | 81 | 82 | %% get_line(+Line, +Pos, +End, -Ascii) 83 | 84 | get_line(_, Pos, End, '') :- 85 | Pos > End, 86 | !. 87 | 88 | get_line(Line, Pos, End, Ascii) :- 89 | ( char(Line, Pos, Char) ; Char = ' ' ), 90 | !, 91 | NewPos is Pos + 1, 92 | get_line(Line, NewPos, End, AsciiRest), 93 | atom_concat(Char, AsciiRest, Ascii). 94 | 95 | 96 | %% draw_tree(+Tree, +Line, +Start, -Head, -End) 97 | 98 | draw_tree(Tree, Line, Start, Start, End) :- 99 | (Tree = [Atom] ; Tree = Atom), 100 | atomic(Atom), 101 | !, 102 | atom_chars(Atom, AtomChars), 103 | final_line(FinalLine), 104 | draw_vertical_line(Start, Line, FinalLine-1), 105 | draw_chars(FinalLine, Start, AtomChars), 106 | length(AtomChars, Length), 107 | End is Start + Length. 108 | 109 | draw_tree([Parent|Children], Line, Start, Head, End) :- 110 | draw_children(Children, Line + 2, Start, ChildrenEnd, [FirstHead|HeadList]), 111 | last([FirstHead|HeadList], LastHead), 112 | draw_horizontal_line(Line + 1, FirstHead, LastHead), 113 | Head is (FirstHead + LastHead) // 2, 114 | atom_chars(Parent, ParentChars), 115 | draw_chars(Line, Head, ParentChars), 116 | draw_char(Line + 1, Head, '|'), 117 | length(ParentChars, Length), 118 | (ChildrenEnd > Head + Length -> End = ChildrenEnd ; End is Head + Length). 119 | 120 | 121 | %% draw_children(+Children, +Line, +Start, -End, -HeadList) 122 | 123 | draw_children([Child], Line, Start, End, [Head]) :- 124 | !, 125 | draw_tree(Child, Line, Start, Head, End). 126 | 127 | draw_children([Child|Rest], Line, Start, End, [Head|HeadList]) :- 128 | draw_tree(Child, Line, Start, Head, TempPos), 129 | draw_children(Rest, Line, TempPos + 1, End, HeadList). 130 | 131 | 132 | %% draw_chars(+Line, +Pos, -CharList) 133 | 134 | draw_chars(_, _, []). 135 | 136 | draw_chars(Line, Pos, [Char|Rest]) :- 137 | draw_char(Line, Pos, Char), 138 | NewPos is Pos + 1, 139 | draw_chars(Line, NewPos, Rest). 140 | 141 | 142 | %% draw_horizontal_line(+Line, +Start, +End) 143 | 144 | draw_horizontal_line(_, Start, End) :- 145 | Start > End, 146 | !. 147 | 148 | draw_horizontal_line(Line, Start, End) :- 149 | draw_char(Line, Start, '_'), 150 | draw_horizontal_line(Line, Start + 1, End). 151 | 152 | 153 | %% draw_vertical_line(+Pos, +LineStart, +LineEnd) 154 | 155 | draw_vertical_line(_, LineStart, LineEnd) :- 156 | LineStart > LineEnd, 157 | !. 158 | 159 | draw_vertical_line(Pos, LineStart, LineEnd) :- 160 | draw_char(LineStart, Pos, '|'), 161 | draw_vertical_line(Pos, LineStart + 1, LineEnd). 162 | 163 | 164 | %% draw_char(+Line, +Pos, +Char) 165 | 166 | draw_char(Line, Pos, Char) :- 167 | LineE is Line, 168 | PosE is Pos, 169 | asserta(char(LineE, PosE, Char)). 170 | 171 | 172 | %% depth(+List, -Depth) 173 | 174 | depth(Atom, 0) :- 175 | atomic(Atom). 176 | 177 | depth([Atom], 0) :- 178 | atomic(Atom), 179 | !. 180 | 181 | depth([H|T], D) :- 182 | depth(H, HD), 183 | depth(T, TD), 184 | (HD + 1 > TD -> D is HD + 1 ; D = TD). 185 | -------------------------------------------------------------------------------- /prolog/utils/xmlterm_to_xmlatom.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- module(xmlterm_to_xmlatom, [ 17 | xmlterm_to_xmlatom/2, % +XMLTerm, -XMLAtom 18 | xmlterm_to_xmlatom/3 % +XMLTerm, +Options, -XMLAtom 19 | ]). 20 | 21 | /** XML term to XML atom converter 22 | 23 | @author Tobias Kuhn 24 | @author Kaarel Kaljurand 25 | @version 2008-03-26 26 | */ 27 | 28 | %% xmlterm_to_xmlatom(+XMLTerm, -XMLAtom) is det. 29 | %% xmlterm_to_xmlatom(+XMLTerm, +Options, -XMLAtom) is det. 30 | % 31 | % Transforms the term representation of an XML structure (using 32 | % element/3) into an atom. 33 | % 34 | % @param XMLTerm is an XML document as SWI's XML term 35 | % @param Options is a list of options for xml_write/3 36 | % @param XMLAtom is an XML document as an atom 37 | % 38 | xmlterm_to_xmlatom(XMLTerm, XMLAtom) :- 39 | xmlterm_to_xmlatom(XMLTerm, [], XMLAtom). 40 | 41 | xmlterm_to_xmlatom(XMLTerm, Options, XMLAtom) :- 42 | new_memory_file(MemHandle), 43 | open_memory_file(MemHandle, write, S), 44 | xml_write(S, XMLTerm, Options), 45 | close(S), 46 | memory_file_to_atom(MemHandle, XMLAtom). 47 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | prolog=swipl 2 | 3 | $prolog -g "working_directory(_, 'prolog/parser'), [fit_to_plp], halt." 4 | $prolog -g "[runape]." 5 | -------------------------------------------------------------------------------- /runape.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | 16 | :- use_module(prolog/utils/drs_to_drslist). 17 | 18 | :- use_module(prolog/parser/ace_to_drs). 19 | :- use_module(prolog/parser/ape_utils). 20 | :- use_module(prolog/parser/tokenizer). 21 | :- use_module(prolog/utils/morphgen, [ 22 | acesentencelist_pp/2 23 | ]). 24 | :- use_module(prolog/utils/is_wellformed, [ 25 | is_wellformed/1 26 | ]). 27 | :- use_module(prolog/utils/drs_to_ascii). 28 | :- use_module(prolog/utils/trees_to_ascii). 29 | :- use_module(prolog/utils/drs_to_ace, [ 30 | drs_to_ace/2 31 | ]). 32 | :- use_module(prolog/logger/error_logger, [ 33 | clear_messages/0, 34 | get_messages/1, 35 | is_error_message/4 36 | ]). 37 | 38 | :- set_prolog_flag(float_format, '%.11g'). 39 | 40 | % Import the lexicons 41 | :- style_check(-singleton). 42 | :- style_check(-discontiguous). 43 | :- use_module(prolog/lexicon/clex). 44 | :- use_module(prolog/lexicon/ulex). 45 | :- style_check(+discontiguous). 46 | :- style_check(+singleton). 47 | 48 | 49 | %% ape is det. 50 | % 51 | % 52 | ape :- 53 | format(' 54 | Attempto Parsing Engine for ACE 6.7~nCopyright 2008-2013, Attempto Group, University of Zurich 55 | This program comes with ABSOLUTELY NO WARRANTY. 56 | This is free software, and you are welcome to redistribute it under certain conditions. 57 | Please visit http://attempto.ifi.uzh.ch for details. 58 | 59 | For help, enter "help".~n~n', []), 60 | ape_input. 61 | 62 | 63 | %% ape_input is det. 64 | % 65 | % 66 | ape_input :- 67 | prompt(Old, 'APE> '), 68 | clear_messages, 69 | ape_utils:read_text_from_commandline(Text), 70 | prompt(_, Old), 71 | tokenizer:tokenize(Text, TokenList), 72 | !, 73 | call_parser(Text, TokenList). 74 | 75 | 76 | %% call_parser(Text:atom, Tokens:list) is det. 77 | % 78 | % @param Text is an ACE text or a commandline command 79 | % @param Tokens is a list of tokens (either of the ACE text or the command) 80 | % 81 | call_parser(_, [Quit]) :- 82 | ( 83 | Quit = quit 84 | ; 85 | Quit = q 86 | ), 87 | !, 88 | nl, write('*** APE has been quit. ***'), nl. 89 | 90 | call_parser(_, [help]) :- 91 | nl, write('APE Prolog-commandline client\'s commands:'), 92 | nl, write(' spy X - spy predicate X'), 93 | nl, write(' gr - (re)compile grammar and contentwords'), 94 | nl, write(' trace - switch Prolog trace-mode on'), 95 | nl, write(' notrace - switch Prolog trace-mode off'), 96 | nl, write(' help - show this help'), 97 | nl, write(' quit/q - quit APE interface (relaunch with "ape.")'), 98 | nl, nl, 99 | !, 100 | ape_input. 101 | 102 | call_parser(_, [gr]) :- 103 | style_check(-discontiguous), 104 | style_check(-singleton), 105 | compile('prolog/parser/grammar.plp'), 106 | compile('prolog/parser/grammar_functionwords.plp'), 107 | compile('prolog/parser/grammar_contentwords.plp'), 108 | style_check(+discontiguous), 109 | style_check(+singleton), 110 | !, 111 | ape_input. 112 | 113 | call_parser(_, [trace]) :- 114 | trace, 115 | !, 116 | ape_input. 117 | 118 | call_parser(_, [notrace]) :- 119 | notrace, 120 | !, 121 | ape_input. 122 | 123 | call_parser(_, [spy, X]) :- 124 | spy(X), 125 | !, 126 | ape_input. 127 | 128 | call_parser(AceTextCodes, _) :- 129 | atom_codes(AceText, AceTextCodes), 130 | parse_and_format(AceText), 131 | !, 132 | ape_input. 133 | 134 | call_parser(_, _) :- 135 | ape_input. 136 | 137 | 138 | parse_and_format(AceText) :- 139 | ace_to_drs:aceparagraph_to_drs(AceText, Sentences, Syntaxtrees, UnresolvedDrs, Drs, Messages), 140 | format('~w~n~n', [Sentences]), 141 | format('Unresolved DRS:~n~n'), 142 | drs_to_ascii(UnresolvedDrs, UnresolvedDrsAscii), 143 | format('~w~n~n', [UnresolvedDrsAscii]), 144 | format('DRS:~n~n'), 145 | drs_to_ascii(Drs, DrsAscii), 146 | format('~w~n~n', [DrsAscii]), 147 | 148 | format('DRS List:~n~n'), 149 | drs_to_drslist:drs_to_drslist(Drs, DrsList), 150 | maplist(drs_to_ascii, DrsList, DrsAsciiList), 151 | maplist(writeln, DrsAsciiList), 152 | 153 | trees_to_ascii(Syntaxtrees, SyntaxtreesAscii), 154 | format('~w~n~n', [SyntaxtreesAscii]), 155 | ( 156 | is_wellformed(Drs) 157 | -> 158 | true 159 | ; 160 | format("WARNING: The DRS is not well-formed!!!~n~n", []) 161 | ), 162 | drs_to_ace(Drs, AceSentenceList), 163 | acesentencelist_pp(AceSentenceList, Paraphrase), 164 | format('~w~n~n', [Paraphrase]), 165 | print_messages(Messages). 166 | 167 | 168 | %% print_messages(+MessageList:list) is det. 169 | % 170 | % @param MessageList is a list of messages 171 | % 172 | print_messages([]) :- nl. 173 | 174 | print_messages([H | T]) :- 175 | format('~w~n~n', [H]), 176 | print_messages(T). 177 | 178 | %% 179 | % 180 | % 181 | % 182 | make_ape :- 183 | working_directory(Old, 'prolog/parser'), 184 | compile(fit_to_plp), 185 | working_directory(_, Old), 186 | make. 187 | 188 | 189 | % Note: we load the interface at startup 190 | :- ape. 191 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | /tmp 2 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | Testing APE 2 | =========== 3 | 4 | Author: Kaarel Kaljurand 5 | 6 | Version: 2019-08-09 7 | 8 | Introduction 9 | ------------ 10 | 11 | This document explains how to test APE including the various DRS translators 12 | that APE contains. 13 | 14 | All the test scripts in this directory depend on a larger lexicon than included 15 | with APE. In order to download the required lexicon, first run 16 | 17 | swipl -f none -g ensure_clex -t halt -s downloader.pl 18 | 19 | 20 | ### APE Regression test 21 | 22 | To regression test APE, just run: 23 | 24 | bash rtest.bash 25 | 26 | or if you want to download the latest regression testset first 27 | then run: 28 | 29 | swipl -f none -g download_acetexts -t halt -s downloader.pl 30 | 31 | A file with a timestamp containing the regression test results 32 | along with APE's output is stored into the `testruns`-directory. 33 | 34 | In order to get a digest of the testrun, grep the file 35 | for regression tester messages, e.g.: 36 | 37 | cat testruns/rtest_050601-1310.txt | grep "^0" 38 | 39 | or cat an already filtered file: 40 | 41 | cat tmp/now.txt 42 | 43 | In order to explore the erronous DRSes, open the file and search 44 | for the strings 45 | 46 | - `0000` (Correctly generated an empty DRS) 47 | - `----` (Correctly generated a DRS which is not empty) 48 | - `0->#` (Failed to generate an empty DRS) 49 | - `#->0` (Incorrectly generated an empty DRS) 50 | - `####` (DRSs which are not empty do not match.) 51 | 52 | To get a listing of all the regressions: 53 | 54 | cat tmp/now.txt | grep "\[.*#.*\]" 55 | 56 | Note: the regression testing is only tested with SWI-Prolog. 57 | It is assumed that SWI-Prolog is called `swipl`, 58 | if it is not the case then modify `rtest.bash` accordingly 59 | or set a symbolic link, e.g.: 60 | 61 | ln -s `which pl` swipl 62 | 63 | Runtime of the complete test run on different machines: 64 | 65 | - Mac OS X G4: ~25 seconds (~3000 testcases) 66 | - Intel i3, 2011-06-20: ~11 seconds (3613 test cases, excluding bug reports) 67 | - Intel i7, 2016-04-02: ~9 seconds (3733 test cases, excluding bug reports, including loading the large lexicon from a flat file) 68 | 69 | 70 | ### Testing Drace Core and Drace NP 71 | 72 | Running the test: 73 | 74 | echo "[test_drace]. test_drace(core)." | swipl > testruns/drace_test_results.txt 75 | echo "[test_drace]. test_drace(np)." | swipl > testruns/dracenp_test_results.txt 76 | 77 | Getting an overview of the problems by filtering out certain testcases 78 | that point to pseudo-problems. 79 | 80 | cat testruns/drace_test_results.txt | grep "FAIL" | grep -v ":" | grep -v "ach of" | wc 81 | 82 | 83 | ### Running all the tests 84 | 85 | time bash test_everything.sh > out.txt 2> err.txt 86 | 87 | This takes about 88 | 89 | - 55 seconds on an i3 Linux laptop with SWI-Prolog v6. 90 | - 45 seconds on an i7 Linux laptop with SWI-Prolog v7. 91 | -------------------------------------------------------------------------------- /tests/bugs_and_requests.pl: -------------------------------------------------------------------------------- 1 | /** 2 | * Convert all bug reports / feature requests to HTML. 3 | * Two types of HTML output are supported 4 | * 5 | * "linear" (default) is simple linear output where reports follow each other 6 | * in a linear fashion 7 | * 8 | * "table" is a sortable HTML-table with columns for bug ID, report date, text, DRS, ... 9 | * 10 | * Usage: 11 | * 12 | * swipl -f bugs_and_requests.pl -g main -t halt > report.html 13 | * swipl -f bugs_and_requests.pl -g "main(table)" -t halt > report.html 14 | * 15 | * @author Kaarel Kaljurand 16 | * @version 2011-06-22 17 | * 18 | * @tbd Escape HTML special symbols (< and &) 19 | */ 20 | 21 | 22 | % We point to the directory where APE modules and the lexicons are located. 23 | :- assert(user:file_search_path(ape, '../prolog')). 24 | 25 | % We point to the directory where the regression test set is located. 26 | :- assert(user:file_search_path(rt, '.')). 27 | 28 | 29 | :- use_module(ape(utils/drs_to_html), [ 30 | drs_to_html_nocontainer/2, 31 | footer/1 32 | ]). 33 | 34 | 35 | % Consult the regression test set. 36 | :- style_check(-singleton). 37 | :- consult(rt(acetexts)). 38 | :- style_check(+singleton). 39 | 40 | :- style_check(-atom). 41 | 42 | main :- 43 | main(linear). 44 | 45 | main(Type) :- 46 | current_stream(1, write, Stream), 47 | set_stream(Stream, encoding(utf8)), 48 | header('APE bugs and ACE feature requests', Header), 49 | footer(Footer), 50 | write(Header), 51 | write('

APE bugs and ACE feature requests

'), 52 | make_another_header(Type), 53 | forall( 54 | text_drs_eval(1, Id, Text, Drs, _Syntax, Date, Author, Comment), 55 | ignore(( 56 | drs_to_html_nocontainer(Drs, HtmlDrs), 57 | display(Type, Id, Text, Date, Author, Comment, HtmlDrs) 58 | )) 59 | ), 60 | make_another_footer(Type), 61 | write(Footer). 62 | 63 | 64 | display(linear, Id, Text, Date, Author, Comment, HtmlDrs) :- 65 | format('
~n~d~n
~w
~n

Comment: ~w

~n~w~n

Submitted: ~w by ~w

~n', [Id, Text, Comment, HtmlDrs, Date, Author]). 66 | 67 | display(table, Id, Text, Date, Author, Comment, HtmlDrs) :- 68 | concat_atom([Year, Month, Day | _], '-', Date), 69 | format('
70 | 71 | 72 | 73 | 74 | 75 | ', [Id, Year-Month-Day, Text, Comment, HtmlDrs, Author]). 76 | 77 | make_another_header(table) :- 78 | !, 79 | write('

Click on a column header to sort by that column.

80 |
" + a + "
~d~w~w~w~w~w
81 | 82 | 83 | 84 | 85 | 86 | 87 | '). 88 | 89 | make_another_header(_). 90 | 91 | 92 | make_another_footer(table) :- 93 | !, 94 | write('
IDDateACE textCommentDRSAuthor
'). 95 | 96 | make_another_footer(_). 97 | 98 | 99 | %% header(+Title:atom, -Header:atom) is det. 100 | % 101 | % Generate an HTML-header. 102 | % 103 | % @param Title is the content for the title-element in the HTML-header 104 | % @param Header is an HTML header 105 | % 106 | header(Title, Header) :- 107 | with_output_to(atom(Header), format(' 108 | 109 | 110 | 111 | ~w 112 | 113 | 114 | 115 | 120 | 135 | 136 | ', [Title])). 137 | -------------------------------------------------------------------------------- /tests/downloader.pl: -------------------------------------------------------------------------------- 1 | % Usage: 2 | % $ swipl -f none -g ensure_clex -t halt -s downloader.pl 3 | % $ swipl -f none -g download_acetexts -t halt -s downloader.pl 4 | 5 | clex_remote_local('https://raw.github.com/Attempto/Clex/master/clex_lexicon.pl', 'clex_lexicon.pl'). 6 | acetexts_remote_local('http://attempto.ifi.uzh.ch/cgi-bin/acetextset/get_acetexts.cgi', 'acetexts.pl'). 7 | 8 | %! ensure_clex 9 | % 10 | % Download the CLex lexicon if not already present. 11 | 12 | ensure_clex :- 13 | clex_remote_local(Url, Filename), 14 | (exists_file(Filename) -> true ; download(Url, Filename)). 15 | 16 | %! download_acetexts 17 | % 18 | % Download the APE regression testsuite. 19 | 20 | download_acetexts :- 21 | acetexts_remote_local(Url, Filename), 22 | download(Url, Filename). 23 | 24 | download(Url, Filename) :- 25 | format(user_error, "Saving ~w as ~w~n", [Url, Filename]), 26 | use_module(library(http/http_open)), 27 | setup_call_cleanup( 28 | ( 29 | http_open(Url, In, []), 30 | set_stream(In, encoding(utf8)) 31 | ), 32 | setup_call_cleanup( 33 | open(Filename, write, Out), 34 | copy_stream_data(In, Out), 35 | close(Out) 36 | ), 37 | close(In) 38 | ). 39 | -------------------------------------------------------------------------------- /tests/make_acetext_drs.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2010-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | /** 16 | This program outputs 17 | 18 | == 19 | acetext_drs(Id, ACEText, DRS). 20 | == 21 | 22 | for every ACE text in the regression test set that passes the test. 23 | 24 | Configuration: change user:file_search_path/2 (first two rules in this program) 25 | to specify the path to APE and to the regression test set. 26 | 27 | 28 | BUG: there is a lot of code overlap with test_ape.pl. 29 | 30 | 31 | Usage: 32 | 33 | == 34 | swipl -f make_acetext_drs.pl -g main -t halt -q > acetext_drs.pl 35 | == 36 | 37 | @author Kaarel Kaljurand 38 | @version 2011-07-21 39 | 40 | */ 41 | 42 | % We point to the directory where APE modules and the lexicons are located. 43 | :- assert(user:file_search_path(ape, '../prolog')). 44 | 45 | % We point to the directory where the regression test set is located. 46 | :- assert(user:file_search_path(rt, '.')). 47 | 48 | 49 | :- use_module(ape(parser/ace_to_drs), [ 50 | acetext_to_drs/5 51 | ]). 52 | 53 | :- use_module(ape(utils/are_equivalent), [ 54 | are_equivalent/2 55 | ]). 56 | 57 | :- use_module(ape(utils/serialize_term), [ 58 | serialize_term/1 59 | ]). 60 | 61 | % Consult the regression test set. 62 | :- style_check(-singleton). 63 | :- consult(rt(acetexts)). 64 | :- style_check(+singleton). 65 | 66 | % Everything which takes longer than 1 second is considered a bug. 67 | time_limit(1). 68 | 69 | %% main is det. 70 | % 71 | main :- 72 | time_limit(TimeLimit), 73 | catch(set_stream(user_output, encoding(utf8)), _, true), 74 | writeln(':- encoding(utf8).'), 75 | forall( 76 | text_drs_eval(0, Number, Text, DrsPre, _Syntax, _TestDate, _Author, _Comment), 77 | ( 78 | remove_pn_conditions(DrsPre, Drs), 79 | run_test(TimeLimit, Number, Text, Drs) 80 | ) 81 | ). 82 | 83 | 84 | % Removes the object conditions for proper names from the old DRSs of the test set. 85 | % BUG: This should be done at a different place! 86 | remove_pn_conditions(drs(DomIn,CondsIn), drs(DomOut,CondsOut)) :- 87 | exclude(is_named, CondsIn, CondsOut), 88 | exclude(ground, DomIn, DomOut). 89 | 90 | is_named(object(named(Name), Name, named, _, _, _)-_). 91 | 92 | 93 | run_test(TimeLimit, Number, Text, Drs) :- 94 | catch( 95 | call_with_time_limit( 96 | TimeLimit, 97 | ( 98 | acetext_to_drs(Text, _, _, RealDrs, _), 99 | result(Drs, RealDrs, Result) 100 | ) 101 | ), 102 | CatchType, 103 | Result = CatchType 104 | ), 105 | show_result(Result, Number, Text, RealDrs). 106 | 107 | 108 | %% result(+Drs1:term, +Drs2:term, -ResultCode:atom) is det. 109 | % 110 | % Compares two DRSs and returns a ResultCode which is to be interpreted as follows: 111 | % 112 | % * =|0000|= - parsing fails as it should 113 | % * =|0->#|= - parsing should fail but instead a non-empty DRS is produced 114 | % * =|#->0|= - parsing should produce a non-empty DRS but instead it fails 115 | % * =|####|= - parsing produces a non-empty DRS but it is different from what it should be 116 | % * =|----|= - parsing produces a DRS that is equivalent to the one stored in the regression test set 117 | % 118 | % Note: it is important that Drs1 and Drs2 contain variables for discourse referents. 119 | % 120 | % @param Drs1 is Attempto DRS 121 | % @param Drs2 is Attempto DRS 122 | % @param ResultCode is one of {=|0000|=, =|0->#|=, =|#->0|=, =|####|=, =|----|=} 123 | % 124 | result(drs([], []), drs([], []), '0000') :- !. 125 | 126 | result(drs([], []), Drs, '0->#') :- Drs \= drs([], []), !. 127 | 128 | result(Drs, drs([], []), '#->0') :- Drs \= drs([], []), !. 129 | 130 | result(Drs1, Drs2, '----') :- 131 | are_equivalent(Drs1, Drs2), 132 | !. 133 | 134 | result(_, _, '####'). 135 | 136 | 137 | % 138 | % 139 | show_result('####', _Number, _Text, _Drs) :- !. 140 | show_result('0->#', _Number, _Text, _Drs) :- !. 141 | show_result('#->0', _Number, _Text, _Drs) :- !. 142 | 143 | show_result(_, Number, Text, Drs) :- 144 | serialize_term(acetext_drs(Number, Text, Drs)), writeln('.'). 145 | -------------------------------------------------------------------------------- /tests/rtest.bash: -------------------------------------------------------------------------------- 1 | # APE regression tester 2 | # 3 | # Usage: 4 | # 5 | # bash rtest.bash 6 | # 7 | # @author Kaarel Kaljurand 8 | # @version 2019-08-10 9 | 10 | prolog=swipl 11 | #prolog=`which swipl` 12 | 13 | echo "Using: `$prolog --version`" 14 | 15 | # Generate a timestamp. 16 | timestamp=`date '+%y%m%d-%H%M'` 17 | 18 | # Ensures a directory for the test results. 19 | mkdir -p testruns/ 20 | 21 | # Convert fit-files into plp-files. 22 | $prolog -g "working_directory(_, '../prolog/parser'), [fit_to_plp], halt." 23 | 24 | # Run the regression test. 25 | #time echo "[test_ape]. main. halt." | $prolog -q > testruns/rtest_$timestamp.txt 26 | time $prolog -f test_ape.pl -g main -t halt -q > testruns/rtest_$timestamp.txt 27 | 28 | echo "" 29 | echo "Regression tester finished." 30 | echo "The results of the regression test were saved into testruns/rtest_$timestamp.txt" 31 | 32 | echo "" 33 | echo "Diff with the previous version:" 34 | echo "" 35 | 36 | mkdir -p tmp/ 37 | ls testruns/rtest*.txt | tail -2 | head -1 | xargs grep "^0" > tmp/before.txt 38 | ls testruns/rtest*.txt | tail -1 | xargs grep "^0" > tmp/now.txt 39 | diff tmp/before.txt tmp/now.txt 40 | 41 | echo "" 42 | echo "Finished." 43 | -------------------------------------------------------------------------------- /tests/test_ape.pl: -------------------------------------------------------------------------------- 1 | % This file is part of the Attempto Parsing Engine (APE). 2 | % Copyright 2008-2013, Attempto Group, University of Zurich (see http://attempto.ifi.uzh.ch). 3 | % 4 | % The Attempto Parsing Engine (APE) is free software: you can redistribute it and/or modify it 5 | % under the terms of the GNU Lesser General Public License as published by the Free Software 6 | % Foundation, either version 3 of the License, or (at your option) any later version. 7 | % 8 | % The Attempto Parsing Engine (APE) is distributed in the hope that it will be useful, but WITHOUT 9 | % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 10 | % PURPOSE. See the GNU Lesser General Public License for more details. 11 | % 12 | % You should have received a copy of the GNU Lesser General Public License along with the Attempto 13 | % Parsing Engine (APE). If not, see http://www.gnu.org/licenses/. 14 | 15 | /** 16 | APE regression tester 17 | 18 | This program compares a stored and manually checked DRS (taken from the APE regression test set) 19 | with an automatically generated DRS for the same ACE text. 20 | If they do not match then a failure message along with both DRSs are displayed. 21 | The matching algorithm is defined in the APE module =|utils/are_equivalent.pl|=. 22 | 23 | Configuration: 24 | 25 | * change the first line of this program to match your SWI-Prolog installation 26 | * change user:file_search_path/2 (first two rules in this program) 27 | to specify the path to APE and to the regression test set 28 | 29 | 30 | Usage: 31 | 32 | == 33 | swipl -f test_ape.pl -g main -t halt -q 34 | == 35 | 36 | Documentation: 37 | 38 | Read the PlDoc comments in the source code to find out how to interpret the result codes 39 | that this program outputs. 40 | 41 | @author Kaarel Kaljurand 42 | @version 2011-07-28 43 | 44 | */ 45 | 46 | % We point to the directory where APE modules and the lexicons are located. 47 | :- assert(user:file_search_path(ape, '../prolog')). 48 | 49 | % We point to the directory where the regression test set is located. 50 | :- assert(user:file_search_path(rt, '.')). 51 | 52 | 53 | :- use_module(ape(parser/ace_to_drs), [ 54 | acetext_to_drs/5 55 | ]). 56 | 57 | :- use_module(ape(utils/are_equivalent), [ 58 | are_equivalent/2 59 | ]). 60 | 61 | :- use_module(ape(utils/drs_to_ascii)). 62 | 63 | % Import the lexicons. 64 | :- style_check(-discontiguous). 65 | :- consult(clex:clex_lexicon). 66 | :- style_check(+discontiguous). 67 | 68 | % Consult the regression test set. 69 | :- style_check(-singleton). 70 | :- consult(rt(acetexts)). 71 | :- style_check(+singleton). 72 | 73 | 74 | % Everything which takes longer than 1 second is considered a bug. 75 | time_limit(1). 76 | 77 | % 78 | % Applies APE to every ACE text that is a part of a positive regression test case, 79 | % and compares the resulting DRS to the DRS that is stored in the regression test set. 80 | % 81 | main :- 82 | time_limit(TimeLimit), 83 | get_time(Timestamp), 84 | format_time(atom(FormattedTimestamp), 'Timestamp: %F %T%z', Timestamp), 85 | writeln(FormattedTimestamp), 86 | forall( 87 | text_drs_eval(0, Number, Text, DrsPre, _Syntax, _TestDate, _Author, _Comment), 88 | ( 89 | remove_pn_conditions(DrsPre, Drs), 90 | run_test(TimeLimit, Number, Text, Drs) 91 | ) 92 | ). 93 | 94 | 95 | % Removes the object conditions for proper names from the old DRSs of the test set. 96 | % BUG: This should be done at a different place! 97 | remove_pn_conditions(drs(DomIn,CondsIn), drs(DomOut,CondsOut)) :- 98 | exclude(is_named, CondsIn, CondsOut), 99 | exclude(ground, DomIn, DomOut). 100 | 101 | is_named(object(named(Name), Name, named, _, _, _)-_). 102 | 103 | 104 | run_test(TimeLimit, Number, Text, Drs) :- 105 | catch( 106 | call_with_time_limit( 107 | TimeLimit, 108 | ( 109 | acetext_to_drs(Text, _, _, RealDrs, Messages), 110 | result(Drs, RealDrs, Result) 111 | ) 112 | ), 113 | CatchType, 114 | Result = CatchType 115 | ), 116 | display_result(Result, Number, Text, Messages), 117 | ( 118 | Result = '####' 119 | -> 120 | display_drs(Drs), nl, 121 | display_drs(RealDrs) 122 | ; 123 | true 124 | ). 125 | 126 | 127 | 128 | %% result(+Drs1:term, +Drs2:term, -ResultCode:atom) is det. 129 | % 130 | % Compares two DRSs and returns a ResultCode which is to be interpreted as follows: 131 | % 132 | % * =|0000|= - parsing fails as it should 133 | % * =|0->#|= - parsing should fail but instead a non-empty DRS is produced 134 | % * =|#->0|= - parsing should produce a non-empty DRS but instead it fails 135 | % * =|####|= - parsing produces a non-empty DRS but it is different from what it should be 136 | % * =|----|= - parsing produces a DRS that is equivalent to the one stored in the regression test set 137 | % 138 | % Note: it is important that Drs1 and Drs2 contain variables for discourse referents. 139 | % 140 | % @param Drs1 is Attempto DRS 141 | % @param Drs2 is Attempto DRS 142 | % @param ResultCode is one of {=|0000|=, =|0->#|=, =|#->0|=, =|####|=, =|----|=} 143 | % 144 | result(drs([], []), drs([], []), '0000') :- !. 145 | 146 | result(drs([], []), Drs, '0->#') :- Drs \= drs([], []), !. 147 | 148 | result(Drs, drs([], []), '#->0') :- Drs \= drs([], []), !. 149 | 150 | result(Drs1, Drs2, '----') :- 151 | are_equivalent(Drs1, Drs2), 152 | !. 153 | 154 | result(_, _, '####'). 155 | 156 | 157 | %% display_results(+ResultCode:atom, +Number:number, +Text:atom, +Messages:list) is det. 158 | % 159 | % Pretty-prints the result of DRS comparison. 160 | % Note: Messages are currently not output. 161 | % 162 | % @param ResultCode is one of {=|0000|=, =|0->#|=, =|#->0|=, =|####|=, =|----|=} 163 | % @param Number is the ID-number of the test case 164 | % @param Text is the ACE text 165 | % @param Messages is a list of possible parser error messages 166 | % 167 | display_result(Result, Number, Text, _) :- 168 | format('~n~*t~d~6| [~w] ~q~n', [0'0, Number, Result, Text]). 169 | 170 | %display_result(Result, Number, Text, [Message | Messages]) :- 171 | % format('~n~*t~d~6| [~w] ~q ~w~n', [0'0, Number, Result, Text, [Message | Messages]]). 172 | -------------------------------------------------------------------------------- /tests/test_apeexe.sh: -------------------------------------------------------------------------------- 1 | 2 | ape=../ape.exe 3 | 4 | # This test should print out 9 times: 5 | # 6 | # If there is a user X1 then Attempto_Parsing_Engine helps the user X1. 7 | # 8 | 9 | file_file1=../../web/site/acetexts/example1.ace.txt 10 | file_url1=http://attempto.ifi.uzh.ch/site/acetexts/example1.ace.txt 11 | ulexfile_file1=../../web/site/acetexts/example1.ulex.pl 12 | ulexfile_url1=http://attempto.ifi.uzh.ch/site/acetexts/example1.ulex.pl 13 | 14 | $ape -text "APE helps every user." -ulextext "pn_sg('APE', 'Attempto_Parsing_Engine', neutr). pn_pl('APEs', 'Attempto_Parsing_Engines', neutr)." -solo paraphrase1 15 | $ape -text "APE helps every user." -ulexfile $ulexfile_file1 -solo paraphrase1 16 | $ape -text "APE helps every user." -ulexfile $ulexfile_url1 -solo paraphrase1 17 | 18 | $ape -file $file_file1 -ulextext "pn_sg('APE', 'Attempto_Parsing_Engine', neutr). pn_pl('APEs', 'Attempto_Parsing_Engines', neutr)." -solo paraphrase1 19 | $ape -file $file_file1 -ulexfile $ulexfile_file1 -solo paraphrase1 20 | $ape -file $file_file1 -ulexfile $ulexfile_url1 -solo paraphrase1 21 | 22 | $ape -file $file_url1 -ulextext "pn_sg('APE', 'Attempto_Parsing_Engine', neutr). pn_pl('APEs', 'Attempto_Parsing_Engines', neutr)." -solo paraphrase1 23 | $ape -file $file_url1 -ulexfile $ulexfile_file1 -solo paraphrase1 24 | $ape -file $file_url1 -ulexfile $ulexfile_url1 -solo paraphrase1 25 | 26 | 27 | # This test should preserve the Unicode characters. 28 | 29 | file_file2=../../web/site/acetexts/example2.ace.txt 30 | 31 | $ape -file $file_file2 -solo paraphrase1 32 | -------------------------------------------------------------------------------- /tests/test_drace.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/swipl -f none -g test_drace(core) -t halt -s 2 | 3 | /** 4 | * @title Test Drace Core or Drace NP 5 | * @author Kaarel Kaljurand 6 | * @version 2009-04-08 7 | * 8 | * This program tests the module drs_to_coreace.pl (or drs_to_npace.pl) 9 | * by applying the composition 10 | * 11 | * ace_to_drs o drs_to_coreace (or drs_to_npace) 12 | * 13 | * to all the correct DRSs in the regression testset. 14 | * 15 | * The test on a given DRS is correct if the composition acts as identity. 16 | * 17 | * 18 | * Usage: 19 | * 20 | * echo "[test_drace]. test_drace(core)." | swipl > drace_test_results.txt 21 | * echo "[test_drace]. test_drace(np)." | swipl > dracenp_test_results.txt 22 | * 23 | * and then compare the results by diff, e.g.: 24 | * 25 | * diff testruns/drace_test_results.txt drace_test_results.txt 26 | * diff testruns/dracenp_test_results.txt dracenp_test_results.txt 27 | * 28 | * Note that the files in the directory testruns/ are under version control. 29 | * They reflect a stable state of the verbalizer. Comparing against them helps 30 | * to detect regression in the verbalizer. 31 | */ 32 | 33 | % We point to the directory where APE modules and the lexicons are located. 34 | :- assert(user:file_search_path(ape, '../prolog')). 35 | 36 | % We point to the directory where the regression test set is located. 37 | :- assert(user:file_search_path(rt, '.')). 38 | 39 | % Consult the regression test set. 40 | :- style_check(-singleton). 41 | :- consult(rt(acetexts)). 42 | :- style_check(+singleton). 43 | 44 | :- use_module(ape('parser/ace_to_drs'), [ 45 | acetext_to_drs/5 46 | ]). 47 | 48 | :- use_module(ape('utils/morphgen'), [ 49 | acesentencelist_pp/2 50 | ]). 51 | 52 | :- use_module(ape('utils/are_equivalent')). 53 | :- use_module(ape('utils/drs_to_coreace')). 54 | :- use_module(ape('utils/drs_to_npace')). 55 | :- use_module(ape('utils/drs_to_ascii')). 56 | 57 | % Import the lexicons 58 | :- style_check(-discontiguous). 59 | :- consult(clex:clex_lexicon). 60 | :- style_check(+discontiguous). 61 | 62 | :- set_prolog_flag(float_format, '%.11g'). 63 | 64 | time_limit(3). 65 | 66 | test_drace(DraceType) :- 67 | time_limit(TimeLimit), 68 | set_stream(user_output, encoding(utf8)), 69 | forall( 70 | text_drs_eval(0, Number, Text, PreDrs, _Syntax, _Date, _Author, _Comment), 71 | ( 72 | remove_pn_conditions(PreDrs, Drs), 73 | run_test(TimeLimit, DraceType, Number, Text, Drs) 74 | ) 75 | ). 76 | 77 | 78 | % Removes the object conditions for proper names from the old DRSs of the test set. 79 | % BUG: This should be done at a different place! 80 | remove_pn_conditions(drs(DomIn,CondsIn), drs(DomOut,CondsOut)) :- 81 | exclude(is_named, CondsIn, CondsOut), 82 | exclude(ground, DomIn, DomOut). 83 | 84 | is_named(object(named(Name), Name, named, _, _, _)-_). 85 | 86 | 87 | run_test(TimeLimit, DraceType, Number, Text1, Drs1) :- 88 | catch( 89 | call_with_time_limit( 90 | TimeLimit, 91 | ( 92 | execute_test(DraceType, Drs1, Text2, Drs2), 93 | compare_results(Drs1, Drs2, Result) 94 | ) 95 | ), 96 | CatchType, 97 | ( 98 | Result = CatchType, 99 | Text2 = '' 100 | )), 101 | display_result(Result, Number, Text1, Text2). 102 | 103 | 104 | execute_test(core, Drs1, AceText, Drs2) :- 105 | bigdrs_to_coreace(Drs1, AceSentenceList), 106 | get_acetext_or_error(AceSentenceList, AceText), 107 | acetext_to_drs(AceText, _, _, Drs2, _Messages). 108 | 109 | execute_test(np, Drs1, AceText, Drs2) :- 110 | drs_to_npace(Drs1, AceSentenceList), 111 | get_acetext_or_error(AceSentenceList, AceText), 112 | acetext_to_drs(AceText, _, _, Drs2, _Messages). 113 | 114 | 115 | % In case the DRS (correctly) fails, we do not report it as ----. 116 | compare_results(drs([], []), _, 'ZERO') :- 117 | !. 118 | 119 | compare_results(Drs1, Drs2, '----') :- 120 | are_equivalent(Drs1, Drs2, [ignore_sid(true)]), 121 | !. 122 | 123 | compare_results(_, _, 'FAIL'). 124 | 125 | 126 | %% display_result(+Result:atom, +Number:integer, +Text1:atom, +Text2:atom) 127 | % 128 | % 129 | display_result('ZERO', Number, Text1, _) :- 130 | !, 131 | format('~*t~d~6| [~w] ~w~n', [0'0, Number, 'ZERO', Text1]). 132 | 133 | display_result('----', Number, Text1, Text2) :- 134 | Text1 = Text2, 135 | !, 136 | format('~*t~d~6| [~w] ~w~n', [0'0, Number, 'SAME', Text1]). 137 | 138 | display_result(Result, Number, Text1, Text2) :- 139 | format('~*t~d~6| [~w] ~w --> ~w~n', [0'0, Number, Result, Text1, Text2]). 140 | 141 | 142 | %% 143 | % 144 | % 145 | get_acetext_or_error([], 'NOT IMPLEMENTED') :- 146 | !. 147 | 148 | get_acetext_or_error(AceSentenceList, AceText) :- 149 | acesentencelist_pp(AceSentenceList, AceText). 150 | -------------------------------------------------------------------------------- /tests/test_drs_to_x.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/swipl -f none -g main -t halt -s 2 | 3 | /** 4 | * 5 | * @title Test the conversion of DRS to other formats 6 | * @author Kaarel Kaljurand 7 | * @version 2009-06-24 8 | * 9 | * This is an attempt to write a more general testing framework 10 | * for testing DRS->X converters on the APE regression test set. 11 | * Currently it just tests the TPTP converter. 12 | * 13 | * TODO: Integrate result codes into the header. 14 | * 15 | */ 16 | 17 | % We point to the directory where APE modules and the lexicons are located. 18 | :- assert(user:file_search_path(ape, '../prolog')). 19 | 20 | % We point to the directory where the regression test set is located. 21 | :- assert(user:file_search_path(rt, '.')). 22 | 23 | % Consult the regression test set. 24 | :- style_check(-singleton). 25 | :- consult(rt(acetexts)). 26 | :- style_check(+singleton). 27 | 28 | :- use_module(ape('parser/ace_to_drs'), [ 29 | acetext_to_drs/5 30 | ]). 31 | 32 | :- use_module(ape('utils/drs_to_tptp'), [ 33 | drs_to_tptp/2, 34 | drs_to_tptplist/2, 35 | tptp_pp/1, 36 | tptplist_pp/1 37 | ]). 38 | 39 | % Import the lexicons 40 | :- style_check(-discontiguous). 41 | :- consult(clex:clex_lexicon). 42 | :- style_check(+discontiguous). 43 | 44 | :- set_prolog_flag(float_format, '%.11g'). 45 | 46 | time_limit(1). 47 | drs_converter(drs_to_tptplist, tptplist_pp). 48 | 49 | main :- 50 | time_limit(TimeLimit), 51 | drs_converter(Converter, Pp), 52 | set_stream(user_output, encoding(utf8)), 53 | forall( 54 | text_drs_eval(0, Number, Text, DrsPre, _Syntax, _Date, _Author, _Comment), 55 | ( 56 | remove_pn_conditions(DrsPre, Drs), 57 | run_test(TimeLimit, Converter, Pp, Number, Text, Drs) 58 | ) 59 | ). 60 | 61 | % Removes the object conditions for proper names from the old DRSs of the test set. 62 | % BUG: This should be done at a different place! 63 | remove_pn_conditions(drs(DomIn,CondsIn), drs(DomOut,CondsOut)) :- 64 | exclude(is_named, CondsIn, CondsOut), 65 | exclude(ground, DomIn, DomOut). 66 | 67 | is_named(object(named(Name), Name, named, _, _, _)-_). 68 | 69 | 70 | run_test(TimeLimit, Converter, Pp, Number, Text, Drs) :- 71 | display_header(Number, Text), 72 | catch( 73 | call_with_time_limit(TimeLimit, apply_converter(Converter, Drs, Result)), 74 | Catcher, 75 | Result = Catcher 76 | ), 77 | display_result(Pp, Result). 78 | 79 | 80 | apply_converter(_Converter, drs(Dom, []), _) :- 81 | throw(error('DRS is empty', context(apply_converter/2, drs(Dom, [])))). 82 | 83 | apply_converter(Converter, Drs, Result) :- 84 | call(Converter, Drs, Result), 85 | !. 86 | 87 | apply_converter(_, Drs, _) :- 88 | throw(error('Converter failed', context(apply_converter/2, Drs))). 89 | 90 | 91 | display_header(Number, Text) :- 92 | format('~*t~d~6| ~w~n', [0'0, Number, Text]). 93 | 94 | 95 | display_result(_, Result) :- 96 | check_and_output_error(Result), 97 | !. 98 | 99 | display_result(Pp, Result) :- 100 | call(Pp, Result), 101 | nl. 102 | 103 | display_result(_, Result) :- 104 | format("ERROR\tWrong exception-term or non-printable result\t~w~n", [Result]). 105 | 106 | 107 | check_and_output_error(time_limit_exceeded) :- 108 | format("ERROR\t~w~n", ['Time limit exceeded']). 109 | 110 | check_and_output_error(error(Message, context(Pred, Arg))) :- 111 | \+ \+ ( numbervars(Arg, 0, _, [singletons(true)]), 112 | format("ERROR\t~w\t~w\t~w~n", [Message, Pred, Arg]) 113 | ). 114 | -------------------------------------------------------------------------------- /tests/test_duration.pl: -------------------------------------------------------------------------------- 1 | /** 2 | * @title Test the duration of APE, Refres, Drace. 3 | * @author Kaarel Kaljurand 4 | * @version 2008-02-15 5 | * 6 | * echo "[test_duration]. test_duration." | swipl -q > testruns/duration_051013-2000.txt 7 | * 8 | * TODO: 9 | * - recover from situations where the automatic generation of the DRS loops or craches 10 | * - better formatting of results 11 | * - benchmark all the main components separately 12 | */ 13 | 14 | % We point to the directory where APE modules and the lexicons are located. 15 | :- assert(user:file_search_path(ape, '../prolog')). 16 | 17 | % We point to the directory where the regression test set is located. 18 | :- assert(user:file_search_path(rt, '.')). 19 | 20 | :- use_module(ape('parser/ace_to_drs'), [ 21 | acetext_to_drs/5 22 | ]). 23 | 24 | :- use_module(ape('parser/ape_utils'), [ 25 | cpu_time/2 26 | ]). 27 | 28 | % Consult the regression test set. 29 | :- style_check(-singleton). 30 | :- consult(rt(acetexts)). 31 | :- style_check(+singleton). 32 | 33 | % Import the lexicons 34 | :- style_check(-discontiguous). 35 | :- consult(clex:clex_lexicon). 36 | :- style_check(+discontiguous). 37 | 38 | :- set_prolog_flag(float_format, '%.11g'). 39 | 40 | test_duration :- 41 | forall( 42 | text_drs_eval(0, Number, Text, DRS, _Syntax, _Date, _Author, _Comment), 43 | execute_test(Number, Text, DRS, _TimeOutLimit) 44 | ). 45 | 46 | execute_test(Number, Text, _Drs1, _TimeOutLimit) :- 47 | cpu_time(acetext_to_drs(Text, _, _, _Drs2, _Messages), Duration), 48 | display_result(Number, Text, Duration). 49 | 50 | display_result(Number, Text, Duration) :- 51 | format('~f\t~d\t~w~n', [Duration, Number, Text]). 52 | -------------------------------------------------------------------------------- /tests/test_everything.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Runs all the APE tests in one go. 4 | # 5 | # Note that these tests overwrite files that are under version 6 | # control. In case the only change in the test results is random 7 | # variable names or IDs, then revert the change by 8 | # 9 | # git checkout . 10 | # 11 | 12 | pl=swipl 13 | 14 | dir=testruns 15 | 16 | results_coreace="${dir}/drace_test_results.txt" 17 | results_npace="${dir}/dracenp_test_results.txt" 18 | results_owlswrl="${dir}/owlswrl_test_results.txt" 19 | results_tptp="${dir}/test_drs_to_tptp_out.txt" 20 | 21 | echo 22 | echo "ACE -> DRS" 23 | echo 24 | 25 | time (bash rtest.bash) 26 | 27 | 28 | echo 29 | echo "DRS -> Core ACE" 30 | echo 31 | 32 | time (echo "[test_drace]. test_drace(core)." | $pl > ${results_coreace}) 33 | 34 | 35 | echo 36 | echo "DRS -> NP ACE" 37 | echo 38 | 39 | time (echo "[test_drace]. test_drace(np)." | $pl > ${results_npace}) 40 | 41 | 42 | echo 43 | echo "DRS -> OWL/SWRL" 44 | echo 45 | 46 | time ($pl -f none -g main -t halt -s test_owlswrl.pl > ${results_owlswrl}) 47 | 48 | 49 | echo 50 | echo "DRS -> TPTP" 51 | echo 52 | 53 | time (echo "[test_drs_to_x]. main." | $pl > ${results_tptp}) 54 | -------------------------------------------------------------------------------- /tests/test_ruleml.sh: -------------------------------------------------------------------------------- 1 | #============================================================================== 2 | # This script validates the RuleML output of APE. 3 | # 4 | # Author: Tobias Kuhn 5 | # 6 | # The programs 'xmllint' and 'trang' need to be installed. 7 | # 8 | # THIS SCRIPT CURRENTLY DOES NOT WORK: 9 | # I tried different XML validation tools like xmllint and xerces and different 10 | # schema files, but I failed to validate even the official RuleML examples. 11 | #============================================================================== 12 | 13 | 14 | # Location of APE executable: 15 | ape=../ape.exe 16 | 17 | # Temporary directory: 18 | tempdir=tmp/ruleml 19 | 20 | echo "=== Create clean temporary directory: $tempdir ===" 21 | mkdir -p $tempdir/output 22 | mkdir -p $tempdir/schema 23 | 24 | echo "=== Create RuleML output for test sentences ===" 25 | $ape -text "Every customer is important." -solo ruleml > $tempdir/output/1.xml 26 | $ape -text "John is a man." -solo ruleml > $tempdir/output/2.xml 27 | $ape -text "Nobody waits." -solo ruleml > $tempdir/output/3.xml 28 | 29 | echo "=== Get XML schema ===" 30 | if [ -e $tempdir/schema/folog_normal.rng ] 31 | then 32 | echo "Use cached schema file: $tempdir/schema/folog_normal.rng" 33 | else 34 | echo "Download and convert schema file..." 35 | trang http://ruleml.org/1.0/relaxng/folog_normal.rnc $tempdir/schema/folog_normal.rng 36 | fi 37 | 38 | echo "=== Validate RuleML output with schema ===" 39 | xmllint --noout --relaxng $tempdir/schema/folog_normal.rng $tempdir/output/1.xml 40 | xmllint --noout --relaxng $tempdir/schema/folog_normal.rng $tempdir/output/2.xml 41 | xmllint --noout --relaxng $tempdir/schema/folog_normal.rng $tempdir/output/3.xml 42 | 43 | echo "=== Finished ===" 44 | -------------------------------------------------------------------------------- /tests/testruns/.gitignore: -------------------------------------------------------------------------------- 1 | /rtest_*.txt 2 | -------------------------------------------------------------------------------- /tests/testruns/README.drace: -------------------------------------------------------------------------------- 1 | #Drace test results on 2006-08-05. 2 | 3 | cat drace_test_results.txt | grep FAIL | wc -l 4 | # 216 5 | 6 | cat drace_test_results.txt | grep FAIL | grep -v "Paraphrase not supported" | wc -l 7 | # 52 8 | 9 | cat drace_test_results.txt | grep FAIL | grep -v "Paraphrase not supported" | grep -v ":" | wc -l 10 | # 31 11 | 12 | 13 | 14 | #Some bugs discovered on 2007-11-14: 15 | 16 | #1) A man's man waits. The man is happy. (APE bug) 17 | 18 | #2) Not less than 5 men wait. (Maybe APE bug) 19 | 20 | #3) 001110 [FAIL] A man sees his own dog and his own cat. --> A man X1 sees a dog of the man X1 and a cat of the man X1. (Paraphraser bug) 21 | 22 | 23 | 24 | # Drace test results on 2007-12-15. 25 | 26 | cat drace_test_results.txt | grep FAIL | wc -l 27 | 227 28 | 29 | cat drace_test_results.txt | grep FAIL | grep -v "NOT IMPLEMENTED" | wc -l 30 | 85 31 | 32 | cat drace_test_results.txt | grep FAIL | grep -v "NOT IMPLEMENTED" | grep -v "each of" | wc -l 33 | 63 34 | 35 | 36 | # Drace test results on 2007-12-17. 37 | 38 | cat drace_test_results.txt | grep FAIL | wc -l 39 | 216 40 | 41 | cat drace_test_results.txt | grep FAIL | grep -v "NOT IMPLEMENTED" | wc -l 42 | 88 43 | 44 | cat drace_test_results.txt | grep FAIL | grep -v "NOT IMPLEMENTED" | grep -v "each of" | wc -l 45 | 66 46 | 47 | 48 | # Drace test results on 2008-02-27 49 | 50 | cat drace_test_results.txt | grep FAIL | wc -l 51 | 279 52 | 53 | cat drace_test_results.txt | grep FAIL | grep -v "NOT IMPLEMENTED" | wc -l 54 | 53 55 | 56 | cat drace_test_results.txt | grep FAIL | grep -v "NOT IMPLEMENTED" | grep -v "each of" | wc -l 57 | 53 58 | 59 | 60 | # Core ACE verbalizer test results on 2008-08-19 61 | # (Test case count, FAIL count, buggy paraphrase count.) 62 | 63 | cat drace_test_results.txt | grep "^00" | wc -l 64 | 3094 65 | 66 | cat drace_test_results.txt | grep FAIL | wc -l 67 | 284 68 | 69 | cat drace_test_results.txt | grep FAIL | grep -v "NOT IMPLEMENTED" | wc -l 70 | 46 71 | 72 | 73 | # Core ACE verbalizer test results on 2008-10-07 74 | # (Test case count, FAIL count, buggy paraphrase count.) 75 | 76 | cat drace_test_results.txt | grep "^00" | wc -l 77 | 3135 78 | cat drace_test_results.txt | grep FAIL | wc -l 79 | 270 80 | cat drace_test_results.txt | grep FAIL | grep -v "NOT IMPLEMENTED" | wc -l 81 | 46 82 | 83 | # Core ACE verbalizer test results on 2008-12-04 84 | # (Test case count, FAIL count, buggy paraphrase count.) 85 | 86 | cat drace_test_results.txt | grep "^00" | wc -l 87 | 3151 88 | cat drace_test_results.txt | grep FAIL | wc -l 89 | 256 90 | cat drace_test_results.txt | grep FAIL | grep -v "NOT IMPLEMENTED" | wc -l 91 | 47 92 | -------------------------------------------------------------------------------- /tests/testruns/sum.perl: -------------------------------------------------------------------------------- 1 | my $s = 0; 2 | my $c = 0; 3 | 4 | while() { 5 | $s += $_; 6 | $c++; 7 | } 8 | 9 | print $c, "\t", $s, "\n"; 10 | -------------------------------------------------------------------------------- /tools/create_zip.sh: -------------------------------------------------------------------------------- 1 | # 2 | # Packages the main contents of the repository as a zip-file. 3 | # Includes the jar-file and Javadoc for the Java interface for APE. 4 | # 5 | # Note: For a new release you probably need to update the version number 6 | # in 'ape-6.7'. 7 | # 8 | echo Compiling APE... 9 | cd ../prolog/parser 10 | bash compile.sh 11 | cd ../.. 12 | 13 | echo Building the Java Interface for APE... 14 | cd java 15 | mvn package site -DskipTests 16 | cd .. 17 | 18 | echo "Generating public regression test set..." 19 | cd tests 20 | swipl -f make_acetext_drs.pl -g main -t halt -q > ../acetext_drs.pl 21 | cd .. 22 | 23 | echo Creating ZIP file... 24 | rm ape-*.zip 25 | 26 | timestamp=`date '+%y%m%d'` 27 | 28 | zip -r \ 29 | ape-6.7.$timestamp.zip \ 30 | ape.pl \ 31 | pack.pl \ 32 | CHANGES.md \ 33 | get_ape_results.pl \ 34 | LICENSE.txt \ 35 | make_exe.bat \ 36 | Makefile \ 37 | README.md \ 38 | runape.pl \ 39 | run.sh \ 40 | acetext_drs.pl \ 41 | examples/ \ 42 | java/install-jpl.sh \ 43 | java/pom.xml \ 44 | java/README.md \ 45 | java/src/ \ 46 | java/target/*.jar \ 47 | java/target/site \ 48 | prolog/ape.pl \ 49 | prolog/lexicon/ \ 50 | prolog/logger/ \ 51 | prolog/parser/ \ 52 | prolog/utils/ \ 53 | -x \ 54 | \*.gitignore \*.plp 55 | 56 | rm acetext_drs.pl 57 | 58 | echo Finished. 59 | -------------------------------------------------------------------------------- /tools/extract_words.perl: -------------------------------------------------------------------------------- 1 | 2 | # Extracts words from an ACE text. 3 | 4 | # TODO 5 | # * Show also multi-word units. Useful for detecting repeated phrases. 6 | 7 | use strict; 8 | use warnings; 9 | 10 | $/ = undef; 11 | $_ = ; 12 | 13 | # Remove comments 14 | s{/\*\*[^*]*\*/}{}sg; 15 | s{/\*[^*]*\*/}{}sg; 16 | s{#.*}{}g; 17 | 18 | s{\.}{ \. }g; 19 | s{,}{ , }g; 20 | s{'s}{ 's }g; 21 | s{\s+}{ }g; 22 | s{^\s+}{}; 23 | s{\s+$}{}; 24 | 25 | my @words = split /\s+/; 26 | 27 | my $words = {}; 28 | 29 | foreach (@words) { 30 | $words->{$_}++; 31 | } 32 | 33 | foreach (sort keys %{$words}) { 34 | print $words->{$_}, "\t", $_, "\n"; 35 | } 36 | -------------------------------------------------------------------------------- /tools/search.sh: -------------------------------------------------------------------------------- 1 | # Looks for a certain sequence of characters () from all the 2 | # pl-files in the current directory and its subdirectories. 3 | # @author Kaarel Kaljurand 4 | # @version 2008-04-16 5 | 6 | if [ $# -eq 1 ] 7 | then 8 | find . -name "*.pl" | xargs grep $1 9 | else 10 | echo "Usage: search.sh " 11 | fi 12 | --------------------------------------------------------------------------------