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