require 'erb' require_relative '../builder' require_relative './ruby_templates' module Shift module Generator class RubyGenerator attr_accessor :builder, :has_models, :defined_hashes def initialize() @blocks = [] @defined_hashes = [] @has_models = false @builder = Shift::ShiftBuilder.new end def get_data(builder) @builder = builder end def get_data_from_file(file_name) @builder.get_data_from_file file_name end def get_import_statements() Shift::Generator::RubyTemplates::IMPORT_SINATRA_STATEMENT + "\n" + Shift::Generator::RubyTemplates::IMPORT_MUSTACHE_STATEMENT + "\n" + (@has_models ? (Shift::Generator::RubyTemplates::IMPORT_DATAMAPPER_STATEMENT + "\n\n") : "") end def get_model_data() result = "" model_name_template = ERB.new(Shift::Generator::RubyTemplates::MODEL_NAME_TEMPLATE) @builder.models.each do | model | model_name = model.name result += model_name_template.result(binding) + "\n" result += ("\t" + Shift::Generator::RubyTemplates::DATAMAPPER_INCLUDE_STATEMENT + "\n\n" ) result += ("\t" + "property :id, Serial\n") model.attributes.each do | attribute | if (attribute[:type] == "string") result += ("\t" + "property :" + attribute[:name] + ", " + RubyTemplates::DB_STRING_PROPERTY + "\n") elsif (attribute[:type] == "integer") result += ("\t" + "property :" + attribute[:name] + ", " + RubyTemplates::DB_INTEGER_PROPERTY + "\n") end end result += "end\n" end result end def get_utility_functions() Shift::Generator::RubyTemplates::UTILITY_FUNCTIONS + "\n\n" + (@has_models ? (Shift::Generator::RubyTemplates::CONFIGURE_BLOCK + "\n\n") : "") end def token_transform(statement, num_tabs) tabs = "" num_tabs.times { tabs += "\t" } key = statement.keys[0] case key when :identifier statement[:identifier].to_s when :object_value if (statement[:object_value].to_s.split(".")[1] == "save") tabs + statement[:object_value].to_s + "\n" else tabs + statement[:object_value].to_s end when :hash_value statement[:hash_value].to_s when :string statement[:string].to_s else statement.to_s end end def expression_transform(statement, num_tabs) tabs = "" num_tabs.times { tabs += "\t" } key = statement.keys[0] case key when :assignment_statement extra = "" if(statement[:assignment_statement][:left].keys[0] == :hash_value) val = statement[:assignment_statement][:left][:hash_value].to_s hash_var = val[0..(val.index('[') - 1)] if !@defined_hashes.include?(hash_var) @defined_hashes.push hash_var extra += tabs + "(" + hash_var + " ||= {})\n" end end left = apply_transforms(statement[:assignment_statement][:left], 0) right = apply_transforms(statement[:assignment_statement][:right], 0) extra + tabs + left.to_s + " = " + right.to_s end end def query_transform(statement, num_tabs) tabs = "" num_tabs.times { tabs += "\t" } statement = statement[:query] case statement[:operation].to_s when "all" (statement[:model_name].to_s + ".all") when "new" (statement[:model_name].to_s + ".new") when "find" attribute = statement[:condition][:attribute].to_s value = apply_transforms(statement[:condition][:value], 0) operator = "" case statement[:condition][:operator].to_s.gsub!(" ", "") when "<=" operator = ".lte" when ">=" operator = ".gte" when "<" operator = ".lt" when ">" operator = ".gt" when "!=" operator = ".not" end (statement[:model_name].to_s + ".all(:" + attribute + operator + " => " + value + ")") when "find_by_id" id = apply_transforms(statement[:item_id], 0) (statement[:model_name].to_s + ".get(params[:" + id + "])" ) when "update" tabs + (statement[:model_name].to_s + ".save\n") when "delete" tabs + (statement[:model_name].to_s + ".destroy\n") end end def write_function_transform(statement, num_tabs) tabs = "" num_tabs.times { tabs += "\t" } write_data_template = ERB.new(Shift::Generator::RubyTemplates::WRITE_DATA_TEMPLATE) write_data = apply_transforms(statement[:write_statement][:write_statement_param], 0) tabs + write_data_template.result(binding) + "\n" + tabs + Shift::Generator::RubyTemplates::WRITE_RESPONSE_TEMPLATE end def write_file_function_transform(statement, num_tabs) tabs = "" num_tabs.times { tabs += "\t" } write_file_template = ERB.new(Shift::Generator::RubyTemplates::WRITE_FILE_TEMPLATE) if(statement[:write_file_statement].is_a?(Array)) file_name = apply_transforms(statement[:write_file_statement][0][:file_name], 0) template_values = apply_transforms(statement[:write_file_statement][1][:template_values], 0) else file_name = apply_transforms(statement[:write_file_statement][:file_name], 0) end tabs + write_file_template.result(binding) end def read_statement_transform(statement, num_tabs) read_param = apply_transforms(statement[:read_statement][:read_statement_param], 0) if ((read_param[0] == "'") || (read_param[0] == '"')) read_param = read_param[1..(read_param.length - 2)] end read_statement = "params[:" + read_param + "]" end def redirect_statement_transform(statement, num_tabs) tabs = "" num_tabs.times { tabs += "\t" } redirect_param = apply_transforms(statement[:redirect_statement][:redirect_statement_param], 0) redirect_statement = tabs + "redirect(" + redirect_param + ")\n" end def value_transform(statement, num_tabs) tabs = "" num_tabs.times { tabs += "\t" } key = statement.keys[0] statement[key].to_s end def control_statement_transform(statement, num_tabs) tabs = "" num_tabs.times { tabs += "\t" } key = statement.keys[0] result = "" @blocks.push (num_tabs) case key when :if_statement result = tabs + "if " + apply_transforms(statement[:if_statement][:condition], 0) when :while_statement result = tabs + "while " + apply_transforms(statement[:while_statement][:condition], 0) end result end def url_transform(url) if(url.is_a?(Array)) result_url = "" url.each do | token | case token.keys[0] when :url_token result_url += "/" + token[:url_token].to_s when :url_variable result_url += "/:" + token[:url_variable].to_s end end result_url else url.to_s end end def concatenated_string_expression_transform(statement, num_tabs) statement = statement.map do | token | apply_transforms(token, 0) end statement.join(" + ") end def integer_casted_expression_transform(statement, num_tabs) statement.delete(:int) "(" + apply_transforms(statement, 0) + ").to_i" end def apply_transforms(statement, num_tabs) tabs = "" if num_tabs > 0 num_tabs = num_tabs - 1 end num_tabs.times { tabs += "\t" } result = "" if(@blocks.length > 0) if(@blocks[@blocks.length - 1] == num_tabs) if (statement.keys[0] != :else_statement) t = "" @blocks.pop.times { t += "\t" } result += t + "end\n" end end end if(statement.is_a?(Hash)) key = statement.keys[0] case key when :assignment_statement result += expression_transform(statement, num_tabs) + "\n" when :query result += query_transform(statement, num_tabs) when :write_statement result += write_function_transform(statement, num_tabs) + "\n" when :write_file_statement result += write_file_function_transform(statement, num_tabs) + "\n" when :read_statement result += read_statement_transform(statement, num_tabs) when :redirect_statement result += redirect_statement_transform(statement, num_tabs) when :arithmetic_expression result += value_transform(statement, num_tabs) when :boolean_expression result += value_transform(statement, num_tabs) when :if_statement result += control_statement_transform(statement, num_tabs) + "\n" when :else_statement result += tabs + value_transform(statement, num_tabs) + "\n" when :for_statement @blocks.push(num_tabs) result += tabs + value_transform(statement, num_tabs) + "\n" when :while_statement result += control_statement_transform(statement, num_tabs) + "\n" when :int integer_casted_expression_transform(statement, num_tabs) else result += token_transform(statement, num_tabs) end else if statement.is_a?(Array) result += concatenated_string_expression_transform(statement, num_tabs) else result += statement.to_s end end end def write_data() if (@builder.models.length != 0) @has_models = true end result = get_import_statements + get_model_data + get_utility_functions @builder.handlers.each do | handlers | defined_hashes = [] result += handlers.method + " '" + url_transform(handlers.url) + "' do\n" handlers.handler.each do | statement | result += apply_transforms(statement[:statement], statement[:num_tabs]) end @blocks.each do | t | tabs = "" t.times { tabs += "\t" } result += tabs + "end" + "\n" end @blocks = [] result += "end\n\n" end result end end end end