├── docs ├── preflop-matchups.zip ├── keys-per-playing-days.zip ├── Poker links.html ├── PokerSource poker hand evaluator and more.htm └── zealots.php.htm ├── src ├── HandEvaluator │ ├── vssver2.scc │ ├── Properties │ │ ├── vssver2.scc │ │ └── AssemblyInfo.cs │ ├── PocketQueryParser │ │ ├── lg.exe │ │ ├── pg.exe │ │ ├── vssver2.scc │ │ ├── Runtime │ │ │ ├── vssver2.scc │ │ │ ├── olist.cs │ │ │ ├── genbase0.cs │ │ │ ├── serialise.cs │ │ │ ├── dfa.cs │ │ │ └── lexer.cs │ │ ├── Exam.lexer │ │ ├── Exam.parser │ │ └── PocketHandsQuery.cs │ ├── HandEvaluator.csproj.user │ └── HandEvaluator.csproj ├── PokerStarsBot │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── PokerStarsBot.csproj.user │ ├── PokerSimulatorUI.cs │ ├── Keys.cs │ ├── Combinatorics.cs │ ├── Utils.cs │ ├── Card.cs │ ├── IO.cs │ ├── PokerSimulatorUI.resx │ ├── PokerStarsBot.csproj │ ├── PokerSimulatorUI.Designer.cs │ ├── PokerApp.cs │ └── Pokerhand.cs └── poker.sln ├── README.md ├── LICENSE └── .gitignore /docs/preflop-matchups.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miguelzf/PokerBot/HEAD/docs/preflop-matchups.zip -------------------------------------------------------------------------------- /docs/keys-per-playing-days.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miguelzf/PokerBot/HEAD/docs/keys-per-playing-days.zip -------------------------------------------------------------------------------- /src/HandEvaluator/vssver2.scc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miguelzf/PokerBot/HEAD/src/HandEvaluator/vssver2.scc -------------------------------------------------------------------------------- /src/HandEvaluator/Properties/vssver2.scc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miguelzf/PokerBot/HEAD/src/HandEvaluator/Properties/vssver2.scc -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/lg.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miguelzf/PokerBot/HEAD/src/HandEvaluator/PocketQueryParser/lg.exe -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/pg.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miguelzf/PokerBot/HEAD/src/HandEvaluator/PocketQueryParser/pg.exe -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/vssver2.scc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miguelzf/PokerBot/HEAD/src/HandEvaluator/PocketQueryParser/vssver2.scc -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/Runtime/vssver2.scc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miguelzf/PokerBot/HEAD/src/HandEvaluator/PocketQueryParser/Runtime/vssver2.scc -------------------------------------------------------------------------------- /src/PokerStarsBot/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PokerBot 2 | ======== 3 | 4 | Automatic intelligent playing bot for PokerStars. 5 | This bot is still in its infancy, the only component done so far is the hand evaluator. 6 | Started it a couple years back, and I haven't got the time to touch it again since, so it's been on hiatus. 7 | 8 | 9 | Included here is Keith Rule's C# Port of the Pokersource Evaluator, which I used to test my own odds evalutor. 10 | Keith Rule's version here: 11 | http://www.codeproject.com/Articles/12279/Fast-Texas-Holdem-Hand-Evaluation-and-Analysis 12 | 13 | More info on Poker hand evaluators: 14 | http://www.codingthewheel.com/archives/poker-hand-evaluator-roundup/ 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/HandEvaluator/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Security.Permissions; 6 | 7 | [assembly: FileIOPermission(SecurityAction.RequestMinimum)] 8 | [assembly: AssemblyTitle("HandEvaluator")] 9 | [assembly: AssemblyDescription("This assembly is released under the LGPL software license.")] 10 | [assembly: AssemblyCopyright("Copyright © Keith Rule 2005-2007")] 11 | [assembly: ComVisible(false)] 12 | [assembly: CLSCompliant(false)] 13 | [assembly: Guid("e98a3374-314d-4597-bfb7-bce75bb7bef6")] 14 | [assembly: AssemblyVersion("2.0.0.0")] 15 | [assembly: AssemblyFileVersion("2.0.0.0")] 16 | -------------------------------------------------------------------------------- /src/PokerStarsBot/PokerStarsBot.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | publish\ 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | en-US 16 | false 17 | ShowAllFiles 18 | 19 | -------------------------------------------------------------------------------- /src/HandEvaluator/HandEvaluator.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | en-US 15 | false 16 | 17 | 18 | Program 19 | C:\Program Files\NUnit-Net-2.0 2.2.5\bin\nunit-gui.exe 20 | 21 | 22 | Program 23 | C:\Program Files (x86)\NUnit-Net-2.0 2.2.6\bin\nunit-gui.exe 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Miguel Ferreira 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/PokerStarsBot/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.1008 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 pokerbot.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/poker.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PokerStarsBot", "PokerStarsBot\PokerStarsBot.csproj", "{69B86D90-C931-4B07-8E2C-5A61F96D96F3}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandEvaluator", "HandEvaluator\HandEvaluator.csproj", "{57836673-FE81-4367-A4EB-AAA46FB954D2}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {69B86D90-C931-4B07-8E2C-5A61F96D96F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {69B86D90-C931-4B07-8E2C-5A61F96D96F3}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {69B86D90-C931-4B07-8E2C-5A61F96D96F3}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {69B86D90-C931-4B07-8E2C-5A61F96D96F3}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {57836673-FE81-4367-A4EB-AAA46FB954D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {57836673-FE81-4367-A4EB-AAA46FB954D2}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {57836673-FE81-4367-A4EB-AAA46FB954D2}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {57836673-FE81-4367-A4EB-AAA46FB954D2}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /src/PokerStarsBot/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PokerStarsBot")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("PokerStarsBot")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2011")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("256c1ba5-ca32-4469-a2a8-8271a1d88603")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/PokerStarsBot/PokerSimulatorUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | 10 | namespace pokermaster 11 | { 12 | public partial class PokerSimulatorUI : Form 13 | { 14 | PokerApp calc; 15 | DateTime startTime = DateTime.Now; 16 | 17 | 18 | public PokerSimulatorUI() : this(null) 19 | { 20 | } 21 | 22 | public PokerSimulatorUI(PokerApp pc) 23 | { 24 | calc = pc; 25 | InitializeComponent(); 26 | } 27 | 28 | private void PokerUI_Load(object sender, EventArgs e) 29 | { 30 | 31 | } 32 | 33 | Card[] parseCards(string str) 34 | { 35 | 36 | 37 | return null; 38 | } 39 | 40 | 41 | // only action function, calls the poker calc class 42 | private void Calculate_Click(object sender, EventArgs e) 43 | { 44 | 45 | 46 | 47 | 48 | } 49 | 50 | 51 | private void PokerUI_Closed(object sender, FormClosedEventArgs e) 52 | { 53 | TimeSpan ts = DateTime.Now - startTime; 54 | Keys.UpdateReqKey((int) ts.TotalSeconds); 55 | 56 | // MessageBox.Show("See you next time young Pokeron"); 57 | } 58 | 59 | private void UITitle_Click(object sender, EventArgs e) 60 | { 61 | 62 | } 63 | 64 | 65 | 66 | /* private System.Windows.Forms.TextBox PlayerCardsBox; 67 | private System.Windows.Forms.TextBox SharedCardsBox; 68 | private System.Windows.Forms.TextBox WinProbBox; 69 | private System.Windows.Forms.ProgressBar progressBar; 70 | private System.Windows.Forms.Button CalculateButton; 71 | private System.Windows.Forms.TextBox NumPlayers; 72 | */ 73 | 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/Runtime/olist.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | /// 4 | public class ObjectList 5 | { 6 | class Link { 7 | internal object it; 8 | internal Link next; 9 | internal Link(object o, Link x) { it=o;next=x; } 10 | } 11 | void Add0(Link a) { 12 | if (head==null) 13 | head = last = a; 14 | else 15 | last = last.next = a; 16 | } 17 | object Get0(Link a,int x) { 18 | if (a==null || x<0) // safety 19 | return null; 20 | if (x==0) 21 | return a.it; 22 | return Get0(a.next,x-1); 23 | } 24 | private Link head = null, last=null; 25 | private int count = 0; 26 | /// 27 | public ObjectList() {} 28 | /// 29 | public void Add(object o) { Add0(new Link(o,null)); count++; } 30 | /// 31 | public void Push(object o) { head = new Link(o,head); count++; } 32 | /// 33 | public object Pop() { object r=head.it; head=head.next; count--; return r; } 34 | /// 35 | public object Top { get { return head.it; }} 36 | /// 37 | public int Count { get { return count; }} 38 | /// 39 | public object this[int ix] { get { return Get0(head,ix); } } 40 | /// 41 | public class OListEnumerator : IEnumerator 42 | { 43 | ObjectList list; 44 | Link cur = null; 45 | /// 46 | public object Current { get { return cur.it; }} 47 | /// 48 | public OListEnumerator(ObjectList o) 49 | { 50 | list = o; 51 | } 52 | /// 53 | public bool MoveNext() 54 | { 55 | if (cur==null) 56 | cur = list.head; 57 | else 58 | cur = cur.next; 59 | return cur!=null; 60 | } 61 | /// 62 | public void Reset() 63 | { 64 | cur = null; 65 | } 66 | } 67 | /// 68 | public IEnumerator GetEnumerator() 69 | { 70 | return new OListEnumerator(this); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/PokerStarsBot/Keys.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Windows.Forms; 6 | using System.ComponentModel; 7 | using System.Data; 8 | using System.Drawing; 9 | using System.Text; 10 | using Microsoft.Win32; 11 | 12 | 13 | namespace pokermaster 14 | { 15 | static public class Keys 16 | { 17 | const string regkeyName = "Software\\Microsoft\\PokerSync"; 18 | 19 | static public bool ValidateKey(string str) 20 | { 21 | if (str == null && str.Trim() == "") 22 | return false; 23 | 24 | const int SecsPerDay = 60 * 60 * 24; 25 | 26 | int secs = ReadReqKey(); 27 | 28 | int day = secs / SecsPerDay; 29 | 30 | return str.Trim().Equals(Utils.hash((uint) day).ToString()); 31 | } 32 | 33 | static public int ReadReqKey() 34 | { 35 | RegistryKey key = Registry.CurrentUser.CreateSubKey(regkeyName); 36 | int val; 37 | 38 | if (key.ValueCount == 0) 39 | val = 1; 40 | else 41 | val = (int) key.GetValue("count"); 42 | 43 | key.Close(); 44 | return val; 45 | } 46 | 47 | static public void UpdateReqKey(int spentSecs) 48 | { 49 | RegistryKey key = Registry.CurrentUser.CreateSubKey(regkeyName); 50 | 51 | if (key.ValueCount == 0) 52 | key.SetValue("count", spentSecs); 53 | else 54 | key.SetValue("count", spentSecs + (int)key.GetValue("count") + 1); 55 | 56 | key.Close(); 57 | } 58 | 59 | 60 | static public void RequireKey() 61 | { 62 | string choice = null; 63 | 64 | while (true) 65 | { 66 | 67 | // if (ValidateKey(Microsoft.VisualBasic.Interaction.InputBox("Enter program key:", "Poker Symulator", null, 100, 100))) break; 68 | 69 | DialogResult res = IO.InputBox("Poker Symulator", "Enter program key:", ref choice); 70 | 71 | if (res == DialogResult.OK && ValidateKey(choice)) 72 | break; 73 | 74 | if (res == DialogResult.Abort 75 | || res == DialogResult.Cancel 76 | || res == DialogResult.Ignore 77 | || res == DialogResult.No) 78 | Environment.Exit(0); 79 | 80 | MessageBox.Show("Invalid Key!", "Poker Symulator"); 81 | } 82 | } 83 | 84 | } 85 | 86 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | [Bb]in/ 3 | [Oo]bj/ 4 | 5 | # mstest test results 6 | TestResults 7 | 8 | ## Ignore Visual Studio temporary files, build results, and 9 | ## files generated by popular Visual Studio add-ons. 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.sln.docstates 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Rr]elease/ 19 | x64/ 20 | *_i.c 21 | *_p.c 22 | *.ilk 23 | *.meta 24 | *.obj 25 | *.pch 26 | *.pdb 27 | *.pgc 28 | *.pgd 29 | *.rsp 30 | *.sbr 31 | *.tlb 32 | *.tli 33 | *.tlh 34 | *.tmp 35 | *.log 36 | *.vspscc 37 | *.vssscc 38 | .builds 39 | 40 | # Visual C++ cache files 41 | ipch/ 42 | *.aps 43 | *.ncb 44 | *.opensdf 45 | *.sdf 46 | 47 | # Visual Studio profiler 48 | *.psess 49 | *.vsp 50 | *.vspx 51 | 52 | # Guidance Automation Toolkit 53 | *.gpState 54 | 55 | # ReSharper is a .NET coding add-in 56 | _ReSharper* 57 | 58 | # NCrunch 59 | *.ncrunch* 60 | .*crunch*.local.xml 61 | 62 | # Installshield output folder 63 | [Ee]xpress 64 | 65 | # DocProject is a documentation generator add-in 66 | DocProject/buildhelp/ 67 | DocProject/Help/*.HxT 68 | DocProject/Help/*.HxC 69 | DocProject/Help/*.hhc 70 | DocProject/Help/*.hhk 71 | DocProject/Help/*.hhp 72 | DocProject/Help/Html2 73 | DocProject/Help/html 74 | 75 | # Click-Once directory 76 | publish 77 | 78 | # Publish Web Output 79 | *.Publish.xml 80 | 81 | # NuGet Packages Directory 82 | packages 83 | 84 | # Windows Azure Build Output 85 | csx 86 | *.build.csdef 87 | 88 | # Windows Store app package directory 89 | AppPackages/ 90 | 91 | # Others 92 | [Bb]in 93 | [Oo]bj 94 | sql 95 | TestResults 96 | [Tt]est[Rr]esult* 97 | *.Cache 98 | ClientBin 99 | [Ss]tyle[Cc]op.* 100 | ~$* 101 | *.dbmdl 102 | Generated_Code #added for RIA/Silverlight projects 103 | 104 | # Backup & report files from converting an old project file to a newer 105 | # Visual Studio version. Backup files are not needed, because we have git ;-) 106 | _UpgradeReport_Files/ 107 | Backup*/ 108 | UpgradeLog*.XML 109 | /src/PokerStarsBot/bin 110 | /src/PokerStarsBot/obj 111 | /src/HandEvaluator/obj 112 | /src/HandEvaluator/bin 113 | -------------------------------------------------------------------------------- /src/PokerStarsBot/Combinatorics.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.IO; 6 | using System.Drawing; 7 | 8 | 9 | namespace pokermaster 10 | { 11 | static class Combinatorics 12 | { 13 | 14 | private static void swap(int a, int b) { int t = a; a = b; b = t; } 15 | 16 | private static void reverse(int[] s, int b, int f) 17 | { 18 | for (; b < f; f--, b++) 19 | swap(s[b], s[f]); 20 | } 21 | 22 | 23 | // best permutation generator 24 | static public void ReversingQuickPerm(int[] a, int N) 25 | { 26 | int[] p = new int[N + 1]; 27 | int i; 28 | 29 | for (i = 0; i <= N; i++) 30 | p[i] = i; 31 | 32 | for (i = 1; i < N; ) 33 | { 34 | p[i]--; 35 | reverse(a, 0, i); 36 | // print(a); 37 | for (i = 1; p[i] == 0; i++) 38 | p[i] = i; // reset p[i] zero value 39 | } 40 | } 41 | 42 | 43 | static Random rand = new Random(2346789); // DateTime.UtcNow.Millisecond); 44 | 45 | // changes fromDeck 46 | static public void selectPermRandom(int[] toDeck, int[] ofromDeck, int N, int total) 47 | { 48 | int[] fromDeck = new int[ofromDeck.Length]; 49 | Array.Copy(ofromDeck, fromDeck, total); 50 | 51 | for (int r = 0; r < N; ) 52 | { 53 | int k = rand.Next(total); 54 | if (fromDeck[k] != 0) { 55 | toDeck[r++] = fromDeck[k]; 56 | fromDeck[k] = 0; 57 | } 58 | } 59 | } 60 | 61 | const int HAND_CARDS = PokerHand.HAND_CARDS; 62 | static private int[] ids = new int[HAND_CARDS + 1]; 63 | 64 | static public void initCombination() 65 | { 66 | for (int i = 1; i <= HAND_CARDS; i++) 67 | ids[i] = i; 68 | } 69 | 70 | 71 | static public void nextCombination(int[] resDeck) 72 | { 73 | int i; 74 | 75 | // generate new combination 76 | for (i = HAND_CARDS; ids[i] == PokerApp.DECK_CARDS - HAND_CARDS + i; i--) ; 77 | if (i == 0) IO.Message("#4tgh"); // last combination 78 | 79 | ids[i]++; 80 | for (int j = i + 1; j <= HAND_CARDS; j++) 81 | ids[j] = ids[i] + j - i; 82 | 83 | Array.Copy(ids, 1, resDeck, 0, HAND_CARDS); 84 | } 85 | 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /docs/Poker links.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | Bookmarks 7 |

Menu de Marcadores

8 | 9 |

10 | 11 |

poker

12 |

13 |

Poker probability (Texas hold 'em) - Wikipedia, the free encyclopedia 14 |
Texas hold 'em - Wikipedia, the free encyclopedia 15 |
List of poker hands - Wikipedia, the free encyclopedia 16 |
PokerStove: Poker Software and Analysis 17 |
Poker Odds Calculator - Calculate Odds for Texas Holdem | PokerNews 18 |
The most advanced poker odds calculator on the web. Know your chances of winning a hand against one or many opponents in Texas Hold'em. 19 |
Poker Odds Calculator - Always Know Your Poker Odds 20 |
Use our poker odds calculator to get an edge over your opponents - Get free poker odds for all major poker variations. 21 |
pokerstars bots - Google Search 22 |
WinHoldEm Home 23 |
How I Built a Working Poker Bot, Part 1 24 |

25 | 26 |

27 | -------------------------------------------------------------------------------- /src/PokerStarsBot/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.1008 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 pokerbot.Properties { 12 | using System; 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 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("pokerbot.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/Exam.lexer: -------------------------------------------------------------------------------- 1 | %lexer Exam 2 | 3 | [AaKkQqJjTt98765432][DdCcHhSs] %Card {yylval = yytext.Clone();} 4 | [AaKkQqJjTt98765432][AaKkQqJjTt98765432]([OoSs\*])? %Card169 {yylval = yytext.Clone();} 5 | [AaKkQqJjTt98765432][Xx\?]([OoSs\*])? %Card169Wild {yylval = yytext.Clone();} 6 | [0123456789]+(\.[0123456789]+)?\% %Percent {yylval = yytext.Substring(0, yytext.Length-1);} 7 | [0123456789]+(\.[0123456789]+)? %Number {yylval = yytext.Clone();} 8 | 9 | "?" %Any {yylval = yytext.Clone();} 10 | [Gg][Aa][Pp]([Pp][Ee][Dd])? %Gapped {yylval = yytext.Clone();} 11 | [Gg][Aa][Pp]([Pp][Ee][Dd])?1 %Gapped1 {yylval = yytext.Clone();} 12 | [Gg][Aa][Pp]([Pp][Ee][Dd])?2 %Gapped2 {yylval = yytext.Clone();} 13 | [Gg][Aa][Pp]([Pp][Ee][Dd])?3 %Gapped3 {yylval = yytext.Clone();} 14 | 15 | "-" %To {yylval = yytext.Clone();} 16 | [Tt][Oo] %To {yylval = yytext.Clone();} 17 | [Tt][Hh][Rr][Oo][Uu][Gg][Hh] %To {yylval = yytext.Clone();} 18 | 19 | [Pp][Aa][Ii][Rr]([Ee][Dd])? %Pair {yylval = yytext.Clone();} 20 | [Nn][Oo][Tt] %Not {yylval = yytext.Clone();} 21 | "!" %Not {yylval = yytext.Clone();} 22 | [Bb][Uu][Tt] %But {yylval = yytext.Clone();} 23 | 24 | [Cc]([Oo][Nn][Nn][Ee][Cc][Tt][Ee][Dd])? %Connected {yylval = yytext.Clone();} 25 | 26 | [Ss]([Uu][Ii][Tt][Ee][Dd])? %Suited {yylval = yytext.Clone();} 27 | [Oo]([Ff][Ff][Ss][Uu][Ii][Tt]([Ed][Dd])?)? %Offsuit {yylval = yytext.Clone();} 28 | 29 | "<=" %LE {yylval = yytext.Clone();} 30 | "<" %LT {yylval = yytext.Clone();} 31 | ">=" %GE {yylval = yytext.Clone();} 32 | ">" %GT {yylval = yytext.Clone();} 33 | [Oo][Rr] %OR {yylval = yytext.Clone();} 34 | [Uu][Nn][Ii][Oo][Nn] %OR {yylval = yytext.Clone();} 35 | "," %OR {yylval = yytext.Clone();} 36 | "|" %OR {yylval = yytext.Clone();} 37 | [Aa][Nn][Dd] %AND {yylval = yytext.Clone();} 38 | "&" %AND {yylval = yytext.Clone();} 39 | [Ii][Nn] %IN {yylval = yytext.Clone();} 40 | [Ii][Nn][Tt][Ee][Rr][Ss][Ee][Cc][Tt]([Ii][Oo][Nn])? %AND {yylval = yytext.Clone();} 41 | "(" %LParen {yylval = yytext.Clone();} 42 | ")" %RParen {yylval = yytext.Clone();} 43 | 44 | [Gg]([Rr][Oo][Uu][Pp])?8 %Group8 {yylval = yytext.Clone();} 45 | [Gg]([Rr][Oo][Uu][Pp])?7 %Group7 {yylval = yytext.Clone();} 46 | [Gg]([Rr][Oo][Uu][Pp])?6 %Group6 {yylval = yytext.Clone();} 47 | [Gg]([Rr][Oo][Uu][Pp])?5 %Group5 {yylval = yytext.Clone();} 48 | [Gg]([Rr][Oo][Uu][Pp])?4 %Group4 {yylval = yytext.Clone();} 49 | [Gg]([Rr][Oo][Uu][Pp])?3 %Group3 {yylval = yytext.Clone();} 50 | [Gg]([Rr][Oo][Uu][Pp])?2 %Group2 {yylval = yytext.Clone();} 51 | [Gg]([Rr][Oo][Uu][Pp])?1 %Group1 {yylval = yytext.Clone();} 52 | [Gg]([Rr][Oo][Uu][Pp])?9 %Group9 {yylval = yytext.Clone();} 53 | [Gg]([Rr][Oo][Uu][Pp])?[Nn]([Oo][Nn][Ee])? %Group9 {yylval = yytext.Clone();} 54 | 55 | [\r\n ] ; -------------------------------------------------------------------------------- /src/PokerStarsBot/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.IO; 6 | using System.Drawing; 7 | using System.Security.Cryptography; 8 | 9 | 10 | namespace pokermaster 11 | { 12 | 13 | class ReserveComp : IComparer 14 | { 15 | int IComparer.Compare (int x, int y) 16 | { 17 | return x-y; 18 | } 19 | } 20 | 21 | 22 | static class Utils 23 | { 24 | 25 | public static void BinaryInsertionSort (int[] a) 26 | { 27 | int i, m; 28 | int hi, lo, tmp; 29 | 30 | for (i = 1; i < a.Length; i++) 31 | { 32 | lo = 0; 33 | hi = i; 34 | m = i / 2; 35 | 36 | // Find 37 | do { 38 | if (a[i] < a[m]) 39 | lo = m + 1; 40 | else if (a[i] > a[m]) 41 | hi = m; 42 | else 43 | break; 44 | 45 | m = lo + ((hi - lo) / 2); 46 | } while (lo < hi); 47 | 48 | // insert 49 | if (m < i) { 50 | tmp = a[i]; 51 | Array.Copy(a, m, a, m + 1, i - m); // copy 1 forward 52 | a[m] = tmp; 53 | } 54 | } 55 | } 56 | 57 | // a is changed. res has result 58 | public static void SelectionSort(int[] a) 59 | { 60 | int n = a.Length; 61 | 62 | for (int i = 0; i < n; i++) 63 | { 64 | int max = i; 65 | int vmax = a[max]; 66 | 67 | for (int j = i + 1; j < n; j++) 68 | if (a[j] > vmax) 69 | { 70 | max = j; 71 | vmax = a[max]; 72 | } 73 | 74 | if (max != i) 75 | { // swap 76 | int tt = a[i]; 77 | a[i] = a[max]; 78 | a[max] = tt; 79 | } 80 | } 81 | } 82 | 83 | 84 | // fastest 85 | static Random rand = new Random(DateTime.UtcNow.Millisecond); 86 | 87 | public static int genSimpleRandom(int min, int max) 88 | { 89 | return rand.Next(min, max+1); 90 | // return (rand.Next() % (max-min+1)) + min; // faster prolly 91 | } 92 | 93 | 94 | static RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); 95 | 96 | // only generates numbers between 1 and 255. VERY SLOW 97 | public static int genCryptoRandom(int min, int max) 98 | { 99 | byte[] val = new byte[1]; 100 | int range = max - min + 1; 101 | int limit = range * (Byte.MaxValue / range); 102 | 103 | do 104 | rng.GetBytes(val); 105 | while (!(val[0] < limit)); // check for leftovers 106 | 107 | return val[0] % range + min; 108 | } 109 | 110 | // slower but simpler to test 111 | // only generates numbers between 1 and 255 112 | public static int genRandom234(int min, int max) 113 | { 114 | byte[] val = new byte[1]; 115 | 116 | do 117 | rng.GetBytes(val); 118 | while (!(val[0] >= min && val[0] <= max)); // check for leftovers 119 | 120 | return val[0]; 121 | } 122 | 123 | public static uint hash(uint a) 124 | { 125 | a = (a + 0x7ed55d16) + (a << 12); 126 | a = (a ^ 0xc761c23c) ^ (a >> 19); 127 | a = (a + 0x165667b1) + (a << 5 ); 128 | a = (a + 0xd3a2646c) ^ (a << 9 ); 129 | a = (a + 0xfd7046c5) + (a << 3 ); 130 | a = (a ^ 0xb55a4f09) ^ (a >> 16); 131 | 132 | return a; 133 | } 134 | 135 | public static void Test() 136 | { 137 | for (uint i = 0; i < 100000; i++) 138 | IO.WriteLine(i + " : " + hash(i)); 139 | } 140 | 141 | 142 | public static int pow(int n, int exp) 143 | { 144 | switch (exp) 145 | { 146 | case 0: return 1; 147 | case 1: return n; 148 | case 2: return n * n; 149 | case 3: return n * n * n; 150 | case 4: return n * n * n * n; 151 | case 5: return n * n * n * n * n; 152 | 153 | default: 154 | int ret = n; 155 | for (int i = 1; i < exp; i++) 156 | ret *= n; 157 | return ret; 158 | } 159 | } 160 | 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/HandEvaluator/HandEvaluator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | 2.0 8 | {57836673-FE81-4367-A4EB-AAA46FB954D2} 9 | Library 10 | Properties 11 | HandEvaluator 12 | HandEvaluator 13 | false 14 | 15 | 16 | 17 | 18 | 3.5 19 | 0 20 | 21 | 22 | v4.0 23 | 24 | 25 | true 26 | full 27 | false 28 | bin\Debug\ 29 | TRACE;DEBUG;GENTIME 30 | prompt 31 | 4 32 | bin\Debug\HandEvaluator.XML 33 | true 34 | 35 | 36 | pdbonly 37 | true 38 | bin\Release\ 39 | TRACE;GENTIME 40 | prompt 41 | 4 42 | bin\Release\HandEvaluator.XML 43 | Off 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 80 | -------------------------------------------------------------------------------- /src/PokerStarsBot/Card.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | 6 | 7 | namespace pokermaster 8 | { 9 | public enum CardType : int 10 | { 11 | Two = 2, 12 | Three = 3, 13 | Four = 4, 14 | Five = 5, 15 | Six = 6, 16 | Seven = 7, 17 | Eight = 8, 18 | Nine = 9, 19 | T = 10, 20 | J = 11, 21 | Q = 12, 22 | K = 13, 23 | A = 14 24 | } 25 | 26 | public enum CardSuit : int 27 | { 28 | c = 0, 29 | d = 1, 30 | h = 2, 31 | s = 3 32 | } 33 | 34 | // Ids from 1 to 52 35 | // Type from 2 to 14 36 | 37 | public class Card 38 | { 39 | public CardType type; 40 | public CardSuit suit; 41 | 42 | public Card(CardType t, CardSuit s) { type = t; suit = s; } 43 | public Card(int suit, int type) : this((CardType)suit, (CardSuit)type) { } 44 | public Card(int id) : this((CardType) idType(id), (CardSuit) idSuit(id)) { } 45 | 46 | // convert the Card struct to a Card ID 47 | public int cardToId() { return cardToId(suit, type); } 48 | public static int cardToId(Card card) { return cardToId(card.suit, card.type); } 49 | public static int cardToId(int suit, int type) { return cardToId((CardSuit) suit, (CardType) type); } 50 | public static int cardToId(CardSuit suit, CardType type) 51 | { 52 | return PokerApp.TOTAL_SUITS * ((int)type-2) + (int)suit +1; 53 | } 54 | 55 | // convert the Card ID to a struct 56 | public static int idSuit(int id) { return (id-1) % PokerApp.TOTAL_SUITS; } 57 | public static int idType(int id) { return (id-1) / PokerApp.TOTAL_SUITS +2; } 58 | 59 | public override string ToString( ) { return ToString(type, suit); } 60 | public static string ToString(int id) { return new Card(id).ToString(); } 61 | public static string ToString(Card c) { return c.ToString(); } 62 | 63 | public static string ToString(CardType type, CardSuit suit) 64 | { 65 | int t = (int)type; 66 | if (t < 10) 67 | return t.ToString() + suit.ToString(); 68 | else 69 | return type.ToString() + suit.ToString(); 70 | } 71 | 72 | 73 | public static int parseCard(string str) 74 | { 75 | string c = str[str.Length-1].ToString().ToLower(); 76 | string t = str.Substring(0, str.Length-1).ToUpper(); 77 | 78 | if (!Enum.IsDefined(typeof(CardSuit), c)) 79 | { 80 | c = str[0].ToString().ToLower(); 81 | t = str.Substring(1, str.Length-0).ToUpper(); 82 | 83 | if (!Enum.IsDefined(typeof(CardSuit), c)) 84 | return 0; 85 | } 86 | 87 | try { 88 | CardSuit suit = (CardSuit) Enum.Parse(typeof(CardSuit), c, true); 89 | 90 | if (t == "T") 91 | return cardToId((int)suit, 10); 92 | 93 | if (!Enum.IsDefined(typeof(CardType), t) 94 | && !Enum.IsDefined(typeof(CardType), 95 | Enum.GetName(typeof(CardType), Int32.Parse(t)))) 96 | return 0; 97 | 98 | CardType type = (CardType) Enum.Parse(typeof(CardType), t, true); 99 | return cardToId(suit, type); 100 | } 101 | catch (Exception) { 102 | return 0; 103 | } 104 | } 105 | 106 | } 107 | 108 | } 109 | 110 | 111 | // MAYBE TODO 112 | /* 113 | * Input format for cards 114 | * 115 | * suits: 116 | * ouros diamond - o d 117 | * copas hearts - h co 118 | * paus clubs - p cl 119 | * spades espadas - s e 120 | * 121 | * court: 122 | * jack knave valete - j n v 123 | * queen rainha - q ra 124 | * king rei - k re 125 | 126 | static readonly string[] diamons= { "o", "d" }; 127 | static readonly string[] hearts = { "h", "do" }; 128 | static readonly string[] clubs = { "p", "cl" }; 129 | static readonly string[] spades = { "s", "e" }; 130 | 131 | static readonly string[] knave = { "j", "n", "v" }; 132 | static readonly string[] queen = { "q", "ra" }; 133 | static readonly string[] king = { "k", "re" }; 134 | */ 135 | -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/Exam.parser: -------------------------------------------------------------------------------- 1 | %parser Exam.lexer 2 | %{ 3 | using System.Collections.Generic; 4 | using HoldemHand; 5 | %} 6 | 7 | %right Not 8 | %left LT LE GT GE 9 | %left IN AND OR But 10 | %left To 11 | %after Suited Offsuit 12 | 13 | SpecDoc : /* empty */ {$$ = new PocketHands();} 14 | | Expr {$$ = $1;} 15 | ; 16 | 17 | Expr : LParen Expr RParen {$$ = (PocketHands) $2.yylval;} 18 | | Expr Suited {$$ = ((PocketHands) $1.yylval) & PocketHands.Suited;} 19 | | Expr Offsuit {$$ = ((PocketHands) $1.yylval) & PocketHands.Offsuit;} 20 | | Expr OR Expr {$$ = ((PocketHands) $1.yylval) | ((PocketHands) $3.yylval);} 21 | | Expr AND Expr {$$ = ((PocketHands) $1.yylval) & ((PocketHands) $3.yylval);} 22 | | Expr IN Expr {$$ = ((PocketHands) $1.yylval) & ((PocketHands) $3.yylval);} 23 | | Not Expr {$$ = !((PocketHands) $2.yylval);} 24 | | Expr To Expr {$$ = PocketHands.GroupRange((PocketHands.GroupTypeEnum) $1.yylval, (PocketHands.GroupTypeEnum) $3.yylval);} 25 | | Expr LT Card169 {$$ = PocketHands.LT(((PocketHands) $1.yylval), (string)$3.yylval);} 26 | | Expr LE Card169 {$$ = PocketHands.LE(((PocketHands) $1.yylval), (string)$3.yylval);} 27 | | Expr GT Card169 {$$ = PocketHands.GT(((PocketHands) $1.yylval), (string)$3.yylval);} 28 | | Expr GE Card169 {$$ = PocketHands.GE(((PocketHands) $1.yylval), (string)$3.yylval);} 29 | | Expr LT Group {$$ = ((PocketHands) $1.yylval) < (PocketHands.GroupTypeEnum) $3.yylval;} 30 | | Expr LE Group {$$ = ((PocketHands) $1.yylval) <= (PocketHands.GroupTypeEnum) $3.yylval;} 31 | | Expr GT Group {$$ = ((PocketHands) $1.yylval) > (PocketHands.GroupTypeEnum) $3.yylval;} 32 | | Expr GE Group {$$ = ((PocketHands) $1.yylval) >= (PocketHands.GroupTypeEnum) $3.yylval;} 33 | | Any {$$ = PocketHands.AllHands;} 34 | | Card Card {$$ = PocketHands.PocketCards(((string) $1.yylval) + " " + ((string) $2.yylval));} 35 | | Card169 {$$ = PocketHands.PocketCards169(((string) $1.yylval));} 36 | | Connected {$$ = PocketHands.Connected;} 37 | | Gapped {$$ = PocketHands.Gap;} 38 | | Gapped1 {$$ = PocketHands.Gap1;} 39 | | Gapped2 {$$ = PocketHands.Gap2;} 40 | | Gapped3 {$$ = PocketHands.Gap3;} 41 | | Suited {$$ = PocketHands.Suited;} 42 | | Offsuit {$$ = PocketHands.Offsuit;} 43 | | Pair {$$ = PocketHands.Pair;} 44 | | Group {$$ = PocketHands.Group((PocketHands.GroupTypeEnum) $1.yylval);} 45 | | Card169Wild {$$ = PocketHands.PocketCards169Wild((string)$1.yylval);} 46 | | Group To Group {$$ = PocketHands.GroupRange((PocketHands.GroupTypeEnum) $1.yylval,(PocketHands.GroupTypeEnum) $3.yylval); } 47 | | Card169 To Card169 {$$ = PocketHands.PocketCards169Range((string) $1.yylval, (string) $3.yylval);} 48 | | Expr LT Number {$$ = ((PocketHands) $1.yylval) < double.Parse((string) $3.yylval);} 49 | | Expr LE Number {$$ = ((PocketHands) $1.yylval) <= double.Parse((string) $3.yylval);} 50 | | Expr GT Number {$$ = ((PocketHands) $1.yylval) > double.Parse((string) $3.yylval);} 51 | | Expr GE Number {$$ = ((PocketHands) $1.yylval) >= double.Parse((string) $3.yylval);} 52 | | Expr LT Percent {$$ = ((PocketHands) $1.yylval) < (double.Parse((string) $3.yylval)/100.0);} 53 | | Expr LE Percent {$$ = ((PocketHands) $1.yylval) <= (double.Parse((string) $3.yylval)/100.0);} 54 | | Expr GT Percent {$$ = ((PocketHands) $1.yylval) > (double.Parse((string) $3.yylval)/100.0);} 55 | | Expr GE Percent {$$ = ((PocketHands) $1.yylval) >= (double.Parse((string) $3.yylval)/100.0);} 56 | ; 57 | 58 | Group : Group8 {$$ = 7;} 59 | | Group7 {$$ = 6;} 60 | | Group6 {$$ = 5;} 61 | | Group5 {$$ = 4;} 62 | | Group4 {$$ = 3;} 63 | | Group3 {$$ = 2;} 64 | | Group2 {$$ = 1;} 65 | | Group1 {$$ = 0;} 66 | | Group9 {$$ = 8;} 67 | ; 68 | -------------------------------------------------------------------------------- /src/PokerStarsBot/IO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using System.IO; 6 | using System.Drawing; 7 | 8 | 9 | namespace pokermaster 10 | { 11 | static class IO 12 | { 13 | public static TextWriter log = new StreamWriter("poker-sym-log.txt"); 14 | 15 | public static void Write (string str) { log.Write (str); log.Flush(); } 16 | 17 | public static void WriteLine(string str) { log.WriteLine(str); log.Flush(); } 18 | 19 | public static void Message (string str) { MessageBox.Show(str); } 20 | 21 | public static string stringIds (int[] bb) { return stringIds (bb, 0, bb.Length); } 22 | public static string stringCards(int[] bb) { return stringCards(bb, 0, bb.Length); } 23 | public static string stringCards(Card[]bb) { return stringCards(bb, 0, bb.Length); } 24 | 25 | public static string stringIds (int[] bb, int i) { return stringIds (bb, i, bb.Length); } 26 | public static string stringCards(int[] bb, int i) { return stringCards(bb, i, bb.Length); } 27 | public static string stringCards(Card[]bb, int i) { return stringCards(bb, i, bb.Length); } 28 | 29 | public static string stringIds(int[] bb, int i, int j) 30 | { 31 | string str = ""; 32 | for (; i < j; i++) 33 | str += String.Format("{0,3}", bb[i]); 34 | return str; 35 | } 36 | 37 | public static string stringCards(Card[] cards, int i, int j) 38 | { 39 | string str = ""; 40 | for (; i < j; i++) 41 | str += String.Format("{0,3}", Card.ToString(cards[i])); 42 | return str; 43 | } 44 | 45 | public static string stringCards(int[] cards, int i, int j) 46 | { 47 | string str = ""; 48 | for (; i < j; i++) 49 | str += String.Format("{0,3}", Card.ToString(cards[i])); 50 | return str; 51 | } 52 | 53 | public static void printDeck(string cards) 54 | { 55 | Write("Deck: " + cards + "\n"); 56 | } 57 | 58 | public static void printHand(string cards) 59 | { 60 | Write("Hand: " + cards + "\n"); 61 | } 62 | 63 | 64 | public static int[] parseCards(string input) 65 | { 66 | string[] cards = input.Split((char[]) null, StringSplitOptions.RemoveEmptyEntries); 67 | int[] ids = new int[PokerApp.TAKEN_CARDS]; //cards.Length]; 68 | int i = 0; 69 | 70 | foreach (string s in cards) 71 | if ((ids[i++] = Card.parseCard(s)) == 0) 72 | { IO.Message("[ERROR] Wrong Format of value: " + s); 73 | return null; 74 | } 75 | 76 | return ids; 77 | } 78 | 79 | 80 | public static DialogResult InputBox(string title, string promptText, ref string value) 81 | { 82 | Form form = new Form(); 83 | Label label = new Label(); 84 | TextBox textBox = new TextBox(); 85 | Button buttonOk = new Button(); 86 | Button buttonCancel = new Button(); 87 | 88 | form.Text = title; 89 | label.Text = promptText; 90 | textBox.Text = value; 91 | 92 | buttonOk.Text = "OK"; 93 | buttonCancel.Text = "Cancel"; 94 | buttonOk.DialogResult = DialogResult.OK; 95 | buttonCancel.DialogResult = DialogResult.Cancel; 96 | 97 | label.SetBounds(9, 20, 372, 13); 98 | textBox.SetBounds(12, 36, 372, 20); 99 | buttonOk.SetBounds(228, 72, 75, 23); 100 | buttonCancel.SetBounds(309, 72, 75, 23); 101 | 102 | label.AutoSize = true; 103 | textBox.Anchor = textBox.Anchor | AnchorStyles.Right; 104 | buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; 105 | buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; 106 | 107 | form.ClientSize = new Size(396, 107); 108 | form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel }); 109 | form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height); 110 | form.FormBorderStyle = FormBorderStyle.FixedDialog; 111 | form.StartPosition = FormStartPosition.CenterScreen; 112 | form.MinimizeBox = false; 113 | form.MaximizeBox = false; 114 | form.AcceptButton = buttonOk; 115 | form.CancelButton = buttonCancel; 116 | 117 | DialogResult dialogResult = form.ShowDialog(); 118 | value = textBox.Text; 119 | return dialogResult; 120 | } 121 | 122 | 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/PocketHandsQuery.cs: -------------------------------------------------------------------------------- 1 | // Much of this code is derived from poker.eval (look for it on sourceforge.net). 2 | // This library is covered by the LGPL Gnu license. See http://www.gnu.org/copyleft/lesser.html 3 | // for more information on this license. 4 | 5 | // This code is a very fast, native C# Texas Holdem mask evaluator (containing no interop or unsafe code). 6 | // This code can enumarate 35 million 5 card hands per second and 29 million 7 card hands per second on my desktop machine. 7 | // That's not nearly as fast as the heavily macro-ed poker.eval C library. However, this implementation is 8 | // in roughly the same ballpark for speed and is quite usable in C#. 9 | 10 | // The speed ups are mostly table driven. That means that there are several very large tables included in this file. 11 | // The code is divided up into several files they are: 12 | // HandEvaluator.cs - base mask evaluator 13 | // HandIterator.cs - methods that support IEnumerable and methods that validate the mask evaluator 14 | // HandAnalysis.cs - methods to aid in analysis of Texas Holdem Hands. 15 | // PocketHands.cs - a class to manipulate pocket hands. 16 | // PocketQueryParser - a parser used to interprete pocket mask query language statements. 17 | // The runtime portion of the query parser is copyrighted by Malcolm Crowe (but is freely distributable) 18 | 19 | // Written (ported) by Keith Rule - Sept 2005, updated May 2007 20 | 21 | using System; 22 | using System.Collections; 23 | using System.Collections.Generic; 24 | using System.Text; 25 | using Tools; 26 | 27 | namespace HoldemHand 28 | { 29 | /// 30 | /// Represents a set of pocket hands and operations that 31 | /// can be applied to them. 32 | /// 33 | public partial class PocketHands 34 | { 35 | /// 36 | /// This function allows a text description (or query) of set 37 | /// of pocket hands to be specified such that all of the hands that match 38 | /// this query (minus the hands containing any of the cards in the 39 | /// dead mask) will be returned. 40 | /// 41 | /// card mask for dead cards 42 | /// string defining PocketHands query 43 | /// 44 | static public PocketHands Query(string s, ulong dead) 45 | { 46 | return Query(s) - dead; 47 | } 48 | 49 | 50 | /// 51 | /// 52 | /// 53 | /// 54 | /// 55 | /// 56 | static public bool ValidateQuery(string s, ulong dead) 57 | { 58 | try 59 | { 60 | return Query(s, dead).Count > 0; 61 | } 62 | catch 63 | { 64 | return false; 65 | } 66 | } 67 | 68 | /// 69 | /// 70 | /// 71 | /// 72 | /// 73 | static public bool ValidateQuery(string s) 74 | { 75 | return ValidateQuery(s, 0UL); 76 | } 77 | 78 | /// 79 | /// This function allows a text description (or query) of set 80 | /// of pocket hands to be specified such that all of the hands that match 81 | /// this query will be returned. 82 | /// 83 | /// Query String 84 | /// 85 | static public PocketHands Query(string s) 86 | { 87 | try 88 | { 89 | syntax p = new syntax(); 90 | // For debugging the parser 91 | //p.m_debug = true; 92 | object obj = p.Parse(s); 93 | return (PocketHands)((Expr)((SpecDoc)obj).yylval).yylval; 94 | } 95 | catch 96 | { 97 | throw new ArgumentException("Syntax Error"); 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/Runtime/genbase0.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using System.IO; 4 | 5 | namespace Tools 6 | { 7 | /// 8 | public class GenBase 9 | { 10 | /// 11 | public ErrorHandler erh; 12 | /// 13 | protected GenBase(ErrorHandler eh) { erh = eh; } 14 | /// 15 | public TextWriter m_outFile; 16 | /// 17 | protected Encoding m_scriptEncoding = Encoding.ASCII; 18 | /// 19 | protected bool toupper = false; 20 | /// 21 | protected string ScriptEncoding 22 | { 23 | set 24 | { 25 | m_scriptEncoding = Encoding.ASCII; 26 | } 27 | } 28 | /// 29 | public string m_outname; 30 | // convenience functions 31 | /// 32 | protected int Braces(int a,string b,ref int p,int max) 33 | { 34 | int rv = a; 35 | int quote = 0; 36 | for (;p 56 | protected string ToBraceIfFound(ref string buf,ref int p,ref int max,CsReader inf) 57 | { 58 | int q = p; 59 | int brack = Braces(0,buf,ref p,max); 60 | string rv = buf.Substring(q,p-q); 61 | while (inf!=null && brack>0) 62 | { 63 | buf=inf.ReadLine(); 64 | max=buf.Length; 65 | if (max==0) 66 | Error(47,q,"EOF in action or class def??"); 67 | p=0; 68 | rv += '\n'; 69 | brack = Braces(brack,buf,ref p,max); 70 | rv += buf.Substring(0,p); 71 | } 72 | return rv; 73 | } 74 | /// 75 | // convenience functions 76 | public bool White(string buf, ref int offset,int max) 77 | { 78 | while (offset 84 | public bool NonWhite(string buf, ref int offset,int max) 85 | { 86 | while (offset 92 | public int EmitClassDefin(string b,ref int p,int max,CsReader inf,string defbas,out string bas, out string name,bool lx) 93 | { 94 | name = ""; 95 | bas = defbas; 96 | NonWhite(b,ref p,max); 97 | White(b,ref p,max); 98 | for(;p 120 | public void Error(int n, int p, string str) 121 | { 122 | if (m_outFile!=null) 123 | { 124 | m_outFile.WriteLine(); 125 | m_outFile.WriteLine("#error Generator failed earlier. Fix the parser script and run ParserGenerator again."); 126 | } 127 | erh.Error(new CSToolsException(n,sourceLineInfo(p),"",str)); 128 | } 129 | /// 130 | public virtual SourceLineInfo sourceLineInfo(int pos) { return new SourceLineInfo(pos); } 131 | /// 132 | public int line(int pos) { return sourceLineInfo(pos).lineNumber; } 133 | /// 134 | public int position(int pos) { return sourceLineInfo(pos).rawCharPosition; } 135 | /// 136 | public string Saypos(int pos) { return sourceLineInfo(pos).ToString(); } 137 | /// 138 | public Production m_prod = null; // current production being parsed 139 | /// 140 | public int LastSymbol = 2; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /docs/PokerSource poker hand evaluator and more.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PokerSource: poker hand evaluator and more 5 | 6 | 7 |

Poker hand evaluator

8 | 9 |

10 | poker-eval is a C library to evaluate poker hands. The result of the 11 | evalution for a given hand is a number. The general idea is that if 12 | the evalution of your hand is lower than the evaluation of the hand of 13 | your opponent, you lose. Many poker variants are supported (draw, 14 | holdem, omaha, etc.) and more can be added. poker-eval is designed 15 | for speed so that it can be used within poker simulation software 16 | using either exhaustive exploration or Monte Carlo. 17 |

18 | 19 | 30 | 31 |

Poker engine

32 | 33 |

34 | poker-engine is a python library that implements poker rules according 35 | to variants and betting structures specified in configuration files. 36 | It designed to be used by a multiplayer poker server, a poker AI or a 37 | poker client. 38 |

39 | 40 | 44 | 45 |

Poker server and client library

46 | 47 |

48 | poker-network includes a poker server, a client library, an abstract 49 | user interface library and a client based on it. 50 |

51 |

52 | The server deals the cards and checks the user actions using a poker 53 | game engine (poker-engine). It listens on a TCP/IP port and 54 | understands a poker-network specific protocol. The persistent 55 | informations (accounts, hand history etc.) are stored in a MySQL 56 | database. The server was designed and tested to gracefully handle 1000 57 | simultaneous players on a single machine also running the MySQL 58 | server. 59 |

60 |

61 | The client library implements the poker-network protocol for 62 | the client. It runs a poker-engine identical to the one used by 63 | the server and uses it to simplify the implementation of a client. 64 | For instance it creates an event indicating that the player lost 65 | position although the server does not send such a packet. A simple 66 | minded bot is provided as an example usage of the client library. 67 |

68 |

69 | The abstract user interface library provides a framework based on the 70 | client library and suited to implement a user friendly client. A 71 | display is fed with events such as give seat S to player P or get 72 | amount A from side pot P to player P so that the rendering part of the 73 | user interface does not need to maintain contextual game 74 | information. A toolkit is fed with high level interaction actions such 75 | as ask login and password or display the following holdem tables. An 76 | animation module is fed with events that can trigger animations or 77 | sounds such as player P timeouted or player P wins the pot. 78 |

79 |

80 | The client based on the user interface library uses GTK. 81 |

82 | 83 | 87 | 88 |

Howto install the server and GTK client on Debian GNU/Linux

89 | 90 | 1. Install Debian Linux.
91 | 2. Change /usr/apt/sources.list to include an 'unstable' server (just change stable to unstable)
92 | 3. apt-get update
93 | 4. apt-get install mysql-server
94 | 5. add a root password to mysql for security. The easiest way I found was: mysqladmin -u root password NEWPASSWORD
95 | 6. apt-get install python2.4-poker2d. you will need to enter some 96 | details regarding the passwords you want to use, and the password you 97 | just set up for root.
98 | 7. run the poker2d client in /usr/games
99 | 100 |

Projects using poker-eval or poker-engine

101 | 102 | (mail Loic Dachary to add your project here) 103 | 104 | 108 | 109 | -------------------------------------------------------------------------------- /src/PokerStarsBot/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 | -------------------------------------------------------------------------------- /src/PokerStarsBot/PokerSimulatorUI.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 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/PokerStarsBot/PokerStarsBot.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {69B86D90-C931-4B07-8E2C-5A61F96D96F3} 9 | WinExe 10 | Properties 11 | pokerbot 12 | PokerStarsBot 13 | v4.0 14 | 512 15 | publish\ 16 | true 17 | Disk 18 | false 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 0 26 | 1.0.0.%2a 27 | false 28 | false 29 | true 30 | 31 | 32 | 33 | 34 | 3.5 35 | 36 | 37 | true 38 | full 39 | false 40 | bin\Debug\ 41 | TRACE;DEBUG 42 | prompt 43 | 4 44 | true 45 | 46 | 47 | pdbonly 48 | true 49 | bin\Release\ 50 | 51 | 52 | prompt 53 | 4 54 | true 55 | 56 | 57 | 58 | 59 | 60 | 3.5 61 | 62 | 63 | 64 | 3.5 65 | 66 | 67 | 3.5 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | Form 82 | 83 | 84 | PokerSimulatorUI.cs 85 | 86 | 87 | 88 | 89 | PokerSimulatorUI.cs 90 | 91 | 92 | ResXFileCodeGenerator 93 | Resources.Designer.cs 94 | Designer 95 | 96 | 97 | True 98 | Resources.resx 99 | True 100 | 101 | 102 | SettingsSingleFileGenerator 103 | Settings.Designer.cs 104 | 105 | 106 | True 107 | Settings.settings 108 | True 109 | 110 | 111 | 112 | 113 | 114 | 115 | False 116 | .NET Framework 2.0 %28x86%29 117 | false 118 | 119 | 120 | False 121 | .NET Framework 3.0 %28x86%29 122 | false 123 | 124 | 125 | False 126 | .NET Framework 3.5 127 | true 128 | 129 | 130 | False 131 | Windows Installer 3.1 132 | true 133 | 134 | 135 | 136 | 137 | {57836673-FE81-4367-A4EB-AAA46FB954D2} 138 | HandEvaluator 139 | 140 | 141 | 142 | 149 | -------------------------------------------------------------------------------- /src/PokerStarsBot/PokerSimulatorUI.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace pokermaster 2 | { 3 | partial class PokerSimulatorUI 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.PlayerCardsBox = new System.Windows.Forms.TextBox(); 32 | this.SharedCardsBox = new System.Windows.Forms.TextBox(); 33 | this.WinProbBox = new System.Windows.Forms.TextBox(); 34 | this.PlayerCardsDesc = new System.Windows.Forms.Label(); 35 | this.SharedCardsDesc = new System.Windows.Forms.Label(); 36 | this.WinProbDesc = new System.Windows.Forms.Label(); 37 | this.UITitle = new System.Windows.Forms.Label(); 38 | this.progressBar = new System.Windows.Forms.ProgressBar(); 39 | this.CalculateButton = new System.Windows.Forms.Button(); 40 | this.NumPlayers = new System.Windows.Forms.TextBox(); 41 | this.NumPlayersDesc = new System.Windows.Forms.Label(); 42 | this.SuspendLayout(); 43 | // 44 | // PlayerCardsBox 45 | // 46 | this.PlayerCardsBox.Location = new System.Drawing.Point(91, 42); 47 | this.PlayerCardsBox.MaxLength = 100; 48 | this.PlayerCardsBox.Name = "PlayerCardsBox"; 49 | this.PlayerCardsBox.Size = new System.Drawing.Size(218, 20); 50 | this.PlayerCardsBox.TabIndex = 0; 51 | // 52 | // SharedCardsBox 53 | // 54 | this.SharedCardsBox.Location = new System.Drawing.Point(91, 80); 55 | this.SharedCardsBox.MaxLength = 1000; 56 | this.SharedCardsBox.Name = "SharedCardsBox"; 57 | this.SharedCardsBox.Size = new System.Drawing.Size(218, 20); 58 | this.SharedCardsBox.TabIndex = 1; 59 | // 60 | // WinProbBox 61 | // 62 | this.WinProbBox.Location = new System.Drawing.Point(91, 139); 63 | this.WinProbBox.MaxLength = 100; 64 | this.WinProbBox.Name = "WinProbBox"; 65 | this.WinProbBox.ReadOnly = true; 66 | this.WinProbBox.Size = new System.Drawing.Size(218, 20); 67 | this.WinProbBox.TabIndex = 2; 68 | // 69 | // PlayerCardsDesc 70 | // 71 | this.PlayerCardsDesc.AutoSize = true; 72 | this.PlayerCardsDesc.Location = new System.Drawing.Point(12, 45); 73 | this.PlayerCardsDesc.Name = "PlayerCardsDesc"; 74 | this.PlayerCardsDesc.Size = new System.Drawing.Size(64, 13); 75 | this.PlayerCardsDesc.TabIndex = 3; 76 | this.PlayerCardsDesc.Text = "Your Cards:"; 77 | // 78 | // SharedCardsDesc 79 | // 80 | this.SharedCardsDesc.AutoSize = true; 81 | this.SharedCardsDesc.Location = new System.Drawing.Point(12, 80); 82 | this.SharedCardsDesc.Name = "SharedCardsDesc"; 83 | this.SharedCardsDesc.Size = new System.Drawing.Size(76, 13); 84 | this.SharedCardsDesc.TabIndex = 4; 85 | this.SharedCardsDesc.Text = "Shared Cards:"; 86 | // 87 | // WinProbDesc 88 | // 89 | this.WinProbDesc.AutoSize = true; 90 | this.WinProbDesc.Location = new System.Drawing.Point(6, 142); 91 | this.WinProbDesc.Name = "WinProbDesc"; 92 | this.WinProbDesc.Size = new System.Drawing.Size(82, 13); 93 | this.WinProbDesc.TabIndex = 5; 94 | this.WinProbDesc.Text = "Win Probability:"; 95 | // 96 | // UITitle 97 | // 98 | this.UITitle.AutoSize = true; 99 | this.UITitle.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 100 | this.UITitle.ForeColor = System.Drawing.Color.Crimson; 101 | this.UITitle.Location = new System.Drawing.Point(87, 9); 102 | this.UITitle.MinimumSize = new System.Drawing.Size(50, 10); 103 | this.UITitle.Name = "UITitle"; 104 | this.UITitle.Size = new System.Drawing.Size(136, 20); 105 | this.UITitle.TabIndex = 6; 106 | this.UITitle.Text = "Poker Simulator"; 107 | this.UITitle.Click += new System.EventHandler(this.UITitle_Click); 108 | // 109 | // progressBar 110 | // 111 | this.progressBar.Location = new System.Drawing.Point(12, 115); 112 | this.progressBar.Name = "progressBar"; 113 | this.progressBar.Size = new System.Drawing.Size(297, 10); 114 | this.progressBar.TabIndex = 7; 115 | // 116 | // CalculateButton 117 | // 118 | this.CalculateButton.Location = new System.Drawing.Point(328, 115); 119 | this.CalculateButton.Name = "CalculateButton"; 120 | this.CalculateButton.Size = new System.Drawing.Size(75, 23); 121 | this.CalculateButton.TabIndex = 8; 122 | this.CalculateButton.Text = "Calculate"; 123 | this.CalculateButton.UseVisualStyleBackColor = true; 124 | this.CalculateButton.Click += new System.EventHandler(this.Calculate_Click); 125 | // 126 | // NumPlayers 127 | // 128 | this.NumPlayers.Location = new System.Drawing.Point(328, 65); 129 | this.NumPlayers.MaxLength = 2; 130 | this.NumPlayers.Name = "NumPlayers"; 131 | this.NumPlayers.Size = new System.Drawing.Size(100, 20); 132 | this.NumPlayers.TabIndex = 9; 133 | // 134 | // NumPlayersDesc 135 | // 136 | this.NumPlayersDesc.AutoSize = true; 137 | this.NumPlayersDesc.Location = new System.Drawing.Point(325, 45); 138 | this.NumPlayersDesc.Name = "NumPlayersDesc"; 139 | this.NumPlayersDesc.Size = new System.Drawing.Size(118, 13); 140 | this.NumPlayersDesc.TabIndex = 10; 141 | this.NumPlayersDesc.Text = "How many Opponents?"; 142 | // 143 | // PokerSimulatorUI 144 | // 145 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 146 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 147 | this.ClientSize = new System.Drawing.Size(457, 177); 148 | this.Controls.Add(this.NumPlayersDesc); 149 | this.Controls.Add(this.NumPlayers); 150 | this.Controls.Add(this.CalculateButton); 151 | this.Controls.Add(this.progressBar); 152 | this.Controls.Add(this.UITitle); 153 | this.Controls.Add(this.WinProbDesc); 154 | this.Controls.Add(this.SharedCardsDesc); 155 | this.Controls.Add(this.PlayerCardsDesc); 156 | this.Controls.Add(this.WinProbBox); 157 | this.Controls.Add(this.SharedCardsBox); 158 | this.Controls.Add(this.PlayerCardsBox); 159 | this.Name = "PokerSimulatorUI"; 160 | this.Text = "PokerSim"; 161 | this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.PokerUI_Closed); 162 | this.Load += new System.EventHandler(this.PokerUI_Load); 163 | this.ResumeLayout(false); 164 | this.PerformLayout(); 165 | 166 | } 167 | 168 | #endregion 169 | 170 | private System.Windows.Forms.TextBox PlayerCardsBox; 171 | private System.Windows.Forms.TextBox SharedCardsBox; 172 | private System.Windows.Forms.TextBox WinProbBox; 173 | private System.Windows.Forms.Label PlayerCardsDesc; 174 | private System.Windows.Forms.Label SharedCardsDesc; 175 | private System.Windows.Forms.Label WinProbDesc; 176 | private System.Windows.Forms.Label UITitle; 177 | private System.Windows.Forms.ProgressBar progressBar; 178 | private System.Windows.Forms.Button CalculateButton; 179 | private System.Windows.Forms.TextBox NumPlayers; 180 | private System.Windows.Forms.Label NumPlayersDesc; 181 | } 182 | } 183 | 184 | -------------------------------------------------------------------------------- /src/PokerStarsBot/PokerApp.cs: -------------------------------------------------------------------------------- 1 | #define REQUIRE_KEY 2 | #undef REQUIRE_KEY 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Windows.Forms; 8 | using System.ComponentModel; 9 | using System.Data; 10 | using System.Drawing; 11 | using System.Text; 12 | using System.Diagnostics; 13 | using Microsoft.Win32; 14 | using HoldemHand; 15 | 16 | 17 | namespace pokermaster 18 | { 19 | public class PokerApp 20 | { 21 | public enum ProbMode 22 | { 23 | MonteCarlo, 24 | Enumerate 25 | }; 26 | 27 | 28 | // global game constants 29 | 30 | public const int TOTAL_HANDS= 2598960; // 2,6 million games 31 | 32 | public const int TOTAL_SYMS = 100000000; 33 | 34 | public const int DECK_CARDS = 52; 35 | 36 | public const int TAKEN_CARDS= 7; 37 | 38 | public const int SUIT_CARDS = 14; 39 | 40 | public const int TOTAL_SUITS= 4; 41 | 42 | int CFourKind = 0; 43 | int CFullHaus = 0; 44 | int CStrFlush = 0; 45 | int CFlushie = 0; 46 | int CStraight = 0; 47 | int COneTrio = 0; 48 | int CTwoPairs = 0; 49 | int COnePair = 0; 50 | int CHighCard = 0; 51 | 52 | 53 | [STAThread] 54 | static void Main() 55 | { 56 | Application.EnableVisualStyles(); 57 | Application.SetCompatibleTextRenderingDefault(false); 58 | 59 | PokerApp poker = new PokerApp(); 60 | 61 | #if REQUIRE_KEY 62 | Keys.RequireKey(); 63 | #endif 64 | 65 | 66 | int[] cards = IO.parseCards("7s 6d"); 67 | // if (!Hand.ValidateHand(str)) 68 | // IO.Message("invalid formart"); 69 | 70 | Process pp = Process.GetCurrentProcess(); 71 | Stopwatch sw = new Stopwatch(); 72 | sw.Start(); 73 | TimeSpan tb = pp.TotalProcessorTime; 74 | // poker.testHands(); 75 | // poker.testHand(IO.parseCards("As 2s 3s 4s 5s")); 76 | // Application.Run(new PokerUI(poker)); 77 | 78 | // double prob = poker.MyComputeProb(cards, new int[TAKEN_CARDS], 0, 1, ProbMode.Enumerate); 79 | double prob = poker.HandEvalComputeProb("7s 6d", "", 0, 1); 80 | 81 | TimeSpan te = pp.TotalProcessorTime; 82 | sw.Stop(); 83 | 84 | IO.Message("Computed " + TOTAL_SYMS + " hands in " + (te-tb).TotalMilliseconds + " millis: " 85 | + (double) TOTAL_SYMS / (te - tb).TotalSeconds + " games/sec"); 86 | 87 | IO.Message("Win Prob: " + prob * 100 + "%"); 88 | // IO.Message("Computed " + TOTAL_SYMS + " hands in " + sw.ElapsedMilliseconds + " millis"); 89 | // poker.printCounts(); 90 | 91 | } 92 | 93 | void printCounts() 94 | { 95 | IO.Message( 96 | "CStrFlush " + CStrFlush + "\r\n" + 97 | "CFourKind " + CFourKind + "\r\n" + 98 | "CFullHaus " + CFullHaus + "\r\n" + 99 | "CFlushie " + CFlushie + "\r\n" + 100 | "CStraight " + CStraight + "\r\n" + 101 | "COneTrio " + COneTrio + "\r\n" + 102 | "CTwoPairs " + CTwoPairs + "\r\n" + 103 | "COnePair " + COnePair + "\r\n" + 104 | "CHighCard " + CHighCard + "\r\n"); 105 | } 106 | 107 | void testHand(Card[] cards) 108 | { 109 | int[] ids = new int[TAKEN_CARDS]; 110 | int i = 0; 111 | foreach (Card c in cards) 112 | ids[i++] = c.cardToId(); 113 | testHand(ids); 114 | } 115 | 116 | void testHand(int[] cards) 117 | { 118 | int val = PokerHand.HandValue(cards); 119 | 120 | if (val <= (int)PokerHand.Hand.HighCard) CHighCard++; 121 | else if (val <= (int)PokerHand.Hand.OnePair ) COnePair++; 122 | else if (val <= (int)PokerHand.Hand.TwoPairs) CTwoPairs++; 123 | else if (val <= (int)PokerHand.Hand.OneTrio ) COneTrio++; 124 | else if (val <= (int)PokerHand.Hand.Straight) CStraight++; 125 | else if (val <= (int)PokerHand.Hand.Flushie ) CFlushie++; 126 | else if (val <= (int)PokerHand.Hand.FullHaus) CFullHaus++; 127 | else if (val <= (int)PokerHand.Hand.FourKind) CFourKind++; 128 | else if (val <= (int)PokerHand.Hand.StrFlush) CStrFlush++; 129 | // IO.WriteLine(IO.stringIds(ids, 1)); 130 | } 131 | 132 | void testHands() 133 | { 134 | const int HAND_CARDS = PokerHand.HAND_CARDS; 135 | 136 | int[] deck = new int[HAND_CARDS]; 137 | int[] ids = new int[HAND_CARDS + 1]; 138 | int i, j; 139 | 140 | for (i = 1; i <= HAND_CARDS; i++) ids[i] = i; 141 | 142 | IO.Write("Generating all possible hands:\n"); 143 | 144 | for (int cc = 0; cc < TOTAL_SYMS; cc++) 145 | { 146 | // calculate hand value 147 | Array.Copy(ids, 1, deck, 0, deck.Length); 148 | testHand(deck); 149 | 150 | // if (cc > TOTAL_SYMS - 10000) 151 | // IO.WriteLine(IO.stringIds(deck)); 152 | 153 | // generate new combination 154 | for (i = HAND_CARDS; ids[i] == DECK_CARDS - HAND_CARDS + i; i--) ; 155 | if (i == 0) break; 156 | 157 | ids[i]++; 158 | for (j = i + 1; j <= HAND_CARDS; j++) 159 | ids[j] = ids[i] + j - i; 160 | } 161 | } 162 | 163 | 164 | // using the HandEvaluator lib, ported from PokerEval by Keith Rule 165 | 166 | public double HandEvalComputeProb(int[] myCards, int[] sharedCards, int NsharedCards, int nplayers) 167 | { 168 | return 0; 169 | } 170 | 171 | // number of opponents 172 | public double HandEvalComputeProb(string myCards, string sharedCards, int NsharedCards, int nplayers) 173 | { 174 | uint wins = 0, losses = 0, draws = 0; 175 | 176 | ulong pocketmask = Hand.ParseHand(myCards); 177 | ulong board = Hand.ParseHand(sharedCards); 178 | 179 | int cc = 0; 180 | 181 | // Iterate through all possible opponent hands 182 | foreach (ulong oppmask in Hand.Hands(0UL, board | pocketmask, 2)) 183 | // Iterate through all possible board cards 184 | foreach (ulong boardmask in Hand.Hands(board, pocketmask | oppmask, 5-NsharedCards)) 185 | { 186 | if (++cc == TOTAL_SYMS) 187 | return (double)(wins + draws / 2) / (double)(draws + losses + wins); 188 | 189 | // Evaluate the player and opponent hands and tally the results 190 | uint pocketHandVal = Hand.Evaluate(pocketmask | boardmask, TAKEN_CARDS); 191 | uint oppHandVal = Hand.Evaluate(oppmask | boardmask, TAKEN_CARDS); 192 | 193 | if (pocketHandVal > oppHandVal) 194 | wins++; 195 | else if (pocketHandVal == oppHandVal) 196 | draws++; 197 | else 198 | losses++; 199 | } 200 | 201 | return (double)(wins + draws / 2) / (double)(draws + losses + wins); 202 | } 203 | 204 | 205 | 206 | // returns number of selected cards. the bdeck array carries the result 207 | int selectDeck(int[] bdeck, int[] remove) 208 | { 209 | int count = 0; 210 | bdeck[0] = 0; 211 | 212 | for (int n = 1; n <= DECK_CARDS; n++) 213 | if (Array.IndexOf(remove, n) < 0) 214 | bdeck[count++] = n; 215 | 216 | for (int n = count+1; n <= DECK_CARDS; n++) 217 | bdeck[n] = 0; 218 | 219 | return count; 220 | } 221 | 222 | 223 | // number of opponents 224 | public double MyComputeProb(int[] myCards, int[] sharedCards, int NsharedCards, int nplayers, ProbMode mode) 225 | { 226 | if (myCards.Length < 2) 227 | throw new Exception("Necessario pelo menos duas cartas"); 228 | 229 | Array.Copy(sharedCards, 0, myCards, 2, NsharedCards); 230 | 231 | int NmyCards= 2+NsharedCards; 232 | int p, wins = 0, losses = 0, draws = 0; 233 | int myMiss = TAKEN_CARDS - NmyCards; 234 | int othersMiss = TAKEN_CARDS - NsharedCards; 235 | 236 | int[] bufCards = new int[TAKEN_CARDS ]; 237 | int[] baseDeck = new int[DECK_CARDS+1]; 238 | int[] gameDeck = new int[DECK_CARDS+1]; 239 | 240 | int permLen = selectDeck(baseDeck, myCards); 241 | 242 | // IO.Write("AVAILABLE CARDS " + permLen + ":\n" + IO.stringIds(baseDeck, 1, permLen+1) + "\n"); 243 | // IO.Write(IO.stringCards(myCards) + ": INITIAL\t\t\tX\t" + IO.stringCards(sharedCards) + ": INITIAL\n"); 244 | 245 | if (mode == ProbMode.Enumerate) 246 | Combinatorics.initCombination(); 247 | 248 | for (int i = 0; i < TOTAL_SYMS; i++) 249 | { 250 | bool draw = false; 251 | 252 | if (mode == ProbMode.Enumerate) 253 | Combinatorics.nextCombination(gameDeck); 254 | else 255 | Combinatorics.selectPermRandom(gameDeck, baseDeck, othersMiss, permLen); 256 | 257 | const bool PHANDS = false; 258 | // IO.Write(IO.stringIds(gameDeck, 0, permLen) + "\n"); 259 | 260 | // take the needed cards from the deck and distribute it along the players 261 | Array.Copy(myCards , 0, bufCards, 0, NmyCards); 262 | Array.Copy(gameDeck, 0, bufCards, NmyCards, myMiss); 263 | 264 | // check Hand. destructive 265 | int myHandVal = PokerHand.HandValue(bufCards); 266 | if (PHANDS) IO.Write(IO.stringCards(bufCards) + ": " + myHandVal + " " + PokerHand.getHand(myHandVal) + "\tX\t"); 267 | 268 | for (p = 0; p < nplayers; p++) 269 | { 270 | Array.Copy(sharedCards, 0, bufCards, 0, NsharedCards); 271 | Array.Copy(gameDeck, 0, bufCards, NsharedCards, othersMiss); 272 | 273 | // check hand 274 | int otherHandVal = PokerHand.HandValue(bufCards); 275 | 276 | if (PHANDS) IO.Write(IO.stringCards(bufCards) + ": " + otherHandVal + " " + PokerHand.getHand(otherHandVal) + "\t"); 277 | 278 | if (myHandVal == otherHandVal) 279 | draw = true; 280 | 281 | if (myHandVal < otherHandVal) 282 | break; 283 | } 284 | 285 | if (p < nplayers) 286 | losses++; 287 | else 288 | if (!draw) 289 | wins++; 290 | else 291 | draws++; 292 | 293 | if (PHANDS) 294 | { 295 | if (p < nplayers) 296 | IO.Write(" => LOSE\n\n"); 297 | else if (!draw) 298 | IO.Write(" => WIN\n\n"); 299 | else 300 | IO.Write(" => DRAW\n\n"); 301 | } 302 | } 303 | 304 | return (double) wins / (double) (losses + wins); 305 | } 306 | 307 | 308 | } 309 | } 310 | 311 | 312 | -------------------------------------------------------------------------------- /docs/zealots.php.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | PokerStove: Poker Software and Analysis 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 28 | 29 | 30 | 213 | 214 | 215 | 216 | 217 | 218 |
20 | 21 | 22 | 23 | 25 | 26 |
24 |
Poker Stove
Agnostics vs. Zealots
A perspective on poker software optimization.
27 |
31 | 32 | 33 | 70 | 71 | 203 | 204 | 209 | 210 | 211 |
72 | 73 |

Yet Another Free Showdown Simulator: Agnostic vs. Zealous

74 | 75 |

I decided to put up some of my hold'em evaluation software. You 76 | can download it from here: 77 | 78 |

www.pokerstove.com 79 | 80 |

There are quite a few programs/packages out there that will do 81 | poker evaluations for you. Some programs are faster than 82 | others, but one thing that they all seem to have in common is 83 | their approach to solving the evaluation/enumeration problem. 84 | 85 |

Agnostic versus Zealous

86 | 87 |

In computer science there is classic tradeoff between size and 88 | time. If you want to solve a problem faster, you can often 89 | achieve this by using more space. If you have limited space you 90 | can solve many of the same problems, but it might take a bit more 91 | time. One concrete example of this is tree traversals. Most 92 | algorithms require O(log(n)) space, where n is the number of 93 | nodes in the tree. But the traversal can be accomplished using a 94 | constant O(1) amount of space if you are willing to visit each 95 | node three times. 96 | 97 |

When it comes to solving complex problems, programmers are often 98 | faced with the decision of whether to create solutions which 99 | address the specific problem at hand (zealous), or create a 100 | solution which is more general and can be applied to multiple 101 | problem domains (agnostic). The zealous approach provides a complex 102 | library which takes into account many of the possible different 103 | situations that the problem might present. The agnostic approach 104 | is to provide a small efficient toolkit from which more and more 105 | complex tools can be built. Conceptually the complex library 106 | uses fewer levels of abstraction than the small toolkit. 107 | 108 |

This relates to the size/speed tradeoff as follows. The same 109 | problems can be solved, but the zealous approach usually requires 110 | more code, more code maintenance, and tends to be more brittle 111 | (susceptible to bugs). The *size* of the zealous solution is 112 | much larger in several dimensions. On the other hand, the 113 | zealous solution can often be faster, since optimizations can be 114 | applied across the conceptual levels that the agnostic solution 115 | separates. [In fact, this is one of the reasons why JIT compiled 116 | Java code can't compete with optimized C code, global 117 | optimizations can't easily be applied to compiled .class files.] 118 | 119 |

What does this have to do with poker software?

120 | 121 |

All of the public poker code I've read, and most of the poker 122 | software I've read about produces agnostic solutions to the 123 | problem of evaluating hands. While this is good for providing a 124 | general low level library, most hand evaluations occur in very 125 | specific contextual circumstances. In particular, many of these 126 | solutions treat evaluation and enumeration as two separate 127 | problems. 128 | 129 |

As I was proctoring my exams (no pun intended -- but feel free), 130 | I decided to take a break from modern RGP and go back and read 131 | about the "good ol' days". 132 | 133 |

An old 134 | thread that I was reading discussed the case of calculating 135 | the equity of AA versus 9 random opponents. The upshot was that 136 | it would require considering over 10^28 combinations. Using an 137 | agnostic hand evaluator would require billions upon billions of 138 | hand evaluations. But a zealous hand evaluator would know that 139 | there are only 133,784,560 different 7-card hands, and only 140 | bother to do that many evaluations. The rest of the code would 141 | be centered around traversing the enumeration space in the most 142 | efficient way possible. 143 | 144 |

To explore the possible speedup by moving from an agnostic 145 | solution to a zealous solution, I wrote a "proof of concept" hand 146 | evaluator which computes the all-in preflop equity of a set of 147 | given hands. In order to tax the evaluator, I added the ability 148 | to compute the subjective all-in equity (SAIE) for full hand 149 | distributions. For example, the evaluator can calculate the 150 | equity of 22 vs. AA when the suits are not specified. It can 151 | also calculate the equity of a hands like 87s versus an early 152 | raiser who might hold one of {99+, AQo+, AJs+}. [The code at pokersource.sourceforge.net 153 | also provides SAIE evaluation.] 154 | 155 |

The results were dramatic. By binding the solution more closely 156 | to the specific problem I was to increase the overall evaluation 157 | speed of my code by a factor of 100. On modern machines, the 158 | code can evaluate upwards of 1/2 billion games per second. 159 | 160 |

The speedup mostly comes from the fact that while there are 161 | millions (or billions) of combinatorial cases to consider, many 162 | of them are equivalent. For example, if we are calculating the 163 | equity of KsKh vs. 8s3s all boards with the other two kings are 164 | going to result in a win for KK. This equivalence class contains 165 | 46 choose 3 = 15,180 combinations, but we can evaluate it once 166 | and apply that evaluation to across all combinations. 167 | 168 |

So what's the point?

169 | 170 | 171 |

The point is that the general state of poker evaluators has been 172 | relatively stagnant for the last half decade. It is time to 173 | actually sit down and do the hard work of producing quality 174 | evaluators which take a more zealous approach. Hand evaluators 175 | may be a rather dry aspect of poker, but it's either come up with 176 | more clever ways of doing complex enumeration/evaluation tasks, 177 | or wait 90 years for computers to "catch up" 178 | 179 | 180 | 181 |

In the real world, most of this work has little meaning. Monte 182 | Carlo simulations work very well for most practical problems, and 183 | enumeration driven software is only going to be of interest to 184 | the true poker geeks who must have all of their i's dotted and 185 | t's crossed. Of course, I'm one of those geeks :) 186 | 187 |

- Andrew 188 | 189 | 190 | 191 | 192 | 193 |

P.S. Maybe I can get Charles Haynes to pay me $50 at BARGE. :) 194 | 195 | 196 | 197 |

P.P.S. I'd like to give credit where credit is due. The 198 | underlying ideas behind this kind of evaluator didn't originate 199 | with me. I was inspired by ancient posts made by Steven R. Jacobs 200 | regarding video poker evaluation/enumeration algorithms. 201 | 202 |

205 | 206 | 207 |
208 |
212 |
219 |
220 | 221 |
222 | Warning: mysql_query(): supplied argument is not a valid MySQL-Link resource in /home/content/a/p/r/aprock/html/ps-php-lib/psdb.php on line 109
223 | 224 | -------------------------------------------------------------------------------- /src/PokerStarsBot/Pokerhand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | 6 | 7 | namespace pokermaster 8 | { 9 | // 10 | // ============================================================== 11 | // || Poker Hands 12 | // ============================================================== 13 | // 14 | // NEVER use suits to evaluate hands (break ties in hand value) 15 | // 16 | // Two straights are ranked by comparing the highest card of each. 17 | // Two straights with the same high card are of equal value, suits 18 | // are not used to separate them. 19 | // 20 | // Two flushes are compared as if they were high card hands; 21 | // the highest ranking card of each is compared to determine the winner 22 | // If both hands have the same highest card, then the 2nd-highest ranking 23 | // card is compared, and so on until a difference is found 24 | // 25 | // Suits are irrelevant for Straight Flush 26 | // Aces can play low in straights and straight flushes: 5? 4? 3? 2? A? 27 | // is a 5-high straight flush, also known as a "steel wheel". 28 | // An ace-high straight flush such as A? K? Q? J? 10? is known as a royal flush, 29 | // and is the highest ranking standard poker hand. 30 | // 31 | // For Pairs, 2-Pairs and Trios, the highest single cards (kickers) 32 | // are used as a tiebreak, sucessively one by one 33 | // 34 | 35 | static public class PokerHand 36 | { 37 | private const int N = PokerApp.SUIT_CARDS+1; // 0 == no card 38 | private const int N1 = N; 39 | private const int N2 = N * N; 40 | private const int N3 = N * N * N; 41 | private const int N4 = N * N * N * N; 42 | private const int N5 = N * N * N * N * N; 43 | 44 | public const int HAND_CARDS = PokerApp.TAKEN_CARDS; 45 | 46 | 47 | // -------------------------------------------------------------- 48 | // Hand Description Value 49 | // -------------------------------------------------------------- 50 | // Highest Card type1*N^4 + type2*N^3 + type3*N^2 + type4*N + type5 51 | // Pair N^5 + Type*N^3 + kicker1*N^2 + kicker2*N + kicker3 52 | // Two Pairs N^5 + N^4 + Type1*N*N + Type2*N + kicker 53 | // Trio N^5 + N^4 + N^3 + Type*N^2 + kicker1*N + kicker2 54 | // 55 | // Straight 5 sucessive diff suits N^5 + N^4 + 2*N^3 + highest Type 56 | // Flush 5 increasing same suit N^5 + N^4 + 3*N^3 + type1*N^4 + type2*N^3 57 | // + type3*N^2 + type4*N + type5 58 | // 59 | // Full House trio + pair 2*N^5 + N^4 + 3*N^3 + N * Trio CardType + Pair CardType 60 | // Four-of-Kind 2*N^5 + N^4 + 4*N^3 + type 61 | // StraightFlush 5 sucessive same suit 2*N^5 + N^4 + 5*N^3 + highest cardtype 62 | 63 | // CardType = card w/o suit (max = SUIT_CARDS) 64 | 65 | public enum Hand: int 66 | { 67 | // max values for each hand 68 | HighCard = N5, 69 | OnePair = N5 + N4, 70 | TwoPairs = N5 + N4 + 1*N3, 71 | OneTrio = N5 + N4 + 2*N3, 72 | Straight = N5 + N4 + 3*N3, 73 | Flushie = 2*N5 + N4 + 3*N3, 74 | FullHaus = 2*N5 + N4 + 4*N3, 75 | FourKind = 2*N5 + N4 + 5*N3, 76 | StrFlush = 2*N5 + N4 + 6*N3, 77 | ERROR 78 | } 79 | 80 | static int[] deck; 81 | 82 | private static ReserveComp qcmp = new ReserveComp(); 83 | 84 | static public Hand getHand(int val) 85 | { 86 | if (val <= 0) 87 | IO.WriteLine("Invalid Hand from outer Space!! " + val); 88 | 89 | if (val <= (int) Hand.HighCard) return Hand.HighCard; 90 | if (val <= (int) Hand.OnePair) return Hand.OnePair; 91 | if (val <= (int) Hand.TwoPairs) return Hand.TwoPairs; 92 | if (val <= (int) Hand.OneTrio) return Hand.OneTrio; 93 | if (val <= (int) Hand.Straight) return Hand.Straight; 94 | if (val <= (int) Hand.Flushie) return Hand.Flushie; 95 | if (val <= (int) Hand.FullHaus) return Hand.FullHaus; 96 | if (val <= (int) Hand.FourKind) return Hand.FourKind; 97 | if (val <= (int) Hand.StrFlush) return Hand.StrFlush; 98 | 99 | IO.WriteLine("Unknown Hand from outer Space!! " + val); 100 | return Hand.ERROR; 101 | } 102 | 103 | 104 | static public int HandValue(int[] odeck) 105 | { 106 | PrepareCards(odeck); 107 | return getHandValue(); 108 | } 109 | 110 | static public void PrepareCards(int[] odeck) 111 | { 112 | deck = odeck; 113 | Utils.BinaryInsertionSort(deck); // faster by large 114 | // Utils.SelectionSort(deck); 115 | // Array.Sort(deck, qcmp); // a LOT slower 116 | } 117 | 118 | static public int getHandValue() 119 | { 120 | int value, valueK; 121 | 122 | if ((value = checkStrFlush()) > 0) 123 | return value; 124 | 125 | // 4kind or fullhouse 126 | if ((valueK = checkKinds()) > (int) Hand.Flushie) 127 | return valueK; 128 | 129 | if ((value = checkFlush()) > 0) 130 | return value; 131 | 132 | if ((value = checkStraight()) > 0) 133 | return value; 134 | 135 | return valueK; 136 | } 137 | 138 | 139 | /* delegate bool CheckKickerDel(int val, int f1, int f2); 140 | CheckKickerDel checkKicker; 141 | bool CheckKicker0(int val, int f1, int f2) { return true; } 142 | bool CheckKicker1(int val, int f1, int f2) { return (val != f1); } 143 | bool CheckKicker2(int val, int f1, int f2) { return (val != f1 && val != f2); } 144 | 145 | // factors only the 5 highest letters 146 | int getKickersValue(int num, int found1, int found2) 147 | { 148 | int val = 0; 149 | 150 | for (int i = 0; num != 0 && i < HAND_CARDS; i++) 151 | if (checkKicker(Card.idType(deck[i]), found1, found2)) 152 | val += Card.idType(deck[i]) * Utils.pow(N, --num); 153 | 154 | return val; 155 | } 156 | */ 157 | // extended 158 | static int getKickersValue0(int num) 159 | { 160 | int val = 0; 161 | for (int i = 0; num != 0 && i < HAND_CARDS; i++) 162 | val += Card.idType(deck[i]) * Utils.pow(N, --num); 163 | return val; 164 | } 165 | 166 | static int getKickersValue1(int num, int found1) 167 | { 168 | int val = 0; 169 | for (int i = 0; num != 0 && i < HAND_CARDS; i++) 170 | if (Card.idType(deck[i]) != found1) 171 | val += Card.idType(deck[i]) * Utils.pow(N, --num); 172 | return val; 173 | } 174 | 175 | static int getKickersValue2(int num, int found1, int found2) 176 | { 177 | int val = 0; 178 | for (int i = 0; num != 0 && i < HAND_CARDS; i++) 179 | { 180 | int tt = Card.idType(deck[i]); 181 | if (tt != found1 && tt != found2) 182 | val += Card.idType(deck[i]) * Utils.pow(N, --num); 183 | } 184 | return val; 185 | } 186 | 187 | 188 | 189 | // Highest Card type1*N^4 + type2*N^3 + type3*N^2 + type4*N + type5 190 | // Pair N^5 + Type*N^3 + kicker1*N^2 + kicker2*N + kicker3 191 | // Two Pairs N^5 + N^4 + Type1*N*N + Type2*N + kicker 192 | // Trio N^5 + N^4 + N^3 + Type*N^2 + kicker1*N + kicker2 193 | // Full House trio + pair 2*N^5 + N^4 + 3*N^3 + N * Trio CardType + Pair CardType 194 | // Four-of-Kind 2*N^5 + N^4 + 4*N^3 + type 195 | 196 | static int checkKinds() 197 | { 198 | int i, idf, idt=-1, idp1=-1, idp2=-1; // four, trio, pair1, pair2 199 | 200 | for (int j = 0; j <= HAND_CARDS-2; j += i) 201 | { 202 | idf = Card.idType(deck[j]); 203 | for (i = 1; i + j < HAND_CARDS; i++) 204 | if (idf != Card.idType(deck[i+j])) 205 | break; 206 | 207 | if (i == 4) // four of a kind 208 | return 2*N5 + N4 + 4*N3 + idf; 209 | 210 | if (i == 3 && idt < 0)// trio 211 | idt = idf; 212 | 213 | else if (i > 1) // single pair or pair from trio 214 | { 215 | if (idp1 < 0) 216 | idp1 = idf; 217 | else if (idp2 < 0) 218 | idp2 = idf; 219 | } 220 | } 221 | 222 | if (idt >= 0) 223 | { 224 | if (idp1 >= 0) // fullhouse 225 | return 2 * N5 + N4 + 3 * N3 + N * idt + idp1; 226 | 227 | else // trio 228 | return N5 + N4 + N3 + N2*idt + getKickersValue1(2, idt); 229 | } 230 | 231 | if (idp1 >= 0) 232 | { 233 | if (idp2 < 0) // pair 234 | return N5 + N3 * idp1 + getKickersValue1(3, idp1); 235 | else // two pairs 236 | return N5 + N4 + N2 * idp1 + N * idp2 + getKickersValue2(1, idp1, idp2); 237 | } 238 | 239 | return getKickersValue0(5); // highest card 240 | } 241 | 242 | 243 | // StraightFlush 5 sucessive same suit 2*N^5 + N^4 + 5*N^3 + highest cardtype 244 | static int checkStrFlush() 245 | { 246 | int i, id = 0, mcount = 0, suit = 0, HandCards = 5; 247 | int ttj = HAND_CARDS - HandCards + 1; 248 | 249 | for (int j = 0; j <= ttj; j++) 250 | { 251 | id = Card.idType(deck[j]); 252 | suit = Card.idSuit(deck[j]); 253 | mcount = HandCards-1; 254 | 255 | for (i = j + 1; mcount != 0 && i < HAND_CARDS && mcount <= HAND_CARDS - i +1; i++) 256 | if (id == Card.idType(deck[i]) +1 && suit== Card.idSuit(deck[i])) 257 | { mcount--; 258 | id = Card.idType(deck[i]); 259 | } 260 | 261 | if (mcount == 0) 262 | return 2 * N5 + N4 + 5 * N3 + Card.idType(deck[j]); 263 | } 264 | 265 | // check for low-Ace straight flush 266 | if (mcount == 1 && id == (int) CardType.Two 267 | && Card.idType(deck[0]) == (int)CardType.A 268 | && Card.idSuit(deck[0]) == suit) 269 | return 2 * N5 + N4 + 5 * N3 + Card.idType(deck[HAND_CARDS-HandCards]); 270 | 271 | return -1; 272 | } 273 | 274 | 275 | 276 | 277 | // Straight 5 sucessive diff suits N^5 + N^4 + 2*N^3 + highest Type 278 | // the Aces may be higher or lower 279 | static int checkStraight() 280 | { 281 | int id = 0, j, mcount = 0, HandCards = 5; 282 | 283 | for (j = 0; j <= HAND_CARDS-HandCards+1; j++) 284 | { 285 | id = Card.idType(deck[j]); 286 | mcount = HandCards - 1; 287 | 288 | for (int i = j + 1; mcount != 0 && i < HAND_CARDS && mcount <= HAND_CARDS - i + 1; i++) 289 | if (id == Card.idType(deck[i]) +1) 290 | { mcount--; 291 | id = Card.idType(deck[i]); 292 | } 293 | 294 | if (mcount == 0) 295 | return N5 + N4 + 2 * N3 + Card.idType(deck[j]); 296 | } 297 | 298 | 299 | // check for low-Ace straight 300 | if (mcount == 1 && id == (int) CardType.Two 301 | && Card.idType(deck[0]) == (int) CardType.A) 302 | return N5 + N4 + 2 * N3 + (int) Card.idType(deck[j-1]); 303 | 304 | return -1; 305 | } 306 | 307 | 308 | // Flush 5 increasing same suit N^5 + N^4 + 3*N^3 + type1*N^4 + type2*N^3 309 | static int checkFlush() 310 | { 311 | int i; 312 | int HandCards = 5; 313 | int[] sol = new int[HandCards]; 314 | 315 | for (int j = 0; j <= HAND_CARDS-HandCards; j++) 316 | { 317 | int count = 1; 318 | int id = sol[HandCards-count] = deck[j]; 319 | 320 | for (i = j+1; count < HandCards && i < HAND_CARDS; i++) 321 | if (Card.idType(id) > Card.idType(deck[i]) 322 | && Card.idSuit(id) == Card.idSuit(deck[i])) 323 | id = sol[HandCards - ++count] = deck[i]; 324 | 325 | if (count == HandCards) 326 | { 327 | int val = N5 + N4 + 3 * N3, exp = 4; 328 | 329 | for (int t = 0; t < HandCards && exp >= 0; t++) 330 | val += Card.idType(sol[t]) * Utils.pow(N, exp--); 331 | 332 | return val; 333 | } 334 | } 335 | 336 | return -1; 337 | } 338 | 339 | } 340 | } 341 | 342 | -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/Runtime/serialise.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.IO; 3 | using System.Text; 4 | using System.Globalization; 5 | using System; 6 | 7 | namespace Tools 8 | { 9 | /// 10 | public class Serialiser 11 | { 12 | const string Version="4.5"; 13 | /// 14 | public void VersionCheck() 15 | { 16 | if (Encode) 17 | Serialise(Version); 18 | else 19 | { 20 | string version=Deserialise() as string; 21 | if (version==null) 22 | throw new Exception("Serialisation error - found data from version 4.4 or earlier"); 23 | else if (version!=Version) 24 | throw new Exception("Serialisation error - expected version "+Version+", found data from version "+version); 25 | } 26 | } 27 | enum SerType 28 | { 29 | Null, Int, Bool, Char, String, Hashtable, Encoding, 30 | UnicodeCategory, Symtype, 31 | Charset, TokClassDef, Action, Dfa, 32 | ResWds, // 4.7 33 | ParserOldAction, ParserSimpleAction, ParserShift, ParserReduce, ParseState, 34 | ParsingInfo, CSymbol, Literal, Production, EOF }; 35 | delegate object ObjectSerialiser(object o,Serialiser s); 36 | static Serialiser() 37 | { 38 | srs[SerType.Null] = new ObjectSerialiser(NullSerialise); 39 | tps[typeof(int)] = SerType.Int; srs[SerType.Int] = new ObjectSerialiser(IntSerialise); 40 | tps[typeof(string)] = SerType.String; srs[SerType.String] = new ObjectSerialiser(StringSerialise); 41 | tps[typeof(Hashtable)] = SerType.Hashtable; srs[SerType.Hashtable] = new ObjectSerialiser(HashtableSerialise); 42 | tps[typeof(char)] = SerType.Char; srs[SerType.Char] = new ObjectSerialiser(CharSerialise); 43 | tps[typeof(bool)] = SerType.Bool; srs[SerType.Bool] = new ObjectSerialiser(BoolSerialise); 44 | tps[typeof(Encoding)] = SerType.Encoding; srs[SerType.Encoding] = new ObjectSerialiser(EncodingSerialise); 45 | tps[typeof(UnicodeCategory)] = SerType.UnicodeCategory; srs[SerType.UnicodeCategory] = new ObjectSerialiser(UnicodeCategorySerialise); 46 | tps[typeof(CSymbol.SymType)] = SerType.Symtype; srs[SerType.Symtype] = new ObjectSerialiser(SymtypeSerialise); 47 | tps[typeof(Charset)] = SerType.Charset; srs[SerType.Charset] = new ObjectSerialiser(Charset.Serialise); 48 | tps[typeof(TokClassDef)] = SerType.TokClassDef; srs[SerType.TokClassDef] = new ObjectSerialiser(TokClassDef.Serialise); 49 | tps[typeof(Dfa)] = SerType.Dfa; srs[SerType.Dfa] = new ObjectSerialiser(Dfa.Serialise); 50 | tps[typeof(ResWds)] = SerType.ResWds; srs[SerType.ResWds] = new ObjectSerialiser(ResWds.Serialise); // 4.7 51 | tps[typeof(Dfa.Action)] = SerType.Action; srs[SerType.Action] = new ObjectSerialiser(Dfa.Action.Serialise); 52 | tps[typeof(ParserOldAction)] = SerType.ParserOldAction; srs[SerType.ParserOldAction] = new ObjectSerialiser(ParserOldAction.Serialise); 53 | tps[typeof(ParserSimpleAction)] = SerType.ParserSimpleAction; srs[SerType.ParserSimpleAction] = new ObjectSerialiser(ParserSimpleAction.Serialise); 54 | tps[typeof(ParserShift)] = SerType.ParserShift; srs[SerType.ParserShift] = new ObjectSerialiser(ParserShift.Serialise); 55 | tps[typeof(ParserReduce)] = SerType.ParserReduce; srs[SerType.ParserReduce] = new ObjectSerialiser(ParserReduce.Serialise); 56 | tps[typeof(ParseState)] = SerType.ParseState; srs[SerType.ParseState] = new ObjectSerialiser(ParseState.Serialise); 57 | tps[typeof(ParsingInfo)] = SerType.ParsingInfo; srs[SerType.ParsingInfo] = new ObjectSerialiser(ParsingInfo.Serialise); 58 | tps[typeof(CSymbol)] = SerType.CSymbol; srs[SerType.CSymbol] = new ObjectSerialiser(CSymbol.Serialise); 59 | tps[typeof(Literal)] = SerType.Literal; srs[SerType.Literal] = new ObjectSerialiser(Literal.Serialise); 60 | tps[typeof(Production)] = SerType.Production; srs[SerType.Production] = new ObjectSerialiser(Production.Serialise); 61 | tps[typeof(EOF)] = SerType.EOF; srs[SerType.EOF] = new ObjectSerialiser(EOF.Serialise); 62 | } 63 | // on Encode, we ignore the return value which is always null 64 | // Otherwise, o if non-null is an instance of the subclass 65 | TextWriter f = null; 66 | int[] b = null; 67 | int pos = 0; 68 | Hashtable obs = new Hashtable(); // object->int (code) or int->object (decode) 69 | static Hashtable tps = new Hashtable(); // type->SerType 70 | static Hashtable srs = new Hashtable(); // SerType->ObjectSerialiser 71 | int id = 100; 72 | int cl = 0; 73 | /// 74 | public Serialiser(TextWriter ff) 75 | { 76 | f = ff; 77 | } 78 | /// 79 | public Serialiser(int[] bb) 80 | { 81 | b = bb; 82 | } 83 | /// 84 | public bool Encode { get { return f!=null; }} 85 | void _Write(SerType t) 86 | { 87 | _Write((int)t); 88 | } 89 | /// 90 | public void _Write(int i) 91 | { 92 | if (cl==5) 93 | { 94 | f.WriteLine(); 95 | cl = 0; 96 | } 97 | cl++; 98 | f.Write(i); 99 | f.Write(","); 100 | } 101 | /// 102 | public int _Read() 103 | { 104 | return b[pos++]; 105 | } 106 | static object NullSerialise(object o,Serialiser s) 107 | { 108 | return null; 109 | } 110 | static object IntSerialise(object o,Serialiser s) 111 | { 112 | if (s.Encode) 113 | { 114 | s._Write((int)o); 115 | return null; 116 | } 117 | return s._Read(); 118 | } 119 | static object StringSerialise(object o,Serialiser s) 120 | { 121 | if (s==null) 122 | return ""; 123 | Encoding e = new UnicodeEncoding(); 124 | if (s.Encode) 125 | { 126 | byte[] b = e.GetBytes((string)o); 127 | s._Write(b.Length); 128 | for (int j=0;j 225 | public void Serialise(object o) 226 | { 227 | if (o==null) 228 | { 229 | _Write(SerType.Null); 230 | return; 231 | } 232 | if (o is Encoding) 233 | { 234 | _Write(SerType.Encoding); 235 | EncodingSerialise(o,this); 236 | return; 237 | } 238 | Type t = o.GetType(); 239 | if (t.IsClass) 240 | { 241 | object p = obs[o]; 242 | if (p!=null) 243 | { 244 | _Write((int)p); 245 | return; 246 | } 247 | else 248 | { 249 | int e = ++id; 250 | _Write(e); 251 | obs[o] = e; 252 | } 253 | } 254 | object so = tps[t]; 255 | if (so!=null) 256 | { 257 | SerType s = (SerType)so; 258 | _Write(s); 259 | ObjectSerialiser os = (ObjectSerialiser)srs[s]; 260 | os(o,this); 261 | } 262 | else 263 | throw new Exception("unknown type "+t.FullName); 264 | } 265 | /// 266 | public object Deserialise() 267 | { 268 | int t = _Read(); 269 | int u = 0; 270 | if (t>100) 271 | { 272 | u = t; 273 | if (u<=obs.Count+100) 274 | return obs[u]; 275 | t = _Read(); 276 | } 277 | ObjectSerialiser os = (ObjectSerialiser)srs[(SerType)t]; 278 | if (os!=null) 279 | { 280 | if (u>0) 281 | { // ?? strange bug in mono: workaround in CSTools 4.5a leads to not chaining assignments here 282 | object r = os(null,null); // allow for recursive structures: create and store first 283 | obs[u] = r; 284 | r = os(r,this); // really deserialise it 285 | obs[u] = r; // we need to store it again for strings 286 | return r; 287 | } 288 | return os(null,this); 289 | } 290 | else 291 | throw new Exception("unknown type "+t); 292 | } 293 | } 294 | /* public class Test 295 | { 296 | static string curline = ""; 297 | static int pos = 0; 298 | static bool EOF = false; 299 | static void GetLine(TextReader f) 300 | { 301 | curline = f.ReadLine(); 302 | pos = 0; 303 | if (curline == null) 304 | EOF = true; 305 | } 306 | static int GetInt(TextReader f) 307 | { 308 | int v = 0; 309 | bool s = false; 310 | while (pos='0' && c<='9') 329 | { 330 | v = v*10 + (c-'0'); 331 | continue; 332 | } 333 | throw new Exception("illegal character"); 334 | } 335 | throw new Exception("bad line"); 336 | } 337 | public static void Main(string[] args) 338 | { 339 | TextWriter x = new StreamWriter("out.txt"); 340 | Hashtable t = new Hashtable(); 341 | t["John"] = 12; 342 | t["Mary"] = 34; 343 | Serialiser sr = new Serialiser(x); 344 | Console.WriteLine("Encoding"); 345 | sr.Serialise(t); 346 | x.Close(); 347 | ArrayList a = new ArrayList(); 348 | TextReader y = new StreamReader("out.txt"); 349 | GetLine(y); 350 | while (!EOF) 351 | a.Add(GetInt(y)); 352 | y.Close(); 353 | for (int k=0;k" + (int)d.Value); 362 | } 363 | } */ 364 | } 365 | -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/Runtime/dfa.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Text; 6 | using System.Runtime.Serialization.Formatters.Binary; 7 | 8 | 9 | namespace Tools 10 | { 11 | /// 12 | public abstract class LNode 13 | { 14 | /// 15 | public int m_state; 16 | #if (GENTIME) 17 | /// 18 | public TokensGen m_tks; 19 | /// 20 | public LNode(TokensGen tks) 21 | { 22 | m_tks = tks; 23 | m_state = tks.NewState(); 24 | } 25 | #endif 26 | /// 27 | protected LNode() {} 28 | } 29 | 30 | /// 31 | public class TokClassDef 32 | { 33 | #if (GENTIME) 34 | /// 35 | public string m_refToken = ""; 36 | /// 37 | public string m_initialisation = ""; 38 | /// 39 | public string m_implement = ""; 40 | /// 41 | public TokClassDef(GenBase gbs,string name,string bas) 42 | { 43 | if (gbs is TokensGen) 44 | { 45 | TokensGen tks = (TokensGen) gbs; 46 | m_name = name; 47 | tks.m_tokens.tokens[name] = this; 48 | m_refToken = bas; 49 | } 50 | m_yynum = ++gbs.LastSymbol; 51 | } 52 | #endif 53 | /// 54 | TokClassDef() {} 55 | /// 56 | public string m_name = ""; 57 | /// 58 | public int m_yynum = 0; 59 | /// 60 | public static object Serialise(object o,Serialiser s) 61 | { 62 | if (s==null) 63 | return new TokClassDef(); 64 | TokClassDef t = (TokClassDef)o; 65 | if (s.Encode) 66 | { 67 | s.Serialise(t.m_name); 68 | s.Serialise(t.m_yynum); 69 | return null; 70 | } 71 | t.m_name = (string)s.Deserialise(); 72 | t.m_yynum = (int)s.Deserialise(); 73 | return t; 74 | } 75 | } 76 | 77 | /// 78 | public class Dfa : LNode 79 | { 80 | /// 81 | Dfa() {} 82 | #if (GENTIME) 83 | /// 84 | public Dfa(TokensGen tks) : base(tks) 85 | { 86 | m_tokens = tks.m_tokens; 87 | } 88 | #endif 89 | /// 90 | YyLexer m_tokens = null; 91 | /// 92 | public static void SetTokens(YyLexer tks, Hashtable h) // needed after deserialisation 93 | { 94 | foreach (Dfa v in h.Values) 95 | { 96 | if (v.m_tokens!=null) 97 | continue; 98 | v.m_tokens = tks; 99 | Dfa.SetTokens(tks,v.m_map); 100 | } 101 | } 102 | /// 103 | public Hashtable m_map = new Hashtable(); // char->Dfa: arcs leaving this node 104 | /// 105 | public class Action 106 | { 107 | /// 108 | public int a_act; 109 | /// 110 | public Action a_next; 111 | /// 112 | public Action(int act,Action next) { a_act = act; a_next = next; } 113 | Action() {} 114 | /// 115 | public static object Serialise(object o,Serialiser s) 116 | { 117 | if (s==null) 118 | return new Action(); 119 | Action a = (Action)o; 120 | if (s.Encode) 121 | { 122 | s.Serialise(a.a_act); 123 | s.Serialise(a.a_next); 124 | return null; 125 | } 126 | a.a_act = (int)s.Deserialise(); 127 | a.a_next = (Action)s.Deserialise(); 128 | return a; 129 | } 130 | } 131 | /// 132 | public string m_tokClass = ""; // token class name if m_actions!=null 133 | /// 134 | public Action m_actions = null; // for old-style REJECT 135 | /// 136 | public int m_reswds = -1; // 4.7 for ResWds handling 137 | #if (GENTIME) 138 | /// 139 | void AddAction(int act) 140 | { 141 | Action a = new Action(act,m_actions); 142 | m_actions = a; 143 | } 144 | /// 145 | void MakeLastAction(int act) 146 | { 147 | while (m_actions!=null && m_actions.a_act>=act) 148 | m_actions = m_actions.a_next; 149 | AddAction(act); 150 | } 151 | /// 152 | public Dfa(Nfa nfa):base(nfa.m_tks) 153 | { 154 | m_tokens = m_tks.m_tokens; 155 | AddNfaNode(nfa); // the starting node is Closure(start) 156 | Closure(); 157 | AddActions(); // recursively build the Dfa 158 | } 159 | /// 160 | internal bool AddNfaNode(NfaNode nfa) 161 | { 162 | if (!m_nfa.Add(nfa)) 163 | return false; 164 | if (nfa.m_sTerminal!="") 165 | { 166 | int qi,n=0; 167 | string tokClass = ""; 168 | string p=nfa.m_sTerminal; 169 | if (p[0]=='%') 170 | { // check for %Tokname special action 171 | for (n=0,qi=1;qi0 && n+10) { 181 | if (st.StartsWith("%except")) 182 | { 183 | m_reswds = nfa.m_state; 184 | m_tks.m_tokens.reswds[nfa.m_state] = ResWds.New(m_tks,st.Substring(7)); 185 | } 186 | } 187 | } 188 | // special action is always last in the list 189 | if (tokClass=="") 190 | { //nfa has an old action 191 | if (m_tokClass=="" // if both are old-style 192 | || // or we have a special action that is later 193 | (m_actions.a_act)>nfa.m_state) // m_actions has at least one entry 194 | AddAction(nfa.m_state); 195 | // else we have a higher-precedence special action so we do nothing 196 | } 197 | else if (m_actions==null || m_actions.a_act>nfa.m_state) 198 | { 199 | MakeLastAction(nfa.m_state); 200 | m_tokClass = tokClass; 201 | } // else we have a higher-precedence special action so we do nothing 202 | } 203 | return true; 204 | } 205 | 206 | /// 207 | internal NList m_nfa = new NList(); // nfa nodes in m_state order 208 | 209 | /// 210 | internal void AddActions() 211 | { 212 | // This routine is called for a new DFA node 213 | m_tks.states.Add(this); 214 | 215 | // Follow all the arcs from here 216 | foreach (Charset cs in m_tks.m_tokens.cats.Values) 217 | foreach (char j in cs.m_chars.Keys) 218 | { 219 | Dfa dfa = Target(j); 220 | if (dfa!=null) 221 | m_map[j] = dfa; 222 | } 223 | } 224 | 225 | /// 226 | internal Dfa Target(char ch) 227 | { // construct or lookup the target for a new arc 228 | Dfa n = new Dfa(m_tks); 229 | 230 | for (NList pos = m_nfa; !pos.AtEnd; pos=pos.m_next) 231 | pos.m_node.AddTarget(ch,n); 232 | // check we actually got something 233 | if (n.m_nfa.AtEnd) 234 | return null; 235 | n.Closure(); 236 | // now check we haven't got it already 237 | for (int pos1=0;pos1 246 | void Closure() 247 | { 248 | for (NList pos=m_nfa; !pos.AtEnd; pos=pos.m_next) 249 | ClosureAdd(pos.m_node); 250 | } 251 | 252 | /// 253 | void ClosureAdd(NfaNode nfa) 254 | { 255 | for (int pos=0;pos 264 | internal bool SameAs(Dfa dfa) 265 | { 266 | NList pos1 = m_nfa; 267 | NList pos2 = dfa.m_nfa; 268 | while (pos1.m_node==pos2.m_node && !pos1.AtEnd) 269 | { 270 | pos1 = pos1.m_next; 271 | pos2 = pos2.m_next; 272 | } 273 | return pos1.m_node==pos2.m_node; 274 | } 275 | 276 | /// 277 | // match a Dfa agsint a given string 278 | public int Match(string str,int ix,ref int action) 279 | { // return number of chars matched 280 | int r=0; 281 | Dfa dfa=null; 282 | // if there is no arc or the string is exhausted, this is okay at a terminal 283 | if (ix>=str.Length || 284 | (dfa=((Dfa)m_map[m_tokens.Filter(str[ix])]))==null || 285 | (r=dfa.Match(str,ix+1,ref action))<0) 286 | { 287 | if (m_actions!=null) 288 | { 289 | action = m_actions.a_act; 290 | return 0; 291 | } 292 | return -1; 293 | } 294 | return r+1; 295 | } 296 | 297 | /// 298 | public void Print() 299 | { 300 | Console.Write("{0}:",m_state); 301 | if (m_actions!=null) 302 | { 303 | Console.Write(" ("); 304 | for (Action a = m_actions; a!=null; a=a.a_next) 305 | Console.Write("{0} <",a.a_act); 306 | if (m_tokClass!="") 307 | Console.Write(m_tokClass); 308 | Console.Write(">)"); 309 | } 310 | Console.WriteLine(); 311 | Hashtable amap = new Hashtable(); // char->bool 312 | IDictionaryEnumerator idx = m_map.GetEnumerator(); 313 | for (int count=m_map.Count; count-->0;) 314 | { 315 | idx.MoveNext(); 316 | char j = (char)idx.Key; 317 | Dfa pD = (Dfa)idx.Value; 318 | if (!amap.Contains(j)) 319 | { 320 | amap[j] = true; 321 | Console.Write(" {0} ",pD.m_state); 322 | int ij = (int)j; 323 | if (ij>=32 && ij<128) 324 | Console.Write(j); 325 | else 326 | Console.Write(" #{0} ",ij); 327 | IDictionaryEnumerator idy = m_map.GetEnumerator(); 328 | for (;;) 329 | { 330 | idy.MoveNext(); 331 | Dfa pD1 = (Dfa)idy.Value; 332 | if (pD1==pD) 333 | break; 334 | } 335 | for (int count1=count;count1>0;count1--) 336 | { 337 | idy.MoveNext(); 338 | j = (char)idy.Key; 339 | Dfa pD1 = (Dfa)idy.Value; 340 | if (pD==pD1) 341 | { 342 | amap[j]=true; 343 | ij = (int)j; 344 | if (ij>=32 && ij<128) 345 | Console.Write(j); 346 | else 347 | Console.Write(" #{0} ",ij); 348 | } 349 | } 350 | Console.WriteLine(); 351 | } 352 | } 353 | } 354 | #endif 355 | /// 356 | public static object Serialise(object o,Serialiser s) 357 | { 358 | if (s==null) 359 | return new Dfa(); 360 | Dfa d = (Dfa)o; 361 | if (s.Encode) 362 | { 363 | s.Serialise(d.m_state); 364 | s.Serialise(d.m_map); 365 | s.Serialise(d.m_actions); 366 | s.Serialise(d.m_tokClass); 367 | s.Serialise(d.m_reswds); 368 | return null; 369 | } 370 | d.m_state = (int)s.Deserialise(); 371 | d.m_map = (Hashtable)s.Deserialise(); 372 | d.m_actions = (Action)s.Deserialise(); 373 | d.m_tokClass = (string)s.Deserialise(); 374 | d.m_reswds = (int)s.Deserialise(); 375 | return d; 376 | } 377 | } 378 | #if (GENTIME) 379 | /// 380 | public class Regex 381 | { 382 | /* 383 | Construct a Regex from a given string 384 | 385 | 1. First examine the given string. 386 | If it is empty, there is nothing to do, so return (having cleared m_sub as a precaution). 387 | 2. Look to see if the string begins with a bracket ( . If so, find the matching ) . 388 | This is not as simple as it might be because )s inside quotes or [] or escaped will not count. 389 | Recursively call the constructor for the regular expression between the () s. 390 | Mark everything up to the ) as used, and go to step 9. 391 | 3. Look to see if the string begins with a bracket [ . If so, find the matching ] , watching for escapes. 392 | Construct a ReRange for everything between the []s. 393 | Mark everything up to the ] as used, and go to step 9. 394 | 4. Look to see if the string begins with a ' or " . If so, build the contents interpreting 395 | escaped special characters correctly, until the matching quote is reached. 396 | Construct a ReStr for the contents, mark everything up to the final quote as used, and go to step 9. 397 | 4a. Look to see if the string begins with a U' or U" . If so, build the contents interpreting 398 | escaped special characters correctly, until the matching quote is reached. 399 | Construct a ReUStr for the contents, mark everything up to the final quote as used, and go to step 9. 400 | 5. Look to see if the string begins with a \ . 401 | If so, build a ReStr for the next character (special action for ntr), 402 | mark it as used, and go to step 9. 403 | 6. Look to see if the string begins with a { . 404 | If so, find the matching }, lookup the symbolic name in the definitions table, 405 | recursively call this constructor on the contents, 406 | mark everything up to the } as used, and go to step 9. 407 | 7. Look to see if the string begins with a dot. 408 | If so, construct a ReRange("^\n"), mark the . as used, and go to step 9. 409 | 8. At this point we conclude that there is a simple character at the start of the regular expression. 410 | Construct a ReStr for it, mark it as used, and go to step 9. 411 | 9. If the string is exhausted, return. 412 | We have a simple Regex whose m_sub contains what we can constructed. 413 | 10. If the next character is a ? , *, or +, construct a ReOpt, ReStart, or RePlus respectively 414 | out of m_sub, and make m_sub point to this new class instead. Mark the character as used. 415 | 11. If the string is exhausted, return. 416 | 12. If the next character is a | , build a ReAlt using the m_sub we have and the rest of the string. 417 | 13. Otherwise build a ReCat using the m_sub we have and the rest of the string. 418 | */ 419 | /// 420 | public Regex(TokensGen tks,int p,string str) 421 | { 422 | int n = str.Length; 423 | int nlp = 0; 424 | int lbrack = 0; 425 | int quote = 0; 426 | int j; 427 | char ch; 428 | 429 | //1. First examine the given string. 430 | // If it is empty, there is nothing to do, so return (having cleared m_sub as a precaution). 431 | m_sub = null; 432 | if (n==0) 433 | return; 434 | //2. Look to see if the string begins with a bracket ( . If so, find the matching ) . 435 | // This is not as simple as it might be because )s inside quotes or [] or escaped will not count. 436 | // Recursively call the constructor for the regular expression between the () s. 437 | // Mark everything up to the ) as used, and go to step 9. 438 | else if (str[0]=='(') 439 | { // identify a bracketed expression 440 | for (j=1;j0) 446 | lbrack = 0; 447 | else if (str[j]=='"' || str[j]=='\'') 448 | { 449 | if (quote==str[j]) 450 | quote = 0; 451 | else if (quote==0) 452 | quote = str[j]; 453 | } 454 | else if (str[j]=='(' && quote==0 && lbrack==0) 455 | nlp++; 456 | else if (str[j]==')' && quote==0 && lbrack==0 && nlp--==0) 457 | break; 458 | if (j==n) 459 | goto bad; 460 | m_sub = new Regex (tks,p+1,str.Substring(1,j-1)); 461 | j++; 462 | //3. Look to see if the string begins with a bracket [ . If so, find the matching ] , watching for escapes. 463 | // Construct a ReRange for everything between the []s. 464 | // Mark everything up to the ] as used, and go to step 9. 465 | } 466 | else if (str[0]=='[') 467 | { // range of characters 468 | for (j=1;j=n) 575 | return; 576 | //10. If the next character is a ? , *, or +, construct a CReOpt, CReStart, or CRePlus respectively 577 | // out of m_sub, and make m_sub point to this new class instead. Mark the character as used. 578 | if (str[j]=='?') 579 | { 580 | m_sub = new ReOpt(m_sub); 581 | j++; 582 | } 583 | else if (str[j]=='*') 584 | { 585 | m_sub = new ReStar(m_sub); 586 | j++; 587 | } 588 | else if (str[j]=='+') 589 | { 590 | m_sub = new RePlus(m_sub); 591 | j++; 592 | } 593 | // 11. If the string is exhausted, return. 594 | if (j>=n) 595 | return; 596 | // 12. If the next character is a | , build a ReAlt using the m_sub we have and the rest of the string. 597 | if (str[j]=='|') 598 | m_sub = new ReAlt(tks,m_sub,p+j+1,str.Substring(j+1,n-j-1)); 599 | // 13. Otherwise build a ReCat using the m_sub we have and the rest of the string. 600 | else if (j 607 | protected Regex() {} // private 608 | /// 609 | public Regex m_sub; 610 | /// 611 | public virtual void Print(TextWriter s) 612 | { 613 | if (m_sub!=null) 614 | m_sub.Print(s); 615 | } 616 | // Match(ch) is used only in arc handling for ReRange 617 | /// 618 | public virtual bool Match(char ch) { return false; } 619 | // These two Match methods are only required if you want to use 620 | // the Regex direcly for lexing. This is a very strange thing to do: 621 | // it is non-deterministic and rather slow. 622 | /// 623 | public int Match(string str) 624 | { 625 | return Match(str,0,str.Length); 626 | } 627 | /// 628 | public virtual int Match(string str,int pos,int max) 629 | { 630 | if (max<0) 631 | return -1; 632 | if (m_sub!=null) 633 | return m_sub.Match(str,pos,max); 634 | return 0; 635 | } 636 | /// 637 | public virtual void Build(Nfa nfa) 638 | { 639 | if (m_sub!=null) 640 | { 641 | Nfa sub = new Nfa(nfa.m_tks,m_sub); 642 | nfa.AddEps(sub); 643 | sub.m_end.AddEps(nfa.m_end); 644 | } 645 | else 646 | nfa.AddEps(nfa.m_end); 647 | } 648 | } 649 | /// 650 | internal class ReAlt : Regex 651 | { 652 | public ReAlt(TokensGen tks,Regex sub,int p,string str) 653 | { 654 | m_sub = sub; 655 | m_alt = new Regex(tks,p,str); 656 | } 657 | public Regex m_alt; 658 | public override void Print(TextWriter s) 659 | { 660 | s.Write("("); 661 | if (m_sub!=null) 662 | m_sub.Print(s); 663 | s.Write("|"); 664 | if (m_alt!=null) 665 | m_alt.Print(s); 666 | s.Write(")"); 667 | } 668 | /// 669 | public override int Match(string str, int pos, int max) 670 | { 671 | int a= -1, b= -1; 672 | if (m_sub!=null) 673 | a = m_sub.Match(str, pos, max); 674 | if (m_alt!=null) 675 | b = m_sub.Match(str, pos, max); 676 | return (a>b)?a:b; 677 | } 678 | /// 679 | public override void Build(Nfa nfa) 680 | { 681 | if (m_alt!=null) 682 | { 683 | Nfa alt = new Nfa(nfa.m_tks,m_alt); 684 | nfa.AddEps(alt); 685 | alt.m_end.AddEps(nfa.m_end); 686 | } 687 | base.Build(nfa); 688 | } 689 | } 690 | 691 | /// 692 | internal class ReCat : Regex 693 | { 694 | /// 695 | public ReCat(TokensGen tks,Regex sub, int p, string str) 696 | { 697 | m_sub = sub; 698 | m_next = new Regex(tks,p,str); 699 | } 700 | /// 701 | Regex m_next; 702 | 703 | /// 704 | public override void Print(TextWriter s) 705 | { 706 | s.Write("("); 707 | if (m_sub!=null) 708 | m_sub.Print(s); 709 | s.Write(")("); 710 | if (m_next!=null) 711 | m_next.Print(s); 712 | s.Write(")"); 713 | } 714 | 715 | /// 716 | public override int Match(string str, int pos, int max) 717 | { 718 | int first, a, b, r = -1; 719 | 720 | if (m_next==null) 721 | return base.Match(str,pos,max); 722 | if (m_sub==null) 723 | return m_next.Match(str,pos,max); 724 | for (first = max;first>=0;first=a-1) 725 | { 726 | a = m_sub.Match(str,pos,first); 727 | if (a<0) 728 | break; 729 | b = m_next.Match(str,pos+a,max); 730 | if (b<0) 731 | continue; 732 | if (a+b>r) 733 | r = a+b; 734 | } 735 | return r; 736 | } 737 | 738 | /// 739 | public override void Build(Nfa nfa) 740 | { 741 | if (m_next!=null) 742 | { 743 | if (m_sub!=null) 744 | { 745 | Nfa first = new Nfa(nfa.m_tks,m_sub); 746 | Nfa second = new Nfa(nfa.m_tks,m_next); 747 | nfa.AddEps(first); 748 | first.m_end.AddEps(second); 749 | second.m_end.AddEps(nfa.m_end); 750 | } 751 | else 752 | m_next.Build(nfa); 753 | } 754 | else 755 | base.Build(nfa); 756 | } 757 | } 758 | /// 759 | internal class ReStr : Regex 760 | { 761 | /// 762 | public ReStr() {} 763 | 764 | /// 765 | public ReStr(TokensGen tks,string str) 766 | { 767 | m_str = str; 768 | for (int i=0;i 773 | public ReStr(TokensGen tks,char ch) 774 | { 775 | m_str = new string(ch,1); 776 | tks.m_tokens.UsingChar(ch); 777 | } 778 | 779 | /// 780 | public string m_str = ""; 781 | 782 | /// 783 | public override void Print(TextWriter s) 784 | { 785 | s.Write(String.Format("(\"{0}\")",m_str)); 786 | } 787 | 788 | /// 789 | public override int Match(string str, int pos, int max) 790 | { 791 | int j,n = m_str.Length; 792 | 793 | if (n>max) 794 | return -1; 795 | if (n>max-pos) 796 | return -1; 797 | for(j=0;j 804 | public override void Build(Nfa nfa) 805 | { 806 | int j,n = m_str.Length; 807 | NfaNode p, pp = nfa; 808 | 809 | for (j=0;j 819 | internal class ReUStr : ReStr 820 | { 821 | /// 822 | public ReUStr(TokensGen tks,string str) 823 | { 824 | m_str = str; 825 | for (int i=0;i 832 | public ReUStr(TokensGen tks,char ch) 833 | { 834 | m_str = new string(ch,1); 835 | tks.m_tokens.UsingChar(Char.ToLower(ch)); 836 | tks.m_tokens.UsingChar(Char.ToUpper(ch)); 837 | } 838 | /// 839 | public override void Print(TextWriter s) 840 | { 841 | s.Write(String.Format("(U\"{0}\")",m_str)); 842 | } 843 | /// 844 | public override int Match(string str, int pos, int max) 845 | { 846 | int j,n = m_str.Length; 847 | 848 | if (n>max) 849 | return -1; 850 | if (n>max-pos) 851 | return -1; 852 | for(j=0;j='0' && str[p]<='7') 905 | { 906 | for (v = str[p++]-'0';p='0' && str[p]<='7';p++) 907 | v=v*8+str[p]-'0'; 908 | ns.Append((char)v); 909 | } 910 | else 911 | switch(str[p]) 912 | { 913 | case 'n' : ns.Append('\n'); break; 914 | case 't' : ns.Append('\t'); break; 915 | case 'r' : ns.Append('\r'); break; 916 | default: ns.Append(str[p]); break; 917 | } 918 | } 919 | else 920 | ns.Append(str[p]); 921 | n = ns.Length; 922 | if (ns[0] == '^') 923 | {// invert range 924 | m_invert = true; 925 | ns.Remove(0,1).Append((char)0).Append((char)0xFFFF); 926 | } 927 | for (p=0;pbool 938 | public bool m_invert = false; // implement ^ 939 | public override void Print(TextWriter s) 940 | { 941 | s.Write("["); 942 | if (m_invert) 943 | s.Write("^"); 944 | foreach (char x in m_map.Keys) 945 | s.Write(x); 946 | s.Write("]"); 947 | } 948 | void Set(TokensGen tks,char ch) 949 | { 950 | m_map[ch] = true; 951 | tks.m_tokens.UsingChar(ch); 952 | } 953 | public override bool Match(char ch) 954 | { 955 | if (m_invert) 956 | return !m_map.Contains(ch); 957 | return m_map.Contains(ch); 958 | } 959 | public override int Match(string str, int pos, int max) 960 | { 961 | if (max0;n+=r) 1011 | { 1012 | r = m_sub.Match(str, pos+n, max); 1013 | if (r<0) 1014 | break; 1015 | } 1016 | return n; 1017 | } 1018 | public override void Build(Nfa nfa) 1019 | { 1020 | base.Build(nfa); 1021 | nfa.m_end.AddEps(nfa); 1022 | } 1023 | } 1024 | 1025 | internal class ReStar : Regex 1026 | { 1027 | public ReStar(Regex sub) {m_sub = sub; } 1028 | public override void Print(TextWriter s) 1029 | { 1030 | m_sub.Print(s); 1031 | s.Write("*"); 1032 | } 1033 | public override int Match(string str, int pos, int max) 1034 | { 1035 | int n,r; 1036 | 1037 | r = m_sub.Match(str,pos,max); 1038 | if (r<0) 1039 | return -1; 1040 | for (n=0;r>0;n+=r) 1041 | { 1042 | r = m_sub.Match(str, pos+n, max); 1043 | if (r<0) 1044 | break; 1045 | } 1046 | return n; 1047 | } 1048 | public override void Build(Nfa nfa) 1049 | { 1050 | Nfa sub = new Nfa(nfa.m_tks,m_sub); 1051 | nfa.AddEps(sub); 1052 | nfa.AddEps(nfa.m_end); 1053 | sub.m_end.AddEps(nfa); 1054 | } 1055 | } 1056 | 1057 | /* The .NET Framework has its own Regex class which is an NFA recogniser 1058 | We don't want to use this for lexing because 1059 | it would be too slow (DFA is always faster) 1060 | programming in actions looks difficult 1061 | we want to explain the NFA->DFA algorithm to students 1062 | So in this project we are not using the Framework's Regex class but the one defined in regex.cs 1063 | */ 1064 | 1065 | internal class Arc 1066 | { 1067 | public char m_ch; 1068 | public NfaNode m_next; 1069 | public Arc() {} 1070 | public Arc(char ch, NfaNode next) { m_ch=ch; m_next=next; } 1071 | public virtual bool Match(char ch) 1072 | { 1073 | return ch==m_ch; 1074 | } 1075 | public virtual void Print(TextWriter s) 1076 | { 1077 | s.WriteLine(String.Format(" {0} {1}",m_ch,m_next.m_state)); 1078 | } 1079 | } 1080 | 1081 | internal class ArcEx : Arc 1082 | { 1083 | public Regex m_ref; 1084 | public ArcEx(Regex re,NfaNode next) { m_ref=re; m_next=next; } 1085 | public override bool Match(char ch) 1086 | { 1087 | return m_ref.Match(ch); 1088 | } 1089 | public override void Print(TextWriter s) 1090 | { 1091 | s.Write(" "); 1092 | m_ref.Print(s); 1093 | s.WriteLine(m_next.m_state); 1094 | } 1095 | } 1096 | 1097 | internal class UArc : Arc 1098 | { 1099 | public UArc() {} 1100 | public UArc(char ch,NfaNode next) : base(ch,next) {} 1101 | public override bool Match(char ch) 1102 | { 1103 | return Char.ToUpper(ch)==Char.ToUpper(m_ch); 1104 | } 1105 | public override void Print(TextWriter s) 1106 | { 1107 | s.WriteLine(String.Format(" U\'{0}\' {1}",m_ch,m_next.m_state)); 1108 | } 1109 | } 1110 | /// 1111 | public class NfaNode : LNode 1112 | { 1113 | /// 1114 | public string m_sTerminal = ""; // or something for the Lexer 1115 | /// 1116 | public ObjectList m_arcs = new ObjectList(); // of Arc for labelled arcs 1117 | /// 1118 | public ObjectList m_eps = new ObjectList(); // of NfaNode for unlabelled arcs 1119 | /// 1120 | public NfaNode(TokensGen tks):base(tks) {} 1121 | 1122 | // build helpers 1123 | /// 1124 | public void AddArc(char ch,NfaNode next) 1125 | { 1126 | m_arcs.Add(new Arc(ch,next)); 1127 | } 1128 | /// 1129 | public void AddUArc(char ch,NfaNode next) 1130 | { 1131 | m_arcs.Add(new UArc(ch,next)); 1132 | } 1133 | /// 1134 | public void AddArcEx(Regex re,NfaNode next) 1135 | { 1136 | m_arcs.Add(new ArcEx(re,next)); 1137 | } 1138 | /// 1139 | public void AddEps(NfaNode next) 1140 | { 1141 | m_eps.Add(next); 1142 | } 1143 | 1144 | // helper for building DFa 1145 | /// 1146 | public void AddTarget(char ch, Dfa next) 1147 | { 1148 | for (int j=0; j 1160 | public class Nfa : NfaNode 1161 | { 1162 | /// 1163 | public NfaNode m_end; 1164 | /// 1165 | public Nfa(TokensGen tks) : base(tks) 1166 | { 1167 | m_end = new NfaNode(m_tks); 1168 | } 1169 | // build an NFA for a given regular expression 1170 | /// 1171 | public Nfa(TokensGen tks,Regex re) : base(tks) 1172 | { 1173 | m_end = new NfaNode(tks); 1174 | re.Build(this); 1175 | } 1176 | } 1177 | 1178 | // shame we have to do this ourselves, but SortedList doesn't allow incremental building of Dfas 1179 | internal class NList 1180 | { // sorted List of NfaNode 1181 | public NfaNode m_node; // null for the sentinel 1182 | public NList m_next; 1183 | public NList() { m_node=null; m_next=null; } // sentinel only 1184 | NList(NfaNode nd,NList nx) { m_node=nd; m_next=nx; } 1185 | public bool Add(NfaNode n) 1186 | { 1187 | if (m_node==null) 1188 | { // m_node==null iff m_next==null 1189 | m_next = new NList(); 1190 | m_node = n; 1191 | } 1192 | else if (m_node.m_state < n.m_state) 1193 | { 1194 | m_next = new NList(m_node,m_next); 1195 | m_node = n; 1196 | } 1197 | else if (m_node.m_state == n.m_state) 1198 | return false; // Add fails, there already 1199 | else 1200 | return m_next.Add(n); 1201 | return true; // was added 1202 | } 1203 | public bool AtEnd { get { return m_node==null; } } 1204 | } 1205 | #endif 1206 | /// 1207 | public class ResWds 1208 | { 1209 | /// 1210 | public bool m_upper = false; 1211 | /// 1212 | public Hashtable m_wds = new Hashtable(); // string->string (token class name) 1213 | /// 1214 | public ResWds() {} 1215 | #if (GENTIME) 1216 | /// 1217 | public static ResWds New(TokensGen tks,string str) 1218 | { 1219 | ResWds r = new ResWds(); 1220 | str = str.Trim(); 1221 | if (str[0]=='U') 1222 | { 1223 | r.m_upper = true; 1224 | str = str.Substring(1).Trim(); 1225 | } 1226 | if (str[0]!='{' || str[str.Length-1]!='}') 1227 | goto bad; 1228 | str = str.Substring(1,str.Length-2).Trim(); 1229 | string[] wds = str.Split(','); 1230 | for (int j=0;j0) 1236 | { 1237 | a = w.Substring(i).Trim(); 1238 | w = w.Substring(0,i); 1239 | } 1240 | r.m_wds[w] = a; 1241 | if (tks.m_tokens.tokens[a]==null) 1242 | { 1243 | TokClassDef t = new TokClassDef(tks,a,"TOKEN"); 1244 | tks.m_outFile.WriteLine("//%{0}+{1}",a,t.m_yynum); 1245 | tks.m_outFile.Write("public class {0} : TOKEN",a); 1246 | tks.m_outFile.WriteLine("{ public override string yyname { get { return \""+a+"\";}}"); 1247 | tks.m_outFile.WriteLine("public override int yynum { get { return "+t.m_yynum+"; }}"); 1248 | tks.m_outFile.WriteLine(" public "+a+"(Lexer yyl):base(yyl) {}}"); 1249 | } 1250 | } 1251 | return r; 1252 | bad: 1253 | tks.m_tokens.erh.Error(new CSToolsException(47,"bad ResWds element")); 1254 | return null; 1255 | } 1256 | #endif 1257 | /// 1258 | public void Check(Lexer yyl,ref TOKEN tok) 1259 | { 1260 | string str = tok.yytext; 1261 | if (m_upper) 1262 | str = str.ToUpper(); 1263 | object o = m_wds[str]; 1264 | if (o==null) 1265 | return; 1266 | tok = (TOKEN)Tfactory.create((string)o,yyl); 1267 | } 1268 | /// 1269 | public static object Serialise(object o,Serialiser s) 1270 | { 1271 | if (s==null) 1272 | return new ResWds(); 1273 | ResWds r = (ResWds)o; 1274 | if (s.Encode) 1275 | { 1276 | s.Serialise(r.m_upper); 1277 | s.Serialise(r.m_wds); 1278 | return null; 1279 | } 1280 | r.m_upper = (bool)s.Deserialise(); 1281 | r.m_wds = (Hashtable)s.Deserialise(); 1282 | return r; 1283 | } 1284 | } 1285 | } 1286 | -------------------------------------------------------------------------------- /src/HandEvaluator/PocketQueryParser/Runtime/lexer.cs: -------------------------------------------------------------------------------- 1 | // Malcolm Crowe 1995,2000 2 | // As far as possible the regular expression notation follows that of lex 3 | 4 | using System; 5 | using System.Collections; 6 | using System.IO; 7 | using System.Text; 8 | using System.Globalization; 9 | 10 | namespace Tools 11 | { 12 | 13 | // We cleverly arrange for the YyLexer class to serialize itself out of a simple integer array. 14 | // So: to use the lexer generated for a script, include the generated tokens.cs file in the build, 15 | // This defines classes tokens (subclass of Lexer) and yytokens (subclass of YyLexer). 16 | 17 | // Call Lexer::Start() to start the input engine going, and then use the 18 | // Lexer::Next() function to get successive TOKENs. 19 | // Note that if you are using ParserGenerator, this is done for you. 20 | 21 | /// 22 | public class YyLexer // we will gather all formerly static definitions for lexing here and in LexerGenerate 23 | { 24 | // Deserializing 25 | /// 26 | public void GetDfa() 27 | { 28 | if (tokens.Count>0) 29 | return; 30 | Serialiser f = new Serialiser(arr); 31 | f.VersionCheck(); 32 | m_encoding = (Encoding)f.Deserialise(); 33 | toupper = (bool)f.Deserialise(); 34 | cats = (Hashtable)f.Deserialise(); 35 | m_gencat = (UnicodeCategory)f.Deserialise(); 36 | usingEOF = (bool)f.Deserialise(); 37 | starts = (Hashtable)f.Deserialise(); 38 | Dfa.SetTokens(this,starts); 39 | tokens = (Hashtable)f.Deserialise(); 40 | reswds = (Hashtable)f.Deserialise(); 41 | } 42 | #if (GENTIME) 43 | /// 44 | public void EmitDfa(TextWriter outFile) 45 | { 46 | Console.WriteLine("Serializing the lexer"); 47 | Serialiser f = new Serialiser(outFile); 48 | f.VersionCheck(); 49 | f.Serialise(m_encoding); 50 | f.Serialise(toupper); 51 | f.Serialise(cats); 52 | f.Serialise(m_gencat); 53 | f.Serialise(usingEOF); 54 | f.Serialise(starts); 55 | f.Serialise(tokens); 56 | f.Serialise(reswds); 57 | outFile.WriteLine("0};"); 58 | } 59 | #endif 60 | // support for Unicode character sets 61 | /// 62 | public Encoding m_encoding = Encoding.ASCII; // overwritten by Deserialize 63 | /// 64 | public string InputEncoding 65 | { 66 | set 67 | { 68 | m_encoding = Charset.GetEncoding(value,ref toupper,erh); 69 | } 70 | } 71 | /// 72 | public bool usingEOF = false; 73 | /// 74 | public bool toupper = false; // for ASCIICAPS 75 | /// 76 | public Hashtable cats = new Hashtable(); // UnicodeCategory -> Charset 77 | /// 78 | public UnicodeCategory m_gencat; // not a UsingCat unless all usbale cats in use 79 | // support for lexer states 80 | /// 81 | public Hashtable starts = new Hashtable(); // string->Dfa 82 | // support for serialization 83 | /// 84 | protected int[] arr; // defined in generated tokens class 85 | // support for token classes 86 | /// 87 | public Hashtable types = new Hashtable(); // string->TCreator 88 | /// 89 | public Hashtable tokens = new Hashtable(); // string->TokClassDef 90 | // support for reserved word sets 91 | /// 92 | public Hashtable reswds = new Hashtable(); // int->ResWds 93 | /// 94 | public ErrorHandler erh; 95 | /// 96 | public YyLexer(ErrorHandler eh) 97 | { 98 | erh = eh; 99 | #if (GENTIME) 100 | UsingCat(UnicodeCategory.OtherPunctuation); 101 | m_gencat = UnicodeCategory.OtherPunctuation; 102 | #endif 103 | new Tfactory(this,"TOKEN",new TCreator(Tokenfactory)); 104 | } 105 | /// 106 | protected object Tokenfactory(Lexer yyl) 107 | { 108 | return new TOKEN(yyl); 109 | } 110 | #if (GENTIME) 111 | /// 112 | public Charset UsingCat(UnicodeCategory cat) 113 | { 114 | if (cat==m_gencat) 115 | { 116 | for (int j=0;j<28;j++) 117 | { 118 | if (!Enum.IsDefined(typeof(UnicodeCategory),j)) 119 | continue; 120 | UnicodeCategory u = (UnicodeCategory)j; 121 | if (u==UnicodeCategory.Surrogate) 122 | continue; 123 | if (cats[u]==null) 124 | { 125 | UsingCat(u); 126 | m_gencat = u; 127 | } 128 | } 129 | return (Charset)cats[cat]; 130 | } 131 | if (cats[cat]!=null) 132 | return (Charset)cats[cat]; 133 | Charset rv = new Charset(cat); 134 | cats[cat] = rv; 135 | return rv; 136 | } 137 | internal void UsingChar(char ch) 138 | { 139 | UnicodeCategory cat = Char.GetUnicodeCategory(ch); 140 | Charset cs = UsingCat(cat); 141 | if (cs.m_generic==ch) 142 | { 143 | do 144 | { 145 | if (cs.m_generic==char.MaxValue) 146 | { 147 | cs.m_generic = ch; // all used: this m_generic will never be used 148 | return; 149 | } 150 | cs.m_generic++; 151 | } while (Char.GetUnicodeCategory(cs.m_generic)!=cs.m_cat || 152 | cs.m_chars.Contains(cs.m_generic)); 153 | cs.m_chars[cs.m_generic] = true; 154 | } 155 | else 156 | cs.m_chars[ch] = true; 157 | } 158 | #endif 159 | internal char Filter(char ch) 160 | { 161 | UnicodeCategory cat = Char.GetUnicodeCategory(ch); 162 | Charset cs = (Charset)cats[cat]; 163 | if (cs==null) 164 | cs = (Charset)cats[m_gencat]; 165 | if (cs.m_chars.Contains(ch)) 166 | return ch; 167 | return cs.m_generic; 168 | } 169 | bool testEOF(char ch) 170 | { 171 | UnicodeCategory cat = Char.GetUnicodeCategory(ch); 172 | return (cat==UnicodeCategory.OtherNotAssigned); 173 | } 174 | #if (GENTIME) 175 | bool CharIsSymbol(char c) 176 | { 177 | UnicodeCategory u = Char.GetUnicodeCategory(c); 178 | return (u==UnicodeCategory.OtherSymbol || u==UnicodeCategory.ModifierSymbol || 179 | u==UnicodeCategory.CurrencySymbol || u==UnicodeCategory.MathSymbol); 180 | } 181 | bool CharIsSeparator(char c) 182 | { 183 | UnicodeCategory u = Char.GetUnicodeCategory(c); 184 | return (u==UnicodeCategory.ParagraphSeparator || u==UnicodeCategory.LineSeparator || 185 | u==UnicodeCategory.SpaceSeparator); 186 | } 187 | internal ChTest GetTest(string name) 188 | { 189 | try { 190 | object o = Enum.Parse(typeof(UnicodeCategory),name); 191 | if (o!=null) 192 | { 193 | UnicodeCategory cat = (UnicodeCategory)o; 194 | UsingCat(cat); 195 | return new ChTest(new CatTest(cat).Test); 196 | } 197 | } catch (Exception) {} 198 | switch (name) 199 | { 200 | case "Symbol": 201 | UsingCat(UnicodeCategory.OtherSymbol); 202 | UsingCat(UnicodeCategory.ModifierSymbol); 203 | UsingCat(UnicodeCategory.CurrencySymbol); 204 | UsingCat(UnicodeCategory.MathSymbol); 205 | return new ChTest(CharIsSymbol); 206 | case "Punctuation": 207 | UsingCat(UnicodeCategory.OtherPunctuation); 208 | UsingCat(UnicodeCategory.FinalQuotePunctuation); 209 | UsingCat(UnicodeCategory.InitialQuotePunctuation); 210 | UsingCat(UnicodeCategory.ClosePunctuation); 211 | UsingCat(UnicodeCategory.OpenPunctuation); 212 | UsingCat(UnicodeCategory.DashPunctuation); 213 | UsingCat(UnicodeCategory.ConnectorPunctuation); 214 | return new ChTest(Char.IsPunctuation); 215 | /* case "PrivateUse": 216 | UsingCat(UnicodeCategory.PrivateUse); 217 | return new ChTest(Char.IsPrivateUse); */ 218 | case "Separator": 219 | UsingCat(UnicodeCategory.ParagraphSeparator); 220 | UsingCat(UnicodeCategory.LineSeparator); 221 | UsingCat(UnicodeCategory.SpaceSeparator); 222 | return new ChTest(CharIsSeparator); 223 | case "WhiteSpace": 224 | UsingCat(UnicodeCategory.Control); 225 | UsingCat(UnicodeCategory.ParagraphSeparator); 226 | UsingCat(UnicodeCategory.LineSeparator); 227 | UsingCat(UnicodeCategory.SpaceSeparator); 228 | return new ChTest(Char.IsWhiteSpace); 229 | case "Number": 230 | UsingCat(UnicodeCategory.OtherNumber); 231 | UsingCat(UnicodeCategory.LetterNumber); 232 | UsingCat(UnicodeCategory.DecimalDigitNumber); 233 | return new ChTest(Char.IsNumber); 234 | case "Digit": 235 | UsingCat(UnicodeCategory.DecimalDigitNumber); 236 | return new ChTest(Char.IsDigit); 237 | /* case "Mark": 238 | UsingCat(UnicodeCategory.EnclosingMark); 239 | UsingCat(UnicodeCategory.SpacingCombiningMark); 240 | UsingCat(UnicodeCategory.NonSpacingMark); 241 | return new ChTest(Char.IsMark); */ 242 | case "Letter": 243 | UsingCat(UnicodeCategory.OtherLetter); 244 | UsingCat(UnicodeCategory.ModifierLetter); 245 | UsingCat(UnicodeCategory.TitlecaseLetter); 246 | UsingCat(UnicodeCategory.LowercaseLetter); 247 | UsingCat(UnicodeCategory.UppercaseLetter); 248 | return new ChTest(Char.IsLetter); 249 | case "Lower": 250 | UsingCat(UnicodeCategory.LowercaseLetter); 251 | return new ChTest(Char.IsLower); 252 | case "Upper": 253 | UsingCat(UnicodeCategory.UppercaseLetter); 254 | return new ChTest(Char.IsUpper); 255 | case "EOF": 256 | UsingCat(UnicodeCategory.OtherNotAssigned); 257 | UsingChar((char)0xFFFF); 258 | usingEOF=true; 259 | return new ChTest(testEOF); 260 | default: 261 | erh.Error(new CSToolsException(24,"No such Charset "+name)); 262 | break; 263 | } 264 | return new ChTest(Char.IsControl); // not reached 265 | } 266 | #endif 267 | /// 268 | public virtual TOKEN OldAction(Lexer yyl,ref string yytext,int action,ref bool reject) 269 | { 270 | return null; 271 | } 272 | /// 273 | public IEnumerator GetEnumerator() 274 | { 275 | return tokens.Values.GetEnumerator(); 276 | } 277 | } 278 | 279 | /// 280 | public class LineManager 281 | { 282 | /// 283 | public int lines = 1; // for error messages etc 284 | /// 285 | public int end = 0; // high water mark of positions 286 | /// 287 | public LineList list = null; 288 | /// 289 | public LineManager() {} 290 | /// 291 | public void newline(int pos) 292 | { 293 | lines++; 294 | backto(pos); 295 | list = new LineList(pos,list); 296 | } 297 | /// 298 | public void backto(int pos) 299 | { 300 | if (pos>end) 301 | end = pos; 302 | while (list!=null && list.head>=pos) 303 | { 304 | list = list.tail; 305 | lines--; 306 | } 307 | } 308 | /// 309 | public void comment(int pos,int len) 310 | { // only for C-style comments not C++ 311 | if (pos>end) 312 | end = pos; 313 | if (list==null) 314 | { 315 | list = new LineList(0,list); 316 | lines = 1; 317 | } 318 | list.comments = new CommentList(pos,len,list.comments); 319 | } 320 | } 321 | #if (GENTIME) 322 | /// 323 | public abstract class TokensGen : GenBase 324 | { 325 | /// 326 | public TokensGen(ErrorHandler eh):base(eh) {} 327 | /// 328 | protected bool m_showDfa; 329 | /// 330 | public YyLexer m_tokens; // the YyLexer class under construction 331 | /// 332 | // %defines in script 333 | public Hashtable defines = new Hashtable(); // string->string 334 | /// 335 | // support for Nfa networks 336 | int state = 0; 337 | /// 338 | public int NewState() { return ++state; } // for LNodes 339 | /// 340 | public ObjectList states = new ObjectList(); // Dfa 341 | /// 342 | public string FixActions(string str) 343 | { 344 | return str.Replace("yybegin","yym.yy_begin").Replace("yyl","(("+m_outname+")yym)"); 345 | } 346 | } 347 | #endif 348 | // support for Unicode character sets 349 | 350 | internal delegate bool ChTest(char ch); 351 | /// 352 | public class CatTest 353 | { 354 | UnicodeCategory cat; 355 | /// 356 | public CatTest(UnicodeCategory c) { cat = c; } 357 | /// 358 | public bool Test(char ch) 359 | { 360 | return Char.GetUnicodeCategory(ch)==cat; 361 | } 362 | } 363 | 364 | /// 365 | public class Charset 366 | { 367 | internal UnicodeCategory m_cat; 368 | internal char m_generic; // not explicitly Using'ed allUsed 369 | internal Hashtable m_chars = new Hashtable(); // char->bool 370 | Charset(){} 371 | #if (GENTIME) 372 | internal Charset(UnicodeCategory cat) 373 | { 374 | m_cat = cat; 375 | for (m_generic=char.MinValue;Char.GetUnicodeCategory(m_generic)!=cat;m_generic++) 376 | ; 377 | m_chars[m_generic] = true; 378 | } 379 | #endif 380 | /// 381 | public static Encoding GetEncoding(string enc, ref bool toupper,ErrorHandler erh) 382 | { 383 | switch (enc) 384 | { 385 | case "": return Encoding.Default; // locale-specific 386 | case "ASCII": return Encoding.ASCII; 387 | case "ASCIICAPS": toupper=true; return Encoding.ASCII; // toupper is currently ignored in scripts 388 | case "UTF7": return Encoding.UTF7; 389 | case "UTF8": return Encoding.UTF8; 390 | case "Unicode": return Encoding.Unicode; 391 | default: 392 | try 393 | { 394 | return Encoding.GetEncoding(int.Parse(enc)); // codepage 395 | } 396 | catch (Exception) 397 | { 398 | erh.Error(new CSToolsException(43,"Warning: Encoding "+enc+" unknown: ignored")); 399 | } 400 | break; 401 | } 402 | return Encoding.ASCII; 403 | } 404 | /// 405 | public static object Serialise(object o,Serialiser s) 406 | { 407 | if (s==null) 408 | return new Charset(); 409 | Charset c = (Charset)o; 410 | if (s.Encode) 411 | { 412 | s.Serialise((int)c.m_cat); 413 | s.Serialise(c.m_generic); 414 | s.Serialise(c.m_chars); 415 | return null; 416 | } 417 | c.m_cat = (UnicodeCategory)s.Deserialise(); 418 | c.m_generic = (char)s.Deserialise(); 419 | c.m_chars = (Hashtable)s.Deserialise(); 420 | return c; 421 | } 422 | } 423 | 424 | // Support for runtime object creation 425 | /// 426 | public delegate object TCreator(Lexer yyl); 427 | /// 428 | public class Tfactory 429 | { 430 | /// 431 | public static object create(string cls_name,Lexer yyl) 432 | { 433 | TCreator cr = (TCreator) yyl.tokens.types[cls_name]; 434 | // Console.WriteLine("TCreating {0} <{1}>",cls_name,yyl.yytext); 435 | if (cr==null) 436 | yyl.tokens.erh.Error(new CSToolsException(6,yyl,cls_name,String.Format("no factory for {0}",cls_name))); 437 | try 438 | { 439 | return cr(yyl); 440 | } 441 | catch (CSToolsException x) 442 | { 443 | yyl.tokens.erh.Error(x); 444 | } 445 | catch (Exception e) 446 | { 447 | yyl.tokens.erh.Error(new CSToolsException(7,yyl,cls_name, 448 | String.Format("Line {0}: Create of {1} failed ({2})",yyl.Saypos(yyl.m_pch),cls_name,e.Message))); 449 | } 450 | int j = cls_name.LastIndexOf('_'); 451 | if (j>0) 452 | { 453 | cr = (TCreator)yyl.tokens.types[cls_name.Substring(0,j)]; 454 | if (cr!=null) 455 | return cr(yyl); 456 | } 457 | return null; 458 | } 459 | /// 460 | public Tfactory(YyLexer tks,string cls_name,TCreator cr) 461 | { 462 | tks.types[cls_name] = cr; 463 | } 464 | } 465 | /// 466 | public class SourceLineInfo 467 | { 468 | /// 469 | public int lineNumber; 470 | /// 471 | public int charPosition; 472 | /// 473 | public int startOfLine; 474 | /// 475 | public int endOfLine; 476 | /// 477 | public int rawCharPosition; 478 | /// 479 | public Lexer lxr = null; 480 | /// 481 | public SourceLineInfo(int pos) // this constructor is not used in anger 482 | { 483 | lineNumber = 1; 484 | startOfLine = 0; 485 | endOfLine = rawCharPosition = charPosition = pos; 486 | } 487 | /// 488 | public SourceLineInfo(LineManager lm,int pos) 489 | { 490 | lineNumber = lm.lines; 491 | startOfLine = 0; 492 | endOfLine = lm.end; 493 | charPosition = pos; 494 | rawCharPosition = pos; 495 | for (LineList p = lm.list; p!=null; p = p.tail, lineNumber-- ) 496 | if (p.head>pos) 497 | endOfLine = p.head; 498 | else 499 | { 500 | startOfLine = p.head+1; 501 | rawCharPosition = p.getpos(pos); 502 | charPosition = pos-startOfLine+1; 503 | break; 504 | } 505 | } 506 | /// 507 | public SourceLineInfo(Lexer lx,int pos) :this(lx.m_LineManager,pos) { lxr=lx; } // 4.5c 508 | /// 509 | public override string ToString() 510 | { 511 | return "Line "+lineNumber+", char "+(rawCharPosition+1); 512 | } 513 | /// 514 | public string sourceLine { get { if (lxr==null) return ""; return lxr.sourceLine(this); }} 515 | } 516 | /// 517 | public class LineList 518 | { 519 | /// 520 | public int head; 521 | /// 522 | public CommentList comments = null; 523 | /// 524 | public LineList tail; // previous line! 525 | /// 526 | public LineList(int h, LineList t) 527 | { 528 | head=h; 529 | comments = null; 530 | tail=t; 531 | } 532 | /// 533 | public int getpos(int pos) 534 | { 535 | int n = pos-head; 536 | for (CommentList c = comments; c!=null; c=c.tail) 537 | if (pos>c.spos) 538 | n += c.len; 539 | return n; 540 | } 541 | } 542 | /// 543 | public class CommentList 544 | { 545 | /// 546 | public int spos,len; 547 | /// 548 | public CommentList tail = null; 549 | /// 550 | public CommentList(int st,int ln, CommentList t) 551 | { 552 | spos = st; len = ln; 553 | tail = t; 554 | } 555 | } 556 | 557 | // the following class gets rid of comments for us 558 | /// 559 | public class CsReader 560 | { 561 | /// 562 | public string fname = ""; 563 | TextReader m_stream; 564 | /// 565 | public LineManager lm = new LineManager(); 566 | int back; // one-char pushback 567 | enum State 568 | { 569 | copy, sol, c_com, cpp_com, c_star, at_eof, transparent 570 | } 571 | State state; 572 | int pos = 0; 573 | bool sol = true; 574 | /// 575 | public CsReader(string data) 576 | { 577 | m_stream = new StringReader(data); 578 | state= State.copy; 579 | back = -1; 580 | } 581 | /// 582 | public CsReader(string fileName,Encoding enc) 583 | { 584 | fname = fileName; 585 | FileStream fs = new FileStream(fileName,FileMode.Open,FileAccess.Read); 586 | m_stream = new StreamReader(fs,enc); 587 | state= State.copy; back = -1; 588 | } 589 | /// 590 | public CsReader(CsReader inf,Encoding enc) 591 | { 592 | fname = inf.fname; 593 | if (inf.m_stream is StreamReader) 594 | m_stream = new StreamReader(((StreamReader)inf.m_stream).BaseStream,enc); 595 | else 596 | m_stream = new StreamReader(inf.m_stream.ReadToEnd()); 597 | state= State.copy; back = -1; 598 | } 599 | /// 600 | public bool Eof() { return state==State.at_eof; } 601 | /// 602 | public int Read(char[] arr,int offset,int count) 603 | { 604 | int c,n; 605 | for (n=0;count>0;count--,n++) 606 | { 607 | c = Read(); 608 | if (c<0) 609 | break; 610 | arr[offset+n] = (char)c; 611 | } 612 | return n; 613 | } 614 | /// 615 | public string ReadLine() 616 | { 617 | int c=0,n; 618 | char[] buf = new char[1024]; 619 | int count = 1024; 620 | for (n=0;count>0;count--) 621 | { 622 | c = Read(); 623 | if (((char)c)=='\r') 624 | continue; 625 | if (c<0 || ((char)c)=='\n') 626 | break; 627 | buf[n++] = (char)c; 628 | } 629 | if (c<0) 630 | state = State.at_eof; 631 | return new string(buf,0,n); 632 | } 633 | /// 634 | public int Read() 635 | { 636 | int c,comlen = 0; 637 | if (state==State.at_eof) 638 | return -1; 639 | while (true) 640 | { 641 | // get a character 642 | if (back>=0) 643 | { // back is used only in copy mode 644 | c = back; back = -1; 645 | } 646 | else if (state==State.at_eof) 647 | c = -1; 648 | else 649 | c = m_stream.Read(); 650 | if (c=='\r') 651 | continue; 652 | while (sol && c=='#') // deal with #line directive 653 | { 654 | while (c!=' ') 655 | c = m_stream.Read(); 656 | lm.lines = 0; 657 | while (c==' ') 658 | c = m_stream.Read(); 659 | while (c>='0' && c<='9') 660 | { 661 | lm.lines = lm.lines*10+(c-'0'); 662 | c = m_stream.Read(); 663 | } 664 | while (c==' ') 665 | c = m_stream.Read(); 666 | if (c=='"') 667 | { 668 | fname = ""; 669 | c = m_stream.Read(); 670 | while (c!='"') 671 | { 672 | fname += c; 673 | c = m_stream.Read(); 674 | } 675 | } 676 | while (c!='\n') 677 | c = m_stream.Read(); 678 | if (c=='\r') 679 | c = m_stream.Read(); 680 | } 681 | if (c<0) 682 | { // at EOF we must leave the loop 683 | if (state==State.sol) 684 | c = '/'; 685 | state = State.at_eof; 686 | pos++; 687 | return c; 688 | } 689 | sol = false; 690 | // otherwise work through a state machine 691 | switch (state) 692 | { 693 | case State.copy: 694 | if (c=='/') 695 | state = State.sol; 696 | else 697 | { 698 | if (c=='\n') 699 | { 700 | lm.newline(pos); 701 | sol = true; 702 | } 703 | pos++; 704 | return c; 705 | } continue; 706 | case State.sol: // solidus '/' 707 | if (c=='*') 708 | state = State.c_com; 709 | else if (c=='/') 710 | { 711 | comlen = 2; 712 | state = State.cpp_com; 713 | } 714 | else 715 | { 716 | back = c; 717 | state = State.copy; 718 | pos++; 719 | return '/'; 720 | } 721 | continue; 722 | case State.c_com: 723 | comlen++; 724 | if (c=='\n') 725 | { 726 | lm.newline(pos); 727 | comlen=0; 728 | sol = true; 729 | } 730 | if (c=='*') 731 | state = State.c_star; 732 | continue; 733 | case State.c_star: 734 | comlen++; 735 | if (c=='/') 736 | { 737 | lm.comment(pos,comlen); 738 | state = State.copy; 739 | } 740 | else 741 | state = State.c_com; 742 | continue; 743 | case State.cpp_com: 744 | if (c=='\n') 745 | { 746 | state = State.copy; 747 | sol = true; 748 | pos++; 749 | return c; 750 | } 751 | else 752 | comlen++; 753 | continue; 754 | } 755 | } 756 | /* notreached */ 757 | } 758 | } 759 | /// 760 | public class SYMBOL 761 | { 762 | /// 763 | public object m_dollar; 764 | /// 765 | public static implicit operator int (SYMBOL s) // 4.0c 766 | { 767 | int rv = 0; 768 | object d; 769 | while (((d=s.m_dollar) is SYMBOL) && d!=null) 770 | s = (SYMBOL)d; 771 | try 772 | { 773 | rv =(int)d; 774 | } 775 | catch(Exception e) 776 | { 777 | Console.WriteLine("attempt to convert from "+s.m_dollar.GetType()); 778 | throw e; 779 | } 780 | return rv; 781 | } 782 | /// 783 | public int pos; 784 | /// 785 | public int Line { get { return yylx.sourceLineInfo(pos).lineNumber; }} 786 | /// 787 | public int Position { get { return yylx.sourceLineInfo(pos).rawCharPosition; }} 788 | /// 789 | public string Pos { get { return yylx.Saypos(pos); }} 790 | /// 791 | protected SYMBOL() {} 792 | /// 793 | public Lexer yylx; 794 | /// 795 | public object yylval { get { return m_dollar; } set { m_dollar=value; } } 796 | /// 797 | public SYMBOL(Lexer yyl) { yylx=yyl; } 798 | /// 799 | public virtual int yynum { get { return 0; }} 800 | /// 801 | public virtual bool IsTerminal() { return false; } 802 | /// 803 | public virtual bool IsAction() { return false; } 804 | /// 805 | public virtual bool IsCSymbol() { return false; } 806 | /// 807 | public Parser yyps = null; 808 | /// 809 | public YyParser yyact { get { return (yyps!=null)?yyps.m_symbols:null; }} 810 | /// 811 | public SYMBOL(Parser yyp) { yyps=yyp; yylx=yyp.m_lexer; } 812 | /// 813 | public virtual bool Pass(YyParser syms,int snum,out ParserEntry entry) 814 | { 815 | ParsingInfo pi = (ParsingInfo)syms.symbolInfo[yynum]; 816 | if (pi==null) 817 | { 818 | string s = string.Format("No parsinginfo for symbol {0} {1}",yyname,yynum); 819 | syms.erh.Error(new CSToolsFatalException(9,yylx,yyname,s)); 820 | } 821 | bool r = pi.m_parsetable.Contains(snum); 822 | entry = r?((ParserEntry)pi.m_parsetable[snum]):null; 823 | return r; 824 | } 825 | /// 826 | public virtual string yyname { get { return "SYMBOL"; }} 827 | /// 828 | public override string ToString() { return yyname; } 829 | /// 830 | public virtual bool Matches(string s) { return false; } 831 | /// 832 | public virtual void Print() { Console.WriteLine(ToString()); } 833 | // 4.2a Support for automatic display of concrete syntax tree 834 | /// 835 | public ObjectList kids = new ObjectList(); 836 | void ConcreteSyntaxTree(string n) 837 | { 838 | if (this is error) 839 | Console.WriteLine(n+" "+ToString()); 840 | else 841 | Console.WriteLine(n+"-"+ToString()); 842 | int j=0; 843 | foreach(SYMBOL s in kids) 844 | s.ConcreteSyntaxTree(n+((j++==kids.Count-1)?" ":" |")); 845 | } 846 | /// 847 | public virtual void ConcreteSyntaxTree() { ConcreteSyntaxTree(""); } 848 | } 849 | 850 | /// 851 | public class TOKEN : SYMBOL 852 | { 853 | /// 854 | public string yytext { get { return m_str; } set { m_str=value; } } 855 | string m_str; 856 | /// 857 | public TOKEN(Parser yyp):base(yyp) {} 858 | /// 859 | public TOKEN(Lexer yyl) : base(yyl) { if (yyl!=null) m_str=yyl.yytext; } 860 | /// 861 | public TOKEN(Lexer yyl,string s) :base(yyl) { m_str=s; } 862 | /// 863 | protected TOKEN() {} 864 | /// 865 | public override bool IsTerminal() { return true; } 866 | int num = 1; 867 | /// 868 | public override bool Pass(YyParser syms,int snum,out ParserEntry entry) 869 | { 870 | if (yynum==1) 871 | { 872 | Literal lit = (Literal)syms.literals[yytext]; 873 | if (lit!=null) 874 | num = (int)lit.m_yynum; 875 | } 876 | ParsingInfo pi = (ParsingInfo)syms.symbolInfo[yynum]; 877 | if (pi==null) 878 | { 879 | string s = string.Format("Parser does not recognise literal {0}",yytext); 880 | syms.erh.Error(new CSToolsFatalException(9,yylx,yyname,s)); 881 | } 882 | bool r = pi.m_parsetable.Contains(snum); 883 | entry = r?((ParserEntry)pi.m_parsetable[snum]):null; 884 | return r; 885 | } 886 | /// 887 | public override string yyname { get { return "TOKEN"; }} 888 | /// 889 | public override int yynum { get { return num; }} 890 | /// 891 | public override bool Matches(string s) { return s.Equals(m_str); } 892 | /// 893 | public override string ToString() { return yyname+"<"+ yytext+">"; } 894 | /// 895 | public override void Print() { Console.WriteLine(ToString()); } 896 | } 897 | /// 898 | public class Lexer 899 | { 900 | /// 901 | public bool m_debug = false; 902 | // source line control 903 | /// 904 | public string m_buf; 905 | internal LineManager m_LineManager = new LineManager(); // 4.5b see EOF 906 | /// 907 | public SourceLineInfo sourceLineInfo(int pos) 908 | { 909 | return new SourceLineInfo(this,pos); // 4.5c 910 | } 911 | /// 912 | public string sourceLine(SourceLineInfo s) 913 | { 914 | // This is the sourceLine after removal of comments 915 | // The position in this line is s.charPosition 916 | // If you want the comments as well, then you should re-read the source file 917 | // and the position in the line is s.rawCharPosition 918 | return m_buf.Substring(s.startOfLine,s.endOfLine-s.startOfLine); 919 | } 920 | /// 921 | public string Saypos(int pos) 922 | { 923 | return sourceLineInfo(pos).ToString(); 924 | } 925 | 926 | // the heart of the lexer is the DFA 927 | /// 928 | public Dfa m_start { get { return (Dfa)m_tokens.starts[m_state]; }} 929 | /// 930 | public string m_state = "YYINITIAL"; // exposed for debugging (by request) 931 | /// 932 | public Lexer(YyLexer tks) 933 | { 934 | m_state="YYINITIAL"; 935 | tokens = tks; 936 | } 937 | 938 | YyLexer m_tokens; 939 | /// 940 | public YyLexer tokens { get { return m_tokens; } // 4.2d 941 | set { m_tokens=value; m_tokens.GetDfa(); } 942 | } 943 | /// 944 | public string yytext; // for collection when a TOKEN is created 945 | /// 946 | public int m_pch = 0; 947 | /// 948 | public int yypos { get { return m_pch; }} 949 | /// 950 | public void yy_begin(string newstate) 951 | { 952 | m_state = newstate; 953 | } 954 | bool m_matching; 955 | int m_startMatch; 956 | // match a Dfa against lexer's input 957 | bool Match(ref TOKEN tok,Dfa dfa) 958 | { 959 | char ch=PeekChar(); 960 | int op=m_pch, mark=0; 961 | Dfa next; 962 | 963 | if (m_debug) 964 | { 965 | Console.Write("state {0} with ",dfa.m_state); 966 | if (char.IsLetterOrDigit(ch)||char.IsPunctuation(ch)) 967 | Console.WriteLine(ch); 968 | else 969 | Console.WriteLine("#"+(int)ch); 970 | } 971 | if (dfa.m_actions!=null) 972 | { 973 | mark = Mark(); 974 | } 975 | if (// ch==0 || 976 | (next=((Dfa)dfa.m_map[m_tokens.Filter(ch)]))==null) 977 | { 978 | if (m_debug) 979 | Console.Write("{0} no arc",dfa.m_state); 980 | if (dfa.m_actions!=null) 981 | { 982 | if (m_debug) 983 | Console.WriteLine(" terminal"); 984 | return TryActions(dfa,ref tok); // fails on REJECT 985 | } 986 | if (m_debug) 987 | Console.WriteLine(" fails"); 988 | return false; 989 | } 990 | Advance(); 991 | if (!Match(ref tok, next)) 992 | { // rest of string fails 993 | if (m_debug) 994 | Console.WriteLine("back to {0} with {1}",dfa.m_state,ch); 995 | if (dfa.m_actions!=null) 996 | { // this is still okay at a terminal 997 | if (m_debug) 998 | Console.WriteLine("{0} succeeds",dfa.m_state); 999 | Restore(mark); 1000 | return TryActions(dfa,ref tok); 1001 | } 1002 | if (m_debug) 1003 | Console.WriteLine("{0} fails",dfa.m_state); 1004 | return false; 1005 | } 1006 | if (dfa.m_reswds>=0) 1007 | { 1008 | ((ResWds)m_tokens.reswds[dfa.m_reswds]).Check(this,ref tok); 1009 | } 1010 | if (m_debug) 1011 | { 1012 | Console.Write("{0} matched ",dfa.m_state); 1013 | if (m_pch<=m_buf.Length) 1014 | Console.WriteLine(m_buf.Substring(op,m_pch-op)); 1015 | else 1016 | Console.WriteLine(m_buf.Substring(op)); 1017 | } 1018 | return true; 1019 | } 1020 | 1021 | // start lexing 1022 | /// 1023 | public void Start(StreamReader inFile) 1024 | { 1025 | m_state="YYINITIAL"; // 4.3e 1026 | m_LineManager.lines = 1; // 1027 | m_LineManager.list = null; // 1028 | inFile = new StreamReader(inFile.BaseStream,m_tokens.m_encoding); 1029 | m_buf = inFile.ReadToEnd(); 1030 | if (m_tokens.toupper) 1031 | m_buf = m_buf.ToUpper(); 1032 | for (m_pch=0; m_pch 1038 | public void Start(CsReader inFile) 1039 | { 1040 | m_state="YYINITIAL"; // 4.3e 1041 | inFile = new CsReader(inFile,m_tokens.m_encoding); 1042 | m_LineManager = inFile.lm; 1043 | if (!inFile.Eof()) 1044 | for (m_buf = inFile.ReadLine(); !inFile.Eof(); m_buf += inFile.ReadLine()) 1045 | m_buf+="\n"; 1046 | if (m_tokens.toupper) 1047 | m_buf = m_buf.ToUpper(); 1048 | m_pch = 0; 1049 | } 1050 | /// 1051 | public void Start(string buf) 1052 | { 1053 | m_state="YYINITIAL"; // 4.3e 1054 | m_LineManager.lines = 1; // 1055 | m_LineManager.list = null; // 1056 | m_buf = buf+"\n"; 1057 | for (m_pch=0; m_pch 1065 | public TOKEN Next() 1066 | { 1067 | TOKEN rv = null; 1068 | while (PeekChar()!=0) 1069 | { 1070 | Matching(true); 1071 | if (!Match(ref rv,(Dfa)m_tokens.starts[m_state])) 1072 | { 1073 | if (yypos==0) 1074 | System.Console.Write("Check text encoding.. "); 1075 | int c = PeekChar(); 1076 | m_tokens.erh.Error(new CSToolsStopException(2,this,"illegal character <"+(char)c+"> "+c)); 1077 | return null; 1078 | } 1079 | Matching (false); 1080 | if (rv!=null) 1081 | { // or special value for empty action? 1082 | rv.pos = m_pch-yytext.Length; 1083 | return rv; 1084 | } 1085 | } 1086 | return null; 1087 | } 1088 | bool TryActions(Dfa dfa,ref TOKEN tok) 1089 | { 1090 | int len = m_pch-m_startMatch; 1091 | if (len==0) 1092 | return false; 1093 | if (m_startMatch+len<=m_buf.Length) 1094 | yytext = m_buf.Substring(m_startMatch,len); 1095 | else // can happen with {EOF} rules 1096 | yytext = m_buf.Substring(m_startMatch); 1097 | // actions is a list of old-style actions for this DFA in order of priority 1098 | // there is a list because of the chance that any of them may REJECT 1099 | Dfa.Action a = dfa.m_actions; 1100 | bool reject = true; 1101 | while (reject && a!=null) 1102 | { 1103 | int action = a.a_act; 1104 | reject = false; 1105 | a = a.a_next; 1106 | if (a==null && dfa.m_tokClass!="") 1107 | { // last one might not be an old-style action 1108 | if (m_debug) 1109 | Console.WriteLine("creating a "+dfa.m_tokClass); 1110 | tok=(TOKEN)Tfactory.create(dfa.m_tokClass,this); 1111 | } 1112 | else 1113 | { 1114 | tok = m_tokens.OldAction(this,ref yytext,action,ref reject); 1115 | if (m_debug && !reject) 1116 | Console.WriteLine("Old action "+action); 1117 | } 1118 | } 1119 | return !reject; 1120 | } 1121 | /// 1122 | public char PeekChar() 1123 | { 1124 | if (m_pch 1131 | public void Advance() { ++m_pch; } 1132 | /// 1133 | public virtual int GetChar() 1134 | { 1135 | int r=PeekChar(); ++m_pch; 1136 | return r; 1137 | } 1138 | /// 1139 | public void UnGetChar() { if (m_pch>0) --m_pch; } 1140 | int Mark() 1141 | { 1142 | return m_pch-m_startMatch; 1143 | } 1144 | void Restore(int mark) 1145 | { 1146 | m_pch = m_startMatch + mark; 1147 | } 1148 | void Matching(bool b) 1149 | { 1150 | m_matching = b; 1151 | if (b) 1152 | m_startMatch = m_pch; 1153 | } 1154 | /// 1155 | public _Enumerator GetEnumerator() 1156 | { 1157 | return new _Enumerator(this); 1158 | } 1159 | /// 1160 | public void Reset() 1161 | { 1162 | m_pch = 0; 1163 | m_LineManager.backto(0); 1164 | } 1165 | /// 1166 | public class _Enumerator 1167 | { 1168 | Lexer lxr; 1169 | TOKEN t; 1170 | /// 1171 | public _Enumerator(Lexer x) { lxr = x; t = null; } 1172 | /// 1173 | public bool MoveNext() 1174 | { 1175 | t = lxr.Next(); 1176 | return t!=null; 1177 | } 1178 | /// 1179 | public TOKEN Current { get { return t; } } 1180 | /// 1181 | public void Reset() { lxr.Reset(); } 1182 | } 1183 | } 1184 | /// 1185 | public class CSToolsException : Exception 1186 | { 1187 | /// 1188 | public int nExceptionNumber; 1189 | /// 1190 | public SourceLineInfo slInfo; 1191 | /// 1192 | public string sInput; 1193 | /// 1194 | public SYMBOL sym = null; 1195 | /// 1196 | public bool handled = false; 1197 | /// 1198 | public CSToolsException(int n,string s) : this(n,new SourceLineInfo(0),"",s) {} 1199 | /// 1200 | public CSToolsException(int n,Lexer yl,string s) : this(n,yl,yl.yytext,s) {} 1201 | /// 1202 | public CSToolsException(int n,Lexer yl,string yy,string s) : this(n,yl,yl.m_pch,yy,s) {} 1203 | /// 1204 | public CSToolsException(int n,TOKEN t,string s) : this(n,t.yylx,t.pos,t.yytext,s) { sym=t; } 1205 | /// 1206 | public CSToolsException(int n,SYMBOL t,string s) : this(n,t.yylx,t.pos,t.yyname,s) { sym=t; } 1207 | /// 1208 | public CSToolsException(int en,Lexer yl,int p, string y, string s) : this(en,yl.sourceLineInfo(p),y,s) {} 1209 | /// 1210 | public CSToolsException(int en,SourceLineInfo s, string y, string m) : base(s.ToString()+": "+m) 1211 | { 1212 | nExceptionNumber = en; 1213 | slInfo = s; 1214 | sInput = y; 1215 | } 1216 | /// 1217 | public virtual void Handle(ErrorHandler erh) // provides the default ErrorHandling implementation 1218 | { 1219 | if (erh.throwExceptions) 1220 | throw this; 1221 | if (handled) 1222 | return; 1223 | handled = true; 1224 | erh.Report(this); // the parse table may allow recovery from this error 1225 | } 1226 | } 1227 | /// 1228 | public class CSToolsFatalException: CSToolsException 1229 | { 1230 | /// 1231 | public CSToolsFatalException(int n,string s) : base(n,s) {} 1232 | /// 1233 | public CSToolsFatalException(int n,Lexer yl,string s) : base(n,yl,yl.yytext,s) {} 1234 | /// 1235 | public CSToolsFatalException(int n,Lexer yl,string yy,string s) : base(n,yl,yl.m_pch,yy,s) {} 1236 | /// 1237 | public CSToolsFatalException(int n,Lexer yl,int p, string y, string s) : base(n,yl,p,y,s) {} 1238 | /// 1239 | public CSToolsFatalException(int n,TOKEN t,string s) : base(n,t,s) {} 1240 | /// 1241 | public CSToolsFatalException(int en,SourceLineInfo s, string y, string m) : base(en,s,y,m) {} 1242 | /// 1243 | public override void Handle(ErrorHandler erh) 1244 | { 1245 | throw this; // we expect to bomb out to the environment with CLR traceback 1246 | } 1247 | } 1248 | 1249 | /// 1250 | public class CSToolsStopException: CSToolsException 1251 | { 1252 | /// 1253 | public CSToolsStopException(int n,string s) : base(n,s) {} 1254 | /// 1255 | public CSToolsStopException(int n,Lexer yl,string s) : base(n,yl,yl.yytext,s) {} 1256 | /// 1257 | public CSToolsStopException(int n,Lexer yl,string yy,string s) : base(n,yl,yl.m_pch,yy,s) {} 1258 | /// 1259 | public CSToolsStopException(int n,Lexer yl,int p, string y, string s) : base(n,yl,p,y,s) {} 1260 | /// 1261 | public CSToolsStopException(int n,TOKEN t,string s) : base(n,t,s) {} 1262 | /// 1263 | public CSToolsStopException(int n,SYMBOL t,string s) : base(n,t,s) {} 1264 | /// 1265 | public CSToolsStopException(int en,SourceLineInfo s, string y, string m) : base(en,s,y,m) {} 1266 | /// 1267 | public override void Handle(ErrorHandler erh) 1268 | { // 4.5b 1269 | throw this; // we expect Parser.Parse() to catch this but stop the parse 1270 | } 1271 | } 1272 | /// 1273 | public class ErrorHandler 1274 | { 1275 | /// 1276 | public int counter = 0; 1277 | /// 1278 | public bool throwExceptions = false; 1279 | /// 1280 | public ErrorHandler() {} 1281 | /// 1282 | public ErrorHandler(bool ee){ throwExceptions = ee;} 1283 | /// 1284 | public virtual void Error(CSToolsException e) 1285 | { 1286 | counter++; 1287 | e.Handle(this); 1288 | } 1289 | /// 1290 | public virtual void Report(CSToolsException e) 1291 | { 1292 | // I don't want to see error messages. 1293 | //Console.WriteLine(e.Message); 1294 | } 1295 | } 1296 | } --------------------------------------------------------------------------------