diff --git a/HACKING b/HACKING index 970a2491e9bcc03b39cc7e3fd18b74c2da136d0a..44f59912c50edd2bf76f01dbe19652926abc41e6 100644 --- a/HACKING +++ b/HACKING @@ -59,4 +59,8 @@ There is a language-independent representation of the Hammer test suite in `lib/test-suite`. This is intended to be used with the tsparser.pl prolog library, along with a language-specific frontend. -No language-specific frontends have been written yet. +Only the C# frontend exists so far; to regenerate the test suites using it, run + + $ swipl -q -t halt -g tsgencsharp:prolog tsgencsharp.pl \ + >../src/bindings/dotnet/test/hammer_tests.cs + diff --git a/lib/test-suite b/lib/test-suite index 207ece4054fabb0c31041e8c394cbe28b60c33ef..133a7731582332cfe054c525950bc5839e2f5e2e 100644 --- a/lib/test-suite +++ b/lib/test-suite @@ -215,7 +215,7 @@ many1 { test "daabbabadef" --> fail; } -repeat-n { +repeat_n { parser repeat_n(choice(ch('a'),ch('b')),0x2); test "adef" --> fail; test "abdef" --> ['a','b']; @@ -270,11 +270,11 @@ and { } not { - parser sequence(ch('a'), choice(token('+'), token("++")), ch('b')); + parser sequence(ch('a'), choice(token("+"), token("++")), ch('b')); test "a+b" --> ['a',"+",'b']; test "a++b" --> fail; - parser sequence(ch('a'), choice(sequence(token('+'), not(ch('+'))), + parser sequence(ch('a'), choice(sequence(token("+"), not(ch('+'))), token("++")), ch('b')); test "a+b" --> ['a', ["+"], 'b']; diff --git a/lib/tsgencsharp.pl b/lib/tsgencsharp.pl index 1e263d6908302c32d584991d56dec5a28412eefa..ca1039dd67bf80501386ecdce9f1290fa0de9336 100644 --- a/lib/tsgencsharp.pl +++ b/lib/tsgencsharp.pl @@ -105,7 +105,7 @@ pp_test_elem(exec, parser(P)) --> ";\n". pp_test_elem(decl, subparser(Name,_)) --> !, indent(3), - "Hammer.Parser ", pp_parser(ref(Name)), + "IndirectParser ", pp_parser(ref(Name)), " = Hammer.Indirect();\n". pp_test_elem(init, subparser(Name, Parser)) --> !, indent(3), @@ -160,7 +160,7 @@ pp_parse_result(none) --> !, pp_parse_result(uint(V)) --> !, "(System.UInt64)", pp_parser(num(V)). pp_parse_result(sint(V)) --> !, - "(System.Int64)", pp_parser(num(V)). + "(System.Int64)(", pp_parser(num(V)), ")". pp_parse_result(string(A)) --> !, "new byte[]{ ", pp_byte_seq(A), "}". %pp_parse_result(A) --> @@ -180,8 +180,8 @@ pp_test_case(testcase(Name, Elems)) --> !, indent(2), "[Test]\n", { format_test_name(Name, TName) }, - indent(2), "public void ", TName, " {\n", - indent(3), "Hammer.Parser parser;\n", + indent(2), "public void ", TName, "() {\n", + indent(3), "Parser parser;\n", pp_test_elems(decl, Elems), pp_test_elems(init, Elems), pp_test_elems(exec, Elems), @@ -196,6 +196,7 @@ pp_test_cases([A|As]) --> pp_test_suite(Suite) --> "namespace Hammer.Test {\n", indent(1), "using NUnit.Framework;\n", + %indent(1), "using Hammer;\n", indent(1), "[TestFixture]\n", indent(1), "public partial class HammerTest {\n", pp_test_cases(Suite), diff --git a/src/bindings/dotnet/SConscript b/src/bindings/dotnet/SConscript index 6448e685dd56ca532ec03eec0f2e8922ea6b704b..64b0a4fbf1f57fce55533586ffe7064f125186f4 100644 --- a/src/bindings/dotnet/SConscript +++ b/src/bindings/dotnet/SConscript @@ -39,11 +39,13 @@ dotnettestenv = dotnetenv.Clone() #dotnettestenv['ENV']['LD_LIBRARY_PATH'] = os.path.dirname(str(libhammer_shared[0])) #dotnettests = ['t/hammer.t'] -dotnettestenv.Append(CILLIBS=['/usr/lib/cli/nunit.core-2.6/nunit.core.dll','/usr/lib/cli/nunit.util-2.6/nunit.util.dll','/usr/lib/cli/nunit.framework-2.6/nunit.framework.dll','/usr/lib/cli/nunit.core.interfaces-2.6/nunit.core.interfaces.dll',str(hammer_dll[0])]) +dotnettestenv.Append(CILLIBS=['/usr/lib/cli/nunit.core-2.6/nunit.core.dll','/usr/lib/cli/nunit.util-2.6/nunit.util.dll','/usr/lib/cli/nunit.framework-2.6/nunit.framework.dll','/usr/lib/cli/nunit.core.interfaces-2.6/nunit.core.interfaces.dll', "src/bindings/dotnet/hammer.dll"]) dotnettestlib = dotnettestenv.CLILibrary('hammer_test.dll', Glob('test/*.cs')) -#dotnettestexec = dotnettestenv.Command(None, dotnettests + libhammer_dotnet + libhammer_shared, "make test -C " + targetdir) -#dotnettest = Alias("testdotnet", [dotnettestexec], dotnettestexec) -#AlwaysBuild(dotnettestexec) +Depends(dotnettestlib, hammer_dll) + +dotnettestexec = dotnettestenv.Command(None, dotnettestlib, "nunit-console $SOURCE") +dotnettest = Alias("testdotnet", [dotnettestexec], dotnettestexec) +AlwaysBuild(dotnettestexec) testruns.append(dotnettestlib) #dotnetinstallexec = dotnetenv.Command(None, libhammer_dotnet, "make install -C " + targetdir) diff --git a/src/bindings/dotnet/ext/hammer.cs b/src/bindings/dotnet/ext/hammer.cs new file mode 100644 index 0000000000000000000000000000000000000000..97812179fb561ba024cfe8d20e78e2cdc03a5f53 --- /dev/null +++ b/src/bindings/dotnet/ext/hammer.cs @@ -0,0 +1,270 @@ +using Hammer.Internal; +using System; +namespace Hammer +{ + + public class Parser + { + internal HParser wrapped; + internal System.Collections.IList pins; // objects that need to stay in scope for this one + internal Parser(HParser parser) + { + wrapped = parser; + pins = new System.Collections.ArrayList(); + } + + internal Parser Pin(Object o) + { + pins.Add(o); + return this; + } + + public Object Parse(byte[] str) + { + unsafe { + fixed(byte* b = &str[0]) { + HParseResult res = hammer.h_parse(wrapped, (IntPtr)b, (uint)str.Length); + if (res != null) { + return Unmarshal(res.ast); + } else { + return null; + } + } + } + } + + internal Object Unmarshal(HParsedToken tok) + { + // TODO + return new Object(); + } + + } + + public class IndirectParser : Parser + { + internal IndirectParser(HParser parser) + : base(parser) + { + } + + public void Bind(Parser p) + { + hammer.h_bind_indirect(this.wrapped, p.wrapped); + } + } + + public class Hammer + { + internal static IntPtr[] BuildParserArray(Parser[] parsers) + { + IntPtr[] rlist = new IntPtr[parsers.Length+1]; + for (int i = 0; i < parsers.Length; i++) + { + rlist[i] = HParser.getCPtr(parsers[i].wrapped).Handle; + } + rlist[parsers.Length] = IntPtr.Zero; + return rlist; + } + public static Parser Sequence(params Parser[] parsers) + { + // TODO + IntPtr[] plist = BuildParserArray(parsers); + unsafe + { + fixed (IntPtr *pp = &plist[0]) + { + return new Parser(hammer.h_sequence__a((IntPtr)pp)).Pin(parsers); + } + } + } + + public static Parser Choice(params Parser[] parsers) + { + // TODO + IntPtr[] plist = BuildParserArray(parsers); + unsafe + { + fixed (IntPtr *pp = &plist[0]) + { + return new Parser(hammer.h_choice__a((IntPtr)pp)).Pin(parsers); + } + } + } + + public static IndirectParser Indirect() + { + return new IndirectParser(hammer.h_indirect()); + } + + public static Parser Ch(byte ch) + { + return new Parser(hammer.h_ch(ch)); + + } + public static Parser Ch(char ch) + { + return Ch((byte)ch); + } + + public static Parser Ch_range(byte c1, byte c2) + { + return 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)); + } + + public static Parser Int_range(Parser p, System.Int64 i1, System.Int64 i2) + { + return new Parser(hammer.h_int_range(p.wrapped, i1, i2)); + } + + public static Parser Token(byte[] token) + { + unsafe { + fixed(byte* b = &token[0]) + { + return new Parser(hammer.h_token((IntPtr)b, (uint)token.Length)); + } + } + } + + public static Parser In(byte[] charset) + { + unsafe { + fixed(byte* b = &charset[0]) + { + return new Parser(hammer.h_in((IntPtr)b, (uint)charset.Length)); + } + } + } + + public static Parser Not_in(byte[] charset) + { + unsafe { + fixed(byte* b = &charset[0]) + { + return new Parser(hammer.h_not_in((IntPtr)b, (uint)charset.Length)); + } + } + } + + public static Parser Token(string token) + { + // Encodes in UTF-8 + return Token(System.Text.Encoding.UTF8.GetBytes(token)); + } + + public static Parser In(string charset) + { + // Encodes in UTF-8 + return In(System.Text.Encoding.UTF8.GetBytes(charset)); + } + + public static Parser Not_in(string charset) + { + // Encodes in UTF-8 + return Not_in(System.Text.Encoding.UTF8.GetBytes(charset)); + } + + // No-arg parsers + public static Parser Int8() {return new Parser(hammer.h_int8());} + public static Parser Int16() {return new Parser(hammer.h_int16());} + public static Parser Int32() {return new Parser(hammer.h_int32());} + public static Parser Int64() {return new Parser(hammer.h_int64());} + public static Parser Uint8() {return new Parser(hammer.h_uint8());} + public static Parser Uint16() {return new Parser(hammer.h_uint16());} + public static Parser Uint32() {return new Parser(hammer.h_uint32());} + public static Parser Uint64() {return new Parser(hammer.h_uint64());} + + public static Parser End_p() {return new Parser(hammer.h_end_p());} + 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) + { + return new Parser(hammer.h_ignore(p.wrapped)); + } + + public static Parser Not(Parser p) + { + return new Parser(hammer.h_not(p.wrapped)); + } + + public static Parser Whitespace(Parser p) + { + return new Parser(hammer.h_whitespace(p.wrapped)); + } + + public static Parser Optional(Parser p) + { + return new Parser(hammer.h_optional(p.wrapped)); + } + + public static Parser And(Parser p) + { + return new Parser(hammer.h_and(p.wrapped)); + } + + public static Parser Many(Parser p) + { + return new Parser(hammer.h_many(p.wrapped)); + } + + public static Parser Many1(Parser p) + { + return new Parser(hammer.h_many1(p.wrapped)); + } + + public static Parser SepBy(Parser p, Parser sep) + { + return new Parser(hammer.h_sepBy(p.wrapped, sep.wrapped)); + } + + public static Parser SepBy1(Parser p, Parser sep) + { + return new Parser(hammer.h_sepBy1(p.wrapped, sep.wrapped)); + } + + // 2-arg parsers + + public static Parser Left(Parser p1, Parser p2) + { + return new Parser(hammer.h_left(p1.wrapped, p2.wrapped)); + } + public static Parser Right(Parser p1, Parser p2) + { + return new Parser(hammer.h_right(p1.wrapped, p2.wrapped)); + } + public static Parser Xor(Parser p1, Parser p2) + { + return new Parser(hammer.h_xor(p1.wrapped, p2.wrapped)); + } + public static Parser Difference(Parser p1, Parser p2) + { + return new Parser(hammer.h_difference(p1.wrapped, p2.wrapped)); + } + public static Parser Butnot(Parser p1, Parser p2) + { + return new Parser(hammer.h_butnot(p1.wrapped, p2.wrapped)); + } + + + // Multi-arg parsers + public static Parser Middle(Parser p1, Parser p2, Parser p3) + { + return new Parser(hammer.h_middle(p1.wrapped, p2.wrapped, p3.wrapped)); + } + public static Parser Repeat_n(Parser p, uint count) + { + return new Parser(hammer.h_repeat_n(p.wrapped, count)); + } + + } + +} \ No newline at end of file diff --git a/src/bindings/dotnet/hammer.i b/src/bindings/dotnet/hammer.i index a04a7cc2620fc202842f52a7a4ac15498148b778..7100bde234667d9f198cd1f6bdaa893385625143 100644 --- a/src/bindings/dotnet/hammer.i +++ b/src/bindings/dotnet/hammer.i @@ -9,9 +9,9 @@ // h_not_in //%typemap(cstype) uint8_t* "byte[]" -%typemap(imtype) uint8_t* "IntPtr" //%typemap(csin, pre="unsafe { fixed(byte* temp$csinput = &$csinput[0]) {", terminator="}}") uint8_t* "(IntPtr)temp$csinput" //%typemap(csvarin) uint8_t +%typemap(imtype) uint8_t* "IntPtr" %typemap(cstype) uint8_t* "IntPtr" %typemap(csin) uint8_t* "$csinput" %typemap(csvarout) uint8_t* %{ @@ -20,6 +20,10 @@ } %} +%typemap(imtype) void*[] "IntPtr" +%typemap(cstype) void*[] "IntPtr" +%typemap(csin) void*[] "$csinput" + %ignore h_bit_writer_get_buffer; %apply (char *STRING, size_t LENGTH) {(uint8_t* str, size_t len)}; %apply (uint8_t* str, size_t len) {(const uint8_t* input, size_t length)} diff --git a/src/bindings/dotnet/test/hammer_tests.cs b/src/bindings/dotnet/test/hammer_tests.cs new file mode 100644 index 0000000000000000000000000000000000000000..6ec1e1d72f06d2ec945fd7d497b54499b8114cee --- /dev/null +++ b/src/bindings/dotnet/test/hammer_tests.cs @@ -0,0 +1,326 @@ +namespace Hammer.Test { + using NUnit.Framework; + [TestFixture] + public partial class HammerTest { + [Test] + public void TestToken() { + Parser parser; + parser = Hammer.Token("95\xa2"); + CheckParseOK(parser, "95\xa2", new byte[]{ 0x39, 0x35, 0xa2}); + CheckParseFail(parser, "95\xa2"); + } + [Test] + public void TestCh() { + Parser parser; + parser = Hammer.Ch(0xa2); + CheckParseOK(parser, "\xa2", (System.Char)'\xa2'); + CheckParseFail(parser, "\xa3"); + } + [Test] + public void TestCh_range() { + Parser parser; + parser = Hammer.Ch_range(0x61, 0x63); + CheckParseOK(parser, "b", (System.Char)'b'); + CheckParseFail(parser, "d"); + } + [Test] + public void TestInt64() { + Parser parser; + parser = Hammer.Int64(); + CheckParseOK(parser, "\xff\xff\xff\xfe\x00\x00\x00\x00", (System.Int64)(-0x200000000)); + CheckParseFail(parser, "\xff\xff\xff\xfe\x00\x00\x00"); + } + [Test] + public void TestInt32() { + Parser parser; + parser = Hammer.Int32(); + CheckParseOK(parser, "\xff\xfe\x00\x00", (System.Int64)(-0x20000)); + CheckParseFail(parser, "\xff\xfe\x00"); + CheckParseOK(parser, "\x00\x02\x00\x00", (System.Int64)(0x20000)); + CheckParseFail(parser, "\x00\x02\x00"); + } + [Test] + public void TestInt16() { + Parser parser; + parser = Hammer.Int16(); + CheckParseOK(parser, "\xfe\x00", (System.Int64)(-0x200)); + CheckParseFail(parser, "\xfe"); + CheckParseOK(parser, "\x02\x00", (System.Int64)(0x200)); + CheckParseFail(parser, "\x02"); + } + [Test] + public void TestInt8() { + Parser parser; + parser = Hammer.Int8(); + CheckParseOK(parser, "\x88", (System.Int64)(-0x78)); + CheckParseFail(parser, ""); + } + [Test] + public void TestUint64() { + Parser parser; + parser = Hammer.Uint64(); + CheckParseOK(parser, "\x00\x00\x00\x02\x00\x00\x00\x00", (System.UInt64)0x200000000); + CheckParseFail(parser, "\x00\x00\x00\x02\x00\x00\x00"); + } + [Test] + public void TestUint32() { + Parser parser; + parser = Hammer.Uint32(); + CheckParseOK(parser, "\x00\x02\x00\x00", (System.UInt64)0x20000); + CheckParseFail(parser, "\x00\x02\x00"); + } + [Test] + public void TestUint16() { + Parser parser; + parser = Hammer.Uint16(); + CheckParseOK(parser, "\x02\x00", (System.UInt64)0x200); + CheckParseFail(parser, "\x02"); + } + [Test] + public void TestUint8() { + Parser parser; + parser = Hammer.Uint8(); + CheckParseOK(parser, "x", (System.UInt64)0x78); + CheckParseFail(parser, ""); + } + [Test] + public void TestInt_range() { + Parser parser; + parser = Hammer.Int_range(Hammer.Uint8(), 0x3, 0x10); + CheckParseOK(parser, "\x05", (System.UInt64)0x5); + CheckParseFail(parser, "\x0b"); + } + [Test] + public void TestWhitespace() { + Parser parser; + parser = Hammer.Whitespace(Hammer.Ch(0x61)); + CheckParseOK(parser, "a", (System.Char)'a'); + CheckParseOK(parser, " a", (System.Char)'a'); + CheckParseOK(parser, " a", (System.Char)'a'); + CheckParseOK(parser, "\x09a", (System.Char)'a'); + CheckParseFail(parser, "_a"); + parser = Hammer.Whitespace(Hammer.End_p()); + CheckParseOK(parser, "", null); + CheckParseOK(parser, " ", null); + CheckParseFail(parser, " x"); + } + [Test] + public void TestLeft() { + Parser parser; + parser = Hammer.Left(Hammer.Ch(0x61), Hammer.Ch(0x20)); + CheckParseOK(parser, "a ", (System.Char)'a'); + CheckParseFail(parser, "a"); + CheckParseFail(parser, " "); + CheckParseFail(parser, "ba"); + } + [Test] + public void TestMiddle() { + Parser parser; + parser = Hammer.Middle(Hammer.Ch(' '), Hammer.Ch('a'), Hammer.Ch(' ')); + CheckParseOK(parser, " a ", (System.Char)'a'); + CheckParseFail(parser, "a"); + CheckParseFail(parser, " a"); + CheckParseFail(parser, "a "); + CheckParseFail(parser, " b "); + CheckParseFail(parser, "ba "); + CheckParseFail(parser, " ab"); + } + [Test] + public void TestIn() { + Parser parser; + parser = Hammer.In("abc"); + CheckParseOK(parser, "b", (System.Char)'b'); + CheckParseFail(parser, "d"); + } + [Test] + public void TestNot_in() { + Parser parser; + parser = Hammer.Not_in("abc"); + CheckParseOK(parser, "d", (System.Char)'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.Char)'a'}); + CheckParseFail(parser, "aa"); + } + [Test] + public void TestNothing_p() { + Parser parser; + parser = Hammer.Nothing_p(); + CheckParseFail(parser, "a"); + } + [Test] + public void TestSequence() { + Parser parser; + parser = Hammer.Sequence(Hammer.Ch('a'), Hammer.Ch('b')); + CheckParseOK(parser, "ab", new object[]{ (System.Char)'a', (System.Char)'b'}); + CheckParseFail(parser, "a"); + CheckParseFail(parser, "b"); + parser = Hammer.Sequence(Hammer.Ch('a'), Hammer.Whitespace(Hammer.Ch('b'))); + CheckParseOK(parser, "ab", new object[]{ (System.Char)'a', (System.Char)'b'}); + CheckParseOK(parser, "a b", new object[]{ (System.Char)'a', (System.Char)'b'}); + CheckParseOK(parser, "a b", new object[]{ (System.Char)'a', (System.Char)'b'}); + } + [Test] + public void TestChoice() { + Parser parser; + parser = Hammer.Choice(Hammer.Ch('a'), Hammer.Ch('b')); + CheckParseOK(parser, "a", (System.Char)'a'); + CheckParseOK(parser, "b", (System.Char)'b'); + CheckParseOK(parser, "ab", (System.Char)'a'); + CheckParseFail(parser, "c"); + } + [Test] + public void TestButnot() { + Parser parser; + parser = Hammer.Butnot(Hammer.Ch('a'), Hammer.Token("ab")); + CheckParseOK(parser, "a", (System.Char)'a'); + CheckParseFail(parser, "ab"); + CheckParseOK(parser, "aa", (System.Char)'a'); + parser = Hammer.Butnot(Hammer.Ch_range('0', '9'), Hammer.Ch('6')); + CheckParseOK(parser, "5", (System.Char)'5'); + CheckParseFail(parser, "6"); + } + [Test] + public void TestDifference() { + Parser parser; + parser = Hammer.Difference(Hammer.Token("ab"), Hammer.Ch('a')); + CheckParseOK(parser, "ab", new byte[]{ 0x61, 0x62}); + CheckParseFail(parser, "a"); + } + [Test] + public void TestXor() { + Parser parser; + parser = Hammer.Xor(Hammer.Ch_range('0', '6'), Hammer.Ch_range('5', '9')); + CheckParseOK(parser, "0", (System.Char)'0'); + CheckParseOK(parser, "9", (System.Char)'9'); + CheckParseFail(parser, "5"); + CheckParseFail(parser, "a"); + } + [Test] + public void TestMany() { + Parser parser; + parser = Hammer.Many(Hammer.Choice(Hammer.Ch('a'), Hammer.Ch('b'))); + CheckParseOK(parser, "", new object[]{ }); + CheckParseOK(parser, "a", new object[]{ (System.Char)'a'}); + CheckParseOK(parser, "b", new object[]{ (System.Char)'b'}); + CheckParseOK(parser, "aabbaba", new object[]{ (System.Char)'a', (System.Char)'a', (System.Char)'b', (System.Char)'b', (System.Char)'a', (System.Char)'b', (System.Char)'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.Char)'a'}); + CheckParseOK(parser, "b", new object[]{ (System.Char)'b'}); + CheckParseOK(parser, "aabbaba", new object[]{ (System.Char)'a', (System.Char)'a', (System.Char)'b', (System.Char)'b', (System.Char)'a', (System.Char)'b', (System.Char)'a'}); + CheckParseFail(parser, "daabbabadef"); + } + [Test] + public void TestRepeat_n() { + Parser parser; + parser = Hammer.Repeat_n(Hammer.Choice(Hammer.Ch('a'), Hammer.Ch('b')), 0x2); + CheckParseFail(parser, "adef"); + CheckParseOK(parser, "abdef", new object[]{ (System.Char)'a', (System.Char)'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.Char)'a', (System.Char)'b', (System.Char)'d'}); + CheckParseOK(parser, "acd", new object[]{ (System.Char)'a', (System.Char)'c', (System.Char)'d'}); + CheckParseOK(parser, "ad", new object[]{ (System.Char)'a', null, (System.Char)'d'}); + CheckParseFail(parser, "aed"); + CheckParseFail(parser, "ab"); + CheckParseFail(parser, "ac"); + } + [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.Char)'a', (System.Char)'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.Char)'1', (System.Char)'2', (System.Char)'3'}); + CheckParseOK(parser, "1,3,2", new object[]{ (System.Char)'1', (System.Char)'3', (System.Char)'2'}); + CheckParseOK(parser, "1,3", new object[]{ (System.Char)'1', (System.Char)'3'}); + CheckParseOK(parser, "3", new object[]{ (System.Char)'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.Char)'1', (System.Char)'2', (System.Char)'3'}); + CheckParseOK(parser, "1,3,2", new object[]{ (System.Char)'1', (System.Char)'3', (System.Char)'2'}); + CheckParseOK(parser, "1,3", new object[]{ (System.Char)'1', (System.Char)'3'}); + CheckParseOK(parser, "3", new object[]{ (System.Char)'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.Char)'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.Char)'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.Char)'a', new byte[]{ 0x2b}, (System.Char)'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.Char)'a', new object[]{ new byte[]{ 0x2b}}, (System.Char)'b'}); + CheckParseOK(parser, "a++b", new object[]{ (System.Char)'a', new byte[]{ 0x2b, 0x2b}, (System.Char)'b'}); + } + [Test] + public void TestLeftrec() { + Parser parser; + IndirectParser sp_lr = Hammer.Indirect(); + sp_lr.Bind(Hammer.Choice(Hammer.Sequence(sp_lr, Hammer.Ch('a')), Hammer.Epsilon_p())); + parser = sp_lr; + CheckParseOK(parser, "a", new object[]{ (System.Char)'a'}); + CheckParseOK(parser, "aa", new object[]{ new object[]{ (System.Char)'a'}, (System.Char)'a'}); + CheckParseOK(parser, "aaa", new object[]{ new object[]{ new object[]{ (System.Char)'a'}, (System.Char)'a'}, (System.Char)'a'}); + } + [Test] + public void TestRightrec() { + Parser parser; + 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.Char)'a'}); + CheckParseOK(parser, "aa", new object[]{ (System.Char)'a', new object[]{ (System.Char)'a'}}); + CheckParseOK(parser, "aaa", new object[]{ (System.Char)'a', new object[]{ (System.Char)'a', new object[]{ (System.Char)'a'}}}); + } + [Test] + public void TestAmbiguous() { + Parser parser; + IndirectParser sp_d = Hammer.Indirect(); + IndirectParser sp_p = Hammer.Indirect(); + IndirectParser sp_e = Hammer.Indirect(); + sp_d.Bind(Hammer.Ch('d')); + 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.Char)'d'); + CheckParseOK(parser, "d+d", new object[]{ (System.Char)'d', (System.Char)'+', (System.Char)'d'}); + CheckParseOK(parser, "d+d+d", new object[]{ new object[]{ (System.Char)'d', (System.Char)'+', (System.Char)'d'}, (System.Char)'+', (System.Char)'d'}); + } + } +} diff --git a/src/bindings/dotnet/test/test_support.cs b/src/bindings/dotnet/test/test_support.cs new file mode 100644 index 0000000000000000000000000000000000000000..b525ca96157e52b3c8bd9d72034d564a3b9835e0 --- /dev/null +++ b/src/bindings/dotnet/test/test_support.cs @@ -0,0 +1,18 @@ +using System; +using Hammer; +namespace Hammer.Test +{ + using NUnit.Framework; + + public partial class HammerTest + { + protected void CheckParseOK(Parser p, string probe, Object expected) + { + + } + protected void CheckParseFail(Parser p, string probe) + { + + } + } +} \ No newline at end of file diff --git a/tools/csharp/mono.py b/tools/csharp/mono.py index 5bc203d83b6bbd83d61ab4a48e3a90c8a0da08ab..a2cc380e7ab8fe4b7aa5face89b51898927f56a5 100644 --- a/tools/csharp/mono.py +++ b/tools/csharp/mono.py @@ -45,7 +45,7 @@ def generate(env): env['BUILDERS']['CLIProgram'] = McsBuilder env['BUILDERS']['CLILibrary'] = McsLibBuilder - env['CSC'] = 'gmcs' + env['CSC'] = 'mcs' env['_CSCLIBS'] = "${_stripixes('-r:', CILLIBS, '', '-r', '', __env__)}" env['_CSCLIBPATH'] = "${_stripixes('-lib:', CILLIBPATH, '', '-r', '', __env__)}" env['CSCFLAGS'] = SCons.Util.CLVar('')