shift-lang 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +2 -0
  6. data/bin/sft +5 -0
  7. data/bin/shift +5 -0
  8. data/lib/app_engine_templates/app.yaml +13 -0
  9. data/lib/app_engine_templates/pystache/__init__.py +8 -0
  10. data/lib/app_engine_templates/pystache/__init__.pyc +0 -0
  11. data/lib/app_engine_templates/pystache/loader.py +47 -0
  12. data/lib/app_engine_templates/pystache/loader.pyc +0 -0
  13. data/lib/app_engine_templates/pystache/template.py +177 -0
  14. data/lib/app_engine_templates/pystache/template.pyc +0 -0
  15. data/lib/app_engine_templates/pystache/view.py +94 -0
  16. data/lib/app_engine_templates/pystache/view.pyc +0 -0
  17. data/lib/heroku_templates/Gemfile +6 -0
  18. data/lib/heroku_templates/Procfile +1 -0
  19. data/lib/shift-lang/builder/db_model.rb +20 -0
  20. data/lib/shift-lang/builder/url_handler.rb +17 -0
  21. data/lib/shift-lang/builder.rb +103 -0
  22. data/lib/shift-lang/generator/javascript_generator.rb +410 -0
  23. data/lib/shift-lang/generator/javascript_templates.rb +37 -0
  24. data/lib/shift-lang/generator/python_generator.rb +330 -0
  25. data/lib/shift-lang/generator/python_templates.rb +44 -0
  26. data/lib/shift-lang/generator/ruby_generator.rb +334 -0
  27. data/lib/shift-lang/generator/ruby_templates.rb +50 -0
  28. data/lib/shift-lang/generator.rb +41 -0
  29. data/lib/shift-lang/parser/control_statement_parser.rb +17 -0
  30. data/lib/shift-lang/parser/db_query_parser.rb +20 -0
  31. data/lib/shift-lang/parser/keyword_parser.rb +52 -0
  32. data/lib/shift-lang/parser/operator_parser.rb +35 -0
  33. data/lib/shift-lang/parser/routing_expression_parser.rb +33 -0
  34. data/lib/shift-lang/parser/simple_expression_parser.rb +87 -0
  35. data/lib/shift-lang/parser/token_parser.rb +69 -0
  36. data/lib/shift-lang/parser/value_returning_expression_parser.rb +18 -0
  37. data/lib/shift-lang/parser/void_statement_parser.rb +12 -0
  38. data/lib/shift-lang/parser.rb +120 -0
  39. data/lib/shift-lang/version.rb +3 -0
  40. data/lib/shift-lang.rb +224 -0
  41. data/shift-lang.gemspec +19 -0
  42. metadata +106 -0
@@ -0,0 +1,410 @@
1
+ require 'erb'
2
+
3
+ require_relative '../builder'
4
+ require_relative './javascript_templates'
5
+
6
+ module Shift
7
+ module Generator
8
+
9
+ class JavaScriptGenerator
10
+ attr_accessor :blocks, :functions, :builder, :url_variables, :has_models, :defined_hashes
11
+
12
+ def initialize()
13
+ @blocks = []
14
+ @defined_hashes = []
15
+ @functions = []
16
+ @has_models = false
17
+ @builder = Shift::ShiftBuilder.new
18
+ end
19
+
20
+ def get_data(builder)
21
+ @builder = builder
22
+ end
23
+
24
+ def get_data_from_file(file_name)
25
+ @builder.get_data_from_file file_name
26
+ end
27
+
28
+ def get_import_statements()
29
+ Shift::Generator::JavaScriptTemplates::IMPORT_JQNODE_STATEMENT +
30
+ Shift::Generator::JavaScriptTemplates::IMPORT_UTIL_STATEMENT +
31
+ Shift::Generator::JavaScriptTemplates::IMPORT_MU_STATEMENT +
32
+ (@has_models ? Shift::Generator::JavaScriptTemplates::IMPORT_DB_STATEMENT : "") +
33
+ Shift::Generator::JavaScriptTemplates::UTILITY_FUNCTIONS + "\n"
34
+ end
35
+
36
+ def get_model_data()
37
+ result = ""
38
+
39
+ model_name_template = ERB.new(Shift::Generator::JavaScriptTemplates::MODEL_NAME_TEMPLATE)
40
+
41
+ @builder.models.each do | model |
42
+ model_name = model.name
43
+ result += model_name_template.result(binding) + "\n"
44
+
45
+ first = true
46
+
47
+ # TODO: Test if comma syntax is valid
48
+
49
+ model.attributes.each do | attribute |
50
+ if (attribute[:type] == "string")
51
+ if (first == true)
52
+ first = false
53
+ else
54
+ result += ","
55
+ end
56
+ result += ("\t" + attribute[:name] + " : " + "String" + "\n")
57
+ else
58
+ if (attribute[:type] == "integer")
59
+ if (first == true)
60
+ first = false
61
+ else
62
+ result += ","
63
+ end
64
+ result += ("\t" + attribute[:name] + " : " + "Number" + "\n")
65
+ end
66
+ end
67
+ end
68
+
69
+ result += "});\n\n"
70
+ end
71
+
72
+ result
73
+ end
74
+
75
+ def url_transform(url)
76
+ if(url.is_a?(Array))
77
+ result_url = ""
78
+
79
+ url.each do | token |
80
+ case token.keys[0]
81
+ when :url_token
82
+ result_url += "/" + token[:url_token].to_s
83
+ when :url_variable
84
+ result_url += "/:" + token[:url_variable].to_s
85
+ end
86
+ end
87
+ result_url
88
+ else
89
+ url.to_s
90
+ end
91
+ end
92
+
93
+ def expression_transform(statement, num_tabs)
94
+ tabs = ""
95
+ num_tabs.times { tabs += "\t" }
96
+ key = statement.keys[0]
97
+ case key
98
+ when :assignment_statement
99
+ extra = ""
100
+ if(statement[:assignment_statement][:left].keys[0] == :hash_value)
101
+ val = statement[:assignment_statement][:left][:hash_value].to_s
102
+ hash_var = val[0..(val.index('[') - 1)]
103
+ if !@defined_hashes.include?(hash_var)
104
+ @defined_hashes.push hash_var
105
+ extra += (tabs + "if (typeof " + hash_var + " == 'undefined')\n")
106
+ extra += (tabs + "\t" + hash_var + " = {}\n")
107
+ end
108
+ end
109
+
110
+ left = apply_transforms(statement[:assignment_statement][:left], 0)
111
+ right = apply_transforms(statement[:assignment_statement][:right], 0)
112
+
113
+ if(statement[:assignment_statement][:left].keys[0] == :object_value)
114
+ value_name = statement[:assignment_statement][:left][:object_value].to_s
115
+ value_name = value_name[(value_name.index('.') + 1)..(value_name.length - 1)]
116
+ end
117
+
118
+ if(statement[:assignment_statement][:right].is_a?(Hash) && statement[:assignment_statement][:right].keys[0] == :query)
119
+ case statement[:assignment_statement][:right][:query][:operation]
120
+ when "all"
121
+ @functions.push (tabs + "});")
122
+ tabs + right.to_s + left.to_s + ") {"
123
+ when "new"
124
+ tabs + "var " + left.to_s + " = " + right.to_s
125
+ when "find"
126
+ @functions.push (tabs + "});")
127
+ tabs + right.to_s + left.to_s + ") {"
128
+ when "find_by_id"
129
+ @functions.push (tabs + "});")
130
+ tabs + right.to_s + left.to_s + ") {"
131
+ end
132
+ else
133
+ extra + tabs + left.to_s + " = " + right.to_s + ";"
134
+ end
135
+ else
136
+ ""
137
+ end
138
+ end
139
+
140
+ def token_transform(statement, num_tabs)
141
+ tabs = ""
142
+ num_tabs.times { tabs += "\t" }
143
+
144
+ key = statement.keys[0]
145
+
146
+ case key
147
+ when :identifier
148
+ result = statement[:identifier].to_s
149
+ @url_variables.include?(result) ? "urlData['" + result + "']" : result
150
+ when :object_value
151
+ if (statement[:object_value].to_s.split(".")[1] == "save")
152
+ tabs + statement[:object_value].to_s.split(".")[0] + ".save();" + "\n"
153
+ else
154
+ tabs + statement[:object_value].to_s
155
+ end
156
+ when :hash_value
157
+ statement[:hash_value].to_s
158
+ when :string
159
+ statement[:string].to_s
160
+ else
161
+ ""
162
+ end
163
+
164
+ end
165
+
166
+ def write_function_transform(statement, num_tabs)
167
+ tabs = ""
168
+ num_tabs.times { tabs += "\t" }
169
+
170
+ write_data_template = ERB.new(Shift::Generator::JavaScriptTemplates::WRITE_DATA_TEMPLATE)
171
+
172
+ write_data = apply_transforms(statement[:write_statement][:write_statement_param], 0)
173
+
174
+ tabs + write_data_template.result(binding)
175
+ end
176
+
177
+ def write_file_function_transform(statement, num_tabs)
178
+ tabs = ""
179
+ num_tabs.times { tabs += "\t" }
180
+
181
+ write_file_template = ERB.new(Shift::Generator::JavaScriptTemplates::WRITE_FILE_TEMPLATE)
182
+
183
+ if(statement[:write_file_statement].is_a?(Array))
184
+ file_name = apply_transforms(statement[:write_file_statement][0][:file_name], 0)
185
+ template_values = apply_transforms(statement[:write_file_statement][1][:template_values], 0)
186
+ args = file_name + ', ' + template_values + ", response"
187
+ else
188
+ file_name = apply_transforms(statement[:write_file_statement][:file_name], 0)
189
+ args = file_name + ', false'
190
+ end
191
+
192
+ tabs + write_file_template.result(binding)
193
+ end
194
+
195
+
196
+ def query_transform(statement, num_tabs)
197
+ tabs = ""
198
+ num_tabs.times { tabs += "\t" }
199
+ statement = statement[:query]
200
+ case statement[:operation].to_s
201
+ when "all"
202
+ statement[:model_name].to_s + ".all(function (err, "
203
+ when "new"
204
+ (statement[:model_name].to_s + "()")
205
+ when "find"
206
+ result = statement[:model_name].to_s + ".all({ where : "
207
+ condition = statement[:condition]
208
+
209
+ condition_attribute = apply_transforms(condition[:value], 0)
210
+
211
+ condition_expression = ""
212
+
213
+ case statement[:condition][:operator].to_s.gsub!(" ", "")
214
+ when "<="
215
+ condition_expression = "{lte : " + condition_attribute + "}"
216
+ else
217
+ puts statement[:operator].to_s.gsub!(" ", "")
218
+ end
219
+
220
+ result += "{ " + condition[:attribute] + " : " + condition_expression + " }"
221
+ result += " }, function (err, "
222
+ when "find_by_id"
223
+ result = statement[:model_name].to_s + ".find("
224
+ result += apply_transforms(statement[:item_id], 0)
225
+ result += ", function(err, "
226
+ when "update"
227
+ @functions.push (tabs + "});")
228
+ result = tabs + statement[:model_name].to_s + ".updateAttributes({}, function() {"
229
+ when "delete"
230
+ @functions.push (tabs + "});")
231
+ result = tabs + statement[:model_name].to_s + ".destroy(function() {"
232
+ end
233
+ end
234
+
235
+ def read_statement_transform(statement, num_tabs)
236
+ param = apply_transforms(statement[:read_statement][:read_statement_param], 0)
237
+ "data[" + param + "]"
238
+ end
239
+
240
+ def redirect_statement_transform(statement, num_tabs)
241
+ tabs = ""
242
+ num_tabs.times { tabs += "\t" }
243
+
244
+ redirect_statement_template = ERB.new(Shift::Generator::JavaScriptTemplates::REDIRECT_STATEMENT_TEMPLATE)
245
+ url = apply_transforms(statement[:redirect_statement][:redirect_statement_param], 0)
246
+ "\n" + tabs + redirect_statement_template.result(binding)
247
+ end
248
+
249
+ def value_transform(statement, num_tabs)
250
+ tabs = ""
251
+ num_tabs.times { tabs += "\t" }
252
+
253
+ key = statement.keys[0]
254
+
255
+ statement[key].to_s
256
+ end
257
+
258
+ def control_statement_transform(statement, num_tabs)
259
+ tabs = ""
260
+ num_tabs.times { tabs += "\t" }
261
+
262
+ key = statement.keys[0]
263
+
264
+ result = ""
265
+
266
+ @blocks.push (num_tabs)
267
+
268
+ case key
269
+ when :if_statement
270
+ result = tabs + "if " + apply_transforms(statement[:if_statement][:condition], 0) + " {"
271
+ when :while_statement
272
+ result = tabs + "while " + apply_transforms(statement[:while_statement][:condition], 0) + " {"
273
+ end
274
+
275
+ result
276
+ end
277
+
278
+ def concatenated_string_expression_transform(statement, num_tabs)
279
+ statement = statement.map do | token |
280
+ apply_transforms(token, 0)
281
+ end
282
+
283
+ statement.join(" + ")
284
+ end
285
+
286
+ def integer_casted_expression_transform(statement, num_tabs)
287
+ statement.delete(:int)
288
+ "Number(" + apply_transforms(statement, 0) + ")"
289
+ end
290
+
291
+ def apply_transforms(statement, num_tabs)
292
+ tabs = ""
293
+ if (num_tabs > 0)
294
+ num_tabs = num_tabs - 1
295
+ end
296
+
297
+ result = ""
298
+
299
+ if(@blocks.length > 0)
300
+ if(@blocks[@blocks.length - 1] == num_tabs)
301
+ t = ""
302
+ @blocks.pop.times { t += "\t" }
303
+ result += t + "}\n"
304
+ end
305
+ end
306
+
307
+ num_tabs.times { tabs += "\t" }
308
+
309
+ if(statement.is_a?(Hash))
310
+ key = statement.keys[0]
311
+ case key
312
+ when :assignment_statement
313
+ result += expression_transform(statement, num_tabs) + "\n"
314
+ when :write_statement
315
+ result += write_function_transform(statement, num_tabs) + "\n"
316
+ when :write_file_statement
317
+ result += write_file_function_transform(statement, num_tabs) + "\n"
318
+ when :read_statement
319
+ result += read_statement_transform(statement, num_tabs)
320
+ when :redirect_statement
321
+ result += redirect_statement_transform(statement, num_tabs) + "\n"
322
+ when :arithmetic_expression
323
+ result += value_transform(statement, num_tabs)
324
+ when :boolean_expression
325
+ result += value_transform(statement, num_tabs)
326
+ when :if_statement
327
+ result += control_statement_transform(statement, num_tabs) + "\n"
328
+ when :else_statement
329
+ @blocks.push (num_tabs)
330
+ result += tabs + value_transform(statement, num_tabs) + " {\n"
331
+ when :for_statement
332
+ statement = statement[:for_statement]
333
+ tokens = statement.to_s.split(" ")
334
+ @blocks.push (num_tabs)
335
+ result += tabs + "for(var k in " + tokens[3] + ") {\n"
336
+ result += tabs + "\t" + tokens[1] + " = " + tokens[3] + "[k];\n"
337
+ when :while_statement
338
+ result += control_statement_transform(statement, num_tabs) + "\n"
339
+ when :query
340
+ result += query_transform(statement, num_tabs)
341
+ when :int
342
+ integer_casted_expression_transform(statement, num_tabs)
343
+ else
344
+ result += token_transform(statement, num_tabs)
345
+ end
346
+ else
347
+ if statement.is_a?(Array)
348
+ concatenated_string_expression_transform(statement, num_tabs)
349
+ else
350
+ result += statement.to_s
351
+ end
352
+ end
353
+ end
354
+
355
+ def write_data()
356
+ if(@builder.models.length != 0)
357
+ @has_models = true
358
+ end
359
+
360
+ result = get_import_statements + get_model_data
361
+
362
+ @builder.handlers.each do | handlers |
363
+ url = url_transform(handlers.url)
364
+ method = handlers.method
365
+
366
+ @url_variables = []
367
+ current_url = handlers.url
368
+ if(current_url.is_a?(Array))
369
+ current_url.each do | token |
370
+ case token.keys[0]
371
+ when :url_variable
372
+ @url_variables.push token[:url_variable]
373
+ end
374
+ end
375
+ end
376
+
377
+ url_handler_template = ERB.new(Shift::Generator::JavaScriptTemplates::URL_HANDLER_DEFINITION)
378
+ result += "\n" + url_handler_template.result(binding) + "\n"
379
+
380
+ defined_hashes = []
381
+
382
+ handlers.handler.each do | statement |
383
+ result += apply_transforms(statement[:statement], statement[:num_tabs] + functions.length)
384
+ end
385
+
386
+ i = @functions.length - 2
387
+
388
+ blocks.each do | t |
389
+ tabs = ""
390
+ t.times { tabs += "\t" }
391
+ result += tabs + "}" + "\n"
392
+ end
393
+
394
+ functions.reverse.each do | closing_block |
395
+ tabs = ""
396
+ i.times { tabs += "\t" }
397
+ result += tabs + closing_block + "\n"
398
+ end
399
+
400
+ @functions = []
401
+ @blocks = []
402
+
403
+ result += "});\n"
404
+ end
405
+
406
+ result += "\n\n" + Shift::Generator::JavaScriptTemplates::APP_START_STATEMENT
407
+ end
408
+ end
409
+ end
410
+ end
@@ -0,0 +1,37 @@
1
+ module Shift
2
+ module Generator
3
+ module JavaScriptTemplates
4
+
5
+ IMPORT_JQNODE_STATEMENT = "var $ = require('jqNode').$;\n"
6
+
7
+ IMPORT_UTIL_STATEMENT = "var util = require('util');\n"
8
+
9
+ IMPORT_MU_STATEMENT = "var mu = require('mu2');\nmu.root = __dirname + '/views';\n"
10
+
11
+ IMPORT_DB_STATEMENT = "_Schema = require('jugglingdb').Schema;\nvar schema = new _Schema('mongodb', {port : 27017});\n"
12
+
13
+ UTILITY_FUNCTIONS = "
14
+ function writeTemplate(fileName, templateValues, response) {
15
+ if(!templateValues) {
16
+ $.writeFile('views/' + fileName);
17
+ } else {
18
+ var templateStream = mu.compileAndRender(fileName, templateValues);
19
+ util.pump(templateStream, response);
20
+ }
21
+ }"
22
+
23
+ MODEL_NAME_TEMPLATE = "var <%= model_name %> = schema.define('<%= model_name %>', {"
24
+
25
+ URL_HANDLER_DEFINITION = '$("<%= url %>").<%= method %>(function(request, response, data, urlData) {'
26
+
27
+ REDIRECT_STATEMENT_TEMPLATE = "$.redirect(<%= url %>);"
28
+
29
+ WRITE_DATA_TEMPLATE = "$.write(<%= write_data %>);"
30
+
31
+ WRITE_FILE_TEMPLATE = "writeTemplate(<%= args %>);"
32
+
33
+ APP_START_STATEMENT = "$.start({port : 8080});"
34
+
35
+ end
36
+ end
37
+ end