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
30
32list_of_langs(X) :-
33 34 35 36 37 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
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
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
167is_var_type_(_, [Name,Params], Type) :-
168 var_type([],[Name,Params],Type).
169
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
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
([A]) --> comment_inner_(A).
301comment_inner([A|B]) --> comment_inner_(A),comment_inner(B).
(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).