1:- module('transpiler', [translate/2,translate/3,translate/4,translate_langs/1]).    2:- use_module(library(chr)).    3:- set_prolog_flag('double_quotes','chars').    4:- multifile parse/5.    5:- use_module(optimized_java_parser/java_transpiler).    6:- use_module(optimized_javascript_parser/javascript_transpiler).    7:- use_module(optimized_python_parser/python_transpiler).    8:- chr_constraint var_type/3.
    9:- chr_constraint unique_var/1.
   10
   11:- initialization(main).   12
   13main :- 
   14	translate("function add(a,b){return a + b;}",javascript,lua,X),
   15	atom_chars(Y,X),
   16	writeln(Y).
   17
   18var_type(Namespace,Var,Type) \ var_type(Namespace,Var,Type) <=> true.
   19unique_var(A) \ unique_var(A) <=> true.
   20var_type(Namespace,Var,Type1),var_type(Namespace,Var,Type2) ==> Type1=Type2.
   21
   22unique_var(V) ==>
   23	gensym('v',V1),writeln(V1),atom_chars(V1,V).
   24
   25unique_var(V),var_type(_,V,_) ==> false.
   26
   27:- set_prolog_flag(double_quotes,chars).   28
   29% This is a program that translates several programming languages into several other languages.
   30
   31% Edit this list to specify the languages that should be translated. Each language should be written in lowercase:
   32list_of_langs(X) :-
   33	%X = ['javascript','c#','ruby','c','c++','go','php','swift','octave','lua','pydatalog','prolog','constraint handling rules','perl','haxe'].
   34	%X = ['lua','ruby','javascript','php','c#','java','c#','haxe','lua','python','constraint handling rules','prolog','perl'].
   35	%X=['python','javascript','php','java','constraint handling rules','prolog','scriptol','systemverilog','vhdl','verilog','erlang','prolog','sympy'].
   36	%X=['definite clause grammars','nearley','lpeg','peg.js','parslet','marpa','antlr','waxeye','parboiled','ometa','wirth syntax notation'].
   37	%X=['english','c#','ruby','lua','perl','prolog','haxe','java','perl','c++','php','erlang','c','javascript','coffeescript','haskell','english'].
   38	X=['python'].
   39
   40translate((Input,Lang2),Output) :-
   41	translate(Input,Lang2,Output).
   42translate((Input,Lang1,Lang2),Output) :-
   43	translate(Input,Lang1,Lang2,Output).
   44	
   45translate(Input_,Lang2,Output) :-
   46	atom_chars(Input_,Input), list_of_langs(X),member(Lang1,X),translate(Input,Lang1,Lang2,Output_), atom_chars(Output,Output_).
   47translate(Input,Lang1,Lang2,Output) :-
   48	parse(Lang1,Lang2,true,Input,Ls),
   49	parse(Lang2,Lang1,false,Output,Ls).
   50
   51namespace(Data,Data1,Name1,Indent) :-
   52	Data = [Lang,Is_input,Namespace,Indent],
   53	Data1 = [Lang,Is_input,[Name1|Namespace],indent(Indent)].
   54
   55namespace(Data,Data1,Name,Indent) -->
   56	    {
   57                namespace(Data,Data1,Name,Indent)
   58        },
   59		optional_indent(Data,Indent).
   60
   61offside_rule_langs(['python','cython','coffeescript','english','cosmos','cobra']).
   62
   63prefix_arithmetic_langs(['racket','z3','clips','gnu smalltalk','newlisp','hy','common lisp','emacs lisp','clojure','sibilant','lispyscript']).
   64infix_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']).
   65
   66
   67%Use this rule to define operators for various languages
   68
   69file_extension(java) --> "java".
   70file_extension(c) --> "c".
   71file_extension('c++') --> "cpp".
   72
   73infix_operator(Symbol,Exp1,Exp2) -->
   74        Exp1,python_ws,Symbol,python_ws,Exp2.
   75
   76prefix_operator(Data,Type,Symbol,Exp1,Exp2) -->
   77        "(",Symbol,ws_,expr(Data,Type,Exp1),ws_,expr(Data,Type,Exp2),")".
   78
   79
   80% this is from http://stackoverflow.com/questions/20297765/converting-1st-letter-of-atom-in-prolog
   81first_char_uppercase(WordLC, WordUC) :-
   82    atom_chars(WordLC, [FirstChLow|LWordLC]),
   83    atom_chars(FirstLow, [FirstChLow]),
   84    upcase_atom(FirstLow, FirstUpp),
   85    atom_chars(FirstUpp, [FirstChUpp]),
   86    atom_chars(WordUC, [FirstChUpp|LWordLC]).
   87
   88function_name(Data,Type,A,Params) -->
   89        symbol(A),{reserved_words(A),is_var_type_(Data,[A,Params], Type)}.
   90
   91
   92indent(Indent) --> (Indent,("\t")).
   93
   94
   95else(Data,Return_type,Statements_) -->
   96        {
   97                indent_data(Indent,Data,Data1),
   98                A = statements(Data1,Return_type,Statements_)
   99        },
  100        else(Data,[Indent,A]),!.
  101
  102
  103first_case(Data,Return_type,Switch_expr,int,[Expr_,Statements_,Case_or_default_]) -->
  104    {
  105            indent_data(Indent,Data,Data1),
  106            B=statements(Data1,Return_type,Statements_),
  107            Compare_expr = expr(Data,bool,compare(int,Switch_expr,Expr_)),
  108            Expr = expr(Data,int,Expr_),
  109
  110            Case_or_default = (case(Data,Return_type,Switch_expr,int,Case_or_default_);default(Data,Return_type,int,Case_or_default_))
  111    },
  112    optional_indent(Data,Indent),
  113    first_case_(Data,[B,Compare_expr,Expr,Case_or_default]),!.
  114
  115case(Data,Return_type,Switch_expr,int,[Expr_,Statements_,Case_or_default_]) -->
  116        {
  117                indent_data(Indent,Data,Data1),
  118                B=statements(Data1,Return_type,Statements_),
  119                A = expr(Data,bool,compare(int,Switch_expr,Expr_)),
  120                Expr = expr(Data,int,Expr_),
  121                Case_or_default = (case(Data,Return_type,Switch_expr,int,Case_or_default_);default(Data,Return_type,int,Case_or_default_))
  122        },
  123    optional_indent(Data,Indent),
  124    case(Data,[A,B,Expr,Case_or_default,Indent]),!.
  125
  126default(Data,Return_type,int,Statements_) -->
  127        {
  128                indent_data(Indent,Data,Data1),
  129                A = statements(Data1,Return_type,Statements_)
  130        },
  131        optional_indent(Data,Indent),
  132        default(Data,[A,Indent]),!.
  133
  134
  135
  136indent(Data,Indent) :-
  137	Data = [_,_,_,Indent].
  138
  139lang(Data,Lang) :-
  140	Data = [Lang|_].
  141
  142elif_statements(Data,Return_type,[A]) --> elif(Data,Return_type,A),!.
  143elif_statements(Data,Return_type,[A|B]) --> elif(Data,Return_type,A),elif_separator(Data),elif_statements(Data,Return_type,B),!.
  144
  145elif_separator(Data) -->
  146	{lang(Data,Lang),indent(Data,Indent)},
  147	({memberchk(Lang,['python','cython'])} -> Indent; {memberchk(Lang,['prolog','erlang','logtalk'])} -> ws,";",(Indent;ws);ws(Data),statement_separator(Data),(Indent;ws(Data))).
  148
  149indent_data(Indent,Data,Data1) :-
  150    Data = [Lang,Is_input,Namespace,Indent],
  151    (
  152    Data1 = [Lang,Is_input,Namespace,indent(Indent)]).
  153
  154elif(Data,Return_type,[Expr_,Statements_]) -->
  155        {
  156                indent_data(Indent,Data,Data1),
  157                B=statements(Data1,Return_type,Statements_),
  158                A=expr(Data,bool,Expr_)
  159        },
  160        elif(Data,[Indent,A,B]),!.
  161
  162
  163is_var_type([_,_,Namespace|_], Name, Type) :-
  164    var_type(Namespace,Name,Type).
  165
  166%This is only for checking types of functions in global scope
  167is_var_type_(_, [Name,Params], Type) :-
  168    var_type([],[Name,Params],Type).
  169
  170%also called optional parameters
  171default_parameter(Data,[Type1,Name1,Default1]) -->
  172        {
  173                Type = type(Data,Type1),
  174                Name = var_name_(Data,Type1,Name1),
  175                Value = var_name_(Data,Type1,Default1)
  176        },
  177        default_parameter_(Data,[Type,Name,Value]).
  178
  179parameter(Data,[Type1,Name1]) -->
  180        {
  181                Type = type(Data,Type1),
  182                Name = var_name_(Data,Type1,Name1)
  183        },
  184		parameter_(Data,[Type,Name]),!.
  185
  186reference_parameter(Data,[Type1,Name1]) -->
  187        {
  188                Type = type(Data,Type1),
  189                Name = var_name_(Data,Type1,Name1)
  190        },
  191		reference_parameter_(Data,[Type,Name]),!.
  192
  193varargs(Data,[Type1,Name1]) -->
  194        {
  195                Type = type(Data,Type1),
  196                Name = var_name_(Data,Type1,Name1)
  197        },
  198		varargs_(Data,[Type,Name]),!.
  199
  200
  201
  202%these parameters are used in a function's definition
  203optional_parameters(Data,A) --> "",parameters(Data,A).
  204
  205parameter1(Data,parameter(A)) -->
  206	parameter(Data,A).
  207parameter1(Data,reference_parameter(A)) -->
  208	reference_parameter(Data,A).
  209parameter1(Data,default_parameter(A)) -->
  210	default_parameter(Data,A).
  211parameter1(Data,varargs(A)) -->
  212	varargs(Data,A).
  213
  214parameters(Data,Params) --> 
  215	{Params = []}, "";parameters_(Data,Params).
  216parameters_(Data,[A]) -->
  217	parameter1(Data,A).
  218parameters_(Data,[A|B]) -->
  219	parameter1(Data,A),python_ws,parameter_separator(Data),python_ws,parameters_(Data,B).
  220
  221function_call_parameters(Data,[Params1_],[[Params2_,_]]) -->
  222        parentheses_expr(Data,Params2_,Params1_).
  223function_call_parameters(Data,[Params1_|Params1__],[[Params2_,_]|Params2__]) -->
  224        (parentheses_expr(Data,Params2_,Params1_),function_call_parameter_separator(Data),function_call_parameters(Data,Params1__,Params2__)).
  225
  226function_call_parameter_separator([Lang|_]) -->
  227    parameter_separator([Lang|_]).
  228
  229top_level_statement_separator(Data) -->
  230	{Data = [Lang|_], memberchk(Lang,['picat','prolog','logtalk','erlang','constraint handling rules'])} -> ws;
  231	statement_separator(Data).
  232
  233key_value(Data,Type,[Key_,Val_]) -->
  234        {
  235                A = symbol(Key_),
  236                B = expr(Data,Type,Val_)
  237        },
  238        key_value_(Data,[A,B]).
  239
  240ws(Data) -->
  241	{Data = [Lang|_]},
  242	({Lang='python'} ->
  243	python_ws;
  244	ws).
  245ws_(Data) -->
  246	{Data = [Lang|_]},
  247	({Lang='python'} ->
  248	python_ws_;ws_).
  249
  250top_level_statement(Data,Type,A_) -->
  251    {A = statement(Data,Type,A_)},
  252    top_level_statement_(Data,A).
  253
  254statements(Data,Return_type,[A]) --> statement(Data,Return_type,A).
  255statements(Data,Return_type,[A|B]) --> statement(Data,Return_type,A),statement_separator(Data),statements(Data,Return_type,B).
  256
  257
  258vars_list(Data,Type,[A]) --> var_name_(Data,Type,A).
  259vars_list(Data,Type,[A|B]) --> var_name_(Data,Type,A),",",vars_list(Data,Type,B).
  260
  261initialize_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_]).
  262initialize_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).
  263
  264ws_separated_statements(Data,[A]) --> top_level_statement(Data,_,A).
  265ws_separated_statements(Data,[A|B]) --> top_level_statement(Data,_,A),top_level_statement_separator(Data),ws_separated_statements(Data,B).
  266
  267class_statements(Data,Class_name,[A]) --> class_statement(Data,Class_name,A).
  268class_statements(Data,Class_name,[A|B]) --> class_statement(Data,Class_name,A),statement_separator(Data),class_statements(Data,Class_name,B).
  269
  270dict_(Data,Type,[A]) --> key_value(Data,Type,A).
  271dict_(Data,Type,[A|B]) --> key_value(Data,Type,A),key_value_separator(Data),dict_(Data,Type,B).
  272
  273initializer_list_(Data,Type,[A]) --> expr(Data,Type,A).
  274initializer_list_(Data,Type,[A|B]) --> expr(Data,Type,A),initializer_list_separator(Data),initializer_list_(Data,Type,B).
  275
  276enum_list(Data,[A]) --> enum_list_(Data,A).
  277enum_list(Data,[A|B]) --> enum_list_(Data,A),enum_list_separator(Data),enum_list(Data,B).
  278
  279enum_list_(Data,A_) -->
  280			{
  281					A = symbol(A_)
  282			},
  283			enum_list_(Data,[A]).
  284
  285
  286
  287
  288
  289between_(A,B,C) :- char_code(A,A1),char_code(B,B1),nonvar(C),char_code(C,C1),between(A1,B1,C1).
  290
  291
  292char_literal(A) --> "\'",{dif(A,"\'"),dif(A,"\n")},[A],"\'".
  293
  294:-include(common_grammar).  295
  296regex_literal(Data,S_) -->
  297    {S = regex_inner(S_)},
  298    regex_literal_(Data,[S]).
  299
  300comment_inner([A]) --> comment_inner_(A).
  301comment_inner([A|B]) --> comment_inner_(A),comment_inner(B).
  302comment_inner_(A) --> {dif(A,'\n')},[A].
  303regex_inner([A]) --> regex_inner_(A).
  304regex_inner([A|B]) --> regex_inner_(A),regex_inner(B).
  305regex_inner_(A) --> {A="\\\"";A="\\\'"},A;{dif(A,'"'),dif(A,'\n')},[A].
  306
  307
  308statements_with_ws(Data,A) -->
  309    (include_in_each_file(Data);""),ws_separated_statements(Data,A),ws.
  310
  311
  312print_var_types([A]) :-
  313    writeln(A).
  314print_var_types([A|Rest]) :-
  315    writeln(A),print_var_types(Rest).
  316
  317translate_langs(Input_) :-
  318	atom_chars(Input_,Input),
  319	list_of_langs(X),
  320	member(Lang,X), parse(Lang,Lang2,true,Input,Ls),
  321	translate_langs(Ls,X,Lang2).
  322
  323parse(python,Lang2,Is_input,Input,Ls) :-
  324	javascript_transpiler:parse(javascript,Lang2,Is_input,Input,Ls).
  325parse(javascript,Lang2,Is_input,Input,Ls) :-
  326	javascript_transpiler:parse(javascript,Lang2,Is_input,Input,Ls).
  327parse(java,Lang2,Is_input,Input,Ls) :-
  328	java_transpiler:parse(java,Lang2,Is_input,Input,Ls).
  329parse(Lang1,Lang2,Is_input,Input,Ls) :-
  330	phrase(statements_with_ws([Lang1,Is_input,[],"\n"],Ls), Input).
  331
  332translate_langs(_,[],_) :-
  333	true.
  334
  335translate_langs(Ls,[Lang|Langs],Lang2) :-
  336    parse(Lang,Lang2,false,Output,Ls),
  337    atom_chars(Output_,Output),writeln(''),writeln(Lang),writeln(''),writeln(Output_),writeln(''),
  338    translate_langs(Ls,Langs,Lang2).
  339
  340:- include(grammars).  341:- include(statement).  342:- include(statement_with_semicolon).  343:- include(class_statement).  344:- include(expr).  345:- include(dot_expr).  346:- include(parentheses_expr).