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 |
20 |
21 |
Go to the pokersource project page to download the software, report bugs or subscribe to the mailing list.
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 |
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 |
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 |
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 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
Copyright 2002-2010, RPS Consulting
216 |
217 |
218 |
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 | }
--------------------------------------------------------------------------------