module Krunimir # Kompiluje Krunimiruv kod do Ruby class Compiler # Novy kompilator inicializovany programem. def initialize(program) @program = program end # Regexp odpovidajici vsem vyrazum EXPRESSION = /[\sa-zA-Z0-9+\/*-]+/ # Regexp odpovidajici seznamu argumentu ARGS = /[a-zA-Z\s\,]*/ # Zkompiluje program a vrati jej jako blok (instance Proc). # # Kompiluje se jednoduchym nahrazovanim pomoci regularnich vyrazu a vyuziva # se tim dynamicnost Ruby. def compile compiled = @program.dup # neupravuje se parametr predany do initialize ale kopie # vycisteni od prebytecnych prazdnych znaku compiled.gsub! /\s+/, " " # zajisti se oddeleni volani metod compiled.gsub! ")", ")\n" # repeat(vyraz) se nahradi na volani _repeat compiled.gsub!(/repeat\s*\(\s*(#{EXPRESSION})\s*\)\s*/) { |s| "_repeat(#$1) " } # if(vyraz) se nahradi na volani metody _if compiled.gsub!(/if\s*\((#{EXPRESSION})\)\s*\{/) do "_if(#{$1}) do\n" end # define name(args) { se nahradi na _define(name) do |args| compiled.gsub!(/define\s+([a-zA-Z_]+)\s*\((#{ARGS})\)\s*\{/) do "_define(#{$1.to_sym.inspect}) do |#{$2}|\n" end # split se nahradi za _split compiled.gsub! "split", "_split" # prevadi se na bloky v Ruby compiled.gsub! "{", " do\n" compiled.gsub! "}", " end\n" # cisteni prazdnych znaku v okoli zavorek compiled.gsub! /[ \t]*\(\s*/, "(" compiled.gsub! /\s+\)/, ")" # cisteni prazdnych znaku kolem operatoru compiled.gsub!(/\s*([+*\/-])\s*/) { $1 } begin return eval("proc do\n#{compiled}\nend\n") # vraci blok rescue SyntaxError => e raise SyntaxError, "Unable to parse input file" end end end end