diff --git a/lib/tsgencsharp.pl b/lib/tsgencsharp.pl index 1a75012827f1a1692a2ee494ce52dc6934834574..a31ffd02cf07bf730b70bf952783648c7334ed7d 100644 --- a/lib/tsgencsharp.pl +++ b/lib/tsgencsharp.pl @@ -151,7 +151,7 @@ pp_byte_seq_r([X|Xs]) --> !, pp_byte_seq_r(Xs). pp_parse_result(char(C)) --> !, - "(System.UInt64)", + %"(System.UInt64)", pp_parser(char(C)). pp_parse_result(seq(Args)) --> !, "new object[]{ ", pp_result_seq(Args), "}". diff --git a/src/bindings/dotnet/ext/hammer.cs b/src/bindings/dotnet/ext/hammer.cs index 00f217fe19acb04850191fba42426e74fa17c6f7..fa7de568f5b219c817ee9ef871cf1c05de8cbab3 100644 --- a/src/bindings/dotnet/ext/hammer.cs +++ b/src/bindings/dotnet/ext/hammer.cs @@ -122,12 +122,17 @@ namespace Hammer public class Hammer { internal static IDictionary tag_to_action; + internal static ulong charify_action; internal static HTokenType tt_dotnet; static Hammer() { tt_dotnet = hammer.h_allocate_token_type("com.upstandinghackers.hammer.dotnet.tagged"); hammer.h_set_dotnet_tagged_token_type(tt_dotnet); tag_to_action = new System.Collections.Hashtable(); + charify_action = RegisterAction(x => { + //System.Console.WriteLine(x.GetType()); + return char.ConvertFromUtf32((int)(ulong)x)[0]; + }); } internal static ulong RegisterAction(HAction action) @@ -137,6 +142,18 @@ namespace Hammer return newAction; } + internal static ulong RegisterPredicate(HPredicate predicate) + { + ulong newPredicate = (ulong)tag_to_action.Count; + tag_to_action[newPredicate] = predicate; + return newPredicate; + } + + internal static Parser CharParser(Parser p) + { + return new Parser(hammer.h_tag(p.wrapped, charify_action)).Pin(p); + } + internal static byte[] ToBytes(string s) { // Probably not what you want unless you're parsing binary data. @@ -192,7 +209,7 @@ namespace Hammer public static Parser Ch(byte ch) { - return new Parser(hammer.h_ch(ch)); + return CharParser(new Parser(hammer.h_ch(ch))); } public static Parser Ch(char ch) @@ -202,12 +219,12 @@ namespace Hammer public static Parser Ch_range(byte c1, byte c2) { - return new Parser(hammer.h_ch_range(c1, c2)); + return CharParser(new Parser(hammer.h_ch_range(c1, c2))); } public static Parser Ch_range(char c1, char c2) { - return new Parser(hammer.h_ch_range((byte)c1, (byte)c2)); + return CharParser(new Parser(hammer.h_ch_range((byte)c1, (byte)c2))); } public static Parser Int_range(Parser p, System.Int64 i1, System.Int64 i2) @@ -230,7 +247,7 @@ namespace Hammer unsafe { fixed(byte* b = &charset[0]) { - return new Parser(hammer.h_in((IntPtr)b, (uint)charset.Length)); + return CharParser(new Parser(hammer.h_in((IntPtr)b, (uint)charset.Length))); } } } @@ -240,7 +257,7 @@ namespace Hammer unsafe { fixed(byte* b = &charset[0]) { - return new Parser(hammer.h_not_in((IntPtr)b, (uint)charset.Length)); + return CharParser(new Parser(hammer.h_not_in((IntPtr)b, (uint)charset.Length))); } } } @@ -277,7 +294,6 @@ namespace Hammer public static Parser Nothing_p() {return new Parser(hammer.h_nothing_p());} public static Parser Epsilon_p() {return new Parser(hammer.h_epsilon_p());} - // 1-arg parsers public static Parser Ignore(Parser p) { @@ -362,6 +378,11 @@ namespace Hammer ulong actionNo = Hammer.RegisterAction(action); return new Parser(hammer.h_tag(p.wrapped, actionNo)).Pin(p).Pin(action); } + public static Parser AttrBool(Parser p, HPredicate predicate) + { + ulong predNo = Hammer.RegisterPredicate(predicate); + return new Parser(hammer.h_tag(p.wrapped, predNo)).Pin(p).Pin(predicate); + } } } \ No newline at end of file diff --git a/src/bindings/dotnet/test/hammer_hand_tests.cs b/src/bindings/dotnet/test/hammer_hand_tests.cs index 0d8852838b5342c57430a5561e0d04e1cc9bb6ff..c6aaac7b7612366852913fc434a405dad7f1a91f 100644 --- a/src/bindings/dotnet/test/hammer_hand_tests.cs +++ b/src/bindings/dotnet/test/hammer_hand_tests.cs @@ -7,11 +7,28 @@ namespace Hammer.Test [Test] public void TestAction() { - Parser parser = Hammer.Action(Hammer.Sequence(Hammer.Choice(Hammer.Token("a"), - Hammer.Token("A")), - Hammer.Choice(Hammer.Token("b"), - Hammer.Token("B"))), - (HAction)(x => char.ToUpper(((string)x)[0]))); + Parser parser = Hammer.Action(Hammer.Sequence(Hammer.Choice(Hammer.Ch('a'), + Hammer.Ch('A')), + Hammer.Choice(Hammer.Ch('b'), + Hammer.Ch('B'))), + (HAction)(x => string.Join(",",(object[])x))); + CheckParseOK(parser, "ab", "a,b"); + CheckParseOK(parser, "AB", "A,B"); + CheckParseFail(parser, "XX"); + } + [Test] + public void TestAttrBool() + { + Parser parser = Hammer.AttrBool(Hammer.Many1(Hammer.Choice(Hammer.Ch('a'), + Hammer.Ch('b'))), + (HPredicate)(x => { + object[] elems = (object[])x; + return elems.Length > 1 && (char)elems[0] == (char)elems[1]; + })); + + CheckParseOK(parser, "aa", new object[]{ 'a','a' }); + CheckParseOK(parser, "bb", new object[]{ 'b','b' }); + CheckParseFail(parser, "ab"); } } diff --git a/src/bindings/dotnet/test/hammer_tests.cs b/src/bindings/dotnet/test/hammer_tests.cs index ce4641359f2668b810c249be425b3f7bbc10e3a5..ac0ac9e2c53c44fa839ea1879d3bbdb74cea3ce8 100644 --- a/src/bindings/dotnet/test/hammer_tests.cs +++ b/src/bindings/dotnet/test/hammer_tests.cs @@ -13,14 +13,14 @@ namespace Hammer.Test { public void TestCh() { Parser parser; parser = Hammer.Ch(0xa2); - CheckParseOK(parser, "\xa2", (System.UInt64)'\xa2'); + CheckParseOK(parser, "\xa2", '\xa2'); CheckParseFail(parser, "\xa3"); } [Test] public void TestCh_range() { Parser parser; parser = Hammer.Ch_range(0x61, 0x63); - CheckParseOK(parser, "b", (System.UInt64)'b'); + CheckParseOK(parser, "b", 'b'); CheckParseFail(parser, "d"); } [Test] @@ -94,10 +94,10 @@ namespace Hammer.Test { public void TestWhitespace() { Parser parser; parser = Hammer.Whitespace(Hammer.Ch(0x61)); - CheckParseOK(parser, "a", (System.UInt64)'a'); - CheckParseOK(parser, " a", (System.UInt64)'a'); - CheckParseOK(parser, " a", (System.UInt64)'a'); - CheckParseOK(parser, "\x09a", (System.UInt64)'a'); + CheckParseOK(parser, "a", 'a'); + CheckParseOK(parser, " a", 'a'); + CheckParseOK(parser, " a", 'a'); + CheckParseOK(parser, "\x09a", 'a'); CheckParseFail(parser, "_a"); parser = Hammer.Whitespace(Hammer.End_p()); CheckParseOK(parser, "", null); @@ -108,7 +108,7 @@ namespace Hammer.Test { public void TestLeft() { Parser parser; parser = Hammer.Left(Hammer.Ch(0x61), Hammer.Ch(0x20)); - CheckParseOK(parser, "a ", (System.UInt64)'a'); + CheckParseOK(parser, "a ", 'a'); CheckParseFail(parser, "a"); CheckParseFail(parser, " "); CheckParseFail(parser, "ba"); @@ -117,7 +117,7 @@ namespace Hammer.Test { public void TestMiddle() { Parser parser; parser = Hammer.Middle(Hammer.Ch(' '), Hammer.Ch('a'), Hammer.Ch(' ')); - CheckParseOK(parser, " a ", (System.UInt64)'a'); + CheckParseOK(parser, " a ", 'a'); CheckParseFail(parser, "a"); CheckParseFail(parser, " a"); CheckParseFail(parser, "a "); @@ -129,21 +129,21 @@ namespace Hammer.Test { public void TestIn() { Parser parser; parser = Hammer.In("abc"); - CheckParseOK(parser, "b", (System.UInt64)'b'); + CheckParseOK(parser, "b", 'b'); CheckParseFail(parser, "d"); } [Test] public void TestNot_in() { Parser parser; parser = Hammer.Not_in("abc"); - CheckParseOK(parser, "d", (System.UInt64)'d'); + CheckParseOK(parser, "d", 'd'); CheckParseFail(parser, "a"); } [Test] public void TestEnd_p() { Parser parser; parser = Hammer.Sequence(Hammer.Ch('a'), Hammer.End_p()); - CheckParseOK(parser, "a", new object[]{ (System.UInt64)'a'}); + CheckParseOK(parser, "a", new object[]{ 'a'}); CheckParseFail(parser, "aa"); } [Test] @@ -156,32 +156,32 @@ namespace Hammer.Test { public void TestSequence() { Parser parser; parser = Hammer.Sequence(Hammer.Ch('a'), Hammer.Ch('b')); - CheckParseOK(parser, "ab", new object[]{ (System.UInt64)'a', (System.UInt64)'b'}); + CheckParseOK(parser, "ab", new object[]{ 'a', 'b'}); CheckParseFail(parser, "a"); CheckParseFail(parser, "b"); parser = Hammer.Sequence(Hammer.Ch('a'), Hammer.Whitespace(Hammer.Ch('b'))); - CheckParseOK(parser, "ab", new object[]{ (System.UInt64)'a', (System.UInt64)'b'}); - CheckParseOK(parser, "a b", new object[]{ (System.UInt64)'a', (System.UInt64)'b'}); - CheckParseOK(parser, "a b", new object[]{ (System.UInt64)'a', (System.UInt64)'b'}); + CheckParseOK(parser, "ab", new object[]{ 'a', 'b'}); + CheckParseOK(parser, "a b", new object[]{ 'a', 'b'}); + CheckParseOK(parser, "a b", new object[]{ 'a', 'b'}); } [Test] public void TestChoice() { Parser parser; parser = Hammer.Choice(Hammer.Ch('a'), Hammer.Ch('b')); - CheckParseOK(parser, "a", (System.UInt64)'a'); - CheckParseOK(parser, "b", (System.UInt64)'b'); - CheckParseOK(parser, "ab", (System.UInt64)'a'); + CheckParseOK(parser, "a", 'a'); + CheckParseOK(parser, "b", 'b'); + CheckParseOK(parser, "ab", 'a'); CheckParseFail(parser, "c"); } [Test] public void TestButnot() { Parser parser; parser = Hammer.Butnot(Hammer.Ch('a'), Hammer.Token("ab")); - CheckParseOK(parser, "a", (System.UInt64)'a'); + CheckParseOK(parser, "a", 'a'); CheckParseFail(parser, "ab"); - CheckParseOK(parser, "aa", (System.UInt64)'a'); + CheckParseOK(parser, "aa", 'a'); parser = Hammer.Butnot(Hammer.Ch_range('0', '9'), Hammer.Ch('6')); - CheckParseOK(parser, "5", (System.UInt64)'5'); + CheckParseOK(parser, "5", '5'); CheckParseFail(parser, "6"); } [Test] @@ -195,8 +195,8 @@ namespace Hammer.Test { public void TestXor() { Parser parser; parser = Hammer.Xor(Hammer.Ch_range('0', '6'), Hammer.Ch_range('5', '9')); - CheckParseOK(parser, "0", (System.UInt64)'0'); - CheckParseOK(parser, "9", (System.UInt64)'9'); + CheckParseOK(parser, "0", '0'); + CheckParseOK(parser, "9", '9'); CheckParseFail(parser, "5"); CheckParseFail(parser, "a"); } @@ -205,18 +205,18 @@ namespace Hammer.Test { Parser parser; parser = Hammer.Many(Hammer.Choice(Hammer.Ch('a'), Hammer.Ch('b'))); CheckParseOK(parser, "", new object[]{ }); - CheckParseOK(parser, "a", new object[]{ (System.UInt64)'a'}); - CheckParseOK(parser, "b", new object[]{ (System.UInt64)'b'}); - CheckParseOK(parser, "aabbaba", new object[]{ (System.UInt64)'a', (System.UInt64)'a', (System.UInt64)'b', (System.UInt64)'b', (System.UInt64)'a', (System.UInt64)'b', (System.UInt64)'a'}); + CheckParseOK(parser, "a", new object[]{ 'a'}); + CheckParseOK(parser, "b", new object[]{ 'b'}); + CheckParseOK(parser, "aabbaba", new object[]{ 'a', 'a', 'b', 'b', 'a', 'b', 'a'}); } [Test] public void TestMany1() { Parser parser; parser = Hammer.Many1(Hammer.Choice(Hammer.Ch('a'), Hammer.Ch('b'))); CheckParseFail(parser, ""); - CheckParseOK(parser, "a", new object[]{ (System.UInt64)'a'}); - CheckParseOK(parser, "b", new object[]{ (System.UInt64)'b'}); - CheckParseOK(parser, "aabbaba", new object[]{ (System.UInt64)'a', (System.UInt64)'a', (System.UInt64)'b', (System.UInt64)'b', (System.UInt64)'a', (System.UInt64)'b', (System.UInt64)'a'}); + CheckParseOK(parser, "a", new object[]{ 'a'}); + CheckParseOK(parser, "b", new object[]{ 'b'}); + CheckParseOK(parser, "aabbaba", new object[]{ 'a', 'a', 'b', 'b', 'a', 'b', 'a'}); CheckParseFail(parser, "daabbabadef"); } [Test] @@ -224,16 +224,16 @@ namespace Hammer.Test { Parser parser; parser = Hammer.Repeat_n(Hammer.Choice(Hammer.Ch('a'), Hammer.Ch('b')), 0x2); CheckParseFail(parser, "adef"); - CheckParseOK(parser, "abdef", new object[]{ (System.UInt64)'a', (System.UInt64)'b'}); + CheckParseOK(parser, "abdef", new object[]{ 'a', 'b'}); CheckParseFail(parser, "dabdef"); } [Test] public void TestOptional() { Parser parser; parser = Hammer.Sequence(Hammer.Ch('a'), Hammer.Optional(Hammer.Choice(Hammer.Ch('b'), Hammer.Ch('c'))), Hammer.Ch('d')); - CheckParseOK(parser, "abd", new object[]{ (System.UInt64)'a', (System.UInt64)'b', (System.UInt64)'d'}); - CheckParseOK(parser, "acd", new object[]{ (System.UInt64)'a', (System.UInt64)'c', (System.UInt64)'d'}); - CheckParseOK(parser, "ad", new object[]{ (System.UInt64)'a', null, (System.UInt64)'d'}); + CheckParseOK(parser, "abd", new object[]{ 'a', 'b', 'd'}); + CheckParseOK(parser, "acd", new object[]{ 'a', 'c', 'd'}); + CheckParseOK(parser, "ad", new object[]{ 'a', null, 'd'}); CheckParseFail(parser, "aed"); CheckParseFail(parser, "ab"); CheckParseFail(parser, "ac"); @@ -242,51 +242,51 @@ namespace Hammer.Test { public void TestIgnore() { Parser parser; parser = Hammer.Sequence(Hammer.Ch('a'), Hammer.Ignore(Hammer.Ch('b')), Hammer.Ch('c')); - CheckParseOK(parser, "abc", new object[]{ (System.UInt64)'a', (System.UInt64)'c'}); + CheckParseOK(parser, "abc", new object[]{ 'a', 'c'}); CheckParseFail(parser, "ac"); } [Test] public void TestSepBy() { Parser parser; parser = Hammer.SepBy(Hammer.Choice(Hammer.Ch('1'), Hammer.Ch('2'), Hammer.Ch('3')), Hammer.Ch(',')); - CheckParseOK(parser, "1,2,3", new object[]{ (System.UInt64)'1', (System.UInt64)'2', (System.UInt64)'3'}); - CheckParseOK(parser, "1,3,2", new object[]{ (System.UInt64)'1', (System.UInt64)'3', (System.UInt64)'2'}); - CheckParseOK(parser, "1,3", new object[]{ (System.UInt64)'1', (System.UInt64)'3'}); - CheckParseOK(parser, "3", new object[]{ (System.UInt64)'3'}); + CheckParseOK(parser, "1,2,3", new object[]{ '1', '2', '3'}); + CheckParseOK(parser, "1,3,2", new object[]{ '1', '3', '2'}); + CheckParseOK(parser, "1,3", new object[]{ '1', '3'}); + CheckParseOK(parser, "3", new object[]{ '3'}); CheckParseOK(parser, "", new object[]{ }); } [Test] public void TestSepBy1() { Parser parser; parser = Hammer.SepBy1(Hammer.Choice(Hammer.Ch('1'), Hammer.Ch('2'), Hammer.Ch('3')), Hammer.Ch(',')); - CheckParseOK(parser, "1,2,3", new object[]{ (System.UInt64)'1', (System.UInt64)'2', (System.UInt64)'3'}); - CheckParseOK(parser, "1,3,2", new object[]{ (System.UInt64)'1', (System.UInt64)'3', (System.UInt64)'2'}); - CheckParseOK(parser, "1,3", new object[]{ (System.UInt64)'1', (System.UInt64)'3'}); - CheckParseOK(parser, "3", new object[]{ (System.UInt64)'3'}); + CheckParseOK(parser, "1,2,3", new object[]{ '1', '2', '3'}); + CheckParseOK(parser, "1,3,2", new object[]{ '1', '3', '2'}); + CheckParseOK(parser, "1,3", new object[]{ '1', '3'}); + CheckParseOK(parser, "3", new object[]{ '3'}); CheckParseFail(parser, ""); } [Test] public void TestAnd() { Parser parser; parser = Hammer.Sequence(Hammer.And(Hammer.Ch('0')), Hammer.Ch('0')); - CheckParseOK(parser, "0", new object[]{ (System.UInt64)'0'}); + CheckParseOK(parser, "0", new object[]{ '0'}); CheckParseFail(parser, "1"); parser = Hammer.Sequence(Hammer.And(Hammer.Ch('0')), Hammer.Ch('1')); CheckParseFail(parser, "0"); CheckParseFail(parser, "1"); parser = Hammer.Sequence(Hammer.Ch('1'), Hammer.And(Hammer.Ch('2'))); - CheckParseOK(parser, "12", new object[]{ (System.UInt64)'1'}); + CheckParseOK(parser, "12", new object[]{ '1'}); CheckParseFail(parser, "13"); } [Test] public void TestNot() { Parser parser; parser = Hammer.Sequence(Hammer.Ch('a'), Hammer.Choice(Hammer.Token("+"), Hammer.Token("++")), Hammer.Ch('b')); - CheckParseOK(parser, "a+b", new object[]{ (System.UInt64)'a', new byte[]{ 0x2b}, (System.UInt64)'b'}); + CheckParseOK(parser, "a+b", new object[]{ 'a', new byte[]{ 0x2b}, 'b'}); CheckParseFail(parser, "a++b"); parser = Hammer.Sequence(Hammer.Ch('a'), Hammer.Choice(Hammer.Sequence(Hammer.Token("+"), Hammer.Not(Hammer.Ch('+'))), Hammer.Token("++")), Hammer.Ch('b')); - CheckParseOK(parser, "a+b", new object[]{ (System.UInt64)'a', new object[]{ new byte[]{ 0x2b}}, (System.UInt64)'b'}); - CheckParseOK(parser, "a++b", new object[]{ (System.UInt64)'a', new byte[]{ 0x2b, 0x2b}, (System.UInt64)'b'}); + CheckParseOK(parser, "a+b", new object[]{ 'a', new object[]{ new byte[]{ 0x2b}}, 'b'}); + CheckParseOK(parser, "a++b", new object[]{ 'a', new byte[]{ 0x2b, 0x2b}, 'b'}); } [Test] public void TestRightrec() { @@ -294,9 +294,9 @@ namespace Hammer.Test { IndirectParser sp_rr = Hammer.Indirect(); sp_rr.Bind(Hammer.Choice(Hammer.Sequence(Hammer.Ch('a'), sp_rr), Hammer.Epsilon_p())); parser = sp_rr; - CheckParseOK(parser, "a", new object[]{ (System.UInt64)'a'}); - CheckParseOK(parser, "aa", new object[]{ (System.UInt64)'a', new object[]{ (System.UInt64)'a'}}); - CheckParseOK(parser, "aaa", new object[]{ (System.UInt64)'a', new object[]{ (System.UInt64)'a', new object[]{ (System.UInt64)'a'}}}); + CheckParseOK(parser, "a", new object[]{ 'a'}); + CheckParseOK(parser, "aa", new object[]{ 'a', new object[]{ 'a'}}); + CheckParseOK(parser, "aaa", new object[]{ 'a', new object[]{ 'a', new object[]{ 'a'}}}); } [Test] public void TestAmbiguous() { @@ -308,9 +308,9 @@ namespace Hammer.Test { sp_p.Bind(Hammer.Ch('+')); sp_e.Bind(Hammer.Choice(Hammer.Sequence(sp_e, sp_p, sp_e), sp_d)); parser = sp_e; - CheckParseOK(parser, "d", (System.UInt64)'d'); - CheckParseOK(parser, "d+d", new object[]{ (System.UInt64)'d', (System.UInt64)'+', (System.UInt64)'d'}); - CheckParseOK(parser, "d+d+d", new object[]{ new object[]{ (System.UInt64)'d', (System.UInt64)'+', (System.UInt64)'d'}, (System.UInt64)'+', (System.UInt64)'d'}); + CheckParseOK(parser, "d", 'd'); + CheckParseOK(parser, "d+d", new object[]{ 'd', '+', 'd'}); + CheckParseOK(parser, "d+d+d", new object[]{ new object[]{ 'd', '+', 'd'}, '+', 'd'}); } } } diff --git a/src/bindings/dotnet/test/test_support.cs b/src/bindings/dotnet/test/test_support.cs index 518a4027f5873ac3ecd5caf947db55414ebc14b1..98e2cdd74c2ed08e75fc6e9361b24cb531beb899 100644 --- a/src/bindings/dotnet/test/test_support.cs +++ b/src/bindings/dotnet/test/test_support.cs @@ -80,6 +80,14 @@ namespace Hammer.Test System.UInt64 i = (System.UInt64)o; return "u0x" + i.ToString("X"); } + else if (o is System.String) + { + return "\"" + o.ToString() + "\""; + } + else if (o is System.Char) + { + return "\'" + o.ToString() + "\'"; + } else return "WAT(" + o.GetType() + ")"; }