From ee751a97c16aca12ce79eb5e19190a0def6817c6 Mon Sep 17 00:00:00 2001
From: Dan Hirsch <thequux@upstandinghackers.com>
Date: Mon, 16 Dec 2013 16:00:34 +0100
Subject: [PATCH] Added CSharp code generator for test suite generator

---
 lib/tsgencsharp.pl | 211 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 211 insertions(+)
 create mode 100644 lib/tsgencsharp.pl

diff --git a/lib/tsgencsharp.pl b/lib/tsgencsharp.pl
new file mode 100644
index 00000000..1e263d69
--- /dev/null
+++ b/lib/tsgencsharp.pl
@@ -0,0 +1,211 @@
+% -*- prolog -*-
+% Run with:
+% $ swipl -q  -t halt -g tsgencsharp:prolog tsgencsharp.pl >output-file
+% Note: this needs to be run from the lib/ directory.
+
+% So,
+% swipl -q  -t halt -g tsgencsharp:prolog tsgencsharp.pl >../src/bindings/dotnet/test/hammer_tests.cs 
+
+
+:- module(tsgencsharp,
+          [gen_ts/2]).
+
+:- expects_dialect(swi).
+:- use_module(tsparser).
+
+% TODO: build a Box-like pretty-printer
+
+format_parser_name(Name, Result) :-
+    atom_codes(Name, [CInit|CName]),
+    code_type(RInit, to_upper(CInit)),
+    append("Hammer.", [RInit|CName], Result), !.
+
+format_test_name(Name, Result) :-
+    atom_codes(Name, [CInit|CName]),
+    code_type(RInit, to_upper(CInit)),
+    append("Test", [RInit|CName], Result), !.
+
+indent(0) --> "", !.
+indent(N) -->
+    {N > 0},
+    "    ",
+    {Np is N - 1},
+    indent(Np).
+
+pp_char_guts(0x22) -->
+    "\\\"", !.
+pp_char_guts(0x27) -->
+    "\\'", !.
+pp_char_guts(A) -->
+    { A >= 0x20, A < 0x7F } ->
+    [A];
+    "\\x",
+    { H is A >> 4, L is A /\ 0xF,
+      code_type(Hc, xdigit(H)),
+      code_type(Lc, xdigit(L)) },
+    [Hc,Lc].
+
+pp_hexnum_guts(0) --> !.
+pp_hexnum_guts(A) -->
+    { L is A /\ 0xF,
+      H is A >> 4,
+      code_type(Lc, xdigit(L)) },
+    pp_hexnum_guts(H),
+    [Lc], !.
+pp_string_guts([]) --> !.
+pp_string_guts([X|Xs]) -->
+    pp_char_guts(X),
+    pp_string_guts(Xs), !.
+
+pp_parser_args([]) --> !.
+pp_parser_args([X|Rest]) -->
+    pp_parser(X),
+    pp_parser_args_rest(Rest).
+pp_parser_args_rest([]) --> !.
+pp_parser_args_rest([X|Xs]) -->
+    ", ",
+    pp_parser(X),
+    pp_parser_args_rest(Xs).
+
+pp_parser(parser(Name, Args)) -->
+    !,
+    {format_parser_name(Name,Fname)},
+    Fname,
+    "(",
+    pp_parser_args(Args),
+    ")".
+pp_parser(string(Str)) --> !,
+    "\"",
+    pp_string_guts(Str),
+    "\"", !.
+pp_parser(num(0)) --> "0", !.
+pp_parser(num(Num)) --> !,
+    ( {Num < 0} ->
+      "-0x", {RNum is -Num}; "0x", {RNum = Num} ),
+    pp_hexnum_guts(RNum).
+pp_parser(char(C)) --> !,
+    "'", pp_char_guts(C), "'", !.
+
+pp_parser(ref(Name)) -->
+    {atom_codes(Name,CName)},
+    "sp_", CName, !.
+
+
+pp_parser(A) -->
+    { writef("WTF is a %w?\n", [A]),
+      !, fail
+    }.
+
+pp_test_elem(decl, parser(_)) --> !.
+pp_test_elem(init, parser(_)) --> !.
+pp_test_elem(exec, parser(P)) -->
+    !, indent(3),
+    "parser = ",
+    pp_parser(P),
+    ";\n".
+pp_test_elem(decl, subparser(Name,_)) -->
+    !, indent(3),
+    "Hammer.Parser ", pp_parser(ref(Name)),
+    " = Hammer.Indirect();\n".
+pp_test_elem(init, subparser(Name, Parser)) -->
+    !, indent(3),
+    pp_parser(ref(Name)), ".Bind(",
+    pp_parser(Parser),
+    ");\n".
+pp_test_elem(exec, subparser(_,_)) --> !.
+pp_test_elem(decl, test(_,_)) --> !.
+pp_test_elem(init, test(_,_)) --> !.
+pp_test_elem(decl, testFail(_)) --> !.
+pp_test_elem(init, testFail(_)) --> !.
+pp_test_elem(exec, test(Str, Result)) -->
+    !, indent(3),
+    "  CheckParseOK(parser, ", pp_parser(string(Str)),
+    ", ",
+    pp_parse_result(Result),
+    ");\n".
+pp_test_elem(exec, testFail(Str)) -->
+    !, indent(3),
+    "  CheckParseFail(parser, ", pp_parser(string(Str)),
+    ");\n".
+
+% pp_test_elem(_, _) --> !.
+
+pp_result_seq([]) --> !.
+pp_result_seq([X|Xs]) --> !,
+    pp_parse_result(X),
+    pp_result_seq_r(Xs).
+pp_result_seq_r([]) --> !.
+pp_result_seq_r([X|Xs]) --> !,
+    ", ",
+    pp_parse_result(X),
+    pp_result_seq_r(Xs).
+
+pp_byte_seq([]) --> !.
+pp_byte_seq([X|Xs]) --> !,
+    pp_parser(num(X)),
+    pp_byte_seq_r(Xs).
+pp_byte_seq_r([]) --> !.
+pp_byte_seq_r([X|Xs]) --> !,
+    ", ",
+    pp_parser(num(X)),
+    pp_byte_seq_r(Xs).
+
+pp_parse_result(char(C)) --> !,
+    "(System.Char)",
+    pp_parser(char(C)).
+pp_parse_result(seq(Args)) --> !,
+    "new object[]{ ", pp_result_seq(Args), "}".
+pp_parse_result(none) --> !,
+    "null".
+pp_parse_result(uint(V)) --> !,
+    "(System.UInt64)", pp_parser(num(V)).
+pp_parse_result(sint(V)) --> !,
+    "(System.Int64)", pp_parser(num(V)).
+pp_parse_result(string(A)) --> !,
+    "new byte[]{ ", pp_byte_seq(A), "}".
+%pp_parse_result(A) -->
+%    "\x1b[1;31m",
+%    {with_output_to(codes(C), write(A))},
+%    C,
+%    "\x1b[0m".
+
+
+pp_test_elems(_, []) --> !.
+pp_test_elems(Phase, [X|Xs]) -->
+    !,
+    pp_test_elem(Phase,X),
+    pp_test_elems(Phase,Xs).
+
+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",
+    pp_test_elems(decl, Elems),
+    pp_test_elems(init, Elems),
+    pp_test_elems(exec, Elems),
+    indent(2), "}\n".
+
+
+pp_test_cases([]) --> !.
+pp_test_cases([A|As]) -->
+    pp_test_case(A),
+    pp_test_cases(As).
+
+pp_test_suite(Suite) -->
+    "namespace Hammer.Test {\n",
+    indent(1), "using NUnit.Framework;\n",
+    indent(1), "[TestFixture]\n",
+    indent(1), "public partial class HammerTest {\n",
+    pp_test_cases(Suite),
+    indent(1), "}\n",
+    "}\n".
+
+gen_ts(Foo,Str) :-
+    phrase(pp_test_suite(Foo),Str).
+
+prolog :-
+    read_tc(A),
+    gen_ts(A, Res),
+    writef("%s", [Res]).
-- 
GitLab