nltk 3.2__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 → nltk-3.3}/INSTALL.txt +6 -6
- {nltk-3.2 → nltk-3.3}/LICENSE.txt +13 -13
- {nltk-3.2 → nltk-3.3}/MANIFEST.in +6 -6
- {nltk-3.2/nltk.egg-info → nltk-3.3}/PKG-INFO +13 -5
- nltk-3.2/README.txt → nltk-3.3/README.md +49 -48
- nltk-3.3/nltk/VERSION +1 -0
- {nltk-3.2 → nltk-3.3}/nltk/__init__.py +185 -185
- {nltk-3.2 → nltk-3.3}/nltk/app/__init__.py +52 -53
- {nltk-3.2 → nltk-3.3}/nltk/app/chartparser_app.py +2276 -2276
- {nltk-3.2 → nltk-3.3}/nltk/app/chunkparser_app.py +1262 -1264
- {nltk-3.2 → nltk-3.3}/nltk/app/collocations_app.py +347 -350
- {nltk-3.2 → nltk-3.3}/nltk/app/concordance_app.py +568 -570
- {nltk-3.2 → nltk-3.3}/nltk/app/nemo_app.py +156 -155
- {nltk-3.2 → nltk-3.3}/nltk/app/rdparser_app.py +892 -894
- {nltk-3.2 → nltk-3.3}/nltk/app/srparser_app.py +809 -809
- {nltk-3.2 → nltk-3.3}/nltk/app/wordfreq_app.py +32 -32
- {nltk-3.2 → nltk-3.3}/nltk/app/wordnet_app.py +968 -968
- {nltk-3.2 → nltk-3.3}/nltk/book.py +91 -90
- {nltk-3.2 → nltk-3.3}/nltk/ccg/__init__.py +22 -22
- {nltk-3.2 → nltk-3.3}/nltk/ccg/api.py +359 -335
- {nltk-3.2 → nltk-3.3}/nltk/ccg/chart.py +394 -361
- {nltk-3.2 → nltk-3.3}/nltk/ccg/combinator.py +343 -312
- {nltk-3.2 → nltk-3.3}/nltk/ccg/lexicon.py +328 -290
- nltk-3.3/nltk/ccg/logic.py +46 -0
- {nltk-3.2 → nltk-3.3}/nltk/chat/__init__.py +49 -49
- {nltk-3.2 → nltk-3.3}/nltk/chat/eliza.py +244 -244
- {nltk-3.2 → nltk-3.3}/nltk/chat/iesha.py +140 -140
- {nltk-3.2 → nltk-3.3}/nltk/chat/rude.py +92 -92
- {nltk-3.2 → nltk-3.3}/nltk/chat/suntsu.py +117 -117
- {nltk-3.2 → nltk-3.3}/nltk/chat/util.py +122 -120
- {nltk-3.2 → nltk-3.3}/nltk/chat/zen.py +282 -282
- {nltk-3.2 → nltk-3.3}/nltk/chunk/__init__.py +190 -190
- {nltk-3.2 → nltk-3.3}/nltk/chunk/api.py +51 -51
- {nltk-3.2 → nltk-3.3}/nltk/chunk/named_entity.py +331 -331
- {nltk-3.2 → nltk-3.3}/nltk/chunk/regexp.py +1390 -1384
- {nltk-3.2 → nltk-3.3}/nltk/chunk/util.py +600 -600
- {nltk-3.2 → nltk-3.3}/nltk/classify/__init__.py +98 -98
- {nltk-3.2 → nltk-3.3}/nltk/classify/api.py +193 -193
- {nltk-3.2 → nltk-3.3}/nltk/classify/decisiontree.py +295 -295
- {nltk-3.2 → nltk-3.3}/nltk/classify/maxent.py +1510 -1492
- {nltk-3.2 → nltk-3.3}/nltk/classify/megam.py +179 -178
- {nltk-3.2 → nltk-3.3}/nltk/classify/naivebayes.py +245 -242
- {nltk-3.2 → nltk-3.3}/nltk/classify/positivenaivebayes.py +170 -170
- {nltk-3.2 → nltk-3.3}/nltk/classify/rte_classify.py +160 -191
- {nltk-3.2 → nltk-3.3}/nltk/classify/scikitlearn.py +153 -151
- {nltk-3.2 → nltk-3.3}/nltk/classify/senna.py +183 -181
- {nltk-3.2 → nltk-3.3}/nltk/classify/svm.py +15 -15
- {nltk-3.2 → nltk-3.3}/nltk/classify/tadm.py +113 -112
- {nltk-3.2 → nltk-3.3}/nltk/classify/textcat.py +193 -193
- {nltk-3.2 → nltk-3.3}/nltk/classify/util.py +324 -312
- {nltk-3.2 → nltk-3.3}/nltk/classify/weka.py +346 -345
- {nltk-3.2 → nltk-3.3}/nltk/cluster/__init__.py +86 -86
- {nltk-3.2 → nltk-3.3}/nltk/cluster/api.py +74 -70
- {nltk-3.2 → nltk-3.3}/nltk/cluster/em.py +247 -247
- {nltk-3.2 → nltk-3.3}/nltk/cluster/gaac.py +168 -168
- {nltk-3.2 → nltk-3.3}/nltk/cluster/kmeans.py +221 -221
- {nltk-3.2 → nltk-3.3}/nltk/cluster/util.py +304 -289
- nltk-3.3/nltk/collections.py +640 -0
- {nltk-3.2 → nltk-3.3}/nltk/collocations.py +388 -388
- nltk-3.3/nltk/compat.py +365 -0
- {nltk-3.2 → nltk-3.3}/nltk/corpus/__init__.py +341 -320
- {nltk-3.2 → nltk-3.3}/nltk/corpus/europarl_raw.py +44 -44
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/__init__.py +147 -145
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/aligned.py +115 -114
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/api.py +448 -446
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bnc.py +252 -252
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bracket_parse.py +227 -227
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/categorized_sents.py +179 -178
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chasen.py +140 -139
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/childes.py +522 -494
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chunked.py +212 -212
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/cmudict.py +97 -95
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/comparative_sents.py +280 -278
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/conll.py +528 -521
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/crubadan.py +116 -116
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/dependency.py +101 -101
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/framenet.py +3059 -2093
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ieer.py +112 -111
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/indian.py +85 -86
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ipipan.py +332 -331
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/knbc.py +187 -187
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/lin.py +156 -156
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/mte.py +311 -310
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nkjp.py +429 -428
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nombank.py +421 -421
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nps_chat.py +73 -73
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/opinion_lexicon.py +115 -115
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/panlex_lite.py +165 -165
- nltk-3.3/nltk/corpus/reader/pl196x.py +292 -0
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/plaintext.py +232 -233
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ppattach.py +96 -95
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/propbank.py +479 -481
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/pros_cons.py +128 -126
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/reviews.py +330 -328
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/rte.py +144 -146
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/semcor.py +256 -256
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/senseval.py +203 -201
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sentiwordnet.py +137 -137
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sinica_treebank.py +75 -75
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/string_category.py +60 -59
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/switchboard.py +119 -119
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/tagged.py +295 -294
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/timit.py +452 -450
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/toolbox.py +68 -68
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/twitter.py +155 -157
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/udhr.py +80 -80
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/util.py +804 -800
- nltk-3.3/nltk/corpus/reader/verbnet.py +595 -0
- nltk-3.3/nltk/corpus/reader/wordlist.py +134 -0
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/wordnet.py +2108 -2036
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/xmldocs.py +392 -387
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ycoe.py +243 -242
- {nltk-3.2 → nltk-3.3}/nltk/corpus/util.py +144 -127
- {nltk-3.2 → nltk-3.3}/nltk/data.py +1487 -1451
- {nltk-3.2 → nltk-3.3}/nltk/decorators.py +219 -215
- {nltk-3.2 → nltk-3.3}/nltk/downloader.py +2278 -2274
- {nltk-3.2 → nltk-3.3}/nltk/draw/__init__.py +27 -27
- {nltk-3.2 → nltk-3.3}/nltk/draw/cfg.py +774 -777
- {nltk-3.2 → nltk-3.3}/nltk/draw/dispersion.py +58 -58
- {nltk-3.2 → nltk-3.3}/nltk/draw/table.py +1098 -1098
- {nltk-3.2 → nltk-3.3}/nltk/draw/tree.py +963 -966
- {nltk-3.2 → nltk-3.3}/nltk/draw/util.py +2356 -2356
- {nltk-3.2 → nltk-3.3}/nltk/featstruct.py +2617 -2500
- {nltk-3.2 → nltk-3.3}/nltk/grammar.py +1559 -1516
- {nltk-3.2 → nltk-3.3}/nltk/help.py +56 -56
- {nltk-3.2 → nltk-3.3}/nltk/inference/__init__.py +20 -20
- {nltk-3.2 → nltk-3.3}/nltk/inference/api.py +597 -589
- {nltk-3.2 → nltk-3.3}/nltk/inference/discourse.py +612 -608
- {nltk-3.2 → nltk-3.3}/nltk/inference/mace.py +311 -311
- {nltk-3.2 → nltk-3.3}/nltk/inference/nonmonotonic.py +509 -509
- {nltk-3.2 → nltk-3.3}/nltk/inference/prover9.py +431 -431
- {nltk-3.2 → nltk-3.3}/nltk/inference/resolution.py +687 -687
- {nltk-3.2 → nltk-3.3}/nltk/inference/tableau.py +607 -607
- {nltk-3.2 → nltk-3.3}/nltk/internals.py +982 -982
- {nltk-3.2 → nltk-3.3}/nltk/jsontags.py +63 -63
- {nltk-3.2 → nltk-3.3}/nltk/lazyimport.py +142 -142
- {nltk-3.2 → nltk-3.3}/nltk/metrics/__init__.py +30 -29
- {nltk-3.2 → nltk-3.3}/nltk/metrics/agreement.py +421 -401
- nltk-3.3/nltk/metrics/aline.py +607 -0
- {nltk-3.2 → nltk-3.3}/nltk/metrics/association.py +414 -410
- {nltk-3.2 → nltk-3.3}/nltk/metrics/confusionmatrix.py +206 -206
- {nltk-3.2 → nltk-3.3}/nltk/metrics/distance.py +207 -202
- {nltk-3.2 → nltk-3.3}/nltk/metrics/paice.py +381 -381
- {nltk-3.2 → nltk-3.3}/nltk/metrics/scores.py +228 -228
- {nltk-3.2 → nltk-3.3}/nltk/metrics/segmentation.py +231 -232
- {nltk-3.2 → nltk-3.3}/nltk/metrics/spearman.py +69 -69
- {nltk-3.2 → nltk-3.3}/nltk/misc/__init__.py +11 -11
- {nltk-3.2 → nltk-3.3}/nltk/misc/babelfish.py +10 -10
- {nltk-3.2 → nltk-3.3}/nltk/misc/chomsky.py +135 -133
- {nltk-3.2 → nltk-3.3}/nltk/misc/minimalset.py +83 -83
- {nltk-3.2 → nltk-3.3}/nltk/misc/sort.py +157 -157
- {nltk-3.2 → nltk-3.3}/nltk/misc/wordfinder.py +129 -129
- {nltk-3.2 → nltk-3.3}/nltk/parse/__init__.py +81 -80
- {nltk-3.2 → nltk-3.3}/nltk/parse/api.py +66 -66
- {nltk-3.2 → nltk-3.3}/nltk/parse/bllip.py +282 -282
- {nltk-3.2 → nltk-3.3}/nltk/parse/chart.py +1682 -1681
- nltk-3.3/nltk/parse/corenlp.py +780 -0
- {nltk-3.2 → nltk-3.3}/nltk/parse/dependencygraph.py +760 -758
- {nltk-3.2 → nltk-3.3}/nltk/parse/earleychart.py +452 -451
- {nltk-3.2 → nltk-3.3}/nltk/parse/evaluate.py +129 -129
- {nltk-3.2 → nltk-3.3}/nltk/parse/featurechart.py +580 -578
- {nltk-3.2 → nltk-3.3}/nltk/parse/generate.py +87 -76
- {nltk-3.2 → nltk-3.3}/nltk/parse/malt.py +356 -356
- {nltk-3.2 → nltk-3.3}/nltk/parse/nonprojectivedependencyparser.py +783 -783
- {nltk-3.2 → nltk-3.3}/nltk/parse/pchart.py +522 -522
- {nltk-3.2 → nltk-3.3}/nltk/parse/projectivedependencyparser.py +579 -578
- {nltk-3.2 → nltk-3.3}/nltk/parse/recursivedescent.py +655 -656
- {nltk-3.2 → nltk-3.3}/nltk/parse/shiftreduce.py +458 -459
- {nltk-3.2 → nltk-3.3}/nltk/parse/stanford.py +431 -406
- {nltk-3.2 → nltk-3.3}/nltk/parse/transitionparser.py +774 -772
- {nltk-3.2 → nltk-3.3}/nltk/parse/util.py +231 -231
- {nltk-3.2 → nltk-3.3}/nltk/parse/viterbi.py +401 -401
- {nltk-3.2 → nltk-3.3}/nltk/probability.py +2410 -2355
- {nltk-3.2 → nltk-3.3}/nltk/sem/__init__.py +61 -61
- {nltk-3.2 → nltk-3.3}/nltk/sem/boxer.py +1261 -1261
- {nltk-3.2 → nltk-3.3}/nltk/sem/chat80.py +782 -782
- {nltk-3.2 → nltk-3.3}/nltk/sem/cooper_storage.py +118 -118
- {nltk-3.2 → nltk-3.3}/nltk/sem/drt.py +1258 -1257
- {nltk-3.2 → nltk-3.3}/nltk/sem/drt_glue_demo.py +485 -489
- {nltk-3.2 → nltk-3.3}/nltk/sem/evaluate.py +790 -784
- {nltk-3.2 → nltk-3.3}/nltk/sem/glue.py +696 -694
- {nltk-3.2 → nltk-3.3}/nltk/sem/hole.py +386 -384
- {nltk-3.2 → nltk-3.3}/nltk/sem/lfg.py +210 -208
- {nltk-3.2 → nltk-3.3}/nltk/sem/linearlogic.py +451 -449
- {nltk-3.2 → nltk-3.3}/nltk/sem/logic.py +1910 -1910
- {nltk-3.2 → nltk-3.3}/nltk/sem/relextract.py +476 -483
- {nltk-3.2 → nltk-3.3}/nltk/sem/skolemize.py +101 -101
- {nltk-3.2 → nltk-3.3}/nltk/sem/util.py +249 -249
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/__init__.py +14 -14
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/sentiment_analyzer.py +229 -229
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/util.py +762 -752
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/vader.py +443 -445
- {nltk-3.2 → nltk-3.3}/nltk/stem/__init__.py +31 -33
- {nltk-3.2 → nltk-3.3}/nltk/stem/api.py +28 -25
- nltk-3.3/nltk/stem/arlstem.py +369 -0
- {nltk-3.2 → nltk-3.3}/nltk/stem/isri.py +345 -345
- {nltk-3.2 → nltk-3.3}/nltk/stem/lancaster.py +337 -310
- nltk-3.3/nltk/stem/porter.py +710 -0
- {nltk-3.2 → nltk-3.3}/nltk/stem/regexp.py +61 -61
- {nltk-3.2 → nltk-3.3}/nltk/stem/rslp.py +142 -142
- {nltk-3.2 → nltk-3.3}/nltk/stem/snowball.py +4236 -3712
- {nltk-3.2 → nltk-3.3}/nltk/stem/util.py +22 -12
- {nltk-3.2 → nltk-3.3}/nltk/stem/wordnet.py +51 -51
- {nltk-3.2 → nltk-3.3}/nltk/tag/__init__.py +152 -127
- {nltk-3.2 → nltk-3.3}/nltk/tag/api.py +86 -81
- {nltk-3.2 → nltk-3.3}/nltk/tag/brill.py +424 -426
- {nltk-3.2 → nltk-3.3}/nltk/tag/brill_trainer.py +608 -608
- {nltk-3.2 → nltk-3.3}/nltk/tag/crf.py +204 -200
- {nltk-3.2 → nltk-3.3}/nltk/tag/hmm.py +1277 -1277
- {nltk-3.2 → nltk-3.3}/nltk/tag/hunpos.py +132 -132
- {nltk-3.2 → nltk-3.3}/nltk/tag/mapping.py +101 -101
- {nltk-3.2 → nltk-3.3}/nltk/tag/perceptron.py +329 -314
- {nltk-3.2 → nltk-3.3}/nltk/tag/senna.py +147 -145
- {nltk-3.2 → nltk-3.3}/nltk/tag/sequential.py +740 -736
- {nltk-3.2 → nltk-3.3}/nltk/tag/stanford.py +219 -196
- {nltk-3.2 → nltk-3.3}/nltk/tag/tnt.py +595 -604
- {nltk-3.2 → nltk-3.3}/nltk/tag/util.py +72 -72
- {nltk-3.2 → nltk-3.3}/nltk/tbl/__init__.py +28 -28
- {nltk-3.2 → nltk-3.3}/nltk/tbl/api.py +1 -1
- {nltk-3.2 → nltk-3.3}/nltk/tbl/demo.py +366 -366
- {nltk-3.2 → nltk-3.3}/nltk/tbl/erroranalysis.py +39 -39
- {nltk-3.2 → nltk-3.3}/nltk/tbl/feature.py +259 -261
- {nltk-3.2 → nltk-3.3}/nltk/tbl/rule.py +321 -321
- {nltk-3.2 → nltk-3.3}/nltk/tbl/template.py +303 -308
- {nltk-3.2 → nltk-3.3}/nltk/test/__init__.py +18 -18
- {nltk-3.2 → nltk-3.3}/nltk/test/all.py +24 -23
- {nltk-3.2 → nltk-3.3}/nltk/test/bleu.doctest +14 -14
- {nltk-3.2 → nltk-3.3}/nltk/test/bnc.doctest +60 -60
- {nltk-3.2 → nltk-3.3}/nltk/test/ccg.doctest +376 -395
- nltk-3.3/nltk/test/ccg_semantics.doctest +553 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/chat80.doctest +234 -234
- {nltk-3.2 → nltk-3.3}/nltk/test/childes.doctest +184 -184
- {nltk-3.2 → nltk-3.3}/nltk/test/childes_fixt.py +14 -13
- {nltk-3.2 → nltk-3.3}/nltk/test/chunk.doctest +373 -373
- {nltk-3.2 → nltk-3.3}/nltk/test/classify.doctest +185 -185
- {nltk-3.2 → nltk-3.3}/nltk/test/classify_fixt.py +11 -10
- nltk-3.3/nltk/test/collections.doctest +20 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/collocations.doctest +276 -276
- {nltk-3.2 → nltk-3.3}/nltk/test/compat.doctest +134 -138
- {nltk-3.2 → nltk-3.3}/nltk/test/compat_fixt.py +9 -8
- nltk-3.3/nltk/test/concordance.doctest +55 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/corpus.doctest +2200 -2212
- {nltk-3.2 → nltk-3.3}/nltk/test/corpus_fixt.py +3 -3
- {nltk-3.2 → nltk-3.3}/nltk/test/crubadan.doctest +65 -65
- {nltk-3.2 → nltk-3.3}/nltk/test/data.doctest +379 -379
- {nltk-3.2 → nltk-3.3}/nltk/test/dependency.doctest +241 -241
- {nltk-3.2 → nltk-3.3}/nltk/test/discourse.doctest +546 -546
- {nltk-3.2 → nltk-3.3}/nltk/test/discourse_fixt.py +14 -13
- {nltk-3.2 → nltk-3.3}/nltk/test/doctest_nose_plugin.py +159 -156
- {nltk-3.2 → nltk-3.3}/nltk/test/drt.doctest +517 -517
- {nltk-3.2 → nltk-3.3}/nltk/test/featgram.doctest +607 -607
- {nltk-3.2 → nltk-3.3}/nltk/test/featstruct.doctest +1229 -1230
- {nltk-3.2 → nltk-3.3}/nltk/test/framenet.doctest +288 -239
- {nltk-3.2 → nltk-3.3}/nltk/test/generate.doctest +67 -67
- {nltk-3.2 → nltk-3.3}/nltk/test/gensim.doctest +140 -141
- {nltk-3.2 → nltk-3.3}/nltk/test/gensim_fixt.py +10 -9
- {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics.doctest +384 -386
- {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt.doctest +68 -68
- {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt_fixt.py +12 -11
- {nltk-3.2 → nltk-3.3}/nltk/test/grammar.doctest +48 -48
- {nltk-3.2 → nltk-3.3}/nltk/test/grammartestsuites.doctest +109 -109
- {nltk-3.2 → nltk-3.3}/nltk/test/index.doctest +100 -100
- {nltk-3.2 → nltk-3.3}/nltk/test/inference.doctest +534 -534
- {nltk-3.2 → nltk-3.3}/nltk/test/inference_fixt.py +12 -11
- {nltk-3.2 → nltk-3.3}/nltk/test/internals.doctest +140 -140
- {nltk-3.2 → nltk-3.3}/nltk/test/japanese.doctest +48 -48
- {nltk-3.2 → nltk-3.3}/nltk/test/logic.doctest +1098 -1098
- {nltk-3.2 → nltk-3.3}/nltk/test/metrics.doctest +270 -270
- {nltk-3.2 → nltk-3.3}/nltk/test/misc.doctest +118 -118
- {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic.doctest +286 -286
- {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic_fixt.py +12 -11
- {nltk-3.2 → nltk-3.3}/nltk/test/paice.doctest +35 -35
- {nltk-3.2 → nltk-3.3}/nltk/test/parse.doctest +884 -884
- {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en.doctest +565 -565
- {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en_fixt.py +16 -16
- {nltk-3.2 → nltk-3.3}/nltk/test/probability.doctest +304 -304
- {nltk-3.2 → nltk-3.3}/nltk/test/probability_fixt.py +13 -12
- {nltk-3.2 → nltk-3.3}/nltk/test/propbank.doctest +176 -176
- {nltk-3.2 → nltk-3.3}/nltk/test/relextract.doctest +263 -263
- {nltk-3.2 → nltk-3.3}/nltk/test/resolution.doctest +221 -221
- {nltk-3.2 → nltk-3.3}/nltk/test/runtests.py +86 -64
- {nltk-3.2 → nltk-3.3}/nltk/test/segmentation_fixt.py +10 -10
- {nltk-3.2 → nltk-3.3}/nltk/test/semantics.doctest +665 -665
- {nltk-3.2 → nltk-3.3}/nltk/test/semantics_fixt.py +7 -7
- {nltk-3.2 → nltk-3.3}/nltk/test/sentiment.doctest +233 -233
- {nltk-3.2 → nltk-3.3}/nltk/test/sentiwordnet.doctest +41 -41
- {nltk-3.2 → nltk-3.3}/nltk/test/simple.doctest +85 -85
- {nltk-3.2 → nltk-3.3}/nltk/test/stem.doctest +78 -78
- {nltk-3.2 → nltk-3.3}/nltk/test/tag.doctest +33 -33
- {nltk-3.2 → nltk-3.3}/nltk/test/tokenize.doctest +273 -166
- {nltk-3.2 → nltk-3.3}/nltk/test/toolbox.doctest +307 -307
- {nltk-3.2 → nltk-3.3}/nltk/test/translate.doctest +242 -242
- {nltk-3.2 → nltk-3.3}/nltk/test/translate_fixt.py +3 -3
- {nltk-3.2 → nltk-3.3}/nltk/test/tree.doctest +1101 -1101
- {nltk-3.2 → nltk-3.3}/nltk/test/treeprettyprinter.doctest +127 -127
- {nltk-3.2 → nltk-3.3}/nltk/test/treetransforms.doctest +156 -156
- nltk-3.3/nltk/test/unit/test_2x_compat.py +63 -0
- 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 → nltk-3.3}/nltk/test/unit/test_classify.py +55 -53
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_collocations.py +88 -79
- 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 → nltk-3.3}/nltk/test/unit/test_corpora.py +200 -183
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpus_views.py +45 -45
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_hmm.py +88 -88
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_json2csv_corpus.py +188 -187
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_naivebayes.py +26 -26
- nltk-3.3/nltk/test/unit/test_rte_classify.py +86 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_seekable_unicode_stream_reader.py +124 -124
- 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 → nltk-3.3}/nltk/test/unit/test_tag.py +20 -20
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tgrep.py +628 -626
- nltk-3.3/nltk/test/unit/test_tokenize.py +168 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_twitter_auth.py +185 -185
- 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.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm1.py +75 -75
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm2.py +87 -87
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm3.py +105 -105
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm4.py +126 -126
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm5.py +166 -166
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm_model.py +270 -270
- nltk-3.3/nltk/test/unit/translate/test_nist.py +37 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_stack_decoder.py +300 -300
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/utils.py +41 -41
- {nltk-3.2 → nltk-3.3}/nltk/test/util.doctest +48 -48
- {nltk-3.2 → nltk-3.3}/nltk/test/wordnet.doctest +595 -581
- {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_fixt.py +7 -6
- {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_lch.doctest +53 -53
- {nltk-3.2 → nltk-3.3}/nltk/test/wsd.doctest +68 -68
- {nltk-3.2 → nltk-3.3}/nltk/text.py +663 -610
- {nltk-3.2 → nltk-3.3}/nltk/tgrep.py +938 -937
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/__init__.py +130 -107
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/api.py +77 -78
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/casual.py +343 -342
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/mwe.py +120 -120
- nltk-3.3/nltk/tokenize/nist.py +173 -0
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/punkt.py +1620 -1601
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/regexp.py +208 -202
- nltk-3.3/nltk/tokenize/repp.py +151 -0
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/sexpr.py +140 -142
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/simple.py +138 -136
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/stanford.py +117 -113
- nltk-3.3/nltk/tokenize/stanford_segmenter.py +246 -0
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/texttiling.py +458 -460
- 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 → nltk-3.3}/nltk/toolbox.py +499 -497
- {nltk-3.2 → nltk-3.3}/nltk/translate/__init__.py +24 -24
- {nltk-3.2 → nltk-3.3}/nltk/translate/api.py +331 -321
- {nltk-3.2 → nltk-3.3}/nltk/translate/bleu_score.py +615 -556
- nltk-3.3/nltk/translate/chrf_score.py +137 -0
- {nltk-3.2 → nltk-3.3}/nltk/translate/gale_church.py +248 -235
- {nltk-3.2 → nltk-3.3}/nltk/translate/gdfa.py +135 -131
- nltk-3.3/nltk/translate/gleu_score.py +193 -0
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm1.py +250 -241
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm2.py +308 -308
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm3.py +337 -337
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm4.py +467 -467
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm5.py +639 -639
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm_model.py +536 -533
- {nltk-3.2 → nltk-3.3}/nltk/translate/metrics.py +40 -40
- nltk-3.3/nltk/translate/nist_score.py +178 -0
- {nltk-3.2 → nltk-3.3}/nltk/translate/phrase_based.py +175 -175
- {nltk-3.2 → nltk-3.3}/nltk/translate/ribes_score.py +325 -325
- {nltk-3.2 → nltk-3.3}/nltk/translate/stack_decoder.py +499 -495
- {nltk-3.2 → nltk-3.3}/nltk/tree.py +1605 -1603
- {nltk-3.2 → nltk-3.3}/nltk/treeprettyprinter.py +564 -564
- {nltk-3.2 → nltk-3.3}/nltk/treetransforms.py +309 -309
- {nltk-3.2 → nltk-3.3}/nltk/twitter/__init__.py +28 -28
- {nltk-3.2 → nltk-3.3}/nltk/twitter/api.py +141 -136
- {nltk-3.2 → nltk-3.3}/nltk/twitter/common.py +264 -258
- {nltk-3.2 → nltk-3.3}/nltk/twitter/twitter_demo.py +288 -288
- {nltk-3.2 → nltk-3.3}/nltk/twitter/twitterclient.py +530 -530
- {nltk-3.2 → nltk-3.3}/nltk/twitter/util.py +147 -146
- nltk-3.3/nltk/util.py +751 -0
- {nltk-3.2 → nltk-3.3}/nltk/wsd.py +53 -53
- {nltk-3.2 → nltk-3.3/nltk.egg-info}/PKG-INFO +13 -5
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/SOURCES.txt +26 -3
- nltk-3.3/nltk.egg-info/requires.txt +31 -0
- {nltk-3.2 → nltk-3.3}/setup.cfg +0 -1
- {nltk-3.2 → nltk-3.3}/setup.py +102 -75
- nltk-3.2/nltk/VERSION +0 -1
- nltk-3.2/nltk/compat.py +0 -680
- nltk-3.2/nltk/corpus/reader/pl196x.py +0 -278
- nltk-3.2/nltk/corpus/reader/verbnet.py +0 -408
- nltk-3.2/nltk/corpus/reader/wordlist.py +0 -37
- nltk-3.2/nltk/sentiment/vader_lexicon.txt +0 -7517
- nltk-3.2/nltk/six.py +0 -868
- nltk-3.2/nltk/stem/porter.py +0 -692
- nltk-3.2/nltk/test/unit/test_2x_compat.py +0 -26
- nltk-3.2/nltk/test/unit/test_stem.py +0 -36
- nltk-3.2/nltk/test/unit/test_tokenize.py +0 -23
- nltk-3.2/nltk/test/unit/translate/test_bleu.py +0 -84
- nltk-3.2/nltk/tokenize/treebank.py +0 -124
- nltk-3.2/nltk/tokenize/util.py +0 -90
- nltk-3.2/nltk/util.py +0 -1364
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/__init__.py +0 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/__init__.py +0 -0
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/dependency_links.txt +0 -0
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/not-zip-safe +0 -0
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/top_level.txt +0 -0
|
@@ -1,777 +1,774 @@
|
|
|
1
|
-
# Natural Language Toolkit: CFG visualization
|
|
2
|
-
#
|
|
3
|
-
# Copyright (C) 2001-
|
|
4
|
-
# Author: Edward Loper <edloper@gmail.com>
|
|
5
|
-
# URL: <http://nltk.org/>
|
|
6
|
-
# For license information, see LICENSE.TXT
|
|
7
|
-
|
|
8
|
-
"""
|
|
9
|
-
Visualization tools for CFGs.
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
# Idea for a nice demo:
|
|
13
|
-
# - 3 panes: grammar, treelet, working area
|
|
14
|
-
# - grammar is a list of productions
|
|
15
|
-
# - when you select a production, the treelet that it licenses appears
|
|
16
|
-
# in the treelet area
|
|
17
|
-
# - the working area has the text on the bottom, and S at top. When
|
|
18
|
-
# you select a production, it shows (ghosted) the locations where
|
|
19
|
-
# that production's treelet could be attached to either the text
|
|
20
|
-
# or the tree rooted at S.
|
|
21
|
-
# - the user can drag the treelet onto one of those (or click on them?)
|
|
22
|
-
# - the user can delete pieces of the tree from the working area
|
|
23
|
-
# (right click?)
|
|
24
|
-
# - connecting top to bottom? drag one NP onto another?
|
|
25
|
-
#
|
|
26
|
-
# +-------------------------------------------------------------+
|
|
27
|
-
# | S -> NP VP | S |
|
|
28
|
-
# |[NP -> Det N ]| / \ |
|
|
29
|
-
# | ... | NP VP |
|
|
30
|
-
# | N -> 'dog' | |
|
|
31
|
-
# | N -> 'cat' | |
|
|
32
|
-
# | ... | |
|
|
33
|
-
# +--------------+ |
|
|
34
|
-
# | NP | Det N |
|
|
35
|
-
# | / \ | | | |
|
|
36
|
-
# | Det N | the cat saw the dog |
|
|
37
|
-
# | | |
|
|
38
|
-
# +--------------+----------------------------------------------+
|
|
39
|
-
#
|
|
40
|
-
# Operations:
|
|
41
|
-
# - connect a new treelet -- drag or click shadow
|
|
42
|
-
# - delete a treelet -- right click
|
|
43
|
-
# - if only connected to top, delete everything below
|
|
44
|
-
# - if only connected to bottom, delete everything above
|
|
45
|
-
# - connect top & bottom -- drag a leaf to a root or a root to a leaf
|
|
46
|
-
# - disconnect top & bottom -- right click
|
|
47
|
-
# - if connected to top & bottom, then disconnect
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
import
|
|
52
|
-
import
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
from nltk.
|
|
58
|
-
|
|
59
|
-
from nltk.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
the CFG
|
|
129
|
-
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
"""
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
self.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
self.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
self.
|
|
167
|
-
self.
|
|
168
|
-
|
|
169
|
-
self.
|
|
170
|
-
self.
|
|
171
|
-
self.
|
|
172
|
-
|
|
173
|
-
self.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
self.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
frame =
|
|
180
|
-
|
|
181
|
-
self._start.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
self.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
frame =
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
self._top.
|
|
201
|
-
self._top.bind('<Control-
|
|
202
|
-
self._top.bind('<Alt-
|
|
203
|
-
self._top.bind('<
|
|
204
|
-
#self._top.bind('<Control-
|
|
205
|
-
self._top.bind('<Alt-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
self._top.bind('<Alt-
|
|
209
|
-
|
|
210
|
-
self._top.bind('<
|
|
211
|
-
self._top.bind('<
|
|
212
|
-
self._top.bind('<
|
|
213
|
-
self._top.bind('<
|
|
214
|
-
self._top.bind('<
|
|
215
|
-
self._top.bind('<
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
self.
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
self.
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
self._textscroll
|
|
227
|
-
|
|
228
|
-
self._textwidget.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
#
|
|
241
|
-
self.
|
|
242
|
-
|
|
243
|
-
#
|
|
244
|
-
self._top.bind('
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
#
|
|
280
|
-
#
|
|
281
|
-
# for
|
|
282
|
-
#
|
|
283
|
-
#
|
|
284
|
-
#
|
|
285
|
-
#
|
|
286
|
-
#
|
|
287
|
-
#
|
|
288
|
-
#
|
|
289
|
-
#
|
|
290
|
-
#
|
|
291
|
-
#
|
|
292
|
-
#
|
|
293
|
-
|
|
294
|
-
#
|
|
295
|
-
#
|
|
296
|
-
|
|
297
|
-
#
|
|
298
|
-
#
|
|
299
|
-
#
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
"""
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
self._textwidget.
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
# Get
|
|
387
|
-
self.
|
|
388
|
-
|
|
389
|
-
#
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
"""
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
if line
|
|
454
|
-
|
|
455
|
-
#
|
|
456
|
-
#
|
|
457
|
-
#
|
|
458
|
-
#
|
|
459
|
-
#(
|
|
460
|
-
#
|
|
461
|
-
#
|
|
462
|
-
#
|
|
463
|
-
#
|
|
464
|
-
#
|
|
465
|
-
#
|
|
466
|
-
#
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
return
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
self.
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
self.
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
self.
|
|
491
|
-
|
|
492
|
-
self.
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
ShowText(self._parent, 'Help: Chart Parser Demo',
|
|
506
|
-
(_CFGEditor_HELP).strip(), width=75
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
self.
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
self.
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
self.
|
|
527
|
-
|
|
528
|
-
#
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
self.
|
|
535
|
-
self.
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
def
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
self._prodlist
|
|
553
|
-
self._prodlist.
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
self.
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
self.
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
self.
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
#
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
#
|
|
600
|
-
for
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
def
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
self._treelet =
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
self._treelet
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
self.
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
self.
|
|
661
|
-
|
|
662
|
-
def
|
|
663
|
-
self._top.
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
Production(
|
|
676
|
-
Production(
|
|
677
|
-
Production(
|
|
678
|
-
Production(
|
|
679
|
-
Production(
|
|
680
|
-
|
|
681
|
-
Production(PP, [
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
Production(
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
Production(
|
|
688
|
-
Production(
|
|
689
|
-
Production(
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
N -> '
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
P -> '
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
top =
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
Production(
|
|
747
|
-
Production(
|
|
748
|
-
Production(
|
|
749
|
-
Production(
|
|
750
|
-
Production(
|
|
751
|
-
|
|
752
|
-
Production(PP, [
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
Production(
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
Production(
|
|
759
|
-
Production(
|
|
760
|
-
Production(
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
p
|
|
770
|
-
p.
|
|
771
|
-
p.
|
|
772
|
-
p.
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
p.mark(productions[8])
|
|
776
|
-
|
|
777
|
-
if __name__ == '__main__': demo()
|
|
1
|
+
# Natural Language Toolkit: CFG visualization
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2001-2018 NLTK Project
|
|
4
|
+
# Author: Edward Loper <edloper@gmail.com>
|
|
5
|
+
# URL: <http://nltk.org/>
|
|
6
|
+
# For license information, see LICENSE.TXT
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
Visualization tools for CFGs.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# Idea for a nice demo:
|
|
13
|
+
# - 3 panes: grammar, treelet, working area
|
|
14
|
+
# - grammar is a list of productions
|
|
15
|
+
# - when you select a production, the treelet that it licenses appears
|
|
16
|
+
# in the treelet area
|
|
17
|
+
# - the working area has the text on the bottom, and S at top. When
|
|
18
|
+
# you select a production, it shows (ghosted) the locations where
|
|
19
|
+
# that production's treelet could be attached to either the text
|
|
20
|
+
# or the tree rooted at S.
|
|
21
|
+
# - the user can drag the treelet onto one of those (or click on them?)
|
|
22
|
+
# - the user can delete pieces of the tree from the working area
|
|
23
|
+
# (right click?)
|
|
24
|
+
# - connecting top to bottom? drag one NP onto another?
|
|
25
|
+
#
|
|
26
|
+
# +-------------------------------------------------------------+
|
|
27
|
+
# | S -> NP VP | S |
|
|
28
|
+
# |[NP -> Det N ]| / \ |
|
|
29
|
+
# | ... | NP VP |
|
|
30
|
+
# | N -> 'dog' | |
|
|
31
|
+
# | N -> 'cat' | |
|
|
32
|
+
# | ... | |
|
|
33
|
+
# +--------------+ |
|
|
34
|
+
# | NP | Det N |
|
|
35
|
+
# | / \ | | | |
|
|
36
|
+
# | Det N | the cat saw the dog |
|
|
37
|
+
# | | |
|
|
38
|
+
# +--------------+----------------------------------------------+
|
|
39
|
+
#
|
|
40
|
+
# Operations:
|
|
41
|
+
# - connect a new treelet -- drag or click shadow
|
|
42
|
+
# - delete a treelet -- right click
|
|
43
|
+
# - if only connected to top, delete everything below
|
|
44
|
+
# - if only connected to bottom, delete everything above
|
|
45
|
+
# - connect top & bottom -- drag a leaf to a root or a root to a leaf
|
|
46
|
+
# - disconnect top & bottom -- right click
|
|
47
|
+
# - if connected to top & bottom, then disconnect
|
|
48
|
+
|
|
49
|
+
import re
|
|
50
|
+
|
|
51
|
+
from six import string_types
|
|
52
|
+
from six.moves.tkinter import (Button, Canvas, Entry, Frame, IntVar, Label,
|
|
53
|
+
Scrollbar, Text, Tk, Toplevel)
|
|
54
|
+
|
|
55
|
+
from nltk.grammar import (CFG, _read_cfg_production,
|
|
56
|
+
Nonterminal, nonterminals)
|
|
57
|
+
from nltk.tree import Tree
|
|
58
|
+
from nltk.draw.tree import TreeSegmentWidget, tree_to_treesegment
|
|
59
|
+
from nltk.draw.util import (CanvasFrame, ColorizedList, ShowText,
|
|
60
|
+
SymbolWidget, TextWidget)
|
|
61
|
+
|
|
62
|
+
######################################################################
|
|
63
|
+
# Production List
|
|
64
|
+
######################################################################
|
|
65
|
+
|
|
66
|
+
class ProductionList(ColorizedList):
|
|
67
|
+
ARROW = SymbolWidget.SYMBOLS['rightarrow']
|
|
68
|
+
|
|
69
|
+
def _init_colortags(self, textwidget, options):
|
|
70
|
+
textwidget.tag_config('terminal', foreground='#006000')
|
|
71
|
+
textwidget.tag_config('arrow', font='symbol', underline='0')
|
|
72
|
+
textwidget.tag_config('nonterminal', foreground='blue',
|
|
73
|
+
font=('helvetica', -12, 'bold'))
|
|
74
|
+
|
|
75
|
+
def _item_repr(self, item):
|
|
76
|
+
contents = []
|
|
77
|
+
contents.append(('%s\t' % item.lhs(), 'nonterminal'))
|
|
78
|
+
contents.append((self.ARROW, 'arrow'))
|
|
79
|
+
for elt in item.rhs():
|
|
80
|
+
if isinstance(elt, Nonterminal):
|
|
81
|
+
contents.append((' %s' % elt.symbol(), 'nonterminal'))
|
|
82
|
+
else:
|
|
83
|
+
contents.append((' %r' % elt, 'terminal'))
|
|
84
|
+
return contents
|
|
85
|
+
|
|
86
|
+
######################################################################
|
|
87
|
+
# CFG Editor
|
|
88
|
+
######################################################################
|
|
89
|
+
|
|
90
|
+
_CFGEditor_HELP = """
|
|
91
|
+
|
|
92
|
+
The CFG Editor can be used to create or modify context free grammars.
|
|
93
|
+
A context free grammar consists of a start symbol and a list of
|
|
94
|
+
productions. The start symbol is specified by the text entry field in
|
|
95
|
+
the upper right hand corner of the editor; and the list of productions
|
|
96
|
+
are specified in the main text editing box.
|
|
97
|
+
|
|
98
|
+
Every non-blank line specifies a single production. Each production
|
|
99
|
+
has the form "LHS -> RHS," where LHS is a single nonterminal, and RHS
|
|
100
|
+
is a list of nonterminals and terminals.
|
|
101
|
+
|
|
102
|
+
Nonterminals must be a single word, such as S or NP or NP_subj.
|
|
103
|
+
Currently, nonterminals must consists of alphanumeric characters and
|
|
104
|
+
underscores (_). Nonterminals are colored blue. If you place the
|
|
105
|
+
mouse over any nonterminal, then all occurrences of that nonterminal
|
|
106
|
+
will be highlighted.
|
|
107
|
+
|
|
108
|
+
Terminals must be surrounded by single quotes (') or double
|
|
109
|
+
quotes(\"). For example, "dog" and "New York" are terminals.
|
|
110
|
+
Currently, the string within the quotes must consist of alphanumeric
|
|
111
|
+
characters, underscores, and spaces.
|
|
112
|
+
|
|
113
|
+
To enter a new production, go to a blank line, and type a nonterminal,
|
|
114
|
+
followed by an arrow (->), followed by a sequence of terminals and
|
|
115
|
+
nonterminals. Note that "->" (dash + greater-than) is automatically
|
|
116
|
+
converted to an arrow symbol. When you move your cursor to a
|
|
117
|
+
different line, your production will automatically be colorized. If
|
|
118
|
+
there are any errors, they will be highlighted in red.
|
|
119
|
+
|
|
120
|
+
Note that the order of the productions is significant for some
|
|
121
|
+
algorithms. To re-order the productions, use cut and paste to move
|
|
122
|
+
them.
|
|
123
|
+
|
|
124
|
+
Use the buttons at the bottom of the window when you are done editing
|
|
125
|
+
the CFG:
|
|
126
|
+
- Ok: apply the new CFG, and exit the editor.
|
|
127
|
+
- Apply: apply the new CFG, and do not exit the editor.
|
|
128
|
+
- Reset: revert to the original CFG, and do not exit the editor.
|
|
129
|
+
- Cancel: revert to the original CFG, and exit the editor.
|
|
130
|
+
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
class CFGEditor(object):
|
|
134
|
+
"""
|
|
135
|
+
A dialog window for creating and editing context free grammars.
|
|
136
|
+
``CFGEditor`` imposes the following restrictions:
|
|
137
|
+
|
|
138
|
+
- All nonterminals must be strings consisting of word
|
|
139
|
+
characters.
|
|
140
|
+
- All terminals must be strings consisting of word characters
|
|
141
|
+
and space characters.
|
|
142
|
+
"""
|
|
143
|
+
# Regular expressions used by _analyze_line. Precompile them, so
|
|
144
|
+
# we can process the text faster.
|
|
145
|
+
ARROW = SymbolWidget.SYMBOLS['rightarrow']
|
|
146
|
+
_LHS_RE = re.compile(r"(^\s*\w+\s*)(->|("+ARROW+"))")
|
|
147
|
+
_ARROW_RE = re.compile("\s*(->|("+ARROW+"))\s*")
|
|
148
|
+
_PRODUCTION_RE = re.compile(r"(^\s*\w+\s*)" + # LHS
|
|
149
|
+
"(->|("+ARROW+"))\s*" + # arrow
|
|
150
|
+
r"((\w+|'[\w ]*'|\"[\w ]*\"|\|)\s*)*$") # RHS
|
|
151
|
+
_TOKEN_RE = re.compile("\\w+|->|'[\\w ]+'|\"[\\w ]+\"|("+ARROW+")")
|
|
152
|
+
_BOLD = ('helvetica', -12, 'bold')
|
|
153
|
+
|
|
154
|
+
def __init__(self, parent, cfg=None, set_cfg_callback=None):
|
|
155
|
+
self._parent = parent
|
|
156
|
+
if cfg is not None: self._cfg = cfg
|
|
157
|
+
else: self._cfg = CFG(Nonterminal('S'), [])
|
|
158
|
+
self._set_cfg_callback = set_cfg_callback
|
|
159
|
+
|
|
160
|
+
self._highlight_matching_nonterminals = 1
|
|
161
|
+
|
|
162
|
+
# Create the top-level window.
|
|
163
|
+
self._top = Toplevel(parent)
|
|
164
|
+
self._init_bindings()
|
|
165
|
+
|
|
166
|
+
self._init_startframe()
|
|
167
|
+
self._startframe.pack(side='top', fill='x', expand=0)
|
|
168
|
+
self._init_prodframe()
|
|
169
|
+
self._prodframe.pack(side='top', fill='both', expand=1)
|
|
170
|
+
self._init_buttons()
|
|
171
|
+
self._buttonframe.pack(side='bottom', fill='x', expand=0)
|
|
172
|
+
|
|
173
|
+
self._textwidget.focus()
|
|
174
|
+
|
|
175
|
+
def _init_startframe(self):
|
|
176
|
+
frame = self._startframe = Frame(self._top)
|
|
177
|
+
self._start = Entry(frame)
|
|
178
|
+
self._start.pack(side='right')
|
|
179
|
+
Label(frame, text='Start Symbol:').pack(side='right')
|
|
180
|
+
Label(frame, text='Productions:').pack(side='left')
|
|
181
|
+
self._start.insert(0, self._cfg.start().symbol())
|
|
182
|
+
|
|
183
|
+
def _init_buttons(self):
|
|
184
|
+
frame = self._buttonframe = Frame(self._top)
|
|
185
|
+
Button(frame, text='Ok', command=self._ok,
|
|
186
|
+
underline=0, takefocus=0).pack(side='left')
|
|
187
|
+
Button(frame, text='Apply', command=self._apply,
|
|
188
|
+
underline=0, takefocus=0).pack(side='left')
|
|
189
|
+
Button(frame, text='Reset', command=self._reset,
|
|
190
|
+
underline=0, takefocus=0,).pack(side='left')
|
|
191
|
+
Button(frame, text='Cancel', command=self._cancel,
|
|
192
|
+
underline=0, takefocus=0).pack(side='left')
|
|
193
|
+
Button(frame, text='Help', command=self._help,
|
|
194
|
+
underline=0, takefocus=0).pack(side='right')
|
|
195
|
+
|
|
196
|
+
def _init_bindings(self):
|
|
197
|
+
self._top.title('CFG Editor')
|
|
198
|
+
self._top.bind('<Control-q>', self._cancel)
|
|
199
|
+
self._top.bind('<Alt-q>', self._cancel)
|
|
200
|
+
self._top.bind('<Control-d>', self._cancel)
|
|
201
|
+
#self._top.bind('<Control-x>', self._cancel)
|
|
202
|
+
self._top.bind('<Alt-x>', self._cancel)
|
|
203
|
+
self._top.bind('<Escape>', self._cancel)
|
|
204
|
+
#self._top.bind('<Control-c>', self._cancel)
|
|
205
|
+
self._top.bind('<Alt-c>', self._cancel)
|
|
206
|
+
|
|
207
|
+
self._top.bind('<Control-o>', self._ok)
|
|
208
|
+
self._top.bind('<Alt-o>', self._ok)
|
|
209
|
+
self._top.bind('<Control-a>', self._apply)
|
|
210
|
+
self._top.bind('<Alt-a>', self._apply)
|
|
211
|
+
self._top.bind('<Control-r>', self._reset)
|
|
212
|
+
self._top.bind('<Alt-r>', self._reset)
|
|
213
|
+
self._top.bind('<Control-h>', self._help)
|
|
214
|
+
self._top.bind('<Alt-h>', self._help)
|
|
215
|
+
self._top.bind('<F1>', self._help)
|
|
216
|
+
|
|
217
|
+
def _init_prodframe(self):
|
|
218
|
+
self._prodframe = Frame(self._top)
|
|
219
|
+
|
|
220
|
+
# Create the basic Text widget & scrollbar.
|
|
221
|
+
self._textwidget = Text(self._prodframe, background='#e0e0e0',
|
|
222
|
+
exportselection=1)
|
|
223
|
+
self._textscroll = Scrollbar(self._prodframe, takefocus=0,
|
|
224
|
+
orient='vertical')
|
|
225
|
+
self._textwidget.config(yscrollcommand = self._textscroll.set)
|
|
226
|
+
self._textscroll.config(command=self._textwidget.yview)
|
|
227
|
+
self._textscroll.pack(side='right', fill='y')
|
|
228
|
+
self._textwidget.pack(expand=1, fill='both', side='left')
|
|
229
|
+
|
|
230
|
+
# Initialize the colorization tags. Each nonterminal gets its
|
|
231
|
+
# own tag, so they aren't listed here.
|
|
232
|
+
self._textwidget.tag_config('terminal', foreground='#006000')
|
|
233
|
+
self._textwidget.tag_config('arrow', font='symbol')
|
|
234
|
+
self._textwidget.tag_config('error', background='red')
|
|
235
|
+
|
|
236
|
+
# Keep track of what line they're on. We use that to remember
|
|
237
|
+
# to re-analyze a line whenever they leave it.
|
|
238
|
+
self._linenum = 0
|
|
239
|
+
|
|
240
|
+
# Expand "->" to an arrow.
|
|
241
|
+
self._top.bind('>', self._replace_arrows)
|
|
242
|
+
|
|
243
|
+
# Re-colorize lines when appropriate.
|
|
244
|
+
self._top.bind('<<Paste>>', self._analyze)
|
|
245
|
+
self._top.bind('<KeyPress>', self._check_analyze)
|
|
246
|
+
self._top.bind('<ButtonPress>', self._check_analyze)
|
|
247
|
+
|
|
248
|
+
# Tab cycles focus. (why doesn't this work??)
|
|
249
|
+
def cycle(e, textwidget=self._textwidget):
|
|
250
|
+
textwidget.tk_focusNext().focus()
|
|
251
|
+
self._textwidget.bind('<Tab>', cycle)
|
|
252
|
+
|
|
253
|
+
prod_tuples = [(p.lhs(),[p.rhs()]) for p in self._cfg.productions()]
|
|
254
|
+
for i in range(len(prod_tuples)-1,0,-1):
|
|
255
|
+
if (prod_tuples[i][0] == prod_tuples[i-1][0]):
|
|
256
|
+
if () in prod_tuples[i][1]: continue
|
|
257
|
+
if () in prod_tuples[i-1][1]: continue
|
|
258
|
+
print(prod_tuples[i-1][1])
|
|
259
|
+
print(prod_tuples[i][1])
|
|
260
|
+
prod_tuples[i-1][1].extend(prod_tuples[i][1])
|
|
261
|
+
del prod_tuples[i]
|
|
262
|
+
|
|
263
|
+
for lhs, rhss in prod_tuples:
|
|
264
|
+
print(lhs, rhss)
|
|
265
|
+
s = '%s ->' % lhs
|
|
266
|
+
for rhs in rhss:
|
|
267
|
+
for elt in rhs:
|
|
268
|
+
if isinstance(elt, Nonterminal): s += ' %s' % elt
|
|
269
|
+
else: s += ' %r' % elt
|
|
270
|
+
s += ' |'
|
|
271
|
+
s = s[:-2] + '\n'
|
|
272
|
+
self._textwidget.insert('end', s)
|
|
273
|
+
|
|
274
|
+
self._analyze()
|
|
275
|
+
|
|
276
|
+
# # Add the producitons to the text widget, and colorize them.
|
|
277
|
+
# prod_by_lhs = {}
|
|
278
|
+
# for prod in self._cfg.productions():
|
|
279
|
+
# if len(prod.rhs()) > 0:
|
|
280
|
+
# prod_by_lhs.setdefault(prod.lhs(),[]).append(prod)
|
|
281
|
+
# for (lhs, prods) in prod_by_lhs.items():
|
|
282
|
+
# self._textwidget.insert('end', '%s ->' % lhs)
|
|
283
|
+
# self._textwidget.insert('end', self._rhs(prods[0]))
|
|
284
|
+
# for prod in prods[1:]:
|
|
285
|
+
# print '\t|'+self._rhs(prod),
|
|
286
|
+
# self._textwidget.insert('end', '\t|'+self._rhs(prod))
|
|
287
|
+
# print
|
|
288
|
+
# self._textwidget.insert('end', '\n')
|
|
289
|
+
# for prod in self._cfg.productions():
|
|
290
|
+
# if len(prod.rhs()) == 0:
|
|
291
|
+
# self._textwidget.insert('end', '%s' % prod)
|
|
292
|
+
# self._analyze()
|
|
293
|
+
|
|
294
|
+
# def _rhs(self, prod):
|
|
295
|
+
# s = ''
|
|
296
|
+
# for elt in prod.rhs():
|
|
297
|
+
# if isinstance(elt, Nonterminal): s += ' %s' % elt.symbol()
|
|
298
|
+
# else: s += ' %r' % elt
|
|
299
|
+
# return s
|
|
300
|
+
|
|
301
|
+
def _clear_tags(self, linenum):
|
|
302
|
+
"""
|
|
303
|
+
Remove all tags (except ``arrow`` and ``sel``) from the given
|
|
304
|
+
line of the text widget used for editing the productions.
|
|
305
|
+
"""
|
|
306
|
+
start = '%d.0'%linenum
|
|
307
|
+
end = '%d.end'%linenum
|
|
308
|
+
for tag in self._textwidget.tag_names():
|
|
309
|
+
if tag not in ('arrow', 'sel'):
|
|
310
|
+
self._textwidget.tag_remove(tag, start, end)
|
|
311
|
+
|
|
312
|
+
def _check_analyze(self, *e):
|
|
313
|
+
"""
|
|
314
|
+
Check if we've moved to a new line. If we have, then remove
|
|
315
|
+
all colorization from the line we moved to, and re-colorize
|
|
316
|
+
the line that we moved from.
|
|
317
|
+
"""
|
|
318
|
+
linenum = int(self._textwidget.index('insert').split('.')[0])
|
|
319
|
+
if linenum != self._linenum:
|
|
320
|
+
self._clear_tags(linenum)
|
|
321
|
+
self._analyze_line(self._linenum)
|
|
322
|
+
self._linenum = linenum
|
|
323
|
+
|
|
324
|
+
def _replace_arrows(self, *e):
|
|
325
|
+
"""
|
|
326
|
+
Replace any ``'->'`` text strings with arrows (char \\256, in
|
|
327
|
+
symbol font). This searches the whole buffer, but is fast
|
|
328
|
+
enough to be done anytime they press '>'.
|
|
329
|
+
"""
|
|
330
|
+
arrow = '1.0'
|
|
331
|
+
while True:
|
|
332
|
+
arrow = self._textwidget.search('->', arrow, 'end+1char')
|
|
333
|
+
if arrow == '': break
|
|
334
|
+
self._textwidget.delete(arrow, arrow+'+2char')
|
|
335
|
+
self._textwidget.insert(arrow, self.ARROW, 'arrow')
|
|
336
|
+
self._textwidget.insert(arrow, '\t')
|
|
337
|
+
|
|
338
|
+
arrow = '1.0'
|
|
339
|
+
while True:
|
|
340
|
+
arrow = self._textwidget.search(self.ARROW, arrow+'+1char',
|
|
341
|
+
'end+1char')
|
|
342
|
+
if arrow == '': break
|
|
343
|
+
self._textwidget.tag_add('arrow', arrow, arrow+'+1char')
|
|
344
|
+
|
|
345
|
+
def _analyze_token(self, match, linenum):
|
|
346
|
+
"""
|
|
347
|
+
Given a line number and a regexp match for a token on that
|
|
348
|
+
line, colorize the token. Note that the regexp match gives us
|
|
349
|
+
the token's text, start index (on the line), and end index (on
|
|
350
|
+
the line).
|
|
351
|
+
"""
|
|
352
|
+
# What type of token is it?
|
|
353
|
+
if match.group()[0] in "'\"": tag = 'terminal'
|
|
354
|
+
elif match.group() in ('->', self.ARROW): tag = 'arrow'
|
|
355
|
+
else:
|
|
356
|
+
# If it's a nonterminal, then set up new bindings, so we
|
|
357
|
+
# can highlight all instances of that nonterminal when we
|
|
358
|
+
# put the mouse over it.
|
|
359
|
+
tag = 'nonterminal_'+match.group()
|
|
360
|
+
if tag not in self._textwidget.tag_names():
|
|
361
|
+
self._init_nonterminal_tag(tag)
|
|
362
|
+
|
|
363
|
+
start = '%d.%d' % (linenum, match.start())
|
|
364
|
+
end = '%d.%d' % (linenum, match.end())
|
|
365
|
+
self._textwidget.tag_add(tag, start, end)
|
|
366
|
+
|
|
367
|
+
def _init_nonterminal_tag(self, tag, foreground='blue'):
|
|
368
|
+
self._textwidget.tag_config(tag, foreground=foreground,
|
|
369
|
+
font=CFGEditor._BOLD)
|
|
370
|
+
if not self._highlight_matching_nonterminals:
|
|
371
|
+
return
|
|
372
|
+
def enter(e, textwidget=self._textwidget, tag=tag):
|
|
373
|
+
textwidget.tag_config(tag, background='#80ff80')
|
|
374
|
+
def leave(e, textwidget=self._textwidget, tag=tag):
|
|
375
|
+
textwidget.tag_config(tag, background='')
|
|
376
|
+
self._textwidget.tag_bind(tag, '<Enter>', enter)
|
|
377
|
+
self._textwidget.tag_bind(tag, '<Leave>', leave)
|
|
378
|
+
|
|
379
|
+
def _analyze_line(self, linenum):
|
|
380
|
+
"""
|
|
381
|
+
Colorize a given line.
|
|
382
|
+
"""
|
|
383
|
+
# Get rid of any tags that were previously on the line.
|
|
384
|
+
self._clear_tags(linenum)
|
|
385
|
+
|
|
386
|
+
# Get the line line's text string.
|
|
387
|
+
line = self._textwidget.get(repr(linenum)+'.0', repr(linenum)+'.end')
|
|
388
|
+
|
|
389
|
+
# If it's a valid production, then colorize each token.
|
|
390
|
+
if CFGEditor._PRODUCTION_RE.match(line):
|
|
391
|
+
# It's valid; Use _TOKEN_RE to tokenize the production,
|
|
392
|
+
# and call analyze_token on each token.
|
|
393
|
+
def analyze_token(match, self=self, linenum=linenum):
|
|
394
|
+
self._analyze_token(match, linenum)
|
|
395
|
+
return ''
|
|
396
|
+
CFGEditor._TOKEN_RE.sub(analyze_token, line)
|
|
397
|
+
elif line.strip() != '':
|
|
398
|
+
# It's invalid; show the user where the error is.
|
|
399
|
+
self._mark_error(linenum, line)
|
|
400
|
+
|
|
401
|
+
def _mark_error(self, linenum, line):
|
|
402
|
+
"""
|
|
403
|
+
Mark the location of an error in a line.
|
|
404
|
+
"""
|
|
405
|
+
arrowmatch = CFGEditor._ARROW_RE.search(line)
|
|
406
|
+
if not arrowmatch:
|
|
407
|
+
# If there's no arrow at all, highlight the whole line.
|
|
408
|
+
start = '%d.0' % linenum
|
|
409
|
+
end = '%d.end' % linenum
|
|
410
|
+
elif not CFGEditor._LHS_RE.match(line):
|
|
411
|
+
# Otherwise, if the LHS is bad, highlight it.
|
|
412
|
+
start = '%d.0' % linenum
|
|
413
|
+
end = '%d.%d' % (linenum, arrowmatch.start())
|
|
414
|
+
else:
|
|
415
|
+
# Otherwise, highlight the RHS.
|
|
416
|
+
start = '%d.%d' % (linenum, arrowmatch.end())
|
|
417
|
+
end = '%d.end' % linenum
|
|
418
|
+
|
|
419
|
+
# If we're highlighting 0 chars, highlight the whole line.
|
|
420
|
+
if self._textwidget.compare(start, '==', end):
|
|
421
|
+
start = '%d.0' % linenum
|
|
422
|
+
end = '%d.end' % linenum
|
|
423
|
+
self._textwidget.tag_add('error', start, end)
|
|
424
|
+
|
|
425
|
+
def _analyze(self, *e):
|
|
426
|
+
"""
|
|
427
|
+
Replace ``->`` with arrows, and colorize the entire buffer.
|
|
428
|
+
"""
|
|
429
|
+
self._replace_arrows()
|
|
430
|
+
numlines = int(self._textwidget.index('end').split('.')[0])
|
|
431
|
+
for linenum in range(1, numlines+1): # line numbers start at 1.
|
|
432
|
+
self._analyze_line(linenum)
|
|
433
|
+
|
|
434
|
+
def _parse_productions(self):
|
|
435
|
+
"""
|
|
436
|
+
Parse the current contents of the textwidget buffer, to create
|
|
437
|
+
a list of productions.
|
|
438
|
+
"""
|
|
439
|
+
productions = []
|
|
440
|
+
|
|
441
|
+
# Get the text, normalize it, and split it into lines.
|
|
442
|
+
text = self._textwidget.get('1.0', 'end')
|
|
443
|
+
text = re.sub(self.ARROW, '->', text)
|
|
444
|
+
text = re.sub('\t', ' ', text)
|
|
445
|
+
lines = text.split('\n')
|
|
446
|
+
|
|
447
|
+
# Convert each line to a CFG production
|
|
448
|
+
for line in lines:
|
|
449
|
+
line = line.strip()
|
|
450
|
+
if line=='': continue
|
|
451
|
+
productions += _read_cfg_production(line)
|
|
452
|
+
#if line.strip() == '': continue
|
|
453
|
+
#if not CFGEditor._PRODUCTION_RE.match(line):
|
|
454
|
+
# raise ValueError('Bad production string %r' % line)
|
|
455
|
+
#
|
|
456
|
+
#(lhs_str, rhs_str) = line.split('->')
|
|
457
|
+
#lhs = Nonterminal(lhs_str.strip())
|
|
458
|
+
#rhs = []
|
|
459
|
+
#def parse_token(match, rhs=rhs):
|
|
460
|
+
# token = match.group()
|
|
461
|
+
# if token[0] in "'\"": rhs.append(token[1:-1])
|
|
462
|
+
# else: rhs.append(Nonterminal(token))
|
|
463
|
+
# return ''
|
|
464
|
+
#CFGEditor._TOKEN_RE.sub(parse_token, rhs_str)
|
|
465
|
+
#
|
|
466
|
+
#productions.append(Production(lhs, *rhs))
|
|
467
|
+
|
|
468
|
+
return productions
|
|
469
|
+
|
|
470
|
+
def _destroy(self, *e):
|
|
471
|
+
if self._top is None: return
|
|
472
|
+
self._top.destroy()
|
|
473
|
+
self._top = None
|
|
474
|
+
|
|
475
|
+
def _ok(self, *e):
|
|
476
|
+
self._apply()
|
|
477
|
+
self._destroy()
|
|
478
|
+
|
|
479
|
+
def _apply(self, *e):
|
|
480
|
+
productions = self._parse_productions()
|
|
481
|
+
start = Nonterminal(self._start.get())
|
|
482
|
+
cfg = CFG(start, productions)
|
|
483
|
+
if self._set_cfg_callback is not None:
|
|
484
|
+
self._set_cfg_callback(cfg)
|
|
485
|
+
|
|
486
|
+
def _reset(self, *e):
|
|
487
|
+
self._textwidget.delete('1.0', 'end')
|
|
488
|
+
for production in self._cfg.productions():
|
|
489
|
+
self._textwidget.insert('end', '%s\n' % production)
|
|
490
|
+
self._analyze()
|
|
491
|
+
if self._set_cfg_callback is not None:
|
|
492
|
+
self._set_cfg_callback(self._cfg)
|
|
493
|
+
|
|
494
|
+
def _cancel(self, *e):
|
|
495
|
+
try: self._reset()
|
|
496
|
+
except: pass
|
|
497
|
+
self._destroy()
|
|
498
|
+
|
|
499
|
+
def _help(self, *e):
|
|
500
|
+
# The default font's not very legible; try using 'fixed' instead.
|
|
501
|
+
try:
|
|
502
|
+
ShowText(self._parent, 'Help: Chart Parser Demo',
|
|
503
|
+
(_CFGEditor_HELP).strip(), width=75, font='fixed')
|
|
504
|
+
except:
|
|
505
|
+
ShowText(self._parent, 'Help: Chart Parser Demo',
|
|
506
|
+
(_CFGEditor_HELP).strip(), width=75)
|
|
507
|
+
|
|
508
|
+
######################################################################
|
|
509
|
+
# New Demo (built tree based on cfg)
|
|
510
|
+
######################################################################
|
|
511
|
+
|
|
512
|
+
class CFGDemo(object):
|
|
513
|
+
def __init__(self, grammar, text):
|
|
514
|
+
self._grammar = grammar
|
|
515
|
+
self._text = text
|
|
516
|
+
|
|
517
|
+
# Set up the main window.
|
|
518
|
+
self._top = Tk()
|
|
519
|
+
self._top.title('Context Free Grammar Demo')
|
|
520
|
+
|
|
521
|
+
# Base font size
|
|
522
|
+
self._size = IntVar(self._top)
|
|
523
|
+
self._size.set(12) # = medium
|
|
524
|
+
|
|
525
|
+
# Set up the key bindings
|
|
526
|
+
self._init_bindings(self._top)
|
|
527
|
+
|
|
528
|
+
# Create the basic frames
|
|
529
|
+
frame1 = Frame(self._top)
|
|
530
|
+
frame1.pack(side='left', fill='y', expand=0)
|
|
531
|
+
self._init_menubar(self._top)
|
|
532
|
+
self._init_buttons(self._top)
|
|
533
|
+
self._init_grammar(frame1)
|
|
534
|
+
self._init_treelet(frame1)
|
|
535
|
+
self._init_workspace(self._top)
|
|
536
|
+
|
|
537
|
+
#//////////////////////////////////////////////////
|
|
538
|
+
# Initialization
|
|
539
|
+
#//////////////////////////////////////////////////
|
|
540
|
+
|
|
541
|
+
def _init_bindings(self, top):
|
|
542
|
+
top.bind('<Control-q>', self.destroy)
|
|
543
|
+
|
|
544
|
+
def _init_menubar(self, parent): pass
|
|
545
|
+
|
|
546
|
+
def _init_buttons(self, parent): pass
|
|
547
|
+
|
|
548
|
+
def _init_grammar(self, parent):
|
|
549
|
+
self._prodlist = ProductionList(parent, self._grammar, width=20)
|
|
550
|
+
self._prodlist.pack(side='top', fill='both', expand=1)
|
|
551
|
+
self._prodlist.focus()
|
|
552
|
+
self._prodlist.add_callback('select', self._selectprod_cb)
|
|
553
|
+
self._prodlist.add_callback('move', self._selectprod_cb)
|
|
554
|
+
|
|
555
|
+
def _init_treelet(self, parent):
|
|
556
|
+
self._treelet_canvas = Canvas(parent, background='white')
|
|
557
|
+
self._treelet_canvas.pack(side='bottom', fill='x')
|
|
558
|
+
self._treelet = None
|
|
559
|
+
|
|
560
|
+
def _init_workspace(self, parent):
|
|
561
|
+
self._workspace = CanvasFrame(parent, background='white')
|
|
562
|
+
self._workspace.pack(side='right', fill='both', expand=1)
|
|
563
|
+
self._tree = None
|
|
564
|
+
self.reset_workspace()
|
|
565
|
+
|
|
566
|
+
#//////////////////////////////////////////////////
|
|
567
|
+
# Workspace
|
|
568
|
+
#//////////////////////////////////////////////////
|
|
569
|
+
|
|
570
|
+
def reset_workspace(self):
|
|
571
|
+
c = self._workspace.canvas()
|
|
572
|
+
fontsize = int(self._size.get())
|
|
573
|
+
node_font = ('helvetica', -(fontsize+4), 'bold')
|
|
574
|
+
leaf_font = ('helvetica', -(fontsize+2))
|
|
575
|
+
|
|
576
|
+
# Remove the old tree
|
|
577
|
+
if self._tree is not None:
|
|
578
|
+
self._workspace.remove_widget(self._tree)
|
|
579
|
+
|
|
580
|
+
# The root of the tree.
|
|
581
|
+
start = self._grammar.start().symbol()
|
|
582
|
+
rootnode = TextWidget(c, start, font=node_font, draggable=1)
|
|
583
|
+
|
|
584
|
+
# The leaves of the tree.
|
|
585
|
+
leaves = []
|
|
586
|
+
for word in self._text:
|
|
587
|
+
leaves.append(TextWidget(c, word, font=leaf_font, draggable=1))
|
|
588
|
+
|
|
589
|
+
# Put it all together into one tree
|
|
590
|
+
self._tree = TreeSegmentWidget(c, rootnode, leaves,
|
|
591
|
+
color='white')
|
|
592
|
+
|
|
593
|
+
# Add it to the workspace.
|
|
594
|
+
self._workspace.add_widget(self._tree)
|
|
595
|
+
|
|
596
|
+
# Move the leaves to the bottom of the workspace.
|
|
597
|
+
for leaf in leaves: leaf.move(0,100)
|
|
598
|
+
|
|
599
|
+
#self._nodes = {start:1}
|
|
600
|
+
#self._leaves = dict([(l,1) for l in leaves])
|
|
601
|
+
|
|
602
|
+
def workspace_markprod(self, production):
|
|
603
|
+
pass
|
|
604
|
+
|
|
605
|
+
def _markproduction(self, prod, tree=None):
|
|
606
|
+
if tree is None: tree = self._tree
|
|
607
|
+
for i in range(len(tree.subtrees())-len(prod.rhs())):
|
|
608
|
+
if tree['color', i] == 'white':
|
|
609
|
+
self._markproduction
|
|
610
|
+
|
|
611
|
+
for j, node in enumerate(prod.rhs()):
|
|
612
|
+
widget = tree.subtrees()[i+j]
|
|
613
|
+
if (isinstance(node, Nonterminal) and
|
|
614
|
+
isinstance(widget, TreeSegmentWidget) and
|
|
615
|
+
node.symbol == widget.label().text()):
|
|
616
|
+
pass # matching nonterminal
|
|
617
|
+
elif (isinstance(node, string_types) and
|
|
618
|
+
isinstance(widget, TextWidget) and
|
|
619
|
+
node == widget.text()):
|
|
620
|
+
pass # matching nonterminal
|
|
621
|
+
else: break
|
|
622
|
+
else:
|
|
623
|
+
# Everything matched!
|
|
624
|
+
print('MATCH AT', i)
|
|
625
|
+
|
|
626
|
+
#//////////////////////////////////////////////////
|
|
627
|
+
# Grammar
|
|
628
|
+
#//////////////////////////////////////////////////
|
|
629
|
+
|
|
630
|
+
def _selectprod_cb(self, production):
|
|
631
|
+
canvas = self._treelet_canvas
|
|
632
|
+
|
|
633
|
+
self._prodlist.highlight(production)
|
|
634
|
+
if self._treelet is not None: self._treelet.destroy()
|
|
635
|
+
|
|
636
|
+
# Convert the production to a tree.
|
|
637
|
+
rhs = production.rhs()
|
|
638
|
+
for (i, elt) in enumerate(rhs):
|
|
639
|
+
if isinstance(elt, Nonterminal): elt = Tree(elt)
|
|
640
|
+
tree = Tree(production.lhs().symbol(), *rhs)
|
|
641
|
+
|
|
642
|
+
# Draw the tree in the treelet area.
|
|
643
|
+
fontsize = int(self._size.get())
|
|
644
|
+
node_font = ('helvetica', -(fontsize+4), 'bold')
|
|
645
|
+
leaf_font = ('helvetica', -(fontsize+2))
|
|
646
|
+
self._treelet = tree_to_treesegment(canvas, tree,
|
|
647
|
+
node_font=node_font,
|
|
648
|
+
leaf_font=leaf_font)
|
|
649
|
+
self._treelet['draggable'] = 1
|
|
650
|
+
|
|
651
|
+
# Center the treelet.
|
|
652
|
+
(x1, y1, x2, y2) = self._treelet.bbox()
|
|
653
|
+
w, h = int(canvas['width']), int(canvas['height'])
|
|
654
|
+
self._treelet.move((w-x1-x2)/2, (h-y1-y2)/2)
|
|
655
|
+
|
|
656
|
+
# Mark the places where we can add it to the workspace.
|
|
657
|
+
self._markproduction(production)
|
|
658
|
+
|
|
659
|
+
def destroy(self, *args):
|
|
660
|
+
self._top.destroy()
|
|
661
|
+
|
|
662
|
+
def mainloop(self, *args, **kwargs):
|
|
663
|
+
self._top.mainloop(*args, **kwargs)
|
|
664
|
+
|
|
665
|
+
def demo2():
|
|
666
|
+
from nltk import Nonterminal, Production, CFG
|
|
667
|
+
nonterminals = 'S VP NP PP P N Name V Det'
|
|
668
|
+
(S, VP, NP, PP, P, N, Name, V, Det) = [Nonterminal(s)
|
|
669
|
+
for s in nonterminals.split()]
|
|
670
|
+
productions = (
|
|
671
|
+
# Syntactic Productions
|
|
672
|
+
Production(S, [NP, VP]),
|
|
673
|
+
Production(NP, [Det, N]),
|
|
674
|
+
Production(NP, [NP, PP]),
|
|
675
|
+
Production(VP, [VP, PP]),
|
|
676
|
+
Production(VP, [V, NP, PP]),
|
|
677
|
+
Production(VP, [V, NP]),
|
|
678
|
+
Production(PP, [P, NP]),
|
|
679
|
+
Production(PP, []),
|
|
680
|
+
|
|
681
|
+
Production(PP, ['up', 'over', NP]),
|
|
682
|
+
|
|
683
|
+
# Lexical Productions
|
|
684
|
+
Production(NP, ['I']), Production(Det, ['the']),
|
|
685
|
+
Production(Det, ['a']), Production(N, ['man']),
|
|
686
|
+
Production(V, ['saw']), Production(P, ['in']),
|
|
687
|
+
Production(P, ['with']), Production(N, ['park']),
|
|
688
|
+
Production(N, ['dog']), Production(N, ['statue']),
|
|
689
|
+
Production(Det, ['my']),
|
|
690
|
+
)
|
|
691
|
+
grammar = CFG(S, productions)
|
|
692
|
+
|
|
693
|
+
text = 'I saw a man in the park'.split()
|
|
694
|
+
d=CFGDemo(grammar, text)
|
|
695
|
+
d.mainloop()
|
|
696
|
+
|
|
697
|
+
######################################################################
|
|
698
|
+
# Old Demo
|
|
699
|
+
######################################################################
|
|
700
|
+
|
|
701
|
+
def demo():
|
|
702
|
+
from nltk import Nonterminal, CFG
|
|
703
|
+
nonterminals = 'S VP NP PP P N Name V Det'
|
|
704
|
+
(S, VP, NP, PP, P, N, Name, V, Det) = [Nonterminal(s)
|
|
705
|
+
for s in nonterminals.split()]
|
|
706
|
+
|
|
707
|
+
grammar = CFG.fromstring("""
|
|
708
|
+
S -> NP VP
|
|
709
|
+
PP -> P NP
|
|
710
|
+
NP -> Det N
|
|
711
|
+
NP -> NP PP
|
|
712
|
+
VP -> V NP
|
|
713
|
+
VP -> VP PP
|
|
714
|
+
Det -> 'a'
|
|
715
|
+
Det -> 'the'
|
|
716
|
+
Det -> 'my'
|
|
717
|
+
NP -> 'I'
|
|
718
|
+
N -> 'dog'
|
|
719
|
+
N -> 'man'
|
|
720
|
+
N -> 'park'
|
|
721
|
+
N -> 'statue'
|
|
722
|
+
V -> 'saw'
|
|
723
|
+
P -> 'in'
|
|
724
|
+
P -> 'up'
|
|
725
|
+
P -> 'over'
|
|
726
|
+
P -> 'with'
|
|
727
|
+
""")
|
|
728
|
+
|
|
729
|
+
def cb(grammar): print(grammar)
|
|
730
|
+
top = Tk()
|
|
731
|
+
editor = CFGEditor(top, grammar, cb)
|
|
732
|
+
Label(top, text='\nTesting CFG Editor\n').pack()
|
|
733
|
+
Button(top, text='Quit', command=top.destroy).pack()
|
|
734
|
+
top.mainloop()
|
|
735
|
+
|
|
736
|
+
def demo3():
|
|
737
|
+
from nltk import Production
|
|
738
|
+
(S, VP, NP, PP, P, N, Name, V, Det) = \
|
|
739
|
+
nonterminals('S, VP, NP, PP, P, N, Name, V, Det')
|
|
740
|
+
|
|
741
|
+
productions = (
|
|
742
|
+
# Syntactic Productions
|
|
743
|
+
Production(S, [NP, VP]),
|
|
744
|
+
Production(NP, [Det, N]),
|
|
745
|
+
Production(NP, [NP, PP]),
|
|
746
|
+
Production(VP, [VP, PP]),
|
|
747
|
+
Production(VP, [V, NP, PP]),
|
|
748
|
+
Production(VP, [V, NP]),
|
|
749
|
+
Production(PP, [P, NP]),
|
|
750
|
+
Production(PP, []),
|
|
751
|
+
|
|
752
|
+
Production(PP, ['up', 'over', NP]),
|
|
753
|
+
|
|
754
|
+
# Lexical Productions
|
|
755
|
+
Production(NP, ['I']), Production(Det, ['the']),
|
|
756
|
+
Production(Det, ['a']), Production(N, ['man']),
|
|
757
|
+
Production(V, ['saw']), Production(P, ['in']),
|
|
758
|
+
Production(P, ['with']), Production(N, ['park']),
|
|
759
|
+
Production(N, ['dog']), Production(N, ['statue']),
|
|
760
|
+
Production(Det, ['my']),
|
|
761
|
+
)
|
|
762
|
+
|
|
763
|
+
t = Tk()
|
|
764
|
+
def destroy(e, t=t): t.destroy()
|
|
765
|
+
t.bind('q', destroy)
|
|
766
|
+
p = ProductionList(t, productions)
|
|
767
|
+
p.pack(expand=1, fill='both')
|
|
768
|
+
p.add_callback('select', p.markonly)
|
|
769
|
+
p.add_callback('move', p.markonly)
|
|
770
|
+
p.focus()
|
|
771
|
+
p.mark(productions[2])
|
|
772
|
+
p.mark(productions[8])
|
|
773
|
+
|
|
774
|
+
if __name__ == '__main__': demo()
|