nltk 3.2.1__zip → 3.3__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nltk-3.2.1 → nltk-3.3}/LICENSE.txt +1 -1
- {nltk-3.2.1/nltk.egg-info → nltk-3.3}/PKG-INFO +13 -5
- nltk-3.3/README.md +49 -0
- nltk-3.3/nltk/VERSION +1 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/__init__.py +3 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/app/__init__.py +2 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/app/chartparser_app.py +92 -92
- {nltk-3.2.1 → nltk-3.3}/nltk/app/chunkparser_app.py +11 -13
- {nltk-3.2.1 → nltk-3.3}/nltk/app/collocations_app.py +8 -11
- {nltk-3.2.1 → nltk-3.3}/nltk/app/concordance_app.py +9 -11
- {nltk-3.2.1 → nltk-3.3}/nltk/app/nemo_app.py +18 -17
- {nltk-3.2.1 → nltk-3.3}/nltk/app/rdparser_app.py +10 -12
- {nltk-3.2.1 → nltk-3.3}/nltk/app/srparser_app.py +16 -16
- {nltk-3.2.1 → nltk-3.3}/nltk/app/wordfreq_app.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/app/wordnet_app.py +11 -11
- {nltk-3.2.1 → nltk-3.3}/nltk/book.py +2 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/ccg/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/ccg/api.py +67 -47
- {nltk-3.2.1 → nltk-3.3}/nltk/ccg/chart.py +7 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/ccg/combinator.py +42 -11
- {nltk-3.2.1 → nltk-3.3}/nltk/ccg/lexicon.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/ccg/logic.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/chat/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/chat/eliza.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/chat/iesha.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/chat/rude.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/chat/suntsu.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/chat/util.py +12 -10
- {nltk-3.2.1 → nltk-3.3}/nltk/chat/zen.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/chunk/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/chunk/api.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/chunk/named_entity.py +13 -13
- {nltk-3.2.1 → nltk-3.3}/nltk/chunk/regexp.py +9 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/chunk/util.py +12 -12
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/api.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/decisiontree.py +18 -18
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/maxent.py +26 -8
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/megam.py +5 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/naivebayes.py +29 -26
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/rte_classify.py +58 -89
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/scikitlearn.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/senna.py +24 -22
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/svm.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/tadm.py +4 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/textcat.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/util.py +13 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/weka.py +7 -6
- {nltk-3.2.1 → nltk-3.3}/nltk/cluster/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/cluster/api.py +9 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/cluster/em.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/cluster/gaac.py +3 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/cluster/kmeans.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/cluster/util.py +35 -20
- nltk-3.3/nltk/collections.py +640 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/collocations.py +2 -2
- nltk-3.3/nltk/compat.py +365 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/__init__.py +37 -16
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/europarl_raw.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/__init__.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/aligned.py +4 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/api.py +12 -10
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/bnc.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/bracket_parse.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/categorized_sents.py +4 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/chasen.py +5 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/childes.py +8 -9
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/chunked.py +4 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/cmudict.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/comparative_sents.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/conll.py +19 -12
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/crubadan.py +2 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/dependency.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/framenet.py +1085 -119
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/ieer.py +4 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/indian.py +4 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/ipipan.py +6 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/knbc.py +2 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/lin.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/mte.py +5 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/nkjp.py +4 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/nombank.py +8 -8
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/nps_chat.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/opinion_lexicon.py +3 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/panlex_lite.py +1 -1
- nltk-3.3/nltk/corpus/reader/pl196x.py +292 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/plaintext.py +3 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/ppattach.py +4 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/propbank.py +8 -10
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/pros_cons.py +5 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/reviews.py +3 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/rte.py +5 -7
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/semcor.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/senseval.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/sentiwordnet.py +3 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/sinica_treebank.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/string_category.py +4 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/switchboard.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/tagged.py +4 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/timit.py +10 -8
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/toolbox.py +4 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/twitter.py +4 -6
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/util.py +7 -3
- nltk-3.3/nltk/corpus/reader/verbnet.py +595 -0
- nltk-3.3/nltk/corpus/reader/wordlist.py +134 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/wordnet.py +357 -285
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/xmldocs.py +10 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/ycoe.py +25 -24
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/util.py +22 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/data.py +65 -29
- {nltk-3.2.1 → nltk-3.3}/nltk/decorators.py +5 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/downloader.py +59 -55
- {nltk-3.2.1 → nltk-3.3}/nltk/draw/__init__.py +4 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/draw/cfg.py +5 -8
- {nltk-3.2.1 → nltk-3.3}/nltk/draw/dispersion.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/draw/table.py +4 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/draw/tree.py +2 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/draw/util.py +17 -17
- {nltk-3.2.1 → nltk-3.3}/nltk/featstruct.py +290 -173
- {nltk-3.2.1 → nltk-3.3}/nltk/grammar.py +87 -44
- {nltk-3.2.1 → nltk-3.3}/nltk/help.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/inference/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/inference/api.py +27 -19
- {nltk-3.2.1 → nltk-3.3}/nltk/inference/discourse.py +20 -16
- {nltk-3.2.1 → nltk-3.3}/nltk/inference/nonmonotonic.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/inference/prover9.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/inference/resolution.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/inference/tableau.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/internals.py +44 -44
- {nltk-3.2.1 → nltk-3.3}/nltk/jsontags.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/metrics/__init__.py +2 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/metrics/agreement.py +29 -9
- nltk-3.3/nltk/metrics/aline.py +607 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/metrics/association.py +8 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/metrics/confusionmatrix.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/metrics/distance.py +12 -7
- {nltk-3.2.1 → nltk-3.3}/nltk/metrics/paice.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/metrics/scores.py +7 -7
- {nltk-3.2.1 → nltk-3.3}/nltk/metrics/segmentation.py +4 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/metrics/spearman.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/misc/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/misc/chomsky.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/misc/minimalset.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/misc/sort.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/misc/wordfinder.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/__init__.py +2 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/api.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/bllip.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/chart.py +8 -7
- nltk-3.3/nltk/parse/corenlp.py +780 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/dependencygraph.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/earleychart.py +4 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/evaluate.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/featurechart.py +6 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/generate.py +15 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/malt.py +2 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/nonprojectivedependencyparser.py +3 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/pchart.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/projectivedependencyparser.py +6 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/recursivedescent.py +2 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/shiftreduce.py +2 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/stanford.py +53 -28
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/transitionparser.py +11 -9
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/util.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/parse/viterbi.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/probability.py +75 -20
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/boxer.py +15 -15
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/chat80.py +6 -6
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/cooper_storage.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/drt.py +9 -8
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/drt_glue_demo.py +5 -9
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/evaluate.py +9 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/glue.py +8 -6
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/hole.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/lfg.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/linearlogic.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/logic.py +14 -14
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/relextract.py +11 -18
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/skolemize.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/sem/util.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/sentiment/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/sentiment/sentiment_analyzer.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/sentiment/util.py +14 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/sentiment/vader.py +41 -42
- {nltk-3.2.1 → nltk-3.3}/nltk/stem/__init__.py +1 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/stem/api.py +7 -4
- nltk-3.3/nltk/stem/arlstem.py +369 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/stem/isri.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/stem/lancaster.py +39 -12
- nltk-3.3/nltk/stem/porter.py +710 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/stem/regexp.py +2 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/stem/rslp.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/stem/snowball.py +537 -13
- {nltk-3.2.1 → nltk-3.3}/nltk/stem/util.py +11 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/stem/wordnet.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/__init__.py +32 -7
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/api.py +13 -8
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/brill.py +4 -6
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/crf.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/hmm.py +11 -11
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/hunpos.py +4 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/mapping.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/perceptron.py +25 -10
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/senna.py +25 -23
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/sequential.py +19 -15
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/stanford.py +59 -36
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/tnt.py +11 -20
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/util.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/tbl/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/tbl/demo.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/tbl/erroranalysis.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/tbl/feature.py +5 -7
- {nltk-3.2.1 → nltk-3.3}/nltk/tbl/rule.py +6 -6
- {nltk-3.2.1 → nltk-3.3}/nltk/tbl/template.py +18 -23
- {nltk-3.2.1 → nltk-3.3}/nltk/test/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/all.py +7 -6
- {nltk-3.2.1 → nltk-3.3}/nltk/test/bnc.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/ccg.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/ccg_semantics.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/chat80.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/childes_fixt.py +1 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/chunk.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/classify.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/classify_fixt.py +2 -1
- nltk-3.3/nltk/test/collections.doctest +20 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/collocations.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/compat.doctest +0 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/test/compat_fixt.py +1 -0
- nltk-3.3/nltk/test/concordance.doctest +55 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/corpus.doctest +38 -49
- {nltk-3.2.1 → nltk-3.3}/nltk/test/crubadan.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/data.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/dependency.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/discourse.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/discourse_fixt.py +1 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/doctest_nose_plugin.py +8 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/test/drt.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/featgram.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/featstruct.doctest +2 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/test/framenet.doctest +82 -33
- {nltk-3.2.1 → nltk-3.3}/nltk/test/generate.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/gensim.doctest +6 -7
- {nltk-3.2.1 → nltk-3.3}/nltk/test/gensim_fixt.py +1 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/gluesemantics.doctest +13 -15
- {nltk-3.2.1 → nltk-3.3}/nltk/test/gluesemantics_malt.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/gluesemantics_malt_fixt.py +1 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/grammar.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/grammartestsuites.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/index.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/inference.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/inference_fixt.py +1 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/internals.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/japanese.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/logic.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/metrics.doctest +3 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/test/misc.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/nonmonotonic.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/nonmonotonic_fixt.py +1 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/parse.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/portuguese_en.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/probability.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/probability_fixt.py +2 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/propbank.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/relextract.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/resolution.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/runtests.py +35 -13
- {nltk-3.2.1 → nltk-3.3}/nltk/test/semantics.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/sentiment.doctest +3 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/test/sentiwordnet.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/simple.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/stem.doctest +2 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/test/tag.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/tokenize.doctest +109 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/test/toolbox.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/translate.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/tree.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/treeprettyprinter.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/treetransforms.doctest +1 -1
- nltk-3.3/nltk/test/unit/test_aline.py +52 -0
- nltk-3.3/nltk/test/unit/test_chunk.py +56 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_classify.py +20 -18
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_collocations.py +16 -7
- nltk-3.3/nltk/test/unit/test_concordance.py +98 -0
- nltk-3.3/nltk/test/unit/test_corenlp.py +1000 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_corpora.py +18 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_json2csv_corpus.py +4 -3
- nltk-3.3/nltk/test/unit/test_rte_classify.py +86 -0
- nltk-3.3/nltk/test/unit/test_senna.py +74 -0
- nltk-3.3/nltk/test/unit/test_stem.py +121 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_tgrep.py +4 -2
- nltk-3.3/nltk/test/unit/test_tokenize.py +168 -0
- nltk-3.3/nltk/test/unit/test_wordnet.py +134 -0
- nltk-3.3/nltk/test/unit/translate/test_bleu.py +244 -0
- nltk-3.3/nltk/test/unit/translate/test_gdfa.py +57 -0
- nltk-3.3/nltk/test/unit/translate/test_nist.py +37 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_stack_decoder.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/util.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/wordnet.doctest +17 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/test/wordnet_fixt.py +1 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/wordnet_lch.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/test/wsd.doctest +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/text.py +92 -39
- {nltk-3.2.1 → nltk-3.3}/nltk/tgrep.py +8 -7
- {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/__init__.py +37 -15
- {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/api.py +3 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/casual.py +10 -9
- {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/mwe.py +2 -2
- nltk-3.3/nltk/tokenize/nist.py +173 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/punkt.py +186 -167
- {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/regexp.py +13 -7
- nltk-3.3/nltk/tokenize/repp.py +151 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/sexpr.py +4 -6
- {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/simple.py +7 -5
- {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/stanford.py +18 -14
- nltk-3.3/nltk/tokenize/stanford_segmenter.py +246 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/tokenize/texttiling.py +43 -45
- nltk-3.3/nltk/tokenize/toktok.py +155 -0
- nltk-3.3/nltk/tokenize/treebank.py +363 -0
- nltk-3.3/nltk/tokenize/util.py +261 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/toolbox.py +4 -2
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/api.py +50 -40
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/bleu_score.py +221 -156
- nltk-3.3/nltk/translate/chrf_score.py +137 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/gale_church.py +32 -19
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/gdfa.py +14 -10
- nltk-3.3/nltk/translate/gleu_score.py +193 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm1.py +17 -8
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm2.py +4 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm4.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm5.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm_model.py +4 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/metrics.py +1 -1
- nltk-3.3/nltk/translate/nist_score.py +178 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/phrase_based.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/ribes_score.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/stack_decoder.py +5 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/tree.py +10 -8
- {nltk-3.2.1 → nltk-3.3}/nltk/treeprettyprinter.py +6 -6
- {nltk-3.2.1 → nltk-3.3}/nltk/twitter/__init__.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/twitter/api.py +8 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/twitter/common.py +9 -3
- {nltk-3.2.1 → nltk-3.3}/nltk/twitter/twitter_demo.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/twitter/twitterclient.py +1 -1
- {nltk-3.2.1 → nltk-3.3}/nltk/twitter/util.py +5 -4
- {nltk-3.2.1 → nltk-3.3}/nltk/util.py +41 -654
- {nltk-3.2.1 → nltk-3.3}/nltk/wsd.py +2 -2
- {nltk-3.2.1 → nltk-3.3/nltk.egg-info}/PKG-INFO +13 -5
- {nltk-3.2.1 → nltk-3.3}/nltk.egg-info/SOURCES.txt +23 -1
- nltk-3.3/nltk.egg-info/requires.txt +31 -0
- {nltk-3.2.1 → nltk-3.3}/setup.cfg +0 -1
- {nltk-3.2.1 → nltk-3.3}/setup.py +32 -5
- nltk-3.2.1/nltk/VERSION +0 -1
- nltk-3.2.1/nltk/compat.py +0 -706
- nltk-3.2.1/nltk/corpus/reader/pl196x.py +0 -278
- nltk-3.2.1/nltk/corpus/reader/verbnet.py +0 -408
- nltk-3.2.1/nltk/corpus/reader/wordlist.py +0 -37
- nltk-3.2.1/nltk/six.py +0 -868
- nltk-3.2.1/nltk/stem/porter.py +0 -692
- nltk-3.2.1/nltk/test/unit/test_stem.py +0 -36
- nltk-3.2.1/nltk/test/unit/test_tokenize.py +0 -23
- nltk-3.2.1/nltk/test/unit/translate/test_bleu.py +0 -138
- nltk-3.2.1/nltk/tokenize/stanford_segmenter.py +0 -157
- nltk-3.2.1/nltk/tokenize/treebank.py +0 -124
- nltk-3.2.1/nltk/tokenize/util.py +0 -90
- {nltk-3.2.1 → nltk-3.3}/INSTALL.txt +0 -0
- {nltk-3.2.1 → nltk-3.3}/MANIFEST.in +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/classify/positivenaivebayes.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/corpus/reader/udhr.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/inference/mace.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/lazyimport.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/misc/babelfish.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/tag/brill_trainer.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/tbl/api.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/bleu.doctest +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/childes.doctest +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/corpus_fixt.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/paice.doctest +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/portuguese_en_fixt.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/segmentation_fixt.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/semantics_fixt.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/translate_fixt.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/__init__.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_2x_compat.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_corpus_views.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_hmm.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_naivebayes.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_seekable_unicode_stream_reader.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_tag.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/test_twitter_auth.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/__init__.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm1.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm2.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm3.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm4.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm5.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/translate/test_ibm_model.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/test/unit/utils.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/translate/ibm3.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk/treetransforms.py +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk.egg-info/dependency_links.txt +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk.egg-info/not-zip-safe +0 -0
- {nltk-3.2.1 → nltk-3.3}/nltk.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Natural Language Toolkit: Feature Structures
|
|
2
2
|
#
|
|
3
|
-
# Copyright (C) 2001-
|
|
3
|
+
# Copyright (C) 2001-2018 NLTK Project
|
|
4
4
|
# Author: Edward Loper <edloper@gmail.com>,
|
|
5
5
|
# Rob Speer,
|
|
6
6
|
# Steven Bird <stevenbird1@gmail.com>
|
|
@@ -92,12 +92,15 @@ from __future__ import print_function, unicode_literals, division
|
|
|
92
92
|
|
|
93
93
|
import re
|
|
94
94
|
import copy
|
|
95
|
+
from functools import total_ordering
|
|
96
|
+
|
|
97
|
+
from six import integer_types, string_types
|
|
95
98
|
|
|
96
99
|
from nltk.internals import read_str, raise_unorderable_types
|
|
97
100
|
from nltk.sem.logic import (Variable, Expression, SubstituteBindingsI,
|
|
98
101
|
LogicParser, LogicalExpressionException)
|
|
99
|
-
from nltk.compat import
|
|
100
|
-
|
|
102
|
+
from nltk.compat import python_2_unicode_compatible, unicode_repr
|
|
103
|
+
|
|
101
104
|
|
|
102
105
|
######################################################################
|
|
103
106
|
# Feature Structure
|
|
@@ -144,7 +147,7 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
144
147
|
feature structue."""
|
|
145
148
|
|
|
146
149
|
##////////////////////////////////////////////////////////////
|
|
147
|
-
#{ Constructor
|
|
150
|
+
# { Constructor
|
|
148
151
|
##////////////////////////////////////////////////////////////
|
|
149
152
|
|
|
150
153
|
def __new__(cls, features=None, **morefeatures):
|
|
@@ -191,7 +194,7 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
191
194
|
**morefeatures)
|
|
192
195
|
|
|
193
196
|
##////////////////////////////////////////////////////////////
|
|
194
|
-
#{ Uniform Accessor Methods
|
|
197
|
+
# { Uniform Accessor Methods
|
|
195
198
|
##////////////////////////////////////////////////////////////
|
|
196
199
|
# These helper functions allow the methods defined by FeatStruct
|
|
197
200
|
# to treat all feature structures as mappings, even if they're
|
|
@@ -200,21 +203,21 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
200
203
|
def _keys(self):
|
|
201
204
|
"""Return an iterable of the feature identifiers used by this
|
|
202
205
|
FeatStruct."""
|
|
203
|
-
raise NotImplementedError()
|
|
206
|
+
raise NotImplementedError() # Implemented by subclasses.
|
|
204
207
|
|
|
205
208
|
def _values(self):
|
|
206
209
|
"""Return an iterable of the feature values directly defined
|
|
207
210
|
by this FeatStruct."""
|
|
208
|
-
raise NotImplementedError()
|
|
211
|
+
raise NotImplementedError() # Implemented by subclasses.
|
|
209
212
|
|
|
210
213
|
def _items(self):
|
|
211
214
|
"""Return an iterable of (fid,fval) pairs, where fid is a
|
|
212
215
|
feature identifier and fval is the corresponding feature
|
|
213
216
|
value, for all features defined by this FeatStruct."""
|
|
214
|
-
raise NotImplementedError()
|
|
217
|
+
raise NotImplementedError() # Implemented by subclasses.
|
|
215
218
|
|
|
216
219
|
##////////////////////////////////////////////////////////////
|
|
217
|
-
#{ Equality & Hashing
|
|
220
|
+
# { Equality & Hashing
|
|
218
221
|
##////////////////////////////////////////////////////////////
|
|
219
222
|
|
|
220
223
|
def equal_values(self, other, check_reentrance=False):
|
|
@@ -264,7 +267,8 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
264
267
|
if not self._frozen:
|
|
265
268
|
raise TypeError('FeatStructs must be frozen before they '
|
|
266
269
|
'can be hashed.')
|
|
267
|
-
try:
|
|
270
|
+
try:
|
|
271
|
+
return self._hash
|
|
268
272
|
except AttributeError:
|
|
269
273
|
self._hash = self._calculate_hashvalue(set())
|
|
270
274
|
return self._hash
|
|
@@ -313,7 +317,7 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
313
317
|
# Keep track of which nodes we've visited.
|
|
314
318
|
visited_self.add(id(self))
|
|
315
319
|
visited_other.add(id(other))
|
|
316
|
-
visited_pairs.add(
|
|
320
|
+
visited_pairs.add((id(self), id(other)))
|
|
317
321
|
|
|
318
322
|
# Now we have to check all values. If any of them don't match,
|
|
319
323
|
# then return false.
|
|
@@ -355,7 +359,7 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
355
359
|
return hashval
|
|
356
360
|
|
|
357
361
|
##////////////////////////////////////////////////////////////
|
|
358
|
-
#{ Freezing
|
|
362
|
+
# { Freezing
|
|
359
363
|
##////////////////////////////////////////////////////////////
|
|
360
364
|
|
|
361
365
|
#: Error message used by mutating methods when called on a frozen
|
|
@@ -397,7 +401,7 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
397
401
|
fval._freeze(visited)
|
|
398
402
|
|
|
399
403
|
##////////////////////////////////////////////////////////////
|
|
400
|
-
#{ Copying
|
|
404
|
+
# { Copying
|
|
401
405
|
##////////////////////////////////////////////////////////////
|
|
402
406
|
|
|
403
407
|
def copy(self, deep=True):
|
|
@@ -415,10 +419,10 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
415
419
|
# Subclasses should define __deepcopy__ to ensure that the new
|
|
416
420
|
# copy will not be frozen.
|
|
417
421
|
def __deepcopy__(self, memo):
|
|
418
|
-
raise NotImplementedError()
|
|
422
|
+
raise NotImplementedError() # Implemented by subclasses.
|
|
419
423
|
|
|
420
424
|
##////////////////////////////////////////////////////////////
|
|
421
|
-
#{ Structural Information
|
|
425
|
+
# { Structural Information
|
|
422
426
|
##////////////////////////////////////////////////////////////
|
|
423
427
|
|
|
424
428
|
def cyclic(self):
|
|
@@ -443,7 +447,7 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
443
447
|
:param visited: A set containing the ids of all feature
|
|
444
448
|
structures we've already visited while freezing.
|
|
445
449
|
"""
|
|
446
|
-
raise NotImplementedError()
|
|
450
|
+
raise NotImplementedError() # Implemented by subclasses.
|
|
447
451
|
|
|
448
452
|
def _walk(self, visited):
|
|
449
453
|
if id(self) in visited: return
|
|
@@ -478,7 +482,7 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
478
482
|
return reentrances
|
|
479
483
|
|
|
480
484
|
##////////////////////////////////////////////////////////////
|
|
481
|
-
#{ Variables & Bindings
|
|
485
|
+
# { Variables & Bindings
|
|
482
486
|
##////////////////////////////////////////////////////////////
|
|
483
487
|
|
|
484
488
|
def substitute_bindings(self, bindings):
|
|
@@ -507,7 +511,7 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
507
511
|
return remove_variables(self)
|
|
508
512
|
|
|
509
513
|
##////////////////////////////////////////////////////////////
|
|
510
|
-
#{ Unification
|
|
514
|
+
# { Unification
|
|
511
515
|
##////////////////////////////////////////////////////////////
|
|
512
516
|
|
|
513
517
|
def unify(self, other, bindings=None, trace=False,
|
|
@@ -523,7 +527,7 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
523
527
|
return subsumes(self, other)
|
|
524
528
|
|
|
525
529
|
##////////////////////////////////////////////////////////////
|
|
526
|
-
#{ String Representations
|
|
530
|
+
# { String Representations
|
|
527
531
|
##////////////////////////////////////////////////////////////
|
|
528
532
|
|
|
529
533
|
def __repr__(self):
|
|
@@ -547,9 +551,12 @@ class FeatStruct(SubstituteBindingsI):
|
|
|
547
551
|
"""
|
|
548
552
|
raise NotImplementedError()
|
|
549
553
|
|
|
554
|
+
|
|
550
555
|
# Mutation: disable if frozen.
|
|
551
556
|
_FROZEN_ERROR = "Frozen FeatStructs may not be modified."
|
|
552
557
|
_FROZEN_NOTICE = "\n%sIf self is frozen, raise ValueError."
|
|
558
|
+
|
|
559
|
+
|
|
553
560
|
def _check_frozen(method, indent=''):
|
|
554
561
|
"""
|
|
555
562
|
Given a method function, return a new method function that first
|
|
@@ -557,9 +564,13 @@ def _check_frozen(method, indent=''):
|
|
|
557
564
|
with an appropriate message. Otherwise, call the method and return
|
|
558
565
|
its result.
|
|
559
566
|
"""
|
|
567
|
+
|
|
560
568
|
def wrapped(self, *args, **kwargs):
|
|
561
|
-
if self._frozen:
|
|
562
|
-
|
|
569
|
+
if self._frozen:
|
|
570
|
+
raise ValueError(_FROZEN_ERROR)
|
|
571
|
+
else:
|
|
572
|
+
return method(self, *args, **kwargs)
|
|
573
|
+
|
|
563
574
|
wrapped.__name__ = method.__name__
|
|
564
575
|
wrapped.__doc__ = (method.__doc__ or '') + (_FROZEN_NOTICE % indent)
|
|
565
576
|
return wrapped
|
|
@@ -585,6 +596,7 @@ class FeatDict(FeatStruct, dict):
|
|
|
585
596
|
:see: ``FeatStruct`` for information about feature paths, reentrance,
|
|
586
597
|
cyclic feature structures, mutability, freezing, and hashing.
|
|
587
598
|
"""
|
|
599
|
+
|
|
588
600
|
def __init__(self, features=None, **morefeatures):
|
|
589
601
|
"""
|
|
590
602
|
Create a new feature dictionary, with the specified features.
|
|
@@ -608,9 +620,9 @@ class FeatDict(FeatStruct, dict):
|
|
|
608
620
|
# update() checks the types of features.
|
|
609
621
|
self.update(features, **morefeatures)
|
|
610
622
|
|
|
611
|
-
|
|
612
|
-
#{ Dict methods
|
|
613
|
-
|
|
623
|
+
# ////////////////////////////////////////////////////////////
|
|
624
|
+
# { Dict methods
|
|
625
|
+
# ////////////////////////////////////////////////////////////
|
|
614
626
|
_INDEX_ERROR = str("Expected feature name or path. Got %r.")
|
|
615
627
|
|
|
616
628
|
def __getitem__(self, name_or_path):
|
|
@@ -623,7 +635,7 @@ class FeatDict(FeatStruct, dict):
|
|
|
623
635
|
val = self
|
|
624
636
|
for fid in name_or_path:
|
|
625
637
|
if not isinstance(val, FeatStruct):
|
|
626
|
-
raise KeyError
|
|
638
|
+
raise KeyError # path contains base value
|
|
627
639
|
val = val[fid]
|
|
628
640
|
return val
|
|
629
641
|
except (KeyError, IndexError):
|
|
@@ -634,13 +646,17 @@ class FeatDict(FeatStruct, dict):
|
|
|
634
646
|
def get(self, name_or_path, default=None):
|
|
635
647
|
"""If the feature with the given name or path exists, return its
|
|
636
648
|
value; otherwise, return ``default``."""
|
|
637
|
-
try:
|
|
638
|
-
|
|
649
|
+
try:
|
|
650
|
+
return self[name_or_path]
|
|
651
|
+
except KeyError:
|
|
652
|
+
return default
|
|
639
653
|
|
|
640
654
|
def __contains__(self, name_or_path):
|
|
641
655
|
"""Return true if a feature with the given name or path exists."""
|
|
642
|
-
try:
|
|
643
|
-
|
|
656
|
+
try:
|
|
657
|
+
self[name_or_path]; return True
|
|
658
|
+
except KeyError:
|
|
659
|
+
return False
|
|
644
660
|
|
|
645
661
|
def has_key(self, name_or_path):
|
|
646
662
|
"""Return true if a feature with the given name or path exists."""
|
|
@@ -658,7 +674,7 @@ class FeatDict(FeatStruct, dict):
|
|
|
658
674
|
else:
|
|
659
675
|
parent = self[name_or_path[:-1]]
|
|
660
676
|
if not isinstance(parent, FeatStruct):
|
|
661
|
-
raise KeyError(name_or_path)
|
|
677
|
+
raise KeyError(name_or_path) # path contains base value
|
|
662
678
|
del parent[name_or_path[-1]]
|
|
663
679
|
else:
|
|
664
680
|
raise TypeError(self._INDEX_ERROR % name_or_path)
|
|
@@ -676,7 +692,7 @@ class FeatDict(FeatStruct, dict):
|
|
|
676
692
|
else:
|
|
677
693
|
parent = self[name_or_path[:-1]]
|
|
678
694
|
if not isinstance(parent, FeatStruct):
|
|
679
|
-
raise KeyError(name_or_path)
|
|
695
|
+
raise KeyError(name_or_path) # path contains base value
|
|
680
696
|
parent[name_or_path[-1]] = value
|
|
681
697
|
else:
|
|
682
698
|
raise TypeError(self._INDEX_ERROR % name_or_path)
|
|
@@ -707,25 +723,30 @@ class FeatDict(FeatStruct, dict):
|
|
|
707
723
|
self[key] = val
|
|
708
724
|
|
|
709
725
|
##////////////////////////////////////////////////////////////
|
|
710
|
-
#{ Copying
|
|
726
|
+
# { Copying
|
|
711
727
|
##////////////////////////////////////////////////////////////
|
|
712
728
|
|
|
713
729
|
def __deepcopy__(self, memo):
|
|
714
730
|
memo[id(self)] = selfcopy = self.__class__()
|
|
715
731
|
for (key, val) in self._items():
|
|
716
|
-
selfcopy[copy.deepcopy(key,memo)] = copy.deepcopy(val,memo)
|
|
732
|
+
selfcopy[copy.deepcopy(key, memo)] = copy.deepcopy(val, memo)
|
|
717
733
|
return selfcopy
|
|
718
734
|
|
|
719
735
|
##////////////////////////////////////////////////////////////
|
|
720
|
-
#{ Uniform Accessor Methods
|
|
736
|
+
# { Uniform Accessor Methods
|
|
721
737
|
##////////////////////////////////////////////////////////////
|
|
722
738
|
|
|
723
|
-
def _keys(self):
|
|
724
|
-
|
|
725
|
-
|
|
739
|
+
def _keys(self):
|
|
740
|
+
return self.keys()
|
|
741
|
+
|
|
742
|
+
def _values(self):
|
|
743
|
+
return self.values()
|
|
744
|
+
|
|
745
|
+
def _items(self):
|
|
746
|
+
return self.items()
|
|
726
747
|
|
|
727
748
|
##////////////////////////////////////////////////////////////
|
|
728
|
-
#{ String Representations
|
|
749
|
+
# { String Representations
|
|
729
750
|
##////////////////////////////////////////////////////////////
|
|
730
751
|
|
|
731
752
|
def __str__(self):
|
|
@@ -744,7 +765,7 @@ class FeatDict(FeatStruct, dict):
|
|
|
744
765
|
# then assign it a unique identifier.
|
|
745
766
|
if reentrances[id(self)]:
|
|
746
767
|
assert id(self) not in reentrance_ids
|
|
747
|
-
reentrance_ids[id(self)] = repr(len(reentrance_ids)+1)
|
|
768
|
+
reentrance_ids[id(self)] = repr(len(reentrance_ids) + 1)
|
|
748
769
|
|
|
749
770
|
# sorting note: keys are unique strings, so we'll never fall
|
|
750
771
|
# through to comparing values.
|
|
@@ -755,7 +776,7 @@ class FeatDict(FeatStruct, dict):
|
|
|
755
776
|
(fname, reentrance_ids[id(fval)]))
|
|
756
777
|
elif (display == 'prefix' and not prefix and
|
|
757
778
|
isinstance(fval, (Variable, string_types))):
|
|
758
|
-
|
|
779
|
+
prefix = '%s' % fval
|
|
759
780
|
elif display == 'slash' and not suffix:
|
|
760
781
|
if isinstance(fval, Variable):
|
|
761
782
|
suffix = '/%s' % fval.name
|
|
@@ -796,7 +817,7 @@ class FeatDict(FeatStruct, dict):
|
|
|
796
817
|
# then tack on an id string.
|
|
797
818
|
if reentrances[id(self)]:
|
|
798
819
|
assert id(self) not in reentrance_ids
|
|
799
|
-
reentrance_ids[id(self)] = repr(len(reentrance_ids)+1)
|
|
820
|
+
reentrance_ids[id(self)] = repr(len(reentrance_ids) + 1)
|
|
800
821
|
|
|
801
822
|
# Special case: empty feature dict.
|
|
802
823
|
if len(self) == 0:
|
|
@@ -814,7 +835,7 @@ class FeatDict(FeatStruct, dict):
|
|
|
814
835
|
for (fname, fval) in sorted(self.items()):
|
|
815
836
|
fname = ("%s" % fname).ljust(maxfnamelen)
|
|
816
837
|
if isinstance(fval, Variable):
|
|
817
|
-
lines.append('%s = %s' % (fname,fval.name))
|
|
838
|
+
lines.append('%s = %s' % (fname, fval.name))
|
|
818
839
|
|
|
819
840
|
elif isinstance(fval, Expression):
|
|
820
841
|
lines.append('%s = <%s>' % (fname, fval))
|
|
@@ -841,12 +862,12 @@ class FeatDict(FeatStruct, dict):
|
|
|
841
862
|
fval_lines = fval._str(reentrances, reentrance_ids)
|
|
842
863
|
|
|
843
864
|
# Indent each line to make room for fname.
|
|
844
|
-
fval_lines = [(' '*(maxfnamelen+3))+l for l in fval_lines]
|
|
865
|
+
fval_lines = [(' ' * (maxfnamelen + 3)) + l for l in fval_lines]
|
|
845
866
|
|
|
846
867
|
# Pick which line we'll display fname on, & splice it in.
|
|
847
|
-
nameline = (len(fval_lines)-1) // 2
|
|
868
|
+
nameline = (len(fval_lines) - 1) // 2
|
|
848
869
|
fval_lines[nameline] = (
|
|
849
|
-
fname+' ='+fval_lines[nameline][maxfnamelen+2:])
|
|
870
|
+
fname + ' =' + fval_lines[nameline][maxfnamelen + 2:])
|
|
850
871
|
|
|
851
872
|
# Add the feature structure to the output.
|
|
852
873
|
lines += fval_lines
|
|
@@ -859,13 +880,13 @@ class FeatDict(FeatStruct, dict):
|
|
|
859
880
|
|
|
860
881
|
# Add brackets around everything.
|
|
861
882
|
maxlen = max(len(line) for line in lines)
|
|
862
|
-
lines = ['[ %s%s ]' % (line, ' '*(maxlen-len(line))) for line in lines]
|
|
883
|
+
lines = ['[ %s%s ]' % (line, ' ' * (maxlen - len(line))) for line in lines]
|
|
863
884
|
|
|
864
885
|
# If it's reentrant, then add on an identifier tag.
|
|
865
886
|
if reentrances[id(self)]:
|
|
866
887
|
idstr = '(%s) ' % reentrance_ids[id(self)]
|
|
867
|
-
lines = [(' '*len(idstr))+l for l in lines]
|
|
868
|
-
idline = (len(lines)-1) // 2
|
|
888
|
+
lines = [(' ' * len(idstr)) + l for l in lines]
|
|
889
|
+
idline = (len(lines) - 1) // 2
|
|
869
890
|
lines[idline] = idstr + lines[idline][len(idstr):]
|
|
870
891
|
|
|
871
892
|
return lines
|
|
@@ -891,6 +912,7 @@ class FeatList(FeatStruct, list):
|
|
|
891
912
|
:see: ``FeatStruct`` for information about feature paths, reentrance,
|
|
892
913
|
cyclic feature structures, mutability, freezing, and hashing.
|
|
893
914
|
"""
|
|
915
|
+
|
|
894
916
|
def __init__(self, features=()):
|
|
895
917
|
"""
|
|
896
918
|
Create a new feature list, with the specified features.
|
|
@@ -905,9 +927,9 @@ class FeatList(FeatStruct, list):
|
|
|
905
927
|
else:
|
|
906
928
|
list.__init__(self, features)
|
|
907
929
|
|
|
908
|
-
|
|
909
|
-
#{ List methods
|
|
910
|
-
|
|
930
|
+
# ////////////////////////////////////////////////////////////
|
|
931
|
+
# { List methods
|
|
932
|
+
# ////////////////////////////////////////////////////////////
|
|
911
933
|
_INDEX_ERROR = "Expected int or feature path. Got %r."
|
|
912
934
|
|
|
913
935
|
def __getitem__(self, name_or_path):
|
|
@@ -918,7 +940,7 @@ class FeatList(FeatStruct, list):
|
|
|
918
940
|
val = self
|
|
919
941
|
for fid in name_or_path:
|
|
920
942
|
if not isinstance(val, FeatStruct):
|
|
921
|
-
raise KeyError
|
|
943
|
+
raise KeyError # path contains base value
|
|
922
944
|
val = val[fid]
|
|
923
945
|
return val
|
|
924
946
|
except (KeyError, IndexError):
|
|
@@ -938,7 +960,7 @@ class FeatList(FeatStruct, list):
|
|
|
938
960
|
else:
|
|
939
961
|
parent = self[name_or_path[:-1]]
|
|
940
962
|
if not isinstance(parent, FeatStruct):
|
|
941
|
-
raise KeyError(name_or_path)
|
|
963
|
+
raise KeyError(name_or_path) # path contains base value
|
|
942
964
|
del parent[name_or_path[-1]]
|
|
943
965
|
else:
|
|
944
966
|
raise TypeError(self._INDEX_ERROR % name_or_path)
|
|
@@ -956,13 +978,13 @@ class FeatList(FeatStruct, list):
|
|
|
956
978
|
else:
|
|
957
979
|
parent = self[name_or_path[:-1]]
|
|
958
980
|
if not isinstance(parent, FeatStruct):
|
|
959
|
-
raise KeyError(name_or_path)
|
|
981
|
+
raise KeyError(name_or_path) # path contains base value
|
|
960
982
|
parent[name_or_path[-1]] = value
|
|
961
983
|
else:
|
|
962
984
|
raise TypeError(self._INDEX_ERROR % name_or_path)
|
|
963
985
|
|
|
964
|
-
# __delslice__ = _check_frozen(list.__delslice__, ' ')
|
|
965
|
-
# __setslice__ = _check_frozen(list.__setslice__, ' ')
|
|
986
|
+
# __delslice__ = _check_frozen(list.__delslice__, ' ')
|
|
987
|
+
# __setslice__ = _check_frozen(list.__setslice__, ' ')
|
|
966
988
|
__iadd__ = _check_frozen(list.__iadd__)
|
|
967
989
|
__imul__ = _check_frozen(list.__imul__)
|
|
968
990
|
append = _check_frozen(list.append)
|
|
@@ -974,24 +996,29 @@ class FeatList(FeatStruct, list):
|
|
|
974
996
|
sort = _check_frozen(list.sort)
|
|
975
997
|
|
|
976
998
|
##////////////////////////////////////////////////////////////
|
|
977
|
-
#{ Copying
|
|
999
|
+
# { Copying
|
|
978
1000
|
##////////////////////////////////////////////////////////////
|
|
979
1001
|
|
|
980
1002
|
def __deepcopy__(self, memo):
|
|
981
1003
|
memo[id(self)] = selfcopy = self.__class__()
|
|
982
|
-
selfcopy.extend(copy.deepcopy(fval,memo) for fval in self)
|
|
1004
|
+
selfcopy.extend(copy.deepcopy(fval, memo) for fval in self)
|
|
983
1005
|
return selfcopy
|
|
984
1006
|
|
|
985
1007
|
##////////////////////////////////////////////////////////////
|
|
986
|
-
#{ Uniform Accessor Methods
|
|
1008
|
+
# { Uniform Accessor Methods
|
|
987
1009
|
##////////////////////////////////////////////////////////////
|
|
988
1010
|
|
|
989
|
-
def _keys(self):
|
|
990
|
-
|
|
991
|
-
|
|
1011
|
+
def _keys(self):
|
|
1012
|
+
return list(range(len(self)))
|
|
1013
|
+
|
|
1014
|
+
def _values(self):
|
|
1015
|
+
return self
|
|
1016
|
+
|
|
1017
|
+
def _items(self):
|
|
1018
|
+
return enumerate(self)
|
|
992
1019
|
|
|
993
1020
|
##////////////////////////////////////////////////////////////
|
|
994
|
-
#{ String Representations
|
|
1021
|
+
# { String Representations
|
|
995
1022
|
##////////////////////////////////////////////////////////////
|
|
996
1023
|
|
|
997
1024
|
# Special handling for: reentrances, variables, expressions.
|
|
@@ -1000,7 +1027,7 @@ class FeatList(FeatStruct, list):
|
|
|
1000
1027
|
# then assign it a unique identifier.
|
|
1001
1028
|
if reentrances[id(self)]:
|
|
1002
1029
|
assert id(self) not in reentrance_ids
|
|
1003
|
-
reentrance_ids[id(self)] = repr(len(reentrance_ids)+1)
|
|
1030
|
+
reentrance_ids[id(self)] = repr(len(reentrance_ids) + 1)
|
|
1004
1031
|
prefix = '(%s)' % reentrance_ids[id(self)]
|
|
1005
1032
|
else:
|
|
1006
1033
|
prefix = ''
|
|
@@ -1020,6 +1047,7 @@ class FeatList(FeatStruct, list):
|
|
|
1020
1047
|
|
|
1021
1048
|
return '%s[%s]' % (prefix, ', '.join(segments))
|
|
1022
1049
|
|
|
1050
|
+
|
|
1023
1051
|
######################################################################
|
|
1024
1052
|
# Variables & Bindings
|
|
1025
1053
|
######################################################################
|
|
@@ -1040,14 +1068,18 @@ def substitute_bindings(fstruct, bindings, fs_class='default'):
|
|
|
1040
1068
|
_substitute_bindings(fstruct, bindings, fs_class, set())
|
|
1041
1069
|
return fstruct
|
|
1042
1070
|
|
|
1071
|
+
|
|
1043
1072
|
def _substitute_bindings(fstruct, bindings, fs_class, visited):
|
|
1044
1073
|
# Visit each node only once:
|
|
1045
1074
|
if id(fstruct) in visited: return
|
|
1046
1075
|
visited.add(id(fstruct))
|
|
1047
1076
|
|
|
1048
|
-
if _is_mapping(fstruct):
|
|
1049
|
-
|
|
1050
|
-
|
|
1077
|
+
if _is_mapping(fstruct):
|
|
1078
|
+
items = fstruct.items()
|
|
1079
|
+
elif _is_sequence(fstruct):
|
|
1080
|
+
items = enumerate(fstruct)
|
|
1081
|
+
else:
|
|
1082
|
+
raise ValueError('Expected mapping or sequence')
|
|
1051
1083
|
for (fname, fval) in items:
|
|
1052
1084
|
while (isinstance(fval, Variable) and fval in bindings):
|
|
1053
1085
|
fval = fstruct[fname] = bindings[fval]
|
|
@@ -1056,6 +1088,7 @@ def _substitute_bindings(fstruct, bindings, fs_class, visited):
|
|
|
1056
1088
|
elif isinstance(fval, SubstituteBindingsI):
|
|
1057
1089
|
fstruct[fname] = fval.substitute_bindings(bindings)
|
|
1058
1090
|
|
|
1091
|
+
|
|
1059
1092
|
def retract_bindings(fstruct, bindings, fs_class='default'):
|
|
1060
1093
|
"""
|
|
1061
1094
|
Return the feature structure that is obtained by replacing each
|
|
@@ -1071,18 +1104,22 @@ def retract_bindings(fstruct, bindings, fs_class='default'):
|
|
|
1071
1104
|
if fs_class == 'default': fs_class = _default_fs_class(fstruct)
|
|
1072
1105
|
(fstruct, new_bindings) = copy.deepcopy((fstruct, bindings))
|
|
1073
1106
|
bindings.update(new_bindings)
|
|
1074
|
-
inv_bindings = dict((id(val),var) for (var,val) in bindings.items())
|
|
1107
|
+
inv_bindings = dict((id(val), var) for (var, val) in bindings.items())
|
|
1075
1108
|
_retract_bindings(fstruct, inv_bindings, fs_class, set())
|
|
1076
1109
|
return fstruct
|
|
1077
1110
|
|
|
1111
|
+
|
|
1078
1112
|
def _retract_bindings(fstruct, inv_bindings, fs_class, visited):
|
|
1079
1113
|
# Visit each node only once:
|
|
1080
1114
|
if id(fstruct) in visited: return
|
|
1081
1115
|
visited.add(id(fstruct))
|
|
1082
1116
|
|
|
1083
|
-
if _is_mapping(fstruct):
|
|
1084
|
-
|
|
1085
|
-
|
|
1117
|
+
if _is_mapping(fstruct):
|
|
1118
|
+
items = fstruct.items()
|
|
1119
|
+
elif _is_sequence(fstruct):
|
|
1120
|
+
items = enumerate(fstruct)
|
|
1121
|
+
else:
|
|
1122
|
+
raise ValueError('Expected mapping or sequence')
|
|
1086
1123
|
for (fname, fval) in items:
|
|
1087
1124
|
if isinstance(fval, fs_class):
|
|
1088
1125
|
if id(fval) in inv_bindings:
|
|
@@ -1098,13 +1135,17 @@ def find_variables(fstruct, fs_class='default'):
|
|
|
1098
1135
|
if fs_class == 'default': fs_class = _default_fs_class(fstruct)
|
|
1099
1136
|
return _variables(fstruct, set(), fs_class, set())
|
|
1100
1137
|
|
|
1138
|
+
|
|
1101
1139
|
def _variables(fstruct, vars, fs_class, visited):
|
|
1102
1140
|
# Visit each node only once:
|
|
1103
1141
|
if id(fstruct) in visited: return
|
|
1104
1142
|
visited.add(id(fstruct))
|
|
1105
|
-
if _is_mapping(fstruct):
|
|
1106
|
-
|
|
1107
|
-
|
|
1143
|
+
if _is_mapping(fstruct):
|
|
1144
|
+
items = fstruct.items()
|
|
1145
|
+
elif _is_sequence(fstruct):
|
|
1146
|
+
items = enumerate(fstruct)
|
|
1147
|
+
else:
|
|
1148
|
+
raise ValueError('Expected mapping or sequence')
|
|
1108
1149
|
for (fname, fval) in items:
|
|
1109
1150
|
if isinstance(fval, Variable):
|
|
1110
1151
|
vars.add(fval)
|
|
@@ -1114,6 +1155,7 @@ def _variables(fstruct, vars, fs_class, visited):
|
|
|
1114
1155
|
vars.update(fval.variables())
|
|
1115
1156
|
return vars
|
|
1116
1157
|
|
|
1158
|
+
|
|
1117
1159
|
def rename_variables(fstruct, vars=None, used_vars=(), new_vars=None,
|
|
1118
1160
|
fs_class='default'):
|
|
1119
1161
|
"""
|
|
@@ -1161,8 +1203,10 @@ def rename_variables(fstruct, vars=None, used_vars=(), new_vars=None,
|
|
|
1161
1203
|
|
|
1162
1204
|
# Default values:
|
|
1163
1205
|
if new_vars is None: new_vars = {}
|
|
1164
|
-
if vars is None:
|
|
1165
|
-
|
|
1206
|
+
if vars is None:
|
|
1207
|
+
vars = find_variables(fstruct, fs_class)
|
|
1208
|
+
else:
|
|
1209
|
+
vars = set(vars)
|
|
1166
1210
|
|
|
1167
1211
|
# Add our own variables to used_vars.
|
|
1168
1212
|
used_vars = find_variables(fstruct, fs_class).union(used_vars)
|
|
@@ -1171,12 +1215,16 @@ def rename_variables(fstruct, vars=None, used_vars=(), new_vars=None,
|
|
|
1171
1215
|
return _rename_variables(copy.deepcopy(fstruct), vars, used_vars,
|
|
1172
1216
|
new_vars, fs_class, set())
|
|
1173
1217
|
|
|
1218
|
+
|
|
1174
1219
|
def _rename_variables(fstruct, vars, used_vars, new_vars, fs_class, visited):
|
|
1175
1220
|
if id(fstruct) in visited: return
|
|
1176
1221
|
visited.add(id(fstruct))
|
|
1177
|
-
if _is_mapping(fstruct):
|
|
1178
|
-
|
|
1179
|
-
|
|
1222
|
+
if _is_mapping(fstruct):
|
|
1223
|
+
items = fstruct.items()
|
|
1224
|
+
elif _is_sequence(fstruct):
|
|
1225
|
+
items = enumerate(fstruct)
|
|
1226
|
+
else:
|
|
1227
|
+
raise ValueError('Expected mapping or sequence')
|
|
1180
1228
|
for (fname, fval) in items:
|
|
1181
1229
|
if isinstance(fval, Variable):
|
|
1182
1230
|
# If it's in new_vars, then rebind it.
|
|
@@ -1200,12 +1248,14 @@ def _rename_variables(fstruct, vars, used_vars, new_vars, fs_class, visited):
|
|
|
1200
1248
|
fstruct[fname] = fval.substitute_bindings(new_vars)
|
|
1201
1249
|
return fstruct
|
|
1202
1250
|
|
|
1251
|
+
|
|
1203
1252
|
def _rename_variable(var, used_vars):
|
|
1204
1253
|
name, n = re.sub('\d+$', '', var.name), 2
|
|
1205
1254
|
if not name: name = '?'
|
|
1206
1255
|
while Variable('%s%s' % (name, n)) in used_vars: n += 1
|
|
1207
1256
|
return Variable('%s%s' % (name, n))
|
|
1208
1257
|
|
|
1258
|
+
|
|
1209
1259
|
def remove_variables(fstruct, fs_class='default'):
|
|
1210
1260
|
"""
|
|
1211
1261
|
:rtype: FeatStruct
|
|
@@ -1215,6 +1265,7 @@ def remove_variables(fstruct, fs_class='default'):
|
|
|
1215
1265
|
if fs_class == 'default': fs_class = _default_fs_class(fstruct)
|
|
1216
1266
|
return _remove_variables(copy.deepcopy(fstruct), fs_class, set())
|
|
1217
1267
|
|
|
1268
|
+
|
|
1218
1269
|
def _remove_variables(fstruct, fs_class, visited):
|
|
1219
1270
|
if id(fstruct) in visited:
|
|
1220
1271
|
return
|
|
@@ -1244,11 +1295,13 @@ class _UnificationFailure(object):
|
|
|
1244
1295
|
def __repr__(self):
|
|
1245
1296
|
return 'nltk.featstruct.UnificationFailure'
|
|
1246
1297
|
|
|
1298
|
+
|
|
1247
1299
|
UnificationFailure = _UnificationFailure()
|
|
1248
1300
|
"""A unique value used to indicate unification failure. It can be
|
|
1249
1301
|
returned by ``Feature.unify_base_values()`` or by custom ``fail()``
|
|
1250
1302
|
functions to indicate that unificaiton should fail."""
|
|
1251
1303
|
|
|
1304
|
+
|
|
1252
1305
|
# The basic unification algorithm:
|
|
1253
1306
|
# 1. Make copies of self and other (preserving reentrance)
|
|
1254
1307
|
# 2. Destructively unify self and other
|
|
@@ -1331,15 +1384,19 @@ def unify(fstruct1, fstruct2, bindings=None, trace=False,
|
|
|
1331
1384
|
# Do the actual unification. If it fails, return None.
|
|
1332
1385
|
forward = {}
|
|
1333
1386
|
if trace: _trace_unify_start((), fstruct1copy, fstruct2copy)
|
|
1334
|
-
try:
|
|
1335
|
-
|
|
1336
|
-
|
|
1387
|
+
try:
|
|
1388
|
+
result = _destructively_unify(fstruct1copy, fstruct2copy, bindings,
|
|
1389
|
+
forward, trace, fail, fs_class, ())
|
|
1390
|
+
except _UnificationFailureError:
|
|
1391
|
+
return None
|
|
1337
1392
|
|
|
1338
1393
|
# _destructively_unify might return UnificationFailure, e.g. if we
|
|
1339
1394
|
# tried to unify a mapping with a sequence.
|
|
1340
1395
|
if result is UnificationFailure:
|
|
1341
|
-
if fail is None:
|
|
1342
|
-
|
|
1396
|
+
if fail is None:
|
|
1397
|
+
return None
|
|
1398
|
+
else:
|
|
1399
|
+
return fail(fstruct1copy, fstruct2copy, ())
|
|
1343
1400
|
|
|
1344
1401
|
# Replace any feature structure that has a forward pointer
|
|
1345
1402
|
# with the target of its forward pointer.
|
|
@@ -1355,10 +1412,12 @@ def unify(fstruct1, fstruct2, bindings=None, trace=False,
|
|
|
1355
1412
|
if trace: _trace_bindings((), bindings)
|
|
1356
1413
|
return result
|
|
1357
1414
|
|
|
1415
|
+
|
|
1358
1416
|
class _UnificationFailureError(Exception):
|
|
1359
1417
|
"""An exception that is used by ``_destructively_unify`` to abort
|
|
1360
1418
|
unification when a failure is encountered."""
|
|
1361
1419
|
|
|
1420
|
+
|
|
1362
1421
|
def _destructively_unify(fstruct1, fstruct2, bindings, forward,
|
|
1363
1422
|
trace, fail, fs_class, path):
|
|
1364
1423
|
"""
|
|
@@ -1413,11 +1472,11 @@ def _destructively_unify(fstruct1, fstruct2, bindings, forward,
|
|
|
1413
1472
|
if fname in fstruct1:
|
|
1414
1473
|
fstruct1[fname] = _unify_feature_values(
|
|
1415
1474
|
fname, fstruct1[fname], fval2, bindings,
|
|
1416
|
-
forward, trace, fail, fs_class, path+(fname,))
|
|
1475
|
+
forward, trace, fail, fs_class, path + (fname,))
|
|
1417
1476
|
else:
|
|
1418
1477
|
fstruct1[fname] = fval2
|
|
1419
1478
|
|
|
1420
|
-
return fstruct1
|
|
1479
|
+
return fstruct1 # Contains the unified value.
|
|
1421
1480
|
|
|
1422
1481
|
# Unifying two sequences:
|
|
1423
1482
|
elif _is_sequence(fstruct1) and _is_sequence(fstruct2):
|
|
@@ -1429,9 +1488,9 @@ def _destructively_unify(fstruct1, fstruct2, bindings, forward,
|
|
|
1429
1488
|
for findex in range(len(fstruct1)):
|
|
1430
1489
|
fstruct1[findex] = _unify_feature_values(
|
|
1431
1490
|
findex, fstruct1[findex], fstruct2[findex], bindings,
|
|
1432
|
-
forward, trace, fail, fs_class, path+(findex,))
|
|
1491
|
+
forward, trace, fail, fs_class, path + (findex,))
|
|
1433
1492
|
|
|
1434
|
-
return fstruct1
|
|
1493
|
+
return fstruct1 # Contains the unified value.
|
|
1435
1494
|
|
|
1436
1495
|
# Unifying sequence & mapping: fail. The failure function
|
|
1437
1496
|
# doesn't get a chance to recover in this case.
|
|
@@ -1442,6 +1501,7 @@ def _destructively_unify(fstruct1, fstruct2, bindings, forward,
|
|
|
1442
1501
|
# Unifying anything else: not allowed!
|
|
1443
1502
|
raise TypeError('Expected mappings or sequences')
|
|
1444
1503
|
|
|
1504
|
+
|
|
1445
1505
|
def _unify_feature_values(fname, fval1, fval2, bindings, forward,
|
|
1446
1506
|
trace, fail, fs_class, fpath):
|
|
1447
1507
|
"""
|
|
@@ -1511,7 +1571,7 @@ def _unify_feature_values(fname, fval1, fval2, bindings, forward,
|
|
|
1511
1571
|
result = fval1.unify(fval2)
|
|
1512
1572
|
# Sanity check: unify value should be symmetric
|
|
1513
1573
|
if (isinstance(fval2, CustomFeatureValue) and
|
|
1514
|
-
|
|
1574
|
+
result != fval2.unify(fval1)):
|
|
1515
1575
|
raise AssertionError(
|
|
1516
1576
|
'CustomFeatureValue objects %r and %r disagree '
|
|
1517
1577
|
'about unification value: %r vs. %r' %
|
|
@@ -1554,6 +1614,7 @@ def _unify_feature_values(fname, fval1, fval2, bindings, forward,
|
|
|
1554
1614
|
|
|
1555
1615
|
return result
|
|
1556
1616
|
|
|
1617
|
+
|
|
1557
1618
|
def _apply_forwards_to_bindings(forward, bindings):
|
|
1558
1619
|
"""
|
|
1559
1620
|
Replace any feature structure that has a forward pointer with
|
|
@@ -1564,6 +1625,7 @@ def _apply_forwards_to_bindings(forward, bindings):
|
|
|
1564
1625
|
value = forward[id(value)]
|
|
1565
1626
|
bindings[var] = value
|
|
1566
1627
|
|
|
1628
|
+
|
|
1567
1629
|
def _apply_forwards(fstruct, forward, fs_class, visited):
|
|
1568
1630
|
"""
|
|
1569
1631
|
Replace any feature structure that has a forward pointer with
|
|
@@ -1576,9 +1638,12 @@ def _apply_forwards(fstruct, forward, fs_class, visited):
|
|
|
1576
1638
|
if id(fstruct) in visited: return
|
|
1577
1639
|
visited.add(id(fstruct))
|
|
1578
1640
|
|
|
1579
|
-
if _is_mapping(fstruct):
|
|
1580
|
-
|
|
1581
|
-
|
|
1641
|
+
if _is_mapping(fstruct):
|
|
1642
|
+
items = fstruct.items()
|
|
1643
|
+
elif _is_sequence(fstruct):
|
|
1644
|
+
items = enumerate(fstruct)
|
|
1645
|
+
else:
|
|
1646
|
+
raise ValueError('Expected mapping or sequence')
|
|
1582
1647
|
for fname, fval in items:
|
|
1583
1648
|
if isinstance(fval, fs_class):
|
|
1584
1649
|
# Replace w/ forwarded value.
|
|
@@ -1590,6 +1655,7 @@ def _apply_forwards(fstruct, forward, fs_class, visited):
|
|
|
1590
1655
|
|
|
1591
1656
|
return fstruct
|
|
1592
1657
|
|
|
1658
|
+
|
|
1593
1659
|
def _resolve_aliases(bindings):
|
|
1594
1660
|
"""
|
|
1595
1661
|
Replace any bound aliased vars with their binding; and replace
|
|
@@ -1599,43 +1665,57 @@ def _resolve_aliases(bindings):
|
|
|
1599
1665
|
while isinstance(value, Variable) and value in bindings:
|
|
1600
1666
|
value = bindings[var] = bindings[value]
|
|
1601
1667
|
|
|
1668
|
+
|
|
1602
1669
|
def _trace_unify_start(path, fval1, fval2):
|
|
1603
1670
|
if path == ():
|
|
1604
1671
|
print('\nUnification trace:')
|
|
1605
1672
|
else:
|
|
1606
1673
|
fullname = '.'.join("%s" % n for n in path)
|
|
1607
|
-
print(' '+'| '*(len(path)-1)+'|')
|
|
1608
|
-
print(' '+'| '*(len(path)-1)+'| Unify feature: %s' % fullname)
|
|
1609
|
-
print(' '+'| '*len(path)+' / '+_trace_valrepr(fval1))
|
|
1610
|
-
print(' '+'| '*len(path)+'|\\ '+_trace_valrepr(fval2))
|
|
1674
|
+
print(' ' + '| ' * (len(path) - 1) + '|')
|
|
1675
|
+
print(' ' + '| ' * (len(path) - 1) + '| Unify feature: %s' % fullname)
|
|
1676
|
+
print(' ' + '| ' * len(path) + ' / ' + _trace_valrepr(fval1))
|
|
1677
|
+
print(' ' + '| ' * len(path) + '|\\ ' + _trace_valrepr(fval2))
|
|
1678
|
+
|
|
1679
|
+
|
|
1611
1680
|
def _trace_unify_identity(path, fval1):
|
|
1612
|
-
print(' '+'| '*len(path)+'|')
|
|
1613
|
-
print(' '+'| '*len(path)+'| (identical objects)')
|
|
1614
|
-
print(' '+'| '*len(path)+'|')
|
|
1615
|
-
print(' '+'| '*len(path)+'+-->'+unicode_repr(fval1))
|
|
1681
|
+
print(' ' + '| ' * len(path) + '|')
|
|
1682
|
+
print(' ' + '| ' * len(path) + '| (identical objects)')
|
|
1683
|
+
print(' ' + '| ' * len(path) + '|')
|
|
1684
|
+
print(' ' + '| ' * len(path) + '+-->' + unicode_repr(fval1))
|
|
1685
|
+
|
|
1686
|
+
|
|
1616
1687
|
def _trace_unify_fail(path, result):
|
|
1617
|
-
if result is UnificationFailure:
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1688
|
+
if result is UnificationFailure:
|
|
1689
|
+
resume = ''
|
|
1690
|
+
else:
|
|
1691
|
+
resume = ' (nonfatal)'
|
|
1692
|
+
print(' ' + '| ' * len(path) + '| |')
|
|
1693
|
+
print(' ' + 'X ' * len(path) + 'X X <-- FAIL' + resume)
|
|
1694
|
+
|
|
1695
|
+
|
|
1621
1696
|
def _trace_unify_succeed(path, fval1):
|
|
1622
1697
|
# Print the result.
|
|
1623
|
-
print(' '+'| '*len(path)+'|')
|
|
1624
|
-
print(' '+'| '*len(path)+'+-->'+unicode_repr(fval1))
|
|
1698
|
+
print(' ' + '| ' * len(path) + '|')
|
|
1699
|
+
print(' ' + '| ' * len(path) + '+-->' + unicode_repr(fval1))
|
|
1700
|
+
|
|
1701
|
+
|
|
1625
1702
|
def _trace_bindings(path, bindings):
|
|
1626
1703
|
# Print the bindings (if any).
|
|
1627
1704
|
if len(bindings) > 0:
|
|
1628
|
-
binditems = sorted(bindings.items(), key=lambda v:v[0].name)
|
|
1705
|
+
binditems = sorted(bindings.items(), key=lambda v: v[0].name)
|
|
1629
1706
|
bindstr = '{%s}' % ', '.join(
|
|
1630
1707
|
'%s: %s' % (var, _trace_valrepr(val))
|
|
1631
1708
|
for (var, val) in binditems)
|
|
1632
|
-
print(' '+'| '*len(path)+' Bindings: '+bindstr)
|
|
1709
|
+
print(' ' + '| ' * len(path) + ' Bindings: ' + bindstr)
|
|
1710
|
+
|
|
1711
|
+
|
|
1633
1712
|
def _trace_valrepr(val):
|
|
1634
1713
|
if isinstance(val, Variable):
|
|
1635
1714
|
return '%s' % val
|
|
1636
1715
|
else:
|
|
1637
1716
|
return '%s' % unicode_repr(val)
|
|
1638
1717
|
|
|
1718
|
+
|
|
1639
1719
|
def subsumes(fstruct1, fstruct2):
|
|
1640
1720
|
"""
|
|
1641
1721
|
Return True if ``fstruct1`` subsumes ``fstruct2``. I.e., return
|
|
@@ -1646,6 +1726,7 @@ def subsumes(fstruct1, fstruct2):
|
|
|
1646
1726
|
"""
|
|
1647
1727
|
return fstruct2 == unify(fstruct1, fstruct2)
|
|
1648
1728
|
|
|
1729
|
+
|
|
1649
1730
|
def conflicts(fstruct1, fstruct2, trace=0):
|
|
1650
1731
|
"""
|
|
1651
1732
|
Return a list of the feature paths of all features which are
|
|
@@ -1654,12 +1735,15 @@ def conflicts(fstruct1, fstruct2, trace=0):
|
|
|
1654
1735
|
:rtype: list(tuple)
|
|
1655
1736
|
"""
|
|
1656
1737
|
conflict_list = []
|
|
1738
|
+
|
|
1657
1739
|
def add_conflict(fval1, fval2, path):
|
|
1658
1740
|
conflict_list.append(path)
|
|
1659
1741
|
return fval1
|
|
1742
|
+
|
|
1660
1743
|
unify(fstruct1, fstruct2, fail=add_conflict, trace=trace)
|
|
1661
1744
|
return conflict_list
|
|
1662
1745
|
|
|
1746
|
+
|
|
1663
1747
|
######################################################################
|
|
1664
1748
|
# Helper Functions
|
|
1665
1749
|
######################################################################
|
|
@@ -1667,16 +1751,21 @@ def conflicts(fstruct1, fstruct2, trace=0):
|
|
|
1667
1751
|
def _is_mapping(v):
|
|
1668
1752
|
return hasattr(v, '__contains__') and hasattr(v, 'keys')
|
|
1669
1753
|
|
|
1754
|
+
|
|
1670
1755
|
def _is_sequence(v):
|
|
1671
1756
|
return (hasattr(v, '__iter__') and hasattr(v, '__len__') and
|
|
1672
1757
|
not isinstance(v, string_types))
|
|
1673
1758
|
|
|
1759
|
+
|
|
1674
1760
|
def _default_fs_class(obj):
|
|
1675
1761
|
if isinstance(obj, FeatStruct): return FeatStruct
|
|
1676
|
-
if isinstance(obj, (dict, list)):
|
|
1762
|
+
if isinstance(obj, (dict, list)):
|
|
1763
|
+
return (dict, list)
|
|
1677
1764
|
else:
|
|
1678
1765
|
raise ValueError('To unify objects of type %s, you must specify '
|
|
1679
1766
|
'fs_class explicitly.' % obj.__class__.__name__)
|
|
1767
|
+
|
|
1768
|
+
|
|
1680
1769
|
######################################################################
|
|
1681
1770
|
# FeatureValueSet & FeatureValueTuple
|
|
1682
1771
|
######################################################################
|
|
@@ -1686,6 +1775,7 @@ class SubstituteBindingsSequence(SubstituteBindingsI):
|
|
|
1686
1775
|
A mixin class for sequence clases that distributes variables() and
|
|
1687
1776
|
substitute_bindings() over the object's elements.
|
|
1688
1777
|
"""
|
|
1778
|
+
|
|
1689
1779
|
def variables(self):
|
|
1690
1780
|
return ([elt for elt in self if isinstance(elt, Variable)] +
|
|
1691
1781
|
sum([list(elt.variables()) for elt in self
|
|
@@ -1700,6 +1790,7 @@ class SubstituteBindingsSequence(SubstituteBindingsI):
|
|
|
1700
1790
|
else:
|
|
1701
1791
|
return bindings.get(v, v)
|
|
1702
1792
|
|
|
1793
|
+
|
|
1703
1794
|
@python_2_unicode_compatible
|
|
1704
1795
|
class FeatureValueTuple(SubstituteBindingsSequence, tuple):
|
|
1705
1796
|
"""
|
|
@@ -1708,7 +1799,8 @@ class FeatureValueTuple(SubstituteBindingsSequence, tuple):
|
|
|
1708
1799
|
variable substitutions will be propagated to the elements
|
|
1709
1800
|
contained by the set. A ``FeatureValueTuple`` is immutable.
|
|
1710
1801
|
"""
|
|
1711
|
-
|
|
1802
|
+
|
|
1803
|
+
def __repr__(self): # [xx] really use %s here?
|
|
1712
1804
|
if len(self) == 0: return '()'
|
|
1713
1805
|
return '(%s)' % ', '.join('%s' % (b,) for b in self)
|
|
1714
1806
|
|
|
@@ -1721,19 +1813,23 @@ class FeatureValueSet(SubstituteBindingsSequence, frozenset):
|
|
|
1721
1813
|
variable substitutions will be propagated to the elements
|
|
1722
1814
|
contained by the set. A ``FeatureValueSet`` is immutable.
|
|
1723
1815
|
"""
|
|
1724
|
-
|
|
1725
|
-
|
|
1816
|
+
|
|
1817
|
+
def __repr__(self): # [xx] really use %s here?
|
|
1818
|
+
if len(self) == 0: return '{/}' # distinguish from dict.
|
|
1726
1819
|
# n.b., we sort the string reprs of our elements, to ensure
|
|
1727
1820
|
# that our own repr is deterministic.
|
|
1728
1821
|
return '{%s}' % ', '.join(sorted('%s' % (b,) for b in self))
|
|
1822
|
+
|
|
1729
1823
|
__str__ = __repr__
|
|
1730
1824
|
|
|
1825
|
+
|
|
1731
1826
|
@python_2_unicode_compatible
|
|
1732
1827
|
class FeatureValueUnion(SubstituteBindingsSequence, frozenset):
|
|
1733
1828
|
"""
|
|
1734
1829
|
A base feature value that represents the union of two or more
|
|
1735
1830
|
``FeatureValueSet`` or ``Variable``.
|
|
1736
1831
|
"""
|
|
1832
|
+
|
|
1737
1833
|
def __new__(cls, values):
|
|
1738
1834
|
# If values contains FeatureValueUnions, then collapse them.
|
|
1739
1835
|
values = _flatten(values, FeatureValueUnion)
|
|
@@ -1757,12 +1853,14 @@ class FeatureValueUnion(SubstituteBindingsSequence, frozenset):
|
|
|
1757
1853
|
# is guaranteed to be 2 or more.
|
|
1758
1854
|
return '{%s}' % '+'.join(sorted('%s' % (b,) for b in self))
|
|
1759
1855
|
|
|
1856
|
+
|
|
1760
1857
|
@python_2_unicode_compatible
|
|
1761
1858
|
class FeatureValueConcat(SubstituteBindingsSequence, tuple):
|
|
1762
1859
|
"""
|
|
1763
1860
|
A base feature value that represents the concatenation of two or
|
|
1764
1861
|
more ``FeatureValueTuple`` or ``Variable``.
|
|
1765
1862
|
"""
|
|
1863
|
+
|
|
1766
1864
|
def __new__(cls, values):
|
|
1767
1865
|
# If values contains FeatureValueConcats, then collapse them.
|
|
1768
1866
|
values = _flatten(values, FeatureValueConcat)
|
|
@@ -1792,10 +1890,13 @@ def _flatten(lst, cls):
|
|
|
1792
1890
|
"""
|
|
1793
1891
|
result = []
|
|
1794
1892
|
for elt in lst:
|
|
1795
|
-
if isinstance(elt, cls):
|
|
1796
|
-
|
|
1893
|
+
if isinstance(elt, cls):
|
|
1894
|
+
result.extend(elt)
|
|
1895
|
+
else:
|
|
1896
|
+
result.append(elt)
|
|
1797
1897
|
return result
|
|
1798
1898
|
|
|
1899
|
+
|
|
1799
1900
|
######################################################################
|
|
1800
1901
|
# Specialized Features
|
|
1801
1902
|
######################################################################
|
|
@@ -1807,11 +1908,12 @@ class Feature(object):
|
|
|
1807
1908
|
A feature identifier that's specialized to put additional
|
|
1808
1909
|
constraints, default values, etc.
|
|
1809
1910
|
"""
|
|
1911
|
+
|
|
1810
1912
|
def __init__(self, name, default=None, display=None):
|
|
1811
1913
|
assert display in (None, 'prefix', 'slash')
|
|
1812
1914
|
|
|
1813
|
-
self._name = name
|
|
1814
|
-
self._default = default
|
|
1915
|
+
self._name = name # [xx] rename to .identifier?
|
|
1916
|
+
self._default = default # [xx] not implemented yet.
|
|
1815
1917
|
self._display = display
|
|
1816
1918
|
|
|
1817
1919
|
if self._display == 'prefix':
|
|
@@ -1855,9 +1957,9 @@ class Feature(object):
|
|
|
1855
1957
|
def __hash__(self):
|
|
1856
1958
|
return hash(self._name)
|
|
1857
1959
|
|
|
1858
|
-
|
|
1960
|
+
# ////////////////////////////////////////////////////////////
|
|
1859
1961
|
# These can be overridden by subclasses:
|
|
1860
|
-
|
|
1962
|
+
# ////////////////////////////////////////////////////////////
|
|
1861
1963
|
|
|
1862
1964
|
def read_value(self, s, position, reentrances, parser):
|
|
1863
1965
|
return parser.read_value(s, position, reentrances)
|
|
@@ -1867,16 +1969,20 @@ class Feature(object):
|
|
|
1867
1969
|
If possible, return a single value.. If not, return
|
|
1868
1970
|
the value ``UnificationFailure``.
|
|
1869
1971
|
"""
|
|
1870
|
-
if fval1 == fval2:
|
|
1871
|
-
|
|
1972
|
+
if fval1 == fval2:
|
|
1973
|
+
return fval1
|
|
1974
|
+
else:
|
|
1975
|
+
return UnificationFailure
|
|
1872
1976
|
|
|
1873
1977
|
|
|
1874
1978
|
class SlashFeature(Feature):
|
|
1875
1979
|
def read_value(self, s, position, reentrances, parser):
|
|
1876
1980
|
return parser.read_partial(s, position, reentrances)
|
|
1877
1981
|
|
|
1982
|
+
|
|
1878
1983
|
class RangeFeature(Feature):
|
|
1879
1984
|
RANGE_RE = re.compile('(-?\d+):(-?\d+)')
|
|
1985
|
+
|
|
1880
1986
|
def read_value(self, s, position, reentrances, parser):
|
|
1881
1987
|
m = self.RANGE_RE.match(s, position)
|
|
1882
1988
|
if not m: raise ValueError('range', position)
|
|
@@ -1889,9 +1995,11 @@ class RangeFeature(Feature):
|
|
|
1889
1995
|
if rng[1] < rng[0]: return UnificationFailure
|
|
1890
1996
|
return rng
|
|
1891
1997
|
|
|
1998
|
+
|
|
1892
1999
|
SLASH = SlashFeature('slash', default=False, display='slash')
|
|
1893
2000
|
TYPE = Feature('type', display='prefix')
|
|
1894
2001
|
|
|
2002
|
+
|
|
1895
2003
|
######################################################################
|
|
1896
2004
|
# Specialized Feature Values
|
|
1897
2005
|
######################################################################
|
|
@@ -1915,6 +2023,7 @@ class CustomFeatureValue(object):
|
|
|
1915
2023
|
Subclasses must define ``unify()``, ``__eq__()`` and ``__lt__()``.
|
|
1916
2024
|
Subclasses may also wish to define ``__hash__()``.
|
|
1917
2025
|
"""
|
|
2026
|
+
|
|
1918
2027
|
def unify(self, other):
|
|
1919
2028
|
"""
|
|
1920
2029
|
If this base value unifies with ``other``, then return the
|
|
@@ -1934,6 +2043,7 @@ class CustomFeatureValue(object):
|
|
|
1934
2043
|
def __hash__(self):
|
|
1935
2044
|
raise TypeError('%s objects or unhashable' % self.__class__.__name__)
|
|
1936
2045
|
|
|
2046
|
+
|
|
1937
2047
|
######################################################################
|
|
1938
2048
|
# Feature Structure Reader
|
|
1939
2049
|
######################################################################
|
|
@@ -1941,7 +2051,7 @@ class CustomFeatureValue(object):
|
|
|
1941
2051
|
class FeatStructReader(object):
|
|
1942
2052
|
def __init__(self, features=(SLASH, TYPE), fdict_class=FeatStruct,
|
|
1943
2053
|
flist_class=FeatList, logic_parser=None):
|
|
1944
|
-
self._features = dict((f.name,f) for f in features)
|
|
2054
|
+
self._features = dict((f.name, f) for f in features)
|
|
1945
2055
|
self._fdict_class = fdict_class
|
|
1946
2056
|
self._flist_class = flist_class
|
|
1947
2057
|
self._prefix_feature = None
|
|
@@ -2045,14 +2155,14 @@ class FeatStructReader(object):
|
|
|
2045
2155
|
if isinstance(fstruct, FeatDict):
|
|
2046
2156
|
fstruct.clear()
|
|
2047
2157
|
return self._read_partial_featdict(s, position, match,
|
|
2048
|
-
|
|
2158
|
+
reentrances, fstruct)
|
|
2049
2159
|
else:
|
|
2050
2160
|
del fstruct[:]
|
|
2051
2161
|
return self._read_partial_featlist(s, position, match,
|
|
2052
|
-
|
|
2162
|
+
reentrances, fstruct)
|
|
2053
2163
|
|
|
2054
2164
|
def _read_partial_featlist(self, s, position, match,
|
|
2055
|
-
|
|
2165
|
+
reentrances, fstruct):
|
|
2056
2166
|
# Prefix features are not allowed:
|
|
2057
2167
|
if match.group(2): raise ValueError('open bracket')
|
|
2058
2168
|
# Bare prefixes are not allowed:
|
|
@@ -2096,7 +2206,7 @@ class FeatStructReader(object):
|
|
|
2096
2206
|
raise ValueError('close bracket', position)
|
|
2097
2207
|
|
|
2098
2208
|
def _read_partial_featdict(self, s, position, match,
|
|
2099
|
-
|
|
2209
|
+
reentrances, fstruct):
|
|
2100
2210
|
# If there was a prefix feature, record it.
|
|
2101
2211
|
if match.group(2):
|
|
2102
2212
|
if self._prefix_feature is None:
|
|
@@ -2198,7 +2308,7 @@ class FeatStructReader(object):
|
|
|
2198
2308
|
v, pos = self._read_value(name, s, match.end(), reentrances)
|
|
2199
2309
|
fstruct[name] = v
|
|
2200
2310
|
## Add any default features. -- handle in unficiation instead?
|
|
2201
|
-
#for feature in self._features_with_defaults:
|
|
2311
|
+
# for feature in self._features_with_defaults:
|
|
2202
2312
|
# fstruct.setdefault(feature, feature.default)
|
|
2203
2313
|
# Return the value.
|
|
2204
2314
|
return fstruct, pos
|
|
@@ -2220,15 +2330,15 @@ class FeatStructReader(object):
|
|
|
2220
2330
|
def _error(self, s, expected, position):
|
|
2221
2331
|
lines = s.split('\n')
|
|
2222
2332
|
while position > len(lines[0]):
|
|
2223
|
-
position -= len(lines.pop(0))+1
|
|
2333
|
+
position -= len(lines.pop(0)) + 1 # +1 for the newline.
|
|
2224
2334
|
estr = ('Error parsing feature structure\n ' +
|
|
2225
|
-
lines[0] + '\n ' + ' '*position + '^ ' +
|
|
2335
|
+
lines[0] + '\n ' + ' ' * position + '^ ' +
|
|
2226
2336
|
'Expected %s' % expected)
|
|
2227
2337
|
raise ValueError(estr)
|
|
2228
2338
|
|
|
2229
|
-
|
|
2230
|
-
#{ Value Readers
|
|
2231
|
-
|
|
2339
|
+
# ////////////////////////////////////////////////////////////
|
|
2340
|
+
# { Value Readers
|
|
2341
|
+
# ////////////////////////////////////////////////////////////
|
|
2232
2342
|
|
|
2233
2343
|
#: A table indicating how feature values should be processed. Each
|
|
2234
2344
|
#: entry in the table is a pair (handler, regexp). The first entry
|
|
@@ -2247,13 +2357,13 @@ class FeatStructReader(object):
|
|
|
2247
2357
|
('read_int_value', re.compile(r'-?\d+')),
|
|
2248
2358
|
('read_sym_value', re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*')),
|
|
2249
2359
|
('read_app_value', re.compile(r'<(app)\((\?[a-z][a-z]*)\s*,'
|
|
2250
|
-
|
|
2251
|
-
# ('read_logic_value', re.compile(r'<([^>]*)>')),
|
|
2252
|
-
#lazily match any character after '<' until we hit a '>' not preceded by '-'
|
|
2360
|
+
r'\s*(\?[a-z][a-z]*)\)>')),
|
|
2361
|
+
# ('read_logic_value', re.compile(r'<([^>]*)>')),
|
|
2362
|
+
# lazily match any character after '<' until we hit a '>' not preceded by '-'
|
|
2253
2363
|
('read_logic_value', re.compile(r'<(.*?)(?<!-)>')),
|
|
2254
2364
|
('read_set_value', re.compile(r'{')),
|
|
2255
2365
|
('read_tuple_value', re.compile(r'\(')),
|
|
2256
|
-
|
|
2366
|
+
]
|
|
2257
2367
|
|
|
2258
2368
|
def read_fstruct_value(self, s, position, reentrances, match):
|
|
2259
2369
|
return self.read_partial(s, position, reentrances)
|
|
@@ -2268,14 +2378,15 @@ class FeatStructReader(object):
|
|
|
2268
2378
|
def read_var_value(self, s, position, reentrances, match):
|
|
2269
2379
|
return Variable(match.group()), match.end()
|
|
2270
2380
|
|
|
2271
|
-
_SYM_CONSTS = {'None':None, 'True':True, 'False':False}
|
|
2381
|
+
_SYM_CONSTS = {'None': None, 'True': True, 'False': False}
|
|
2382
|
+
|
|
2272
2383
|
def read_sym_value(self, s, position, reentrances, match):
|
|
2273
2384
|
val, end = match.group(), match.end()
|
|
2274
2385
|
return self._SYM_CONSTS.get(val, val), end
|
|
2275
2386
|
|
|
2276
2387
|
def read_app_value(self, s, position, reentrances, match):
|
|
2277
2388
|
"""Mainly included for backwards compat."""
|
|
2278
|
-
return self._logic_parser.parse('%s(%s)' % match.group(2,3)), match.end()
|
|
2389
|
+
return self._logic_parser.parse('%s(%s)' % match.group(2, 3)), match.end()
|
|
2279
2390
|
|
|
2280
2391
|
def read_logic_value(self, s, position, reentrances, match):
|
|
2281
2392
|
try:
|
|
@@ -2289,14 +2400,14 @@ class FeatStructReader(object):
|
|
|
2289
2400
|
|
|
2290
2401
|
def read_tuple_value(self, s, position, reentrances, match):
|
|
2291
2402
|
return self._read_seq_value(s, position, reentrances, match, ')',
|
|
2292
|
-
|
|
2403
|
+
FeatureValueTuple, FeatureValueConcat)
|
|
2293
2404
|
|
|
2294
2405
|
def read_set_value(self, s, position, reentrances, match):
|
|
2295
2406
|
return self._read_seq_value(s, position, reentrances, match, '}',
|
|
2296
|
-
|
|
2407
|
+
FeatureValueSet, FeatureValueUnion)
|
|
2297
2408
|
|
|
2298
2409
|
def _read_seq_value(self, s, position, reentrances, match,
|
|
2299
|
-
|
|
2410
|
+
close_paren, seq_class, plus_class):
|
|
2300
2411
|
"""
|
|
2301
2412
|
Helper function used by read_tuple_value and read_set_value.
|
|
2302
2413
|
"""
|
|
@@ -2312,8 +2423,10 @@ class FeatStructReader(object):
|
|
|
2312
2423
|
# Close paren: return value.
|
|
2313
2424
|
m = re.compile(r'\s*%s' % cp).match(s, position)
|
|
2314
2425
|
if m:
|
|
2315
|
-
if seen_plus:
|
|
2316
|
-
|
|
2426
|
+
if seen_plus:
|
|
2427
|
+
return plus_class(values), m.end()
|
|
2428
|
+
else:
|
|
2429
|
+
return seq_class(values), m.end()
|
|
2317
2430
|
|
|
2318
2431
|
# Read the next value.
|
|
2319
2432
|
val, position = self.read_value(s, position, reentrances)
|
|
@@ -2325,8 +2438,9 @@ class FeatStructReader(object):
|
|
|
2325
2438
|
if m.group(1) == '+': seen_plus = True
|
|
2326
2439
|
position = m.end()
|
|
2327
2440
|
|
|
2441
|
+
|
|
2328
2442
|
######################################################################
|
|
2329
|
-
#{ Demo
|
|
2443
|
+
# { Demo
|
|
2330
2444
|
######################################################################
|
|
2331
2445
|
|
|
2332
2446
|
def display_unification(fs1, fs2, indent=' '):
|
|
@@ -2334,33 +2448,34 @@ def display_unification(fs1, fs2, indent=' '):
|
|
|
2334
2448
|
fs1_lines = ("%s" % fs1).split('\n')
|
|
2335
2449
|
fs2_lines = ("%s" % fs2).split('\n')
|
|
2336
2450
|
if len(fs1_lines) > len(fs2_lines):
|
|
2337
|
-
blankline = '['+' '*(len(fs2_lines[0])-2)+']'
|
|
2338
|
-
fs2_lines += [blankline]*len(fs1_lines)
|
|
2451
|
+
blankline = '[' + ' ' * (len(fs2_lines[0]) - 2) + ']'
|
|
2452
|
+
fs2_lines += [blankline] * len(fs1_lines)
|
|
2339
2453
|
else:
|
|
2340
|
-
blankline = '['+' '*(len(fs1_lines[0])-2)+']'
|
|
2341
|
-
fs1_lines += [blankline]*len(fs2_lines)
|
|
2454
|
+
blankline = '[' + ' ' * (len(fs1_lines[0]) - 2) + ']'
|
|
2455
|
+
fs1_lines += [blankline] * len(fs2_lines)
|
|
2342
2456
|
for (fs1_line, fs2_line) in zip(fs1_lines, fs2_lines):
|
|
2343
2457
|
print(indent + fs1_line + ' ' + fs2_line)
|
|
2344
|
-
print(indent+'-'*len(fs1_lines[0])+' '+'-'*len(fs2_lines[0]))
|
|
2458
|
+
print(indent + '-' * len(fs1_lines[0]) + ' ' + '-' * len(fs2_lines[0]))
|
|
2345
2459
|
|
|
2346
|
-
linelen = len(fs1_lines[0])*2+3
|
|
2347
|
-
print(indent+'| |'.center(linelen))
|
|
2348
|
-
print(indent+'+-----UNIFY-----+'.center(linelen))
|
|
2349
|
-
print(indent+'|'.center(linelen))
|
|
2350
|
-
print(indent+'V'.center(linelen))
|
|
2460
|
+
linelen = len(fs1_lines[0]) * 2 + 3
|
|
2461
|
+
print(indent + '| |'.center(linelen))
|
|
2462
|
+
print(indent + '+-----UNIFY-----+'.center(linelen))
|
|
2463
|
+
print(indent + '|'.center(linelen))
|
|
2464
|
+
print(indent + 'V'.center(linelen))
|
|
2351
2465
|
|
|
2352
2466
|
bindings = {}
|
|
2353
2467
|
|
|
2354
2468
|
result = fs1.unify(fs2, bindings)
|
|
2355
2469
|
if result is None:
|
|
2356
|
-
print(indent+'(FAILED)'.center(linelen))
|
|
2470
|
+
print(indent + '(FAILED)'.center(linelen))
|
|
2357
2471
|
else:
|
|
2358
|
-
print('\n'.join(indent+l.center(linelen)
|
|
2359
|
-
|
|
2472
|
+
print('\n'.join(indent + l.center(linelen)
|
|
2473
|
+
for l in ("%s" % result).split('\n')))
|
|
2360
2474
|
if bindings and len(bindings.bound_variables()) > 0:
|
|
2361
2475
|
print(repr(bindings).center(linelen))
|
|
2362
2476
|
return result
|
|
2363
2477
|
|
|
2478
|
+
|
|
2364
2479
|
def interactive_demo(trace=False):
|
|
2365
2480
|
import random, sys
|
|
2366
2481
|
|
|
@@ -2396,7 +2511,7 @@ def interactive_demo(trace=False):
|
|
|
2396
2511
|
'[subj=[agr=[gender=?y]], obj=[agr=[gender=?y]]]',
|
|
2397
2512
|
'[gender=masc, agr=?C]',
|
|
2398
2513
|
'[gender=?S, agr=[gender=?S,person=3]]'
|
|
2399
|
-
|
|
2514
|
+
]
|
|
2400
2515
|
|
|
2401
2516
|
all_fstructs = [(i, FeatStruct(fstruct_strings[i]))
|
|
2402
2517
|
for i in range(len(fstruct_strings))]
|
|
@@ -2405,11 +2520,10 @@ def interactive_demo(trace=False):
|
|
|
2405
2520
|
for i, fstruct in fstructs:
|
|
2406
2521
|
print()
|
|
2407
2522
|
lines = ("%s" % fstruct).split('\n')
|
|
2408
|
-
print('%3d: %s' % (i+1, lines[0]))
|
|
2409
|
-
for line in lines[1:]: print(' '+line)
|
|
2523
|
+
print('%3d: %s' % (i + 1, lines[0]))
|
|
2524
|
+
for line in lines[1:]: print(' ' + line)
|
|
2410
2525
|
print()
|
|
2411
2526
|
|
|
2412
|
-
|
|
2413
2527
|
while True:
|
|
2414
2528
|
# Pick 5 feature structures at random from the master list.
|
|
2415
2529
|
MAX_CHOICES = 5
|
|
@@ -2418,13 +2532,13 @@ def interactive_demo(trace=False):
|
|
|
2418
2532
|
else:
|
|
2419
2533
|
fstructs = all_fstructs
|
|
2420
2534
|
|
|
2421
|
-
print('_'*75)
|
|
2535
|
+
print('_' * 75)
|
|
2422
2536
|
|
|
2423
2537
|
print('Choose two feature structures to unify:')
|
|
2424
2538
|
list_fstructs(fstructs)
|
|
2425
2539
|
|
|
2426
|
-
selected = [None,None]
|
|
2427
|
-
for (nth,i) in (('First',0), ('Second',1)):
|
|
2540
|
+
selected = [None, None]
|
|
2541
|
+
for (nth, i) in (('First', 0), ('Second', 1)):
|
|
2428
2542
|
while selected[i] is None:
|
|
2429
2543
|
print(('%s feature structure (1-%d,q,t,l,?): '
|
|
2430
2544
|
% (nth, len(all_fstructs))), end=' ')
|
|
@@ -2436,10 +2550,12 @@ def interactive_demo(trace=False):
|
|
|
2436
2550
|
print(' Trace = %s' % trace)
|
|
2437
2551
|
continue
|
|
2438
2552
|
if input in ('h', 'H', '?'):
|
|
2439
|
-
print(HELP % len(fstructs));
|
|
2553
|
+
print(HELP % len(fstructs));
|
|
2554
|
+
continue
|
|
2440
2555
|
if input in ('l', 'L'):
|
|
2441
|
-
list_fstructs(all_fstructs);
|
|
2442
|
-
|
|
2556
|
+
list_fstructs(all_fstructs);
|
|
2557
|
+
continue
|
|
2558
|
+
num = int(input) - 1
|
|
2443
2559
|
selected[i] = all_fstructs[num][1]
|
|
2444
2560
|
print()
|
|
2445
2561
|
except:
|
|
@@ -2460,11 +2576,12 @@ def interactive_demo(trace=False):
|
|
|
2460
2576
|
input = sys.stdin.readline().strip()
|
|
2461
2577
|
if input in ('q', 'Q', 'x', 'X'): return
|
|
2462
2578
|
|
|
2579
|
+
|
|
2463
2580
|
def demo(trace=False):
|
|
2464
2581
|
"""
|
|
2465
2582
|
Just for testing
|
|
2466
2583
|
"""
|
|
2467
|
-
#import random
|
|
2584
|
+
# import random
|
|
2468
2585
|
|
|
2469
2586
|
# processor breaks with values like '3rd'
|
|
2470
2587
|
fstruct_strings = [
|
|
@@ -2480,12 +2597,12 @@ def demo(trace=False):
|
|
|
2480
2597
|
'[gender=?S, agr=[gender=?S,person=3]]'
|
|
2481
2598
|
]
|
|
2482
2599
|
all_fstructs = [FeatStruct(fss) for fss in fstruct_strings]
|
|
2483
|
-
#MAX_CHOICES = 5
|
|
2484
|
-
#if len(all_fstructs) > MAX_CHOICES:
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
#else:
|
|
2488
|
-
|
|
2600
|
+
# MAX_CHOICES = 5
|
|
2601
|
+
# if len(all_fstructs) > MAX_CHOICES:
|
|
2602
|
+
# fstructs = random.sample(all_fstructs, MAX_CHOICES)
|
|
2603
|
+
# fstructs.sort()
|
|
2604
|
+
# else:
|
|
2605
|
+
# fstructs = all_fstructs
|
|
2489
2606
|
|
|
2490
2607
|
for fs1 in all_fstructs:
|
|
2491
2608
|
for fs2 in all_fstructs:
|