├── .gitignore ├── .travis.yml ├── Digger - Markdown Online Editor.url ├── LICENSE ├── NltkNet.csproj.nuspec ├── NltkNet.sln ├── NltkNet ├── Helpers │ ├── BaseClasses.cs │ ├── Extensions.cs │ └── NltkResult.cs ├── Nltk │ ├── Nltk.Classify.cs │ ├── Nltk.Corpus.cs │ ├── Nltk.Probability.cs │ ├── Nltk.Stem.cs │ ├── Nltk.Tag.cs │ ├── Nltk.Tokenize.cs │ └── Nltk.cs ├── NltkNet.csproj ├── NltkNet.nuspec ├── Properties │ └── AssemblyInfo.cs ├── Python │ └── BuiltIns.cs ├── PythonWrapper.cs ├── README.md └── package.nuspec ├── README.md ├── SampleApp ├── App.config ├── App.xaml ├── App.xaml.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── SampleApp.csproj └── packages.config ├── TestApp ├── Program.cs ├── TestApp.csproj ├── Tests │ ├── TestBuiltIn.cs │ ├── TestClassify.cs │ ├── TestCorpus.cs │ └── TestProbability.cs ├── Workarounds.cs └── files │ └── test.txt ├── click-8.1.8-py3-none-any.whl ├── colorama-0.4.6-py2.py3-none-any.whl ├── icon.png ├── ironpkg-1.0.0.py ├── joblib-1.4.2-py3-none-any.whl ├── nltk-3.9.1-py3-none-any.whl ├── regex-2024.11.6-cp312-cp312-win_amd64.whl ├── small_icon.png └── tqdm-4.67.1-py3-none-any.whl /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | NltkNet README.docx 332 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrcpp/NltkNet/1634e537a0f263869d1b6661e72f60e5e4245260/.travis.yml -------------------------------------------------------------------------------- /Digger - Markdown Online Editor.url: -------------------------------------------------------------------------------- 1 | [{000214A0-0000-0000-C000-000000000046}] 2 | Prop3=19,11 3 | [InternetShortcut] 4 | IDList= 5 | URL=https://dillinger.io/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Denis Kazakov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NltkNet.csproj.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | NltkNet.csproj 5 | 1.0.0 6 | nrcpp 7 | nrcpp 8 | http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE 9 | http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE 10 | http://ICON_URL_HERE_OR_DELETE_THIS_LINE 11 | false 12 | Package description 13 | Summary of changes made in this release of the package. 14 | Copyright 2018 15 | Tag1 Tag2 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /NltkNet.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.13.35828.75 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NltkNet", "NltkNet\NltkNet.csproj", "{9803F52C-3ABD-446F-AD0F-4C5C9B615780}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApp", "TestApp\TestApp.csproj", "{9E113B4F-0C4B-4055-82A7-D34880C150E9}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{78389EC9-36C3-4870-8CE2-C8B203933F2E}" 11 | ProjectSection(SolutionItems) = preProject 12 | README.md = README.md 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {9803F52C-3ABD-446F-AD0F-4C5C9B615780}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {9803F52C-3ABD-446F-AD0F-4C5C9B615780}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {9803F52C-3ABD-446F-AD0F-4C5C9B615780}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {9803F52C-3ABD-446F-AD0F-4C5C9B615780}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {9E113B4F-0C4B-4055-82A7-D34880C150E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {9E113B4F-0C4B-4055-82A7-D34880C150E9}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {9E113B4F-0C4B-4055-82A7-D34880C150E9}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {9E113B4F-0C4B-4055-82A7-D34880C150E9}.Release|Any CPU.Build.0 = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | GlobalSection(ExtensibilityGlobals) = postSolution 34 | SolutionGuid = {890AC7EA-003C-4572-A6C7-065FA6411C9D} 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /NltkNet/Helpers/BaseClasses.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Dynamic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace NltkNet 10 | { 11 | public static partial class Nltk 12 | { 13 | /// 14 | /// Class that could be expanded with additional properties and methods 15 | /// 16 | public class NltkDynamicObject : DynamicObject 17 | { 18 | protected readonly Dictionary _dictionary = new Dictionary(); 19 | 20 | public override bool TryGetMember(GetMemberBinder binder, out object result) 21 | { 22 | _dictionary.TryGetValue(binder.Name, out result); 23 | return true; 24 | } 25 | 26 | public override bool TrySetMember(SetMemberBinder binder, object value) 27 | { 28 | _dictionary[binder.Name] = value; 29 | return true; 30 | } 31 | } 32 | 33 | 34 | public class NltkClass 35 | { 36 | public dynamic PyObject { get; protected set; } 37 | 38 | protected NltkClass(params object[] args) 39 | { 40 | PyObject = CreateNltkObject(typeof(T).Name, args); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /NltkNet/Helpers/Extensions.cs: -------------------------------------------------------------------------------- 1 | using IronPython.Hosting; 2 | using IronPython.Runtime; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Dynamic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace NltkNet 11 | { 12 | public static partial class Nltk 13 | { 14 | public static IEnumerable ToEnumerable(this IEnumerator enumerator) 15 | { 16 | while (enumerator.MoveNext()) 17 | { 18 | yield return enumerator.Current; 19 | } 20 | } 21 | 22 | #region From Python To .NET types converters 23 | 24 | public static Dictionary ToNetDictionary(IronPython.Runtime.List list) 25 | { 26 | Dictionary result = new Dictionary(); 27 | foreach (PythonTuple item in list) 28 | { 29 | result.Add((T1)item[0], (T2)item[1]); 30 | } 31 | 32 | return result; 33 | } 34 | 35 | public static List ToNetList(this IronPython.Runtime.List list) 36 | => list.Cast().ToList(); 37 | 38 | public static List ToNetList(this PythonGenerator generatorObj, Func converter) 39 | { 40 | var result = new List(); 41 | foreach (T item in generatorObj) 42 | result.Add(converter(item)); 43 | return result; 44 | } 45 | 46 | 47 | public static List> ToNetListTuple(this PythonGenerator generatorObj) 48 | { 49 | List> result = new List>(); 50 | foreach (PythonTuple item in generatorObj) 51 | { 52 | result.Add(new Tuple((T1)item[0], (T2)item[1])); 53 | } 54 | 55 | return result; 56 | } 57 | 58 | public static List> ToNetListTupleIntInt(dynamic generatorObj) => ToNetListTuple(generatorObj); 59 | 60 | #endregion 61 | 62 | 63 | #region from C# to Python extensions 64 | 65 | public static IronPython.Runtime.List ToIronPythonList(this IEnumerable list) 66 | { 67 | var result = new IronPython.Runtime.List(); 68 | 69 | foreach (var item in list) 70 | result.Add(item); 71 | 72 | return result; 73 | } 74 | 75 | #endregion 76 | 77 | 78 | #region C#-only extensions 79 | 80 | private readonly static Random _random = new Random(); 81 | 82 | public static void Shuffle(this IList list) 83 | { 84 | int n = list.Count; 85 | while (n > 1) 86 | { 87 | n--; 88 | int k = _random.Next(n + 1); 89 | T value = list[k]; 90 | list[k] = list[n]; 91 | list[n] = value; 92 | } 93 | } 94 | 95 | #endregion 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /NltkNet/Helpers/NltkResult.cs: -------------------------------------------------------------------------------- 1 | using IronPython.Runtime; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Dynamic; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace NltkNet 11 | { 12 | public static partial class Nltk 13 | { 14 | public class NltkResult : DynamicObject 15 | { 16 | private NetType _asNet; 17 | 18 | public NetType AsNet 19 | { 20 | get 21 | { 22 | // Lazy pattern 23 | if (_asNet == null && ToNetConverter != null) 24 | _asNet = ToNetConverter(AsPython); 25 | 26 | return _asNet; 27 | } 28 | 29 | set => _asNet = value; 30 | } 31 | 32 | public PythonType AsPython { get; set; } 33 | public dynamic AsDynamic => AsPython; 34 | 35 | virtual public Func ToNetConverter { get; set; } 36 | 37 | public NltkResult() 38 | { 39 | } 40 | 41 | public NltkResult(NetType netValue, PythonType pythonValue) 42 | { 43 | AsNet = netValue; 44 | AsPython = pythonValue; 45 | } 46 | 47 | public NltkResult(Func converter, PythonType pythonValue) 48 | { 49 | ToNetConverter = (Func)converter; 50 | AsPython = pythonValue; 51 | } 52 | 53 | #region DynamicObject overrides 54 | 55 | public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) 56 | { 57 | MethodInfo method = AsPython.GetType().GetMethod(binder.Name); 58 | result = method.Invoke(AsPython, args); 59 | return true; 60 | } 61 | 62 | 63 | // TODO: access multi-dimesional 64 | // https://stackoverflow.com/questions/2783502/c-sharp-using-the-dynamic-keyword-to-access-properties-via-strings-without-refle 65 | public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) 66 | { 67 | result = AsDynamic[indexes[0]]; 68 | return true; 69 | } 70 | 71 | public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) 72 | { 73 | AsDynamic[indexes[0]] = value; 74 | return true; 75 | } 76 | 77 | public override bool TryGetMember(GetMemberBinder binder, out object result) 78 | { 79 | result = AsPython.GetType().GetProperty(binder.Name).GetValue(AsPython); 80 | return true; 81 | } 82 | 83 | public override bool TrySetMember(SetMemberBinder binder, object value) 84 | { 85 | AsPython.GetType().GetProperty(binder.Name).SetValue(AsPython, value); 86 | return true; 87 | } 88 | 89 | #endregion 90 | } 91 | 92 | public class NltkResult : NltkResult { } 93 | 94 | public class NltkResult : NltkResult { } 95 | 96 | public class NltkResultTupleStrStr : NltkResult<(string, string), dynamic> 97 | { 98 | public override Func ToNetConverter => tuple => ValueTuple.Create((string)tuple[0], (string)tuple[1]); 99 | } 100 | 101 | public class NltkResultListString : NltkResult, IronPython.Runtime.List> 102 | { 103 | public override Func> ToNetConverter => list => list.Cast().ToList(); 104 | } 105 | 106 | public class NltkResultListStringDynamic : NltkResult, dynamic> 107 | { 108 | public override Func> ToNetConverter => list => 109 | { 110 | List result = new List(); 111 | foreach (var item in list) 112 | result.Add((string)item); 113 | return result; 114 | }; 115 | } 116 | 117 | 118 | public class NltkResultListListString : NltkResult>, dynamic> 119 | { 120 | public override Func>> ToNetConverter 121 | => listOflistOfStr => Convert(listOflistOfStr); 122 | 123 | static List> Convert(dynamic listOflistOfStr) 124 | { 125 | var result = new List>(); 126 | foreach (var s in listOflistOfStr) 127 | { 128 | var words = new List(); 129 | foreach (var w in s) 130 | words.Add((string)w); 131 | 132 | result.Add(words); 133 | } 134 | 135 | return result; 136 | } 137 | } 138 | 139 | 140 | public class NltkResultListListListString : NltkResult>>, dynamic> 141 | { 142 | public override Func>>> ToNetConverter => listOflistOflistOfStr => Convert(listOflistOflistOfStr); 143 | 144 | static List>> Convert(dynamic listOflistOflistOfStr) 145 | { 146 | var result = new List>>(); 147 | foreach (var p in listOflistOflistOfStr) 148 | { 149 | var sents = new List>(); 150 | foreach (var s in p) 151 | { 152 | var words = new List(); 153 | foreach (var w in s) 154 | words.Add((string)w); 155 | 156 | sents.Add(words); 157 | } 158 | 159 | result.Add(sents); 160 | } 161 | 162 | return result; 163 | } 164 | } 165 | 166 | 167 | public class NltkResultListTupleStringString : NltkResult>, dynamic> 168 | { 169 | public override Func>> ToNetConverter => 170 | tupleStrStr => Convert(tupleStrStr); 171 | 172 | static List> Convert(dynamic tupleStrStr) 173 | { 174 | List> result = new List>(); 175 | 176 | foreach (var tw in tupleStrStr) 177 | { 178 | var wordTag = new Tuple(tw[0], tw[1]); 179 | result.Add(wordTag); 180 | } 181 | 182 | return result; 183 | } 184 | } 185 | 186 | // list of list of tuple str str 187 | public class NltkResultListListTupleStringString : NltkResult>, dynamic> 188 | { 189 | public override Func>> ToNetConverter => 190 | tupleStrStr => Convert(tupleStrStr); 191 | 192 | static List> Convert(dynamic listOfListOftupleStrStr) 193 | { 194 | var result = new List>(); 195 | 196 | foreach (var listOfList in listOfListOftupleStrStr) 197 | { 198 | var taggedSent = new List<(string, string)>(); 199 | foreach (var sent in listOfList) 200 | { 201 | taggedSent.Add((sent[0], sent[1])); 202 | } 203 | 204 | result.Add(taggedSent); 205 | } 206 | 207 | 208 | return result; 209 | } 210 | } 211 | 212 | 213 | public class NltkResultDictionaryStringInt : NltkResult, dynamic> 214 | { 215 | public override Func> ToNetConverter => 216 | listOftupleStrInt => Nltk.ToNetDictionary(listOftupleStrInt); 217 | } 218 | 219 | public class NltkResultListTupleIntInt : NltkResult>, dynamic> 220 | { 221 | public override Func>> ToNetConverter => 222 | listOftupleIntInt => Nltk.ToNetListTuple(listOftupleIntInt); 223 | } 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /NltkNet/Nltk/Nltk.Classify.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NltkNet 8 | { 9 | public partial class Nltk 10 | { 11 | public static class Classify 12 | { 13 | public readonly static dynamic Module; 14 | 15 | static Classify() 16 | { 17 | Module = BuiltIns.ImportNames("nltk.classify"); 18 | } 19 | 20 | // accuracy(classifier, test_set)) 21 | public static dynamic Accuracy(dynamic classifier, dynamic test_set) 22 | { 23 | dynamic classify = BuiltIns.ImportNames("nltk.classify", "accuracy"); 24 | return classify.accuracy(classifier, test_set); 25 | } 26 | 27 | public static class NaiveBayes 28 | { 29 | public readonly static dynamic Module; 30 | 31 | static NaiveBayes() 32 | { 33 | Module = BuiltIns.ImportNames("nltk.classify.naivebayes"); 34 | } 35 | 36 | public static class NaiveBayesClassifier 37 | { 38 | public readonly static dynamic Class = BuiltIns.ImportNames("nltk.classify.naivebayes", "NaiveBayesClassifier").NaiveBayesClassifier; 39 | 40 | public static dynamic Train(dynamic featureSet) => Class.train(featureSet); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /NltkNet/Nltk/Nltk.Corpus.cs: -------------------------------------------------------------------------------- 1 | using IronPython.Runtime; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace NltkNet 8 | { 9 | public static partial class Nltk 10 | { 11 | public static class Corpus 12 | { 13 | static Corpus() 14 | { 15 | Py.ImportModule("nltk.corpus"); 16 | } 17 | 18 | /// 19 | /// class nltk.corpus.util.LazyCorpusLoader(name, reader_cls, *args, **kwargs) 20 | /// 21 | public class LazyCorpusLoader : NltkClass 22 | { 23 | public LazyCorpusLoader(string name, object reader_cls, params object[] args) : base(name, reader_cls, args) 24 | { 25 | } 26 | 27 | // TODO: 28 | } 29 | 30 | public class BaseCorpus 31 | { 32 | public string CorpusName { get; } 33 | public dynamic CorpusObj { get; } 34 | 35 | protected BaseCorpus(string name) 36 | { 37 | CorpusName = name; 38 | 39 | Py.ExecuteScript($"from nltk.corpus import {name}"); 40 | CorpusObj = Py.GetVariable(name); 41 | } 42 | 43 | public NltkResultListString FileIds() 44 | { 45 | var words = Py.CallMethod(CorpusObj, "fileids"); 46 | 47 | return new NltkResultListString() 48 | { 49 | AsPython = words, 50 | }; 51 | } 52 | 53 | public NltkResultListStringDynamic Words(string fileid = null) 54 | { 55 | var words = Py.CallMethod(CorpusObj, "words", fileid); 56 | 57 | return new NltkResultListStringDynamic() 58 | { 59 | AsPython = words, 60 | }; 61 | } 62 | 63 | 64 | // list of(list of str) 65 | public NltkResultListListString Sents(string fileid = null) 66 | { 67 | var sents = Py.CallMethod(CorpusObj, "sents", fileid); 68 | 69 | return new NltkResultListListString() 70 | { 71 | AsPython = (dynamic)sents 72 | }; 73 | } 74 | 75 | 76 | // paras() : list of(list of (list of str)) 77 | public NltkResultListListListString Paras(string fileid = null) 78 | { 79 | var paras = Py.CallMethod(CorpusObj, "paras", fileid); 80 | 81 | return new NltkResultListListListString() 82 | { 83 | AsPython = paras, 84 | }; 85 | } 86 | 87 | public string Raw(string fileid) => Py.CallMethod(CorpusObj, "raw", fileid); 88 | 89 | public virtual NltkResultListTupleStringString TaggedWords(string fileid = null) 90 | { 91 | var taggedWords = Py.CallMethod(CorpusObj, "tagged_words", fileid); 92 | 93 | return new NltkResultListTupleStringString() 94 | { 95 | AsPython = taggedWords, 96 | }; 97 | } 98 | } 99 | 100 | public class Brown : BaseCorpus 101 | { 102 | public Brown() : base("brown") { } 103 | 104 | 105 | public NltkResultListListTupleStringString TaggedSents(List fileids = null, string categories = null, string tagset = null) 106 | { 107 | var taggedSents = Py.CallMethod(CorpusObj, "tagged_sents", fileids, categories); 108 | 109 | return new NltkResultListListTupleStringString() 110 | { 111 | AsPython = taggedSents, 112 | }; 113 | } 114 | } 115 | 116 | public class Gutenberg : BaseCorpus 117 | { 118 | public Gutenberg() : base("gutenberg") { } 119 | } 120 | 121 | public class StopWords : BaseCorpus 122 | { 123 | public StopWords() : base("stopwords") { } 124 | 125 | public NltkResultListStringDynamic EnglishWords() => Words("english"); 126 | } 127 | 128 | public class Inaugural : BaseCorpus 129 | { 130 | public Inaugural() : base("inaugural") { } 131 | } 132 | 133 | public class WebText : BaseCorpus 134 | { 135 | public WebText() : base("webtext") { } 136 | } 137 | 138 | public class NpsChat : BaseCorpus 139 | { 140 | public NpsChat() : base("nps_chat") { } 141 | } 142 | 143 | public class Words : BaseCorpus 144 | { 145 | public Words() : base("words") { } 146 | } 147 | 148 | public class Timit : BaseCorpus 149 | { 150 | public Timit() : base("timit") { } 151 | } 152 | 153 | public class Names : BaseCorpus 154 | { 155 | public Names() : base("names") { } 156 | } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /NltkNet/Nltk/Nltk.Probability.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace NltkNet 7 | { 8 | public static partial class Nltk 9 | { 10 | public static class Probability 11 | { 12 | public class FreqDist : NltkClass 13 | { 14 | public FreqDist(object samples) : base(samples) 15 | { 16 | } 17 | 18 | public NltkResultDictionaryStringInt MostCommon(int? number = null) 19 | { 20 | var dict = PyObject.most_common(number); 21 | 22 | return new NltkResultDictionaryStringInt() 23 | { 24 | AsPython = dict 25 | }; 26 | } 27 | } 28 | 29 | 30 | public class ConditionalFreqDist : NltkClass 31 | { 32 | public ConditionalFreqDist() : base() 33 | { 34 | } 35 | 36 | public ConditionalFreqDist(string pythonExpresion) 37 | { 38 | if (pythonExpresion != null) 39 | { 40 | dynamic expr = Py.ExecuteScript(pythonExpresion); 41 | PyObject = CreateNltkObject(nameof(ConditionalFreqDist), expr); 42 | } 43 | 44 | } 45 | 46 | int N() => PyObject.N(); 47 | 48 | public dynamic Hapaxes() => PyObject.hapaxes(); 49 | 50 | public void AddCondition(object conditionKey, string word) 51 | { 52 | var pyCondition = PyObject[conditionKey]; 53 | 54 | pyCondition[word] += 1; 55 | } 56 | 57 | public dynamic this[object conditionKey] 58 | { 59 | get => PyObject[conditionKey]; 60 | } 61 | 62 | //{ 63 | // get 64 | // { 65 | // var condition = PyObject[word]; 66 | // if (condition == null || condition == 0) 67 | // condition = PyObject[word] = new Dictionary(); 68 | 69 | // return condition; 70 | // } 71 | 72 | // set 73 | // { 74 | // AddCondition((string)word, value); 75 | // } 76 | //} 77 | 78 | public NltkResult MostCommon(int? number = null) 79 | { 80 | var dict = PyObject.most_common(number); 81 | 82 | return new NltkResult() 83 | { 84 | AsPython = dict 85 | }; 86 | } 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /NltkNet/Nltk/Nltk.Stem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace NltkNet 7 | { 8 | public static partial class Nltk 9 | { 10 | public static class Stem 11 | { 12 | public class PorterStemmer : NltkClass 13 | { 14 | public string Stem(string word) => PyObject.stem(word); 15 | } 16 | 17 | public class WordNetLemmatizer : NltkClass 18 | { 19 | public string Lemmatize(string word) => PyObject.lemmatize(word); 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /NltkNet/Nltk/Nltk.Tag.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NltkNet 8 | { 9 | public static partial class Nltk 10 | { 11 | //nltk.tag 12 | public static class Tag 13 | { 14 | static Tag() 15 | { 16 | Py.ImportModule("nltk.tag"); 17 | Py.ExecuteScript($"from nltk.tag import str2tuple"); 18 | } 19 | 20 | public static NltkResultTupleStrStr Str2Tuple(string str) 21 | { 22 | var str2tuple = Py.GetVariable("str2tuple"); 23 | 24 | var result = str2tuple(str); 25 | return new NltkResultTupleStrStr() 26 | { 27 | AsPython = result, 28 | AsNet = ValueTuple.Create((string)result[0], (string)result[1]) 29 | }; 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /NltkNet/Nltk/Nltk.Tokenize.cs: -------------------------------------------------------------------------------- 1 | using IronPython.Runtime; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace NltkNet 8 | { 9 | public static partial class Nltk 10 | { 11 | public static class Tokenize 12 | { 13 | private static NltkResultListString TokenizeCall(string funcName, string text) 14 | { 15 | IronPython.Runtime.List list = Call(funcName, text); 16 | 17 | return new NltkResultListString() 18 | { 19 | AsPython = list, 20 | }; 21 | } 22 | 23 | public static NltkResultListString WordTokenize(string text) => TokenizeCall("word_tokenize", text); 24 | 25 | public static NltkResultListString WordpunctTokenize(string text) => TokenizeCall("wordpunct_tokenize", text); 26 | 27 | public static NltkResultListString SentTokenize(string text) => TokenizeCall("sent_tokenize", text); 28 | 29 | 30 | public static class Util 31 | { 32 | public static NltkResultListTupleIntInt RegexpSpanTokenize(string text, string regexp) 33 | { 34 | PythonGenerator generator = Call("regexp_span_tokenize", text, regexp); 35 | 36 | return new NltkResultListTupleIntInt() 37 | { 38 | AsPython = generator, 39 | }; 40 | } 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /NltkNet/Nltk/Nltk.cs: -------------------------------------------------------------------------------- 1 | using IronPython.Runtime; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Text; 8 | 9 | namespace NltkNet 10 | { 11 | public static partial class Nltk 12 | { 13 | public static PythonWrapper Py { get; private set; } 14 | 15 | public static void Init(List libsPaths) 16 | { 17 | Py = new PythonWrapper(); 18 | Py.AddLibPaths(libsPaths); 19 | 20 | // resolves assembly for NumPy/SciPy 21 | InitAssemblyResolve(); 22 | 23 | Py.ImportModule("nltk"); 24 | Py.SetDefaultModule("nltk"); 25 | 26 | // we need to set os platform to 'win', instead of 'cli' to make it work such things as 'nltk.pos_tag(words)' 27 | Py.ImportModule("sys"); 28 | Py.ExecuteScript("sys.platform = 'win32'"); 29 | } 30 | 31 | private static void InitAssemblyResolve() 32 | { 33 | AppDomain.CurrentDomain.AssemblyResolve += (s, e) => { 34 | var filename = new AssemblyName(e.Name).Name; 35 | var path = $@"C:\Program Files\IronPython 3.4\DLLs\{filename}.dll"; 36 | if (File.Exists(path)) 37 | return Assembly.LoadFrom(path); 38 | return null; 39 | }; 40 | } 41 | 42 | public static dynamic Call(string funcName, params dynamic[] arguments) => Py.CallModuleFunction(funcName, arguments); 43 | public static T Call(string funcName, params dynamic[] arguments) => Py.CallModuleFunction(funcName, arguments); 44 | 45 | public static dynamic CreateNltkObject(string className, params dynamic[] arguments) => Py.CallModuleFunction(className, arguments); 46 | 47 | #region NLTK namespace methods 48 | 49 | public static NltkResultListTupleStringString PosTag(List words) 50 | { 51 | var taggedWords = Py.CallModuleFunction("nltk", "pos_tag", words); 52 | 53 | return new NltkResultListTupleStringString() 54 | { 55 | AsPython = taggedWords 56 | }; 57 | } 58 | 59 | public static dynamic NeChunk(dynamic posTaggedText) 60 | { 61 | var namedEntities = Py.CallModuleFunction("nltk", "ne_chunk", posTaggedText); 62 | 63 | return namedEntities; 64 | } 65 | 66 | 67 | public static class NaiveBayesClassifier 68 | { 69 | public static dynamic Train(dynamic featureSet) => Classify.NaiveBayes.NaiveBayesClassifier.Train(featureSet); 70 | } 71 | 72 | 73 | public class Text : NltkClass 74 | { 75 | public Text(object pyObject) : base(pyObject) 76 | { 77 | } 78 | 79 | public NltkResult Similar(string word) 80 | { 81 | var result = Py.CallMethod(PyObject, "similar", word); 82 | 83 | return new NltkResult() 84 | { 85 | AsPython = result ?? new System.Dynamic.ExpandoObject(), 86 | AsNet = (string)result 87 | }; 88 | } 89 | } 90 | 91 | #endregion 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /NltkNet/NltkNet.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net8.0 4 | latest 5 | Library 6 | false 7 | NltkNet 8 | .NET wrapper for NLTK library written on Python 9 | Denis Kazakov 10 | NltkNet 11 | Copyright © 2019 12 | 1.0.%2a 13 | 1.0.13 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /NltkNet/NltkNet.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE 10 | http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE 11 | http://ICON_URL_HERE_OR_DELETE_THIS_LINE 12 | false 13 | $description$ 14 | Summary of changes made in this release of the package. 15 | Copyright 2018 16 | Tag1 Tag2 17 | 18 | -------------------------------------------------------------------------------- /NltkNet/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrcpp/NltkNet/1634e537a0f263869d1b6661e72f60e5e4245260/NltkNet/Properties/AssemblyInfo.cs -------------------------------------------------------------------------------- /NltkNet/Python/BuiltIns.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace NltkNet 8 | { 9 | public static class BuiltIns 10 | { 11 | static BuiltIns() 12 | { 13 | // built-in functions: print, len 14 | Nltk.Py.ExecuteScript("def __print__(obj):\r\n\tprint obj\r\n" + 15 | "def __len__(obj):\r\n\treturn len(obj)\r\n" + 16 | "def __str__(obj):\r\n\treturn str(obj)\r\n" + 17 | "def __set__(obj):\r\n\treturn set(obj)\r\n" + 18 | "def __list__(obj):\r\n\treturn list(obj)\r\n" + 19 | "def __dict__(*obj):\r\n\treturn dict(*obj)\r\n" + 20 | "def __sorted__(obj):\r\n\treturn sorted(obj)\r\n" + 21 | "def __range__(p1, p2, p3):\r\n\treturn range(start=p1, stop=p2, step=p3)\r\n" + 22 | "def __zip__(*obj):\r\n\treturn zip(*obj)\r\n" + 23 | "def __importfunc__(name, globals, locals, fromlist, level):\r\n\treturn __import__(name, globals, locals, fromlist, level)\r\n" + 24 | "def __globals__():\r\n\treturn globals()\r\n" + 25 | "def __locals__():\r\n\treturn locals()\r\n" 26 | ); 27 | } 28 | 29 | public static void Print(dynamic pyObj) => Nltk.Py.CallFunction("__print__", pyObj); 30 | public static long Len(dynamic pyObj) => Nltk.Py.CallFunction("__len__", pyObj); 31 | public static string Str(dynamic pyObj) => Nltk.Py.CallFunction("__str__", pyObj ?? ""); 32 | public static dynamic Set(dynamic pyObj) => Nltk.Py.CallFunction("__set__", pyObj); 33 | public static dynamic List(dynamic pyObj) => Nltk.Py.CallFunction("__list__", pyObj); 34 | public static dynamic Dict(dynamic pyObj) => Nltk.Py.CallFunction("__dict__", pyObj); 35 | public static dynamic Dict() => Nltk.Py.CallFunction("__dict__"); 36 | public static dynamic Sorted(dynamic pyObj) => Nltk.Py.CallFunction("__sorted__", pyObj); 37 | public static dynamic Range(int start, int stop, int step = 1) => Nltk.Py.CallFunction("__range__", start, stop, step); 38 | public static dynamic Zip(params dynamic[] objects) => Nltk.Py.CallFunction("__zip__", objects); 39 | public static dynamic Import(string name, dynamic globals, dynamic locals, dynamic fromlist, int level) => 40 | Nltk.Py.CallFunction("__importfunc__", name, globals, locals, fromlist, level); 41 | 42 | public static dynamic ImportModule(string name) => ImportNames(name); 43 | public static dynamic ImportNames(string moduleName, params string[] fromList) => Import(moduleName, Globals(), Locals(), fromList, -1); 44 | 45 | public static dynamic Globals() => Nltk.Py.CallFunction("__globals__"); 46 | public static dynamic Locals() => Nltk.Py.CallFunction("__locals__"); 47 | 48 | 49 | public static void InternalTest() 50 | { 51 | 52 | // Test import corpuses 53 | dynamic corpuses = ImportNames("nltk.corpus", "brown", "wordnet" ); 54 | dynamic brown = corpuses.brown; 55 | dynamic wordnet = corpuses.wordnet; 56 | 57 | Print(brown.words()); 58 | 59 | //Print("Len: " + Len(lst)); 60 | //Print("Sorted: " + Str(Sorted(lst))); 61 | //var tuple = (1, 2, "str"); 62 | //Print("Tuple2List: " + tuple); 63 | //Print(List(tuple)); 64 | //Print("Set: " + Str(Set(lst))); 65 | //var range = Range(0, 30, 3); 66 | //Print("Range: " + Str(List(range))); 67 | 68 | //Print("Zip: " + Str(Zip(lst, lst2))); 69 | //Print(Globals()); 70 | Console.ReadLine(); 71 | //Print(Locals()); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /NltkNet/PythonWrapper.cs: -------------------------------------------------------------------------------- 1 | using IronPython.Hosting; 2 | using Microsoft.Scripting.Hosting; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Text; 7 | 8 | namespace NltkNet 9 | { 10 | public class PythonWrapper 11 | { 12 | private ScriptEngine _engine; 13 | private ScriptScope _scope; 14 | private ScriptSource _source; 15 | private CompiledCode _compiled; 16 | private dynamic _pythonClass; 17 | private dynamic _defaultModule; 18 | 19 | public PythonWrapper() 20 | { 21 | _engine = Python.CreateEngine(); 22 | _scope = _engine.CreateScope(); 23 | } 24 | 25 | public void LoadCodeFromFile(string pyfile, string className = null) 26 | { 27 | string code = File.ReadAllText(pyfile); 28 | 29 | dynamic result = ExecuteScript(code); 30 | if (className != null) 31 | _pythonClass = _engine.Operations.Invoke(_scope.GetVariable(className)); 32 | } 33 | 34 | 35 | public dynamic ExecuteScript(string code) 36 | { 37 | _source = _engine.CreateScriptSourceFromString(code, Microsoft.Scripting.SourceCodeKind.Statements); 38 | _compiled = _source.Compile(); 39 | 40 | dynamic result = _compiled.Execute(_scope); 41 | 42 | return result; 43 | } 44 | 45 | 46 | public void ImportModule(string moduleName) => 47 | _scope.ImportModule(moduleName); 48 | 49 | public void AddLibPaths(List libsPaths) 50 | { 51 | if (libsPaths == null || libsPaths.Count == 0) return; 52 | 53 | ICollection searchPaths = _engine.GetSearchPaths(); 54 | 55 | foreach (var path in libsPaths) 56 | { 57 | searchPaths.Add(path); 58 | } 59 | 60 | _engine.SetSearchPaths(searchPaths); 61 | } 62 | 63 | 64 | public void SetVariable(string variable, dynamic value) 65 | { 66 | _scope.SetVariable(variable, value); 67 | } 68 | 69 | public dynamic CreateObject(string className, params dynamic[] parameters) 70 | { 71 | return _engine.Operations.Invoke(_scope.GetVariable(className), parameters); 72 | } 73 | 74 | public void SetDefaultClass(string className, params dynamic[] arguments) 75 | { 76 | _pythonClass = CreateObject(className, arguments); 77 | } 78 | 79 | public void SetDefaultModule(string moduleName) 80 | { 81 | _defaultModule = _scope.GetVariable(moduleName); 82 | } 83 | 84 | public dynamic GetVariable(string variable) 85 | { 86 | return _scope.GetVariable(variable); 87 | } 88 | 89 | public T GetVariable(string variable) 90 | { 91 | return _scope.GetVariable(variable); 92 | } 93 | 94 | // aliases 95 | public T GetFunction(string funcName) => _scope.GetVariable(funcName); 96 | public dynamic GetObject(string objectName) => _scope.GetVariable(objectName); 97 | public dynamic GetModule(string moduleName) => _scope.GetVariable(moduleName); 98 | 99 | 100 | public dynamic CallMethod(dynamic pyObject, string method, params dynamic[] parameters) 101 | { 102 | return _engine.Operations.InvokeMember(pyObject, method, parameters); 103 | } 104 | 105 | public dynamic CallMethod(string method, params dynamic[] parameters) 106 | { 107 | return _engine.Operations.InvokeMember(_pythonClass, method, parameters); 108 | } 109 | 110 | public dynamic CallFunction(string funcName, params dynamic[] parameters) 111 | { 112 | var func = GetVariable(funcName); 113 | return _engine.Operations.Invoke(func, parameters); 114 | } 115 | 116 | public dynamic CallModuleFunction(string moduleName, string funcName, params dynamic[] arguments) 117 | { 118 | var module = GetVariable(moduleName); 119 | return _engine.Operations.InvokeMember(module, funcName, arguments); 120 | } 121 | 122 | 123 | public dynamic CallModuleFunction(string funcName, params dynamic[] arguments) 124 | { 125 | return _engine.Operations.InvokeMember(_defaultModule, funcName, arguments); 126 | } 127 | 128 | public T CallModuleFunction(string funcName, params dynamic[] arguments) => 129 | (T)CallModuleFunction(funcName, arguments); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /NltkNet/README.md: -------------------------------------------------------------------------------- 1 | # NltkNet 2 | [![Build Status](https://travis-ci.com/nrcpp/NltkNet.svg?branch=master)](https://travis-ci.com/nrcpp/NltkNet) 3 | ![NltkNet Logo](https://i.ibb.co/phKzWqj/small-icon.png) 4 | 5 | ### C# wrapper for NLTK library ([http://nltk.org](http://nltk.org)) 6 | 7 | - [Nuget package](https://www.nuget.org/packages/NltkNet/) 8 | 9 | ## **Frameworks supported** 10 | 11 | - .NET 4.5 or later 12 | 13 | ## **Dependencies** 14 | 15 | - [IronPython](https://www.nuget.org/packages/IronPython) - 2.7.9 or later (Includes [DynamicLanguageRuntime](https://www.nuget.org/packages/DynamicLanguageRuntime/)) 16 | - [System.ValueTuple](https://www.nuget.org/packages/System.ValueTuple) - 4.3.0 17 | 18 | ## **Pre-Requirements** 19 | 20 | Before start using NltkNet wrapper it is required to download and install latest IronPython binaries from [official site](http://ironpython.net/). You will need IronPython standard libraries for NLTK, as well as installing NLTK library for IronPython. Also IronPython interpreter will be helpful to test python scripts interactively from Visual Studio or command line. 21 | 22 | It is expectable that most developers already have experience with NLTK library using Python and looking for a way to use in C#. Guides in this section are mostly for a developers who just started learning NLP using NLTK and haven't much experience with Python. 23 | 24 | ### **Installing IronPython** 25 | 26 | - [Download](http://ironpython.net/download/) IronPython MSI package (you could also download ZIP archive) 27 | - Run installer. By default IronPython binaries will be installed to _C:\Program Files \IronPython_ folder. _Tip:_ For your convenience IronPython could be installed to **C:\IronPython27** folder. Further, in examples below we'll use that path for initialization of path to IronPython and NLTK libs. 28 | - Add IronPython installation path to PATH environment variable 29 | 30 | ### **Add IronPython environment to Visual Studio** 31 | 32 | - In order to have ability to run IronPython from _within Visual Studio_ you may add IronPython environment to Python Environments there. 33 | - Use this [documentation](https://docs.microsoft.com/en-us/visualstudio/python/managing-python-environments-in-visual-studio) for details 34 | 35 | ### **Install NLTK library for IronPython** 36 | 37 | There are different ways to install nltk library. If you have experience with using Python and installing packages then everything is clear here. 38 | 39 | - _From Visual Studio._ Make sure you're added IronPython to Python Environments of Visual Studio on the previous step. 40 | - Then go to View->Other Windows->Python Environments to open existing Python Environments. 41 | - Choose IronPython environment and then choose _Packages (PyPi)_ from combobox below 42 | - Type there nltk and choose 'pip install nltk' 43 | - After installing, make sure you have installed nltk folder at <IronPython Path>\Libs\site-packages\nltk 44 | - _From command line using pip._ Run 'pip install nltk' from command line. Path to _Pip.exe_ have to be added to PATH environment variable. If you have several Python environments in system then, make sure you're installing _nltk_ library to IronPython path. 45 | - _From binaries._ Download binaries from [https://pypi.org/project/nltk/#files](https://pypi.org/project/nltk/#files). And run installer or unpack archive to <IronPythonPath>\Libs\site-packages\nltk. See [https://www.nltk.org/install.html](https://www.nltk.org/install.html) for more details. 46 | 47 | ### **Install NLTK corpuses** 48 | 49 | _Corpus_(plural _corpora_) or _text corpus_ is a large and structured set of texts (nowadays usually electronically stored and processed). In corpus linguistics, they are used to do statistical analysis and hypothesis testing, checking occurrences or validating linguistic rules within a specific language territory. 50 | 51 | NLTK library contains lots of ready-to-use corpuses which usually stores as a set of text files. It will be useful to load certain corpus on studying NLP using NLTK library, instead of creating it from scratch. 52 | 53 | If you're using NLTK library for learning NLP, download NLTK _book_ related corpuses and linguistic data. 54 | 55 | Use such script either from *Visual Studio Python Interactive Window* or *Iron Python command line* to do so: 56 | 57 | ```python 58 | import nltk 59 | import nltk.corpus 60 | nltk.download('book') 61 | ``` 62 | 63 | ## Getting Started 64 | 65 | When whole third-party stuff is in-place then we are ready to test NltkNet. Install NltkNet nuget package using your usual way. For example from Package Manager Console by pasting: 66 | 67 | ``` 68 | Install-Package NltkNet 69 | ``` 70 | 71 | **Use this code to initialize paths to IronPython standard and third-party libraries:** 72 | ```C# 73 | using System; 74 | using System.Collections.Generic; 75 | using System.IO; 76 | using System.Linq; 77 | using NltkNet; 78 | 79 | namespace TestApp 80 | { 81 | class Program 82 | { 83 | static void Main(string[] args) 84 | { 85 | Nltk.Init(new List 86 | { 87 | @"C:\IronPython27\Lib", // Path to IronPython standard libraries 88 | @"C:\IronPython27\Lib\site-packages", // Path to IronPython third-party libraries 89 | }); 90 | } 91 | } 92 | } 93 | ``` 94 | 95 | **More practical samples** 96 | ```C# 97 | using System; 98 | using System.Collections.Generic; 99 | using System.Dynamic; 100 | using System.IO; 101 | using System.Linq; 102 | using NltkNet; 103 | 104 | namespace TestApp 105 | { 106 | class Program 107 | { 108 | static string text = "This IronPython script works fine when I run it by itself."; 109 | 110 | private static void TestNltkResultClass() 111 | { 112 | var corpus = new Nltk.Corpus.Inaugural(); 113 | 114 | // example of using NltkResult class 115 | var fileidsResult = corpus.FileIds(); 116 | 117 | // Get .NET List 118 | List fileidsNet = fileidsResult.AsNet; 119 | 120 | // Get IronPython.Runtime.List 121 | IronPython.Runtime.List fileidsPython = fileidsResult.AsPython; 122 | 123 | // Cast to Dynamic to access object fields in Python-like style 124 | dynamic fileids = fileidsResult; 125 | 126 | // using DynamicObject 127 | Console.WriteLine(fileids[0]); 128 | Console.WriteLine(fileids.__len__()); 129 | 130 | // access sentences (list of list of strings) 131 | var sentencesResult = corpus.Sents(); 132 | dynamic sentences = sentencesResult; 133 | 134 | // Manipulating with Python object: first word in first sentense 135 | Console.WriteLine(sentences[0][0]); 136 | List> netSentences = sentencesResult.AsNet; 137 | 138 | Console.WriteLine(netSentences[0][0]); // the same with .NET object 139 | Console.WriteLine(netSentences.First().First()); // using LINQ 140 | } 141 | 142 | static void TestTokenize() 143 | { 144 | var tuples = Nltk.Tokenize.Util.RegexpSpanTokenize(text, "\\s"); 145 | 146 | var list = Nltk.Tokenize.SentTokenize(text).AsNet; 147 | foreach (var item in list) 148 | Console.Write(item + ", "); 149 | } 150 | 151 | static void TestProbability() 152 | { 153 | var words = Nltk.Tokenize.WordTokenize(text); 154 | var fd = new Nltk.Probability.FreqDist(words.AsPython); 155 | 156 | var result = fd.MostCommon(null).AsNet; 157 | foreach (var item in result) 158 | Console.WriteLine(item.Key + ": " + item.Value); 159 | } 160 | 161 | static void TestStem() 162 | { 163 | var stemmer = new Nltk.Stem.PorterStemmer(); 164 | var words = new List() { "program", "programs", "programmer", "programming", "programmers" }; 165 | var stem = stemmer.Stem("girls"); 166 | 167 | Console.WriteLine("Stem: " +stem); 168 | 169 | var lemmatizer = new Nltk.Stem.WordNetLemmatizer(); 170 | Console.WriteLine("Lemmatize: " + lemmatizer.Lemmatize("best")); 171 | } 172 | 173 | 174 | private static void TestCorpus() 175 | { 176 | // NOTE: brown corpus have to be installed. By default to %appdata%\nltk_data\corpora\brown 177 | // See https://github.com/nrcpp/NltkNet/blob/master/NltkNet/Nltk/Nltk.Corpus.cs for more corpora 178 | var corpus = new Nltk.Corpus.Brown(); 179 | 180 | var fileidsResult = corpus.FileIds(); 181 | List fileidsNet = fileidsResult.AsNet; 182 | dynamic fileids = fileidsResult; 183 | 184 | Console.WriteLine(fileids[0]); 185 | 186 | var words = corpus.Words(fileidsNet.First()); 187 | var sentences = corpus.Sents(fileidsNet.First()); 188 | var paragraphs = corpus.Paras(fileidsNet.First()); 189 | string text = corpus.Raw(fileidsNet.First()); 190 | var taggedWords = corpus.TaggedWords(fileidsNet.First()); 191 | 192 | var stopWordsCorpus = new Nltk.Corpus.StopWords(); 193 | var stopWords = stopWordsCorpus.Words(null); 194 | 195 | // Process given 196 | Console.WriteLine("Stopwords: \r\n" + string.Join(", ", stopWords)); 197 | Console.WriteLine("Words from Brown corpus: \r\n" + string.Join(", ", words)); 198 | } 199 | 200 | 201 | static void Main(string[] args) 202 | { 203 | Nltk.Init(new List 204 | { 205 | @"C:\IronPython27\Lib", 206 | @"C:\IronPython27\Lib\site-packages", 207 | }); 208 | 209 | TestNltkResultClass(); 210 | TestCorpus(); 211 | TestTokenize(); 212 | TestProbability(); 213 | TestStem(); 214 | } 215 | } 216 | } 217 | 218 | ``` 219 | 220 | ## What if there is no required NLTK feature in wrapper? 221 | 222 | **NltkNet** wrapper may be considered as a starting point for learning NLP using C# and Visual Studio. Current version of NltkNet does not cover lots of features of original NLTK library written in Python. You may use workarounds to execute Python code that didn't wrapped yet. 223 | First is direct access to **Nltk.Py** property which provides you ability to execute any IronPython script, including wrappers arround method calls and creating objects. Consider the below example that illustrates possibility of using `unwrapped` features of NLTK: 224 | ```C# 225 | using NltkNet; 226 | using System; 227 | using System.Collections.Generic; 228 | namespace TestApp 229 | { 230 | class Workarounds 231 | { 232 | public static void TestPurePython() 233 | { 234 | // Initialization required 235 | Nltk.Init(new List 236 | { 237 | @"C:\IronPython27\Lib", 238 | @"C:\IronPython27\Lib\site-packages", 239 | }); 240 | 241 | 242 | // Imports NLTK corpus module 243 | Nltk.Py.ImportModule("nltk.corpus"); 244 | 245 | // Import 'names' object to access corpus content 246 | Nltk.Py.ExecuteScript("from nltk.corpus import names"); 247 | 248 | // Get object by name 249 | dynamic namesObj = Nltk.Py.GetObject("names"); 250 | 251 | // Call object's method 'names.words()' 252 | dynamic namesList = Nltk.Py.CallMethod(namesObj, "words"); 253 | 254 | foreach (var name in namesList) 255 | Console.Write(name + ", "); 256 | } 257 | } 258 | } 259 | ``` 260 | 261 | 262 | 263 | ### Other examples that uses IronPython built-in functions: 264 | 265 | ```C# 266 | using NltkNet; 267 | 268 | namespace TestApp 269 | { 270 | using System; 271 | using System.Collections.Generic; 272 | 273 | // Using NltkNet.BuiltIn static class to access Print, Str, Len, List, Sorted, Import and other IronPython built-in functions. 274 | // See https://ironpython-test.readthedocs.io/en/latest/library/functions.html for details 275 | using static NltkNet.BuiltIns; 276 | 277 | static class TestBuiltIn 278 | { 279 | public static void OverallTest() 280 | { 281 | Nltk.Init(new List() 282 | { 283 | @"C:\IronPython27\Lib", 284 | @"C:\IronPython27\Lib\site-packages", 285 | }); 286 | 287 | TestImport(); 288 | TestStandard(); 289 | } 290 | 291 | 292 | // Using '__import__' built-in to import 'nltk.corpus.brown' and 'nltk.corpus.wordnet' 293 | public static void TestImport() 294 | { 295 | dynamic corpuses = ImportNames("nltk.corpus", "brown", "wordnet"); 296 | dynamic brown = corpuses.brown; 297 | dynamic wordnet = corpuses.wordnet; 298 | 299 | Print(brown.words(brown.fileids()[0])); 300 | } 301 | 302 | // Test standard python 2.7 functions (camel-case): Len,Str,List,Sorted,Range,Zip etc. 303 | public static void TestStandard() 304 | { 305 | var lst1 = new List { 5, 4, 3, 2, 1, 5, 4, 3, 2, 1 }; 306 | var lst2 = new List { 10, 20, 30, 40, 50 }; 307 | var lst3 = new List() { "A", "B", "C", "D" }; 308 | 309 | Print("Len: " + Len(lst1)); 310 | Print("Sorted: " + Str(Sorted(lst1))); 311 | var tuple = (1, 2, "str"); 312 | 313 | Print("Tuple2List: " + tuple); 314 | Print(List(tuple)); 315 | 316 | Print("Set: " + Str(Set(lst1))); 317 | var range = Range(0, 30, 3); 318 | Print("Range: " + Str(List(range))); 319 | 320 | Print("Zip: " + Str(Zip(lst1, lst2))); 321 | 322 | Print(Globals()); 323 | Console.ReadLine(); 324 | } 325 | } 326 | } 327 | ``` 328 | 329 | 330 | 331 | -------------------------------------------------------------------------------- /NltkNet/package.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NltkNet 6 | 7 | 1.0.14 8 | NltkNet 9 | 10 | Denis Kazakov 11 | Denis Kazakov 12 | https://opensource.org/licenses/MIT 13 | https://github.com/nrcpp/NltkNet 14 | https://i.ibb.co/CtfNJy6/icon.png 15 | false 16 | 17 | NLTK python library wrapper for .NET 18 | 19 | - Nltk.NaiveBayesClassifier.Train(train_set) 20 | - Nltk.Classify.Accuracy(classifier, test_set) 21 | Copyright © 2021 22 | nltk,nlp,,parser, tokenizer, categorizer, POS, NER, chunker,IronPython 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NltkNet 2 | [![Build Status](https://travis-ci.com/nrcpp/NltkNet.svg?branch=master)](https://travis-ci.com/nrcpp/NltkNet) 3 | ![NltkNet Logo](https://i.ibb.co/phKzWqj/small-icon.png) 4 | 5 | ### C# wrapper for NLTK library ([http://nltk.org](http://nltk.org)) 6 | 7 | - [Nuget package](https://www.nuget.org/packages/NltkNet/) 8 | 9 | ## **Frameworks supported** 10 | 11 | - .NET 4.5 or later, .NET 8 12 | 13 | ## **Dependencies** 14 | 15 | - [IronPython](https://www.nuget.org/packages/IronPython) - 2.7.9 or later (Includes [DynamicLanguageRuntime](https://www.nuget.org/packages/DynamicLanguageRuntime/)) 16 | - [System.ValueTuple](https://www.nuget.org/packages/System.ValueTuple) - 4.3.0 17 | 18 | ## **Pre-Requirements** 19 | 20 | Before start using NltkNet wrapper it is required to download and install latest IronPython binaries from [official site](http://ironpython.net/). You will need IronPython standard libraries for NLTK, as well as installing NLTK library for IronPython. Also IronPython interpreter will be helpful to test python scripts interactively from Visual Studio or command line. 21 | 22 | It is expectable that most developers already have experience with NLTK library using Python and looking for a way to use in C#. Guides in this section are mostly for a developers who just started learning NLP using NLTK and haven't much experience with Python. 23 | 24 | ### **Installing IronPython** 25 | 26 | - [Download](http://ironpython.net/download/) IronPython MSI package (you could also download ZIP archive) 27 | - Run installer. By default IronPython binaries will be installed to _C:\Program Files \IronPython_ folder. _Tip:_ For your convenience IronPython could be installed to **C:\IronPython27** folder. Further, in examples below we'll use that path for initialization of path to IronPython and NLTK libs. 28 | - Add IronPython installation path to PATH environment variable 29 | 30 | ### **Add IronPython environment to Visual Studio** 31 | 32 | - In order to have ability to run IronPython from _within Visual Studio_ you may add IronPython environment to Python Environments there. 33 | - Use this [documentation](https://docs.microsoft.com/en-us/visualstudio/python/managing-python-environments-in-visual-studio) for details 34 | 35 | ### **Install NLTK library for IronPython** 36 | 37 | There are different ways to install nltk library. If you have experience with using Python and installing packages then everything is clear here. 38 | 39 | - _From Visual Studio._ Make sure you're added IronPython to Python Environments of Visual Studio on the previous step. 40 | - Then go to View->Other Windows->Python Environments to open existing Python Environments. 41 | - Choose IronPython environment and then choose _Packages (PyPi)_ from combobox below 42 | - Type there nltk and choose 'pip install nltk' 43 | - After installing, make sure you have installed nltk folder at <IronPython Path>\Libs\site-packages\nltk 44 | - _From command line using pip._ Run 'pip install nltk==3.4.5' from command line. Path to _Pip.exe_ have to be added to PATH environment variable. If you have several Python environments in system then, make sure you're installing _nltk_ library to IronPython path. 45 | - _From binaries._ Download binaries from [https://pypi.org/project/nltk/#files](https://pypi.org/project/nltk/#files). And run installer or unpack archive to <IronPythonPath>\Libs\site-packages\nltk. See [https://www.nltk.org/install.html](https://www.nltk.org/install.html) for more details. 46 | 47 | 48 | ### **Install NLTK corpuses** 49 | 50 | _Corpus_(plural _corpora_) or _text corpus_ is a large and structured set of texts (nowadays usually electronically stored and processed). In corpus linguistics, they are used to do statistical analysis and hypothesis testing, checking occurrences or validating linguistic rules within a specific language territory. 51 | 52 | NLTK library contains lots of ready-to-use corpuses which usually stores as a set of text files. It will be useful to load certain corpus on studying NLP using NLTK library, instead of creating it from scratch. 53 | 54 | If you're using NLTK library for learning NLP, download NLTK _book_ related corpuses and linguistic data. 55 | 56 | Use such script either from *Visual Studio Python Interactive Window* or *Iron Python command line* to do so: 57 | 58 | ```python 59 | import nltk 60 | import nltk.corpus 61 | nltk.download('book') 62 | ``` 63 | 64 | ## Getting Started 65 | 66 | When whole third-party stuff is in-place then we are ready to test NltkNet. Install NltkNet nuget package using your usual way. For example from Package Manager Console by pasting: 67 | 68 | ``` 69 | Install-Package NltkNet 70 | ``` 71 | 72 | **Use this code to initialize paths to IronPython standard and third-party libraries:** 73 | ```C# 74 | using System; 75 | using System.Collections.Generic; 76 | using System.IO; 77 | using System.Linq; 78 | using NltkNet; 79 | 80 | namespace TestApp 81 | { 82 | class Program 83 | { 84 | static void Main(string[] args) 85 | { 86 | Nltk.Init(new List 87 | { 88 | @"C:\IronPython27\Lib", // Path to IronPython standard libraries 89 | @"C:\IronPython27\Lib\site-packages", // Path to IronPython third-party libraries 90 | }); 91 | } 92 | } 93 | } 94 | ``` 95 | 96 | **More practical samples** 97 | ```C# 98 | using System; 99 | using System.Collections.Generic; 100 | using System.Dynamic; 101 | using System.IO; 102 | using System.Linq; 103 | using NltkNet; 104 | 105 | namespace TestApp 106 | { 107 | class Program 108 | { 109 | static string text = "This IronPython script works fine when I run it by itself."; 110 | 111 | private static void TestNltkResultClass() 112 | { 113 | var corpus = new Nltk.Corpus.Inaugural(); 114 | 115 | // example of using NltkResult class 116 | var fileidsResult = corpus.FileIds(); 117 | 118 | // Get .NET List 119 | List fileidsNet = fileidsResult.AsNet; 120 | 121 | // Get IronPython.Runtime.List 122 | IronPython.Runtime.List fileidsPython = fileidsResult.AsPython; 123 | 124 | // Cast to Dynamic to access object fields in Python-like style 125 | dynamic fileids = fileidsResult; 126 | 127 | // using DynamicObject 128 | Console.WriteLine(fileids[0]); 129 | Console.WriteLine(fileids.__len__()); 130 | 131 | // access sentences (list of list of strings) 132 | var sentencesResult = corpus.Sents(); 133 | dynamic sentences = sentencesResult; 134 | 135 | // Manipulating with Python object: first word in first sentense 136 | Console.WriteLine(sentences[0][0]); 137 | List> netSentences = sentencesResult.AsNet; 138 | 139 | Console.WriteLine(netSentences[0][0]); // the same with .NET object 140 | Console.WriteLine(netSentences.First().First()); // using LINQ 141 | } 142 | 143 | static void TestTokenize() 144 | { 145 | var tuples = Nltk.Tokenize.Util.RegexpSpanTokenize(text, "\\s"); 146 | 147 | var list = Nltk.Tokenize.SentTokenize(text).AsNet; 148 | foreach (var item in list) 149 | Console.Write(item + ", "); 150 | } 151 | 152 | static void TestProbability() 153 | { 154 | var words = Nltk.Tokenize.WordTokenize(text); 155 | var fd = new Nltk.Probability.FreqDist(words.AsPython); 156 | 157 | var result = fd.MostCommon(null).AsNet; 158 | foreach (var item in result) 159 | Console.WriteLine(item.Key + ": " + item.Value); 160 | } 161 | 162 | static void TestStem() 163 | { 164 | var stemmer = new Nltk.Stem.PorterStemmer(); 165 | var words = new List() { "program", "programs", "programmer", "programming", "programmers" }; 166 | var stem = stemmer.Stem("girls"); 167 | 168 | Console.WriteLine("Stem: " +stem); 169 | 170 | var lemmatizer = new Nltk.Stem.WordNetLemmatizer(); 171 | Console.WriteLine("Lemmatize: " + lemmatizer.Lemmatize("best")); 172 | } 173 | 174 | 175 | private static void TestCorpus() 176 | { 177 | // NOTE: brown corpus have to be installed. By default to %appdata%\nltk_data\corpora\brown 178 | // See https://github.com/nrcpp/NltkNet/blob/master/NltkNet/Nltk/Nltk.Corpus.cs for more corpora 179 | var corpus = new Nltk.Corpus.Brown(); 180 | 181 | var fileidsResult = corpus.FileIds(); 182 | List fileidsNet = fileidsResult.AsNet; 183 | dynamic fileids = fileidsResult; 184 | 185 | Console.WriteLine(fileids[0]); 186 | 187 | var words = corpus.Words(fileidsNet.First()); 188 | var sentences = corpus.Sents(fileidsNet.First()); 189 | var paragraphs = corpus.Paras(fileidsNet.First()); 190 | string text = corpus.Raw(fileidsNet.First()); 191 | var taggedWords = corpus.TaggedWords(fileidsNet.First()); 192 | 193 | var stopWordsCorpus = new Nltk.Corpus.StopWords(); 194 | var stopWords = stopWordsCorpus.Words(null); 195 | 196 | // Process given 197 | Console.WriteLine("Stopwords: \r\n" + string.Join(", ", stopWords)); 198 | Console.WriteLine("Words from Brown corpus: \r\n" + string.Join(", ", words)); 199 | } 200 | 201 | 202 | static void Main(string[] args) 203 | { 204 | Nltk.Init(new List 205 | { 206 | @"C:\IronPython27\Lib", 207 | @"C:\IronPython27\Lib\site-packages", 208 | }); 209 | 210 | TestNltkResultClass(); 211 | TestCorpus(); 212 | TestTokenize(); 213 | TestProbability(); 214 | TestStem(); 215 | } 216 | } 217 | } 218 | 219 | ``` 220 | 221 | ## What if there is no required NLTK feature in wrapper? 222 | 223 | **NltkNet** wrapper may be considered as a starting point for learning NLP using C# and Visual Studio. Current version of NltkNet does not cover lots of features of original NLTK library written in Python. You may use workarounds to execute Python code that didn't wrapped yet. 224 | First is direct access to **Nltk.Py** property which provides you ability to execute any IronPython script, including wrappers arround method calls and creating objects. Consider the below example that illustrates possibility of using `unwrapped` features of NLTK: 225 | ```C# 226 | using NltkNet; 227 | using System; 228 | using System.Collections.Generic; 229 | namespace TestApp 230 | { 231 | class Workarounds 232 | { 233 | public static void TestPurePython() 234 | { 235 | // Initialization required 236 | Nltk.Init(new List 237 | { 238 | @"C:\IronPython27\Lib", 239 | @"C:\IronPython27\Lib\site-packages", 240 | }); 241 | 242 | 243 | // Imports NLTK corpus module 244 | Nltk.Py.ImportModule("nltk.corpus"); 245 | 246 | // Import 'names' object to access corpus content 247 | Nltk.Py.ExecuteScript("from nltk.corpus import names"); 248 | 249 | // Get object by name 250 | dynamic namesObj = Nltk.Py.GetObject("names"); 251 | 252 | // Call object's method 'names.words()' 253 | dynamic namesList = Nltk.Py.CallMethod(namesObj, "words"); 254 | 255 | foreach (var name in namesList) 256 | Console.Write(name + ", "); 257 | } 258 | } 259 | } 260 | ``` 261 | 262 | 263 | 264 | ### Other examples that uses IronPython [built-in functions](https://ironpython-test.readthedocs.io/en/latest/library/functions.html): 265 | 266 | ```C# 267 | using NltkNet; 268 | 269 | namespace TestApp 270 | { 271 | using System; 272 | using System.Collections.Generic; 273 | 274 | // Using NltkNet.BuiltIn static class to access Print, Str, Len, List, Sorted, Import and other IronPython built-in functions. 275 | // See https://ironpython-test.readthedocs.io/en/latest/library/functions.html for details 276 | using static NltkNet.BuiltIns; 277 | 278 | static class TestBuiltIn 279 | { 280 | public static void OverallTest() 281 | { 282 | Nltk.Init(new List() 283 | { 284 | @"C:\IronPython27\Lib", 285 | @"C:\IronPython27\Lib\site-packages", 286 | }); 287 | 288 | TestImport(); 289 | TestStandard(); 290 | } 291 | 292 | 293 | // Using '__import__' built-in to import 'nltk.corpus.brown' and 'nltk.corpus.wordnet' 294 | public static void TestImport() 295 | { 296 | dynamic corpuses = ImportNames("nltk.corpus", "brown", "wordnet"); 297 | dynamic brown = corpuses.brown; 298 | dynamic wordnet = corpuses.wordnet; 299 | 300 | Print(brown.words(brown.fileids()[0])); 301 | } 302 | 303 | // Test standard python 2.7 functions (camel-case): Len,Str,List,Sorted,Range,Zip etc. 304 | public static void TestStandard() 305 | { 306 | var lst1 = new List { 5, 4, 3, 2, 1, 5, 4, 3, 2, 1 }; 307 | var lst2 = new List { 10, 20, 30, 40, 50 }; 308 | var lst3 = new List() { "A", "B", "C", "D" }; 309 | 310 | Print("Len: " + Len(lst1)); 311 | Print("Sorted: " + Str(Sorted(lst1))); 312 | var tuple = (1, 2, "str"); 313 | 314 | Print("Tuple2List: " + tuple); 315 | Print(List(tuple)); 316 | 317 | Print("Set: " + Str(Set(lst1))); 318 | var range = Range(0, 30, 3); 319 | Print("Range: " + Str(List(range))); 320 | 321 | Print("Zip: " + Str(Zip(lst1, lst2))); 322 | 323 | Print(Globals()); 324 | Console.ReadLine(); 325 | } 326 | } 327 | } 328 | ``` 329 | 330 | 331 | 332 | -------------------------------------------------------------------------------- /SampleApp/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /SampleApp/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /SampleApp/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace SampleApp 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SampleApp/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /SampleApp/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using NltkNet; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace SampleApp 18 | { 19 | /// 20 | /// Interaction logic for MainWindow.xaml 21 | /// 22 | public partial class MainWindow : Window 23 | { 24 | static MainWindow _instance; 25 | 26 | public MainWindow() 27 | { 28 | InitializeComponent(); 29 | 30 | _instance = this; 31 | Loaded += MainWindow_Loaded; 32 | } 33 | 34 | public static void Log(string msg) 35 | { 36 | _instance.Dispatcher.BeginInvoke(new Action(() => _instance._logText.Text += msg + "\r\n")); 37 | } 38 | 39 | public static void ClearLog(string msg) => 40 | _instance.Dispatcher.BeginInvoke(new Action(() => _instance._logText.Text = "")); 41 | 42 | 43 | private void MainWindow_Loaded(object sender, RoutedEventArgs e) 44 | { 45 | Task.Run(() => 46 | { 47 | Log("Nltk.Init() Begin"); 48 | 49 | Nltk.Init(new List 50 | { 51 | @"C:\IronPython27\Lib", 52 | @"C:\IronPython27\Lib\site-packages", 53 | }); 54 | 55 | Log("Nltk.Init() Done"); 56 | }); 57 | } 58 | 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SampleApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("SampleApp")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("SampleApp")] 15 | [assembly: AssemblyCopyright("Copyright © 2018")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /SampleApp/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace SampleApp.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleApp.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /SampleApp/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 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 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /SampleApp/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace SampleApp.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /SampleApp/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /SampleApp/SampleApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {4F258002-CA9B-4BF7-9FAE-EAB8DA6617B8} 8 | WinExe 9 | SampleApp 10 | SampleApp 11 | v4.5 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | ..\packages\IronPython.2.7.9\lib\net45\IronPython.dll 39 | 40 | 41 | ..\packages\IronPython.2.7.9\lib\net45\IronPython.Modules.dll 42 | 43 | 44 | ..\packages\IronPython.2.7.9\lib\net45\IronPython.SQLite.dll 45 | 46 | 47 | ..\packages\IronPython.2.7.9\lib\net45\IronPython.Wpf.dll 48 | 49 | 50 | ..\packages\DynamicLanguageRuntime.1.2.2\lib\net45\Microsoft.Dynamic.dll 51 | 52 | 53 | ..\packages\DynamicLanguageRuntime.1.2.2\lib\net45\Microsoft.Scripting.dll 54 | 55 | 56 | ..\packages\DynamicLanguageRuntime.1.2.2\lib\net45\Microsoft.Scripting.Metadata.dll 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 4.0 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | MSBuild:Compile 76 | Designer 77 | 78 | 79 | MSBuild:Compile 80 | Designer 81 | 82 | 83 | App.xaml 84 | Code 85 | 86 | 87 | MainWindow.xaml 88 | Code 89 | 90 | 91 | 92 | 93 | Code 94 | 95 | 96 | True 97 | True 98 | Resources.resx 99 | 100 | 101 | True 102 | Settings.settings 103 | True 104 | 105 | 106 | ResXFileCodeGenerator 107 | Resources.Designer.cs 108 | 109 | 110 | 111 | SettingsSingleFileGenerator 112 | Settings.Designer.cs 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | {9803f52c-3abd-446f-ad0f-4c5c9b615780} 121 | NltkNet 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /SampleApp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /TestApp/Program.cs: -------------------------------------------------------------------------------- 1 | using IronPython.Hosting; 2 | using NltkNet; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Dynamic; 6 | using System.IO; 7 | using System.Linq; 8 | 9 | namespace TestApp 10 | { 11 | class Program 12 | { 13 | static string text = "Hello colleague! Thanks for using NltkNet library. Wish you no bugs there!"; 14 | 15 | 16 | private static void TestNltkResultClass() 17 | { 18 | var corpus = new Nltk.Corpus.Inaugural(); 19 | 20 | // example of using NltkResult class 21 | var fileidsResult = corpus.FileIds(); 22 | 23 | List fileidsNet = fileidsResult.AsNet; // Get .NET List 24 | IronPython.Runtime.List fileidsPython = fileidsResult.AsPython; // Get IronPython.Runtime.List 25 | dynamic fileids = fileidsResult; // Cast to Dynamic to access object fields in Python-like style 26 | 27 | // using DynamicObject 28 | Console.WriteLine(fileids[0]); 29 | Console.WriteLine(fileids.__len__()); 30 | 31 | // access sentences (list of list of strings) 32 | var sentencesResult = corpus.Sents(); 33 | dynamic sentences = sentencesResult; 34 | 35 | Console.WriteLine(sentences[0][0]); // Manipulating with Python object: first word in first sentense 36 | List> netSentences = sentencesResult.AsNet; 37 | 38 | Console.WriteLine(netSentences[0][0]); // the same with .NET object 39 | Console.WriteLine(netSentences.First().First()); // using LINQ 40 | } 41 | 42 | 43 | static void TestTokenize() 44 | { 45 | var tuples = Nltk.Tokenize.Util.RegexpSpanTokenize(text, "\\s").AsNet; 46 | 47 | Console.WriteLine("Nltk.Tokenize.Util.RegexpSpanTokenize:"); 48 | foreach (var item in tuples) 49 | Console.Write($"({item.Item1}, {item.Item2}), "); 50 | 51 | var list = Nltk.Tokenize.SentTokenize(text).AsNet; 52 | foreach (var item in list) 53 | Console.Write(item + ", "); 54 | } 55 | 56 | static void TestStem() 57 | { 58 | var stemmer = new Nltk.Stem.PorterStemmer(); 59 | var words = new List() { "program", "programs", "programmer", "programming", "programmers" }; 60 | var stem = stemmer.Stem("girls"); 61 | 62 | Console.WriteLine("Stem: " +stem); 63 | 64 | var lemmatizer = new Nltk.Stem.WordNetLemmatizer(); 65 | Console.WriteLine("Lemmatize: " + lemmatizer.Lemmatize("best")); 66 | } 67 | 68 | 69 | 70 | static void TestPosTagger() 71 | { 72 | var words = Nltk.Tokenize.WordTokenize(text); 73 | //var taggedWords = Nltk.PosTag(words.AsNet); 74 | 75 | //BuiltIn.Print(taggedWords.AsPython); 76 | //BuiltIn.Print(taggedWords.AsPython); 77 | //Console.WriteLine("Length = " + BuiltIn.Len(taggedWords.AsPython)); 78 | 79 | //var myText = new Nltk.Text(words.AsPython); 80 | //var r = myText.Similar("Denis"); 81 | //BuiltIn.Print(r.AsPython); 82 | 83 | var tuple = Nltk.Tag.Str2Tuple("fly/NN").AsNet; 84 | Console.WriteLine(tuple.Item1 + " " + tuple.Item2); 85 | } 86 | 87 | static void TestNameEntityRecognizer() 88 | { 89 | string text = "WASHINGTON -- In the wake of a string of abuses by New York police officers in the 1990s, Loretta E. Lynch, "+ 90 | "the top federal prosecutor in Brooklyn, spoke forcefully about the pain of a broken trust that African-Americans "+ 91 | "felt and said the responsibility for repairing generations of miscommunication and mistrust fell to law enforcement."; 92 | 93 | var tokens = Nltk.Tokenize.WordTokenize(text); 94 | var posTaggedWords = Nltk.PosTag(tokens.AsNet); 95 | 96 | // NOTE: This operation requires NumPy library for IronPython 97 | var neChunks = Nltk.NeChunk(posTaggedWords); 98 | 99 | BuiltIns.Print($"NER output for text: '{text}'"); 100 | BuiltIns.Print(neChunks); 101 | } 102 | 103 | static void Main(string[] args) 104 | { 105 | var engine = Python.CreateEngine(); 106 | var scope = engine.CreateScope(); 107 | string pythonCode = @" 108 | 109 | print('hello from ironPython') 110 | "; 111 | try 112 | { 113 | engine.Execute(pythonCode, scope); 114 | } 115 | catch (Exception ex) 116 | { 117 | Console.WriteLine(ex.ToString()); 118 | } 119 | Nltk.Init(new List 120 | { 121 | @"C:\Program Files\IronPython 3.4\Lib", 122 | @"C:\Program Files\IronPython 3.4\Lib\site-packages", 123 | }); 124 | 125 | 126 | //TestCorpus.TestBrown(); 127 | 128 | //TestPosTagger(); 129 | //TestBuiltIn.OverallTest(); 130 | 131 | //TestNltkResultClass(); 132 | //TestTokenize(); 133 | //TestProbability.OverallTest(); 134 | 135 | //TestClassify.TestNames(); 136 | TestNameEntityRecognizer(); 137 | //TestStem(); 138 | 139 | //Workarounds.TestPurePython(); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /TestApp/TestApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Exe 4 | net8.0 5 | latest 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Always 16 | 17 | 18 | -------------------------------------------------------------------------------- /TestApp/Tests/TestBuiltIn.cs: -------------------------------------------------------------------------------- 1 | using NltkNet; 2 | 3 | namespace TestApp 4 | { 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | // Using NltkNet.BuiltIn static class to access Print, Str, Len, List, Sorted, Import and other IronPython built-in functions. 9 | // See https://ironpython-test.readthedocs.io/en/latest/library/functions.html for details 10 | using static NltkNet.BuiltIns; 11 | 12 | static class TestBuiltIn 13 | { 14 | public static void OverallTest() 15 | { 16 | Nltk.Init(new List() 17 | { 18 | @"C:\IronPython27\Lib", 19 | @"C:\IronPython27\Lib\site-packages", 20 | }); 21 | 22 | TestImport(); 23 | TestStandard(); 24 | } 25 | 26 | 27 | // Using **__import__** built-in to import *nltk.corpus.brown* and *nltk.corpus.wordnet* 28 | public static void TestImport() 29 | { 30 | dynamic corpuses = ImportNames("nltk.corpus", "brown", "wordnet"); 31 | dynamic brown = corpuses.brown; 32 | dynamic wordnet = corpuses.wordnet; 33 | 34 | Print(brown.words(brown.fileids()[0])); 35 | } 36 | 37 | // Test standard python 2.7 functions (camel-case): Len,Str,List,Sorted,Range,Zip etc. 38 | public static void TestStandard() 39 | { 40 | var lst1 = new List { 5, 4, 3, 2, 1, 5, 4, 3, 2, 1 }; 41 | var lst2 = new List { 10, 20, 30, 40, 50 }; 42 | var lst3 = new List() { "A", "B", "C", "D" }; 43 | 44 | Print("Len: " + Len(lst1)); 45 | Print("Sorted: " + Str(Sorted(lst1))); 46 | var tuple = (1, 2, "str"); 47 | 48 | Print("Tuple2List: " + tuple); 49 | Print(List(tuple)); 50 | 51 | Print("Set: " + Str(Set(lst1))); 52 | var range = Range(0, 30, 3); 53 | Print("Range: " + Str(List(range))); 54 | 55 | Print("Zip: " + Str(Zip(lst1, lst2))); 56 | 57 | //Print(Globals()); 58 | Console.ReadLine(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /TestApp/Tests/TestClassify.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Linq; 5 | using System.Collections; 6 | using NltkNet; 7 | using static NltkNet.BuiltIns; 8 | 9 | namespace TestApp 10 | { 11 | static class TestClassify 12 | { 13 | public static void TestNames() 14 | { 15 | //def gender_features(word): 16 | // return { 'last_letter': word[-1]} 17 | dynamic GenderFeature(string word) 18 | { 19 | var dict = BuiltIns.Dict(); 20 | dict["last_letter"] = string.IsNullOrEmpty(word) ? "" : word.Last().ToString(); 21 | return dict; 22 | } 23 | 24 | //from nltk.corpus import names 25 | //>>> labeled_names = ([(name, 'male') for name in names.words('male.txt')] + 26 | //... [(name, 'female') for name in names.words('female.txt')]) 27 | var namesCorpus = new NltkNet.Nltk.Corpus.Names(); 28 | var maleNames = namesCorpus.Words("male.txt").AsNet.Select(name => (name, gender:"male")); 29 | var femaleNames = namesCorpus.Words("female.txt").AsNet.Select(name => (name, gender:"female")); 30 | var labeledNames = maleNames.ToList(); 31 | labeledNames.AddRange(femaleNames); 32 | 33 | //>>> import random 34 | //>>> random.shuffle(labeled_names) 35 | labeledNames.Shuffle(); 36 | 37 | //featuresets = [(gender_features(n), gender) for (n, gender) in labeled_names] 38 | //train_set, test_set = featuresets[500:], featuresets[:500] 39 | var featuresets = labeledNames.Select(nameAndGender => (GenderFeature(nameAndGender.name), nameAndGender.gender)).ToList(); 40 | var train_set = featuresets.SkipLast(500).ToList(); 41 | var test_set = featuresets.TakeLast(500).ToList(); 42 | 43 | // nltk.NaiveBayesClassifier.train(train_set) 44 | dynamic classifier = Nltk.NaiveBayesClassifier.Train(train_set); 45 | 46 | // classifier.classify(gender_features('Neo')) 47 | Print("Neo=" + classifier.classify(GenderFeature("Neo"))); 48 | Print("Trinity=" + classifier.classify(GenderFeature("Trinity"))); 49 | Print(Nltk.Classify.Accuracy(classifier, test_set)); 50 | classifier.show_most_informative_features(5); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /TestApp/Tests/TestCorpus.cs: -------------------------------------------------------------------------------- 1 | using NltkNet; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Dynamic; 5 | using System.IO; 6 | using System.Linq; 7 | 8 | namespace TestApp 9 | { 10 | static class TestCorpus 11 | { 12 | public static void OverallTest() 13 | { 14 | // NOTE: brown corpus have to be installed. By default to %appdata%\nltk_data\corpora\brown 15 | // See https://github.com/nrcpp/NltkNet/blob/master/NltkNet/Nltk/Nltk.Corpus.cs for more corpora 16 | var corpus = new Nltk.Corpus.Brown(); 17 | 18 | var fileidsResult = corpus.FileIds(); 19 | List fileidsNet = fileidsResult.AsNet; 20 | dynamic fileids = fileidsResult; 21 | 22 | Console.WriteLine(fileids[0]); 23 | 24 | var words = corpus.Words(fileidsNet.First()); 25 | var sentences = corpus.Sents(fileidsNet.First()); 26 | var paragraphs = corpus.Paras(fileidsNet.First()); 27 | string text = corpus.Raw(fileidsNet.First()); 28 | var taggedWords = corpus.TaggedWords(fileidsNet.First()); 29 | 30 | var stopWordsCorpus = new Nltk.Corpus.StopWords(); 31 | var stopWords = stopWordsCorpus.Words(null); 32 | 33 | // Process given 34 | Console.WriteLine("Stopwords: \r\n" + string.Join(", ", stopWords.AsNet)); 35 | Console.WriteLine("Words from Brown corpus: \r\n" + string.Join(", ", words.AsNet)); 36 | } 37 | 38 | 39 | public static void TestBrown() 40 | { 41 | var corpus = new Nltk.Corpus.Brown(); 42 | var sents = corpus.TaggedSents(null, "adventure").AsNet; 43 | 44 | foreach (var s in sents) 45 | foreach (var item in s) 46 | { 47 | Console.WriteLine($"({item.Item1}, {item.Item2})"); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /TestApp/Tests/TestProbability.cs: -------------------------------------------------------------------------------- 1 | using NltkNet; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Dynamic; 5 | using System.IO; 6 | using System.Linq; 7 | 8 | namespace TestApp 9 | { 10 | static class TestProbability 11 | { 12 | static string text = "cow cat mouse cat tiger"; 13 | 14 | public static void OverallTest() 15 | { 16 | // See https://www.nltk.org/_modules/nltk/probability.html for more details 17 | 18 | //TestFreqDist(); 19 | TestCondFreqDist(); 20 | } 21 | 22 | private static void TestFreqDist() 23 | { 24 | var words = Nltk.Tokenize.WordTokenize(text); 25 | var fdist = new Nltk.Probability.FreqDist(words.AsPython); 26 | 27 | var result = fdist.MostCommon().AsNet; 28 | 29 | Console.WriteLine("Most common words: "); 30 | foreach (var item in result) 31 | Console.WriteLine(item.Key + ": " + item.Value); 32 | } 33 | 34 | static void TestCondFreqDist() 35 | { 36 | var words = Nltk.Tokenize.WordTokenize(text); 37 | var cfdist = new Nltk.Probability.ConditionalFreqDist(); 38 | 39 | foreach (string word in words.AsNet) 40 | { 41 | var condition = word.Length; 42 | cfdist[condition][word] += 1; 43 | } 44 | 45 | foreach (var condition in cfdist.PyObject) 46 | foreach (var word in cfdist[condition]) 47 | BuiltIns.Print("Cond. frequency of " + word + " " + cfdist[condition].freq(word) + " [condition is word length =" + condition + "]"); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /TestApp/Workarounds.cs: -------------------------------------------------------------------------------- 1 | using NltkNet; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Dynamic; 5 | using System.IO; 6 | using System.Linq; 7 | 8 | namespace TestApp 9 | { 10 | class Workarounds 11 | { 12 | public static void TestPurePython() 13 | { 14 | // Initialization required 15 | Nltk.Init(new List 16 | { 17 | @"C:\Program Files\IronPython 3.4\Lib", 18 | @"C:\Program Files\IronPython 3.4\Lib\site-packages", 19 | }); 20 | 21 | 22 | // Imports NLTK corpus module 23 | Nltk.Py.ImportModule("nltk.corpus"); 24 | 25 | // Import 'names' object to access corpus content 26 | Nltk.Py.ExecuteScript("from nltk.corpus import names"); 27 | 28 | // Get object by name 29 | dynamic namesObj = Nltk.Py.GetObject("names"); 30 | 31 | // Call object's method 'names.words()' 32 | dynamic namesList = Nltk.Py.CallMethod(namesObj, "words"); 33 | 34 | foreach (var name in namesList) 35 | { 36 | Console.Write(name + ", "); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /TestApp/files/test.txt: -------------------------------------------------------------------------------- 1 | I'm using Visual Studio 2010. I have an IronPython console project and a C# console project. 2 | This IronPython script works fine when I run it by itself. 3 | -------------------------------------------------------------------------------- /click-8.1.8-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrcpp/NltkNet/1634e537a0f263869d1b6661e72f60e5e4245260/click-8.1.8-py3-none-any.whl -------------------------------------------------------------------------------- /colorama-0.4.6-py2.py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrcpp/NltkNet/1634e537a0f263869d1b6661e72f60e5e4245260/colorama-0.4.6-py2.py3-none-any.whl -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrcpp/NltkNet/1634e537a0f263869d1b6661e72f60e5e4245260/icon.png -------------------------------------------------------------------------------- /ironpkg-1.0.0.py: -------------------------------------------------------------------------------- 1 | """\ 2 | Self installs IronPkg into the current IronPython environment. 3 | egg: ironpkg-1.0.0-1.egg 4 | md5: 41787f5a12384e482e8e9f1d90f8bcdc 5 | 6 | Options: 7 | -h, --help show this help message and exit 8 | --install self install 9 | """ 10 | import os 11 | import sys 12 | import base64 13 | import hashlib 14 | import tempfile 15 | import zipfile 16 | from os.path import dirname, isdir, join 17 | 18 | 19 | b64eggdata = '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' 20 | 21 | 22 | def unzip(zip_file, dir_path): 23 | """Unzip the zip_file into the directory dir_path.""" 24 | z = zipfile.ZipFile(zip_file) 25 | for name in z.namelist(): 26 | if name.endswith('/'): 27 | continue 28 | path = join(dir_path, *name.split('/')) 29 | if not isdir(dirname(path)): 30 | os.makedirs(dirname(path)) 31 | fo = open(path, 'wb') 32 | fo.write(z.read(name)) 33 | fo.close() 34 | z.close() 35 | 36 | 37 | def self_install(): 38 | tmp_dir = tempfile.mkdtemp() 39 | egg_path = join(tmp_dir, 'ironpkg-1.0.0-1.egg') 40 | data = base64.b64decode(b64eggdata) 41 | assert hashlib.md5(data).hexdigest() == '41787f5a12384e482e8e9f1d90f8bcdc' 42 | fo = open(egg_path, 'wb') 43 | fo.write(data) 44 | fo.close() 45 | unzip(egg_path, tmp_dir) 46 | sys.path.insert(0, tmp_dir) 47 | import egginst 48 | print "Bootstrapping:", egg_path 49 | ei = egginst.EggInst(egg_path) 50 | ei.install() 51 | 52 | 53 | if __name__ == '__main__': 54 | if '--install' in sys.argv: 55 | self_install() 56 | else: 57 | print __doc__ 58 | -------------------------------------------------------------------------------- /joblib-1.4.2-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrcpp/NltkNet/1634e537a0f263869d1b6661e72f60e5e4245260/joblib-1.4.2-py3-none-any.whl -------------------------------------------------------------------------------- /nltk-3.9.1-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrcpp/NltkNet/1634e537a0f263869d1b6661e72f60e5e4245260/nltk-3.9.1-py3-none-any.whl -------------------------------------------------------------------------------- /regex-2024.11.6-cp312-cp312-win_amd64.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrcpp/NltkNet/1634e537a0f263869d1b6661e72f60e5e4245260/regex-2024.11.6-cp312-cp312-win_amd64.whl -------------------------------------------------------------------------------- /small_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrcpp/NltkNet/1634e537a0f263869d1b6661e72f60e5e4245260/small_icon.png -------------------------------------------------------------------------------- /tqdm-4.67.1-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nrcpp/NltkNet/1634e537a0f263869d1b6661e72f60e5e4245260/tqdm-4.67.1-py3-none-any.whl --------------------------------------------------------------------------------