class RubimRipper
Public Class Methods
add_binding_to_init(source)
click to toggle source
# File lib/rubimc/preprocessor.rb, line 135 def self.add_binding_to_init(source) # for initialize variables with methods 'integer', 'float', e.t. helpers_array = ["boolean", "bool", "integer", "int", "float", "double"] helpers_array += ["string"] helpers_array += ["output", "input"] sexp = Ripper.sexp(source) command_array = find_rec(sexp, :command) command_array.reverse_each do |elem| varies_name = [] symb, helper_name, helper_pos = elem[1] if helper_name.in? helpers_array # if one of helper methods args_add_block = find_rec(elem, :args_add_block)[0][1] args_add_block.each do |arg| if arg[0] == :symbol_literal tmp_res = [] tmp_res << find_rec(arg, :@ident)[0] tmp_res << find_rec(arg, :@ivar)[0] tmp_res << find_rec(arg, :@gvar)[0] varies_name << tmp_res.compact.map {|el| el[1]} elsif arg[0] == :bare_assoc_hash bare_array = find_rec(arg, :@label) bare_array.each do |bare| varies_name << bare[1][0..-2] end break else raise ArgumentError.new("Wrong arguments for helper '#{helper_name}'") end end varies_name = [varies_name[0]] if helper_name.in? ['output', 'input'] var_str = varies_name.join(', ') # list of vars, defined in helper method source = paste_before_pos(source, "#{var_str} = ", helper_pos) # paste vars before helper method end end return source end
replace_all_numeric(source)
click to toggle source
-
(готово )замена всех цифр(целые, дробные, отриц.)
# File lib/rubimc/preprocessor.rb, line 47 def self.replace_all_numeric(source) lexs = Ripper.lex(source) lexs.reverse_each do |lex| pos, ident, symb = lex if (ident.in? [:on_int, :on_float]) bug_plus = (symb[0]=="+" ? "+" : "") # Note: space before "UserVariable" is neсessary source = replace_words(source, symb, "#{bug_plus} RubimCode::UserVariable.new(#{symb}, 'fixed')", pos) end end return source end
replace_assing_operators(source)
click to toggle source
-
(готово) замена оператора присваивания: “=” на “.c_assign=”
# File lib/rubimc/preprocessor.rb, line 35 def self.replace_assing_operators(source) lexs = Ripper.lex(source) lexs.reverse_each do |lex| pos, ident, symb = lex if (ident == :on_op and symb == "=") source = replace_words(source, symb, ".c_assign=", pos) end end return source end
replace_boolean_kw(source)
click to toggle source
# File lib/rubimc/preprocessor.rb, line 129 def self.replace_boolean_kw(source) source = replace_keywords(source, "true", "RubimCode::UserVariable.new(true, 'fixed')") source = replace_keywords(source, "false", "RubimCode::UserVariable.new(false, 'fixed')") return source end
replace_flat_express(source, kw_str = "if")
click to toggle source
# File lib/rubimc/preprocessor.rb, line 86 def self.replace_flat_express(source, kw_str = "if") source = replace_keywords(source, "then", ";") kw_sym = "#{kw_str}".to_sym parse_array = Ripper.sexp(source) flat_expresses = find_rec(parse_array, kw_sym) flat_expresses.reverse_each do |record| kw_pos = find_keyword_pos(source, record, kw_str) # 1. find modify 'if/unless' keywords cond_pos = find_express_end(source, record[1]) # 2. find end of 'if/unless' condition lineno, charno = cond_pos if (source.lines[lineno-1][charno..charno+1] != "do") source = paste_before_pos(source, " do", cond_pos) # 4. paste "str" at the end of condition end source = replace_words(source, kw_str, "RubimCode.rubim_#{kw_str}", kw_pos) end return source end
replace_instructions(source)
click to toggle source
# File lib/rubimc/preprocessor.rb, line 172 def self.replace_instructions(source) source = replace_keywords(source, "next", "RubimCode.rubim_next") source = replace_keywords(source, "break", "RubimCode.rubim_break") return source end
replace_loop(source)
click to toggle source
# File lib/rubimc/preprocessor.rb, line 107 def self.replace_loop(source) lexs = Ripper.lex(source) lexs.reverse_each do |lex| kw_pos, ident, symb = lex if (ident == :on_ident and symb == "loop") source = replace_words(source, symb, "RubimCode.rubim_loop", kw_pos) end end return source end
replace_modify_express(source, kw_str = "if")
click to toggle source
# File lib/rubimc/preprocessor.rb, line 60 def self.replace_modify_express(source, kw_str = "if") kw_sym = "#{kw_str}_mod".to_sym parse_array = Ripper.sexp(source) mod_expresses = find_rec(parse_array, kw_sym) mod_expresses.reverse_each do |record| kw_pos = find_keyword_pos(source, record, kw_str) # 1. find modify 'if/unless' keywords cond_pos = find_express_end(source, record[1]) # 2. find end of 'if/unless' condition case kw_str when "if" source = paste_before_pos(source, "; RubimCode.rubim_end;", cond_pos) # 3. paste "rubim_end" at the end of condition source = replace_words(source, kw_str, ";RubimCode.rubim_tmpif RubimCode.rubim_ifmod", kw_pos) # 4. replace "if/unless" keywords to "rubim_ifmod/__rubim_unlessmod" when "unless" source = paste_before_pos(source, "; RubimCode.rubim_end;", cond_pos) # 3. paste "rubim_end" at the end of condition source = replace_words(source, kw_str, ";RubimCode.rubim_tmpif RubimCode.rubim_unlessmod", kw_pos) # 4. replace "if/unless" keywords to "rubim_ifmod/__rubim_unlessmod" when "while" source = replace_words(source, kw_str, ";RubimCode.rubim_tmpif RubimCode.rubim_begin; RubimCode.rubim_whilemod", kw_pos) # 4. replace "while/until" keywords when "until" source = replace_words(source, kw_str, ";RubimCode.rubim_tmpif RubimCode.rubim_begin; RubimCode.rubim_untilmod", kw_pos) # 4. replace "while/until" keywords end end return source end
replace_rubim_tmpif(source)
click to toggle source
# File lib/rubimc/preprocessor.rb, line 125 def self.replace_rubim_tmpif(source) source.gsub(/;RubimCode.rubim_tmpif/, 'if') end
replace_then_else_elsif_kw(source)
click to toggle source
# File lib/rubimc/preprocessor.rb, line 118 def self.replace_then_else_elsif_kw(source) source = replace_keywords(source, "then", ";") source = replace_keywords(source, "else", "RubimCode.rubim_else") source = replace_keywords(source, "elsif", "RubimCode.rubim_elsif") return source end
Private Class Methods
find_express_end(source, express_array)
click to toggle source
Поиск окончания выражения
# File lib/rubimc/preprocessor.rb, line 273 def self.find_express_end(source, express_array) start_pos = find_far_pos(express_array) lineno, charno = start_pos lexs = Ripper.lex(source) lexs.each do |lex| lex_pos, ident, symb = lex if ((lex_pos <=> start_pos) >= 0) then if ((ident==:on_nl && symb=="\n") or (ident==:on_semicolon && symb==";") or (ident==:on_kw && symb=="do") or (ident==:on_kw && symb=="end")) then return lex_pos end end end lcount = source.lines.count return [lcount, source.lines[lcount-1].length] end
find_far_pos(array)
click to toggle source
Поиск позиции наиболее дальнего идентификатора справа (рекурсивно)
# File lib/rubimc/preprocessor.rb, line 247 def self.find_far_pos(array) array.reverse_each do |el| if el.is_a? Array # если найден идентификатор, указывающий на позицию if (el[0].is_a? Symbol and el.size==3 and /\A@/===el[0].to_s) return el[2] else res = find_far_pos(el) return res unless res.nil? end end end raise "can not find far position in array #{array}" end
find_keyword_pos(source, array, kw_str)
click to toggle source
Поиск ключевого слова “kw_str” начиная с позиции near_pos и левее
# File lib/rubimc/preprocessor.rb, line 262 def self.find_keyword_pos(source, array, kw_str) near_pos = find_near_pos(array) lineno, charno = near_pos curline = source.lines[lineno-1] charno.downto(0) do |index| return [lineno, index-1] if /#{kw_str} / === curline[index-1..-1] end raise "can not find keyword '#{kw_str}' if array #{array}" end
find_near_pos(array)
click to toggle source
Поиск позиции наиболее близкого идентификатора справа
# File lib/rubimc/preprocessor.rb, line 232 def self.find_near_pos(array) array.each do |el| if el.is_a? Array # если найден идентификатор, указывающий на позицию if (el[0].is_a? Symbol and el.size==3 and /\A@/===el[0].to_s) return el[2] else res = find_near_pos(el) return res unless res.nil? end end end raise "can not find near position in array #{array}" end
find_rec(array, find_sym)
click to toggle source
Поиск вложенного массива (sexp) с ключевым символом find_sym (рекурсивный вызов)
# File lib/rubimc/preprocessor.rb, line 183 def self.find_rec(array, find_sym) return [] unless array.is_a? Array result = [] array.each do |elem| result << array if elem == find_sym result += find_rec(elem, find_sym) end return result end
paste_before_pos(source, rstr, pos)
click to toggle source
Вставка слова до указанной позиции
# File lib/rubimc/preprocessor.rb, line 207 def self.paste_before_pos(source, rstr, pos) output = "" lineno, charno = pos source.lines.each_with_index do |line, index| if index == lineno-1 line.insert(charno, rstr) end output += line end return output end
replace_keywords(source, kw, repl_kw)
click to toggle source
Замена ключевых слов
# File lib/rubimc/preprocessor.rb, line 220 def self.replace_keywords(source, kw, repl_kw) lexs = Ripper.lex(source) lexs.reverse_each do |lex| kw_pos, ident, symb = lex if (ident == :on_kw and symb == kw) source = replace_words(source, symb, repl_kw, kw_pos) end end return source end
replace_words(source, dstr, rstr, pos)
click to toggle source
Замена слов
# File lib/rubimc/preprocessor.rb, line 194 def self.replace_words(source, dstr, rstr, pos) # источник, исходное слово, конечное слово, начальная позиция output = "" lineno, charno = pos source.lines.each_with_index do |line, index| if index == lineno-1 line[charno .. charno+dstr.length-1] = rstr end output += line end return output end