# FreeRIDE Ruby Integrated Development Environment # # Author: Rich Kilmer # Copyright (c) 2001, Richard Kilmer, rich@infoether.com # Licensed under the Ruby License # # Updated 2003 for Scintilla 1.52 class ScintillaGenerator VALUE = /val\s+([A-Z_]\w+)=/ FUNCTION = /fun\s([a-z]\w+)\s(\w+)=([0-9]\w+)\((\w+)?\s?(\w+)?,\s?(\w+)?\s?(\w+)?\)/ SET = /set\s([a-z]\w+)\s(\w+)=([0-9]\w+)\((\w+)?\s?(\w+)?,\s?(\w+)?\s?(\w+)?\)/ GET = /get\s([a-z]\w+)\s(\w+)=([0-9]\w+)\((\w+)?\s?(\w+)?,\s?(\w+)?\s?(\w+)?\)/ EVENT = /evt\s([a-z]\w+)\s(\w+)=([0-9]\w+)\((.*)\)/ COMMENT = /##/ LINE_COMMENT = /#\s/ INT = "int" VOID = "void" BOOL = "bool" POSITION = "position" COLOUR = "colour" STRING_RESULT = "stringresult" STRING = "string" if ARGV.size ==1 DEBUG = eval(ARGV[0]) else DEBUG=false end ## void ## int ## bool -> integer, 1=true, 0=false ## position -> integer position in a document ## colour -> colour integer containing red, green and blue bytes. ## string -> pointer to const character ## stringresult -> pointer to character ## cells -> pointer to array of cells, each cell containing a style byte and character byte ## textrange -> charrange + output string ## findtext -> searchrange, text -> foundposition ## keymod -> integer containing key in low half and modifiers in high half ## formatrange def initialize(input, output) @input = input @output = output @event_stubs = [] @event_cases = [] end def generate o = File.new(@output, "w") o.puts "## ***** WARNING...THIS FILE IS GENERATED BY FROM SCINTILLA.IFACE" o.puts "## ***** DO NOT MODIFY...MODIFY SCINTILLA.RB INSTEAD\n\n" o.puts "module Scintilla" i = File.new(@input) i.each_line do |line| parse_line(line) { |text| o.puts text } end i.close o.puts " module ScintillaEvents" o.puts " def handle_notification(from, id, scn)" o.puts " case id" @event_cases.each {|ecase| o.puts ecase} o.puts " end" o.puts " end" @event_stubs.each {|event| o.puts event} o.puts " end" o.puts "end" o.close end def parse_line(line) if line.length==1 yield "" return end case line when VALUE @in_line_comment = false yield " #{$1} = #{$'}" when LINE_COMMENT unless @in_line_comment yield " ##\n" @in_line_comment = true end yield " #{line}" when EVENT @in_line_comment = false returnType = $1 function = $2 function = "on_"+un_camelcase(function) id = $3 params = $4.split(",").collect {|p| p.strip} params = nil if params == ['void'] event = " def #{function}" if params event << "(" event << (params.collect {|param| un_camelcase(param.split(' ')[1])}).join(", ") event << ")\n" else event << "\n" end event << " end\n" @event_stubs << event event_case = " when #{id}\n" event_case += " #{function}" if params event_case << "(" event_case << (params.collect {|param| "scn."+param.split(' ')[1]}).join(", ") event_case << ")\n" else event_case << "\n" end @event_cases << event_case when GET, SET, FUNCTION @in_line_comment = false returnType = $1 function = $2 function = (line[1,2]=='et' ? line[0,3] : '') + function unless function[0,3].downcase==line[0,3] function = un_camelcase(function) id = $3 param1Type = $4 param1 = $5 param2Type = $6 param2 = $7 param1 = "finish" if param1=="end" param2 = "finish" if param2=="end" if param1Type==INT && param1=="length" && param2Type==STRING && param2=="text" str = " def #{function}( text )\n" str << " send_message(#{id}, text.length, text)\n" str << " end\n\n" elsif param2Type==STRING_RESULT str = " def #{function}" str << "( " if param1 str << param1 if param1 str << " )" if param1 str << "\n" if param1 && param1=="length" str << " buffer = ' '*#{param1}\n" str << " send_message(#{id}, #{param1}, buffer)\n" else if param1 str << " len = send_message(#{id}, #{param1}, '')\n" str << " buffer = ' '*len\n" str << " send_message(#{id}, #{param1}, buffer)\n" else str << " len = send_message(#{id}, 0, '')\n" str << " buffer = ' '*len\n" str << " send_message(#{id}, len, buffer)\n" end end str << " return buffer\n" str << " end\n" if line[0,3]=='get' str << " alias :#{function[4..-1]} :#{function}\n" elsif line[0,3]=='set' str << " alias :#{function[4..-1]}= :#{function}\n" end else str = " def #{function}" #str << "?" if returnType==BOOL str << "( " if param1 || param2 str << param1 if param1 str << " , " if param1 && param2 str << param2 if param2 str << " )" if param1 || param2 str << "\n" if DEBUG str << (" puts "+'"'+"called #{function} ") str << "( " if param1 || param2 str << ('#{'+param1+'}') if param1 str << " , " if param1 && param2 str << ('#{'+param2+'}') if param2 str << " )" if param1 || param2 str << ('"'+"\n") end str << " return (send_message(#{id}, #{caste_param(param1, param1Type)}, #{caste_param(param2, param2Type)})" str << (returnType==BOOL ? "==1 ? true : false)\n" : ")\n") str << " end\n" if line[0,3]=='get' str << " alias :#{function[4..-1] + (returnType==BOOL ? '?' : '')} :#{function}\n" elsif line[0,3]=='set' && !param2 && param1 str << " alias :#{function[4..-1]}= :#{function}\n" end end yield str when COMMENT @in_line_comment = false else end # case line end # def parseLine(line) def caste_param(param, type) return "0" unless param case type when COLOUR result = "#{param}.to_i" when BOOL result = "( #{param} ? 1 : 0 )" else result = param end return result end def un_camelcase(func) result = "" scratch = "" func.each_byte do |byte| if (?A..?Z).include? byte scratch << byte.chr else if scratch.size==1 result += "_"+scratch scratch = "" elsif scratch.size>1 result += "_"+scratch[0..-2]+"_"+scratch[-1,1] scratch = "" end result += byte.chr end end result += "_"+scratch if scratch!="" result = result[1..-1] if result[0,1]=='_' result.downcase end end # class ScintillaParser if __FILE__ == $0 ScintillaGenerator.new("Scintilla.iface", "scintilla_wrapper.rb").generate end