1:- module('java_transpiler', [parse/5]).    2:- use_module(library(chr)).    3:- chr_constraint var_type/3.
    4:- chr_constraint unique_var/1.
    5
    6var_type(Namespace,Var,Type) \ var_type(Namespace,Var,Type) <=> true.
    7unique_var(A) \ unique_var(A) <=> true.
    8var_type(Namespace,Var,Type1),var_type(Namespace,Var,Type2) ==> Type1=Type2.
    9
   10unique_var(V) ==>
   11	gensym('v',V1),writeln(V1),atom_chars(V1,V).
   12
   13unique_var(V),var_type(_,V,_) ==> false.
   14
   15:- set_prolog_flag(double_quotes,chars).   16
   17% This is a program that translates several programming languages into several other languages.
   18
   19% Edit this list to specify the languages that should be translated. Each language should be written in lowercase:
   20
   21namespace(Data,Data1,Name1,Indent) :-
   22	Data = [Lang,Is_input,Namespace,Indent],
   23	Data1 = [Lang,Is_input,[Name1|Namespace],indent(Indent)].
   24
   25namespace(Data,Data1,Name,Indent) -->
   26	    {
   27                namespace(Data,Data1,Name,Indent)
   28        },
   29		optional_indent(Data,Indent).
   30
   31offside_rule_langs(['python','cython','coffeescript','english','cosmos','cobra']).
   32
   33prefix_arithmetic_langs(['racket','z3','clips','gnu smalltalk','newlisp','hy','common lisp','emacs lisp','clojure','sibilant','lispyscript']).
   34infix_arithmetic_langs(['pascal','sympy','vhdl','elixir','python','visual basic .net','ruby','lua','scriptol', 'z3py','ats','pydatalog','e','vbscript','livecode','monkey x','perl 6','englishscript','cython','gap','mathematical notation','wolfram','chapel','katahdin','frink','minizinc','picat','java','eclipse','d','ooc','genie','janus','pl/i','idp','processing','maxima','seed7','self','gnu smalltalk','drools','standard ml','oz','cobra','pike','prolog','engscript','kotlin','pawn','freebasic','matlab','ada','freebasic','gosu','gambas','nim','autoit','algol 68','ceylon','groovy','rust','coffeescript','typescript','fortran','octave','ml','hack','autohotkey','scala','delphi','tcl','swift','vala','c','f#','c++','dart','javascript','rebol','julia','erlang','ocaml','c#','nemerle','awk','java','perl','haxe','php','haskell','go','r','bc','visual basic']).
   35
   36
   37%Use this rule to define operators for various languages
   38
   39infix_operator(Symbol,Exp1,Exp2) -->
   40        Exp1,python_ws,Symbol,python_ws,Exp2.
   41
   42prefix_operator(Data,Type,Symbol,Exp1,Exp2) -->
   43        "(",Symbol,ws_,expr(Data,Type,Exp1),ws_,expr(Data,Type,Exp2),")".
   44
   45
   46% this is from http://stackoverflow.com/questions/20297765/converting-1st-letter-of-atom-in-prolog
   47first_char_uppercase(WordLC, WordUC) :-
   48    atom_chars(WordLC, [FirstChLow|LWordLC]),
   49    atom_chars(FirstLow, [FirstChLow]),
   50    upcase_atom(FirstLow, FirstUpp),
   51    atom_chars(FirstUpp, [FirstChUpp]),
   52    atom_chars(WordUC, [FirstChUpp|LWordLC]).
   53
   54function_name(Data,Type,A,Params) -->
   55        symbol(A),{reserved_words(A),is_var_type_(Data,[A,Params], Type)}.
   56
   57
   58indent(Indent) --> (Indent,("\t")).
   59
   60
   61else(Data,Return_type,Statements_) -->
   62        {
   63                indent_data(Indent,Data,Data1),
   64                A = statements(Data1,Return_type,Statements_)
   65        },
   66        else(Data,[Indent,A]),!.
   67
   68
   69first_case(Data,Return_type,Switch_expr,int,[Expr_,Statements_,Case_or_default_]) -->
   70    {
   71            indent_data(Indent,Data,Data1),
   72            B=statements(Data1,Return_type,Statements_),
   73            Compare_expr = expr(Data,bool,compare(int,Switch_expr,Expr_)),
   74            Expr = expr(Data,int,Expr_),
   75
   76            Case_or_default = (case(Data,Return_type,Switch_expr,int,Case_or_default_);default(Data,Return_type,int,Case_or_default_))
   77    },
   78    optional_indent(Data,Indent),
   79    first_case_(Data,[B,Compare_expr,Expr,Case_or_default]),!.
   80
   81case(Data,Return_type,Switch_expr,int,[Expr_,Statements_,Case_or_default_]) -->
   82        {
   83                indent_data(Indent,Data,Data1),
   84                B=statements(Data1,Return_type,Statements_),
   85                A = expr(Data,bool,compare(int,Switch_expr,Expr_)),
   86                Expr = expr(Data,int,Expr_),
   87                Case_or_default = (case(Data,Return_type,Switch_expr,int,Case_or_default_);default(Data,Return_type,int,Case_or_default_))
   88        },
   89    optional_indent(Data,Indent),
   90    case(Data,[A,B,Expr,Case_or_default,Indent]),!.
   91
   92default(Data,Return_type,int,Statements_) -->
   93        {
   94                indent_data(Indent,Data,Data1),
   95                A = statements(Data1,Return_type,Statements_)
   96        },
   97        optional_indent(Data,Indent),
   98        default(Data,[A,Indent]),!.
   99
  100
  101
  102indent(Data,Indent) :-
  103	Data = [_,_,_,Indent].
  104
  105lang(Data,Lang) :-
  106	Data = [Lang|_].
  107
  108elif_statements(Data,Return_type,[A]) --> elif(Data,Return_type,A),!.
  109elif_statements(Data,Return_type,[A|B]) --> elif(Data,Return_type,A),elif_separator(Data),elif_statements(Data,Return_type,B),!.
  110
  111elif_separator(Data) -->
  112	{lang(Data,Lang),indent(Data,Indent)},
  113	({memberchk(Lang,['python','cython'])} -> Indent; {memberchk(Lang,['prolog','erlang','logtalk'])} -> ws,";",(Indent;ws);ws(Data),statement_separator(Data),(Indent;ws(Data))).
  114
  115indent_data(Indent,Data,Data1) :-
  116    Data = [Lang,Is_input,Namespace,Indent],
  117    (
  118    Data1 = [Lang,Is_input,Namespace,indent(Indent)]).
  119
  120elif(Data,Return_type,[Expr_,Statements_]) -->
  121        {
  122                indent_data(Indent,Data,Data1),
  123                B=statements(Data1,Return_type,Statements_),
  124                A=expr(Data,bool,Expr_)
  125        },
  126        elif(Data,[Indent,A,B]),!.
  127
  128
  129is_var_type([_,_,Namespace|_], Name, Type) :-
  130    var_type(Namespace,Name,Type).
  131
  132%This is only for checking types of functions in global scope
  133is_var_type_(_, [Name,Params], Type) :-
  134    var_type([],[Name,Params],Type).
  135
  136%also called optional parameters
  137default_parameter(Data,[Type1,Name1,Default1]) -->
  138        {
  139                Type = type(Data,Type1),
  140                Name = var_name_(Data,Type1,Name1),
  141                Value = var_name_(Data,Type1,Default1)
  142        },
  143        default_parameter_(Data,[Type,Name,Value]).
  144
  145parameter(Data,[Type1,Name1]) -->
  146        {
  147                Type = type(Data,Type1),
  148                Name = var_name_(Data,Type1,Name1)
  149        },
  150		parameter_(Data,[Type,Name]).
  151
  152
  153varargs(Data,[Type1,Name1]) -->
  154        {
  155                Type = type(Data,Type1),
  156                Name = var_name_(Data,Type1,Name1)
  157        },
  158		varargs_(Data,[Type,Name]).
  159
  160
  161
  162%these parameters are used in a function's definition
  163optional_parameters(Data,A) --> "",parameters(Data,A).
  164
  165parameter1(Data,parameter(A)) -->
  166	parameter(Data,A).
  167parameter1(Data,default_parameter(A)) -->
  168	default_parameter(Data,A).
  169parameter1(Data,varargs(A)) -->
  170	varargs(Data,A).
  171
  172parameters(Data,Params) --> 
  173	{Params = []}, "";parameters_(Data,Params).
  174parameters_(Data,[A]) -->
  175	parameter1(Data,A).
  176parameters_(Data,[A|B]) -->
  177	parameter1(Data,A),python_ws,parameter_separator(Data),python_ws,parameters_(Data,B).
  178
  179function_call_parameters(Data,[Params1_],[[Params2_,_]]) -->
  180        parentheses_expr(Data,Params2_,Params1_).
  181function_call_parameters(Data,[Params1_|Params1__],[[Params2_,_]|Params2__]) -->
  182        (parentheses_expr(Data,Params2_,Params1_),function_call_parameter_separator(Data),function_call_parameters(Data,Params1__,Params2__)).
  183
  184function_call_parameter_separator([Lang|_]) -->
  185    parameter_separator([Lang|_]).
  186
  187top_level_statement_separator(Data) -->
  188	{Data = [Lang|_], memberchk(Lang,['picat','prolog','logtalk','erlang','constraint handling rules'])} -> ws;
  189	statement_separator(Data).
  190
  191key_value(Data,Type,[Key_,Val_]) -->
  192        {
  193                A = symbol(Key_),
  194                B = expr(Data,Type,Val_)
  195        },
  196        key_value_(Data,[A,B]).
  197
  198ws(Data) -->
  199	{Data = [Lang|_]},
  200	({Lang='python'} ->
  201	python_ws;
  202	ws).
  203ws_(Data) -->
  204	{Data = [Lang|_]},
  205	({Lang='python'} ->
  206	python_ws_;ws_).
  207
  208top_level_statement(Data,Type,A_) -->
  209    {A = statement(Data,Type,A_)},
  210    top_level_statement_(Data,A).
  211
  212statements(Data,Return_type,[A]) --> statement(Data,Return_type,A).
  213statements(Data,Return_type,[A|B]) --> statement(Data,Return_type,A),statement_separator(Data),statements(Data,Return_type,B).
  214
  215
  216vars_list(Data,Type,[A]) --> var_name_(Data,Type,A).
  217vars_list(Data,Type,[A|B]) --> var_name_(Data,Type,A),",",vars_list(Data,Type,B).
  218
  219initialize_vars_list(Data,Type,[A]) --> {A = [A1,A2],A1_=var_name_(Data,Type,A1),A2_=parentheses_expr(Data,Type,A2)},set_var_(Data,[A1_,Type,A2_]).
  220initialize_vars_list(Data,Type,[A|B]) --> {A = [A1,A2],A1_=var_name_(Data,Type,A1),A2_=parentheses_expr(Data,Type,A2)},set_var_(Data,[A1_,Type,A2_]),",",initialize_vars_list(Data,Type,B).
  221
  222ws_separated_statements(Data,[A]) --> top_level_statement(Data,_,A).
  223ws_separated_statements(Data,[A|B]) --> top_level_statement(Data,_,A),top_level_statement_separator(Data),ws_separated_statements(Data,B).
  224
  225class_statements(Data,Class_name,[A]) --> class_statement(Data,Class_name,A).
  226class_statements(Data,Class_name,[A|B]) --> class_statement(Data,Class_name,A),statement_separator(Data),class_statements(Data,Class_name,B).
  227
  228dict_(Data,Type,[A]) --> key_value(Data,Type,A).
  229dict_(Data,Type,[A|B]) --> key_value(Data,Type,A),key_value_separator(Data),dict_(Data,Type,B).
  230
  231initializer_list_(Data,Type,[A]) --> expr(Data,Type,A).
  232initializer_list_(Data,Type,[A|B]) --> expr(Data,Type,A),initializer_list_separator(Data),initializer_list_(Data,Type,B).
  233
  234enum_list(Data,[A]) --> enum_list_(Data,A).
  235enum_list(Data,[A|B]) --> enum_list_(Data,A),enum_list_separator(Data),enum_list(Data,B).
  236
  237enum_list_(Data,A_) -->
  238			{
  239					A = symbol(A_)
  240			},
  241			enum_list_(Data,[A]).
  242
  243
  244
  245
  246
  247between_(A,B,C) :- char_code(A,A1),char_code(B,B1),nonvar(C),char_code(C,C1),between(A1,B1,C1).
  248
  249
  250char_literal(A) --> "\'",{dif(A,"\'"),dif(A,"\n")},[A],"\'".
  251
  252:-include(common_grammar).  253
  254regex_literal(Data,S_) -->
  255    {S = regex_inner(S_)},
  256    regex_literal_(Data,[S]).
  257
  258comment_inner([A]) --> comment_inner_(A).
  259comment_inner([A|B]) --> comment_inner_(A),comment_inner(B).
  260comment_inner_(A) --> {dif(A,'\n')},[A].
  261regex_inner([A]) --> regex_inner_(A).
  262regex_inner([A|B]) --> regex_inner_(A),regex_inner(B).
  263regex_inner_(A) --> {A="\\\"";A="\\\'"},A;{dif(A,'"'),dif(A,'\n')},[A].
  264
  265statements_with_ws(Data,A) -->
  266    (include_in_each_file(Data);""),ws_separated_statements(Data,A),ws.
  267
  268
  269print_var_types([A]) :-
  270    writeln(A).
  271print_var_types([A|Rest]) :-
  272    writeln(A),print_var_types(Rest).
  273
  274parse(Lang1,Lang2,Is_input,Input,Ls) :-
  275	phrase(statements_with_ws([Lang1,Is_input,[],"\n"],Ls), Input).
  276
  277:- include(grammars).  278:- include(statement).  279:- include(statement_with_semicolon).  280:- include(class_statement).  281:- include(expr).  282:- include(dot_expr).  283:- include(parentheses_expr).