diff options
Diffstat (limited to 'src/3rdparty/phonon/phonon/extractmethodcalls.rb')
-rwxr-xr-x | src/3rdparty/phonon/phonon/extractmethodcalls.rb | 527 |
1 files changed, 527 insertions, 0 deletions
diff --git a/src/3rdparty/phonon/phonon/extractmethodcalls.rb b/src/3rdparty/phonon/phonon/extractmethodcalls.rb new file mode 100755 index 0000000000..910048969e --- /dev/null +++ b/src/3rdparty/phonon/phonon/extractmethodcalls.rb @@ -0,0 +1,527 @@ +#!/usr/bin/ruby + +class MethodDef + def initialize(returnType, signature, optional) + @returnType = returnType + @signature = signature + @optional = optional + end + + attr_reader :returnType, :signature, :optional + attr_writer :optional +end + +class SignalDef + def initialize(signature) + @signature = signature + end + + attr_reader :signature +end + +class Parser + def initialize(filename) + @file = File.new filename, "r" + @signatures = Hash.new + parse + end + + attr_reader :signatures + + private + def addSignal(signature) + unless @signatures.include? signature + @signatures[signature] = SignalDef.new(signature) + end + end + + def addMethod(returnType, signature, optional) + if @signatures.include? signature + if returnType != '' + if @signatures[signature].returnType == '' + optional = false if @signatures[signature].optional == false + @signatures[signature] = MethodDef.new(returnType, signature, optional) + elsif @signatures[signature].returnType != returnType + fail "same signature '#{signature}' but differing return types: #{returnType} and #{@signatures[signature].returnType}" + end + elsif not optional and @signatures[signature].optional + @signatures[signature].optional = false + end + else + @signatures[signature] = MethodDef.new(returnType, signature, optional) + end + end + + PARSER_RETURN_TYPE = 0 + PARSER_RETURN_VAR = 1 + PARSER_METHOD_NAME = 2 + PARSER_ARGUMENT_TYPE = 3 + PARSER_ARGUMENT_VAR = 4 + + PARSER2_CLASSNAME = 0 + PARSER2_METHODPREFIX = 1 + + PARSER3_QMETAOBJECT = 0 + PARSER3_SCOPEDELIMIT = 1 + PARSER3_INVOKEMETHOD = 2 + PARSER3_OPENPARENTH = 3 + PARSER3_BACKENDOBJ = 4 + PARSER3_METHODNAME = 5 + PARSER3_CONNECTION = 6 + PARSER3_RET_OR_ARG = 7 + PARSER3_RET_OPEN = 8 + PARSER3_RET_TYPE = 9 + PARSER3_RET_NAME = 10 + PARSER3_RET_CLOSE = 11 + PARSER3_ARG = 12 + PARSER3_ARG_OPEN = 13 + PARSER3_ARG_TYPE = 14 + PARSER3_ARG_NAME = 15 + PARSER3_ARG_CLOSE = 16 + PARSER3_CLOSE = 17 + PARSER3_DONE = 18 + + PARSER4_OPENING_PAREN = 0 + PARSER4_SENDER = 1 + PARSER4_PRIVATE_SENDER = 2 + PARSER4_COMMA_1 = 3 + PARSER4_SIGNAL_MACRO = 4 + PARSER4_SIGNAL_OPENING_PAREN = 5 + PARSER4_SIGNAL_SIGNATURE = 6 + PARSER4_SIGNAL_SIGNATURE_OPENING_PAREN = 7 + PARSER4_SIGNAL_SIGNATURE_CONST = 8 + PARSER4_SIGNAL_SIGNATURE_TYPE1 = 9 + PARSER4_SIGNAL_SIGNATURE_TYPE2_1 = 10 + PARSER4_SIGNAL_SIGNATURE_TYPE2_2 = 11 + PARSER4_SIGNAL_CLOSING_PAREN = 12 + + def parse + inbackendcall = false + innamedescriptioncall = false + ininvokemethodcall = false + invokemethodcallOnBackendObject = false + inconnect = false + optionalmethod = false + lasttoken = ';' + thistoken = ';' + returnType = String.new + signature = String.new + parserstate = PARSER_RETURN_TYPE + depth = 0 + tokenize do |token| + #STDERR.puts token + lasttoken = thistoken + thistoken = token + token = token[1..-1] if token[0,9] == "pBACKEND_" + if token[0,8] == "BACKEND_" + fail if innamedescriptioncall + fail if inbackendcall + fail if ininvokemethodcall + fail if inconnect + inbackendcall = true + if token[8,3] != "GET" # skip return arg + parserstate = PARSER_METHOD_NAME + returnType = '' + else + parserstate = PARSER_RETURN_TYPE + end + elsif token == 'NAMEDESCRIPTIONFROMINDEX' + fail if innamedescriptioncall + fail if inbackendcall + fail if ininvokemethodcall + fail if inconnect + innamedescriptioncall = true + parserstate = PARSER2_CLASSNAME + elsif token == 'QMetaObject' + fail if innamedescriptioncall + fail if inbackendcall + fail if ininvokemethodcall + fail if inconnect + ininvokemethodcall = true + parserstate = PARSER3_SCOPEDELIMIT + optionalmethod = (lasttoken[-1,1] == '=' or lasttoken == '(' or lasttoken == '!') ? true : false + elsif token == 'connect' + fail if innamedescriptioncall + fail if inbackendcall + fail if ininvokemethodcall + fail if inconnect + inconnect = true + parserstate = PARSER4_OPENING_PAREN + elsif inconnect + #puts "state = #{parserstate}, token = #{token}" + lastparserstate = parserstate + case parserstate + when PARSER4_OPENING_PAREN + parserstate = PARSER4_SENDER if token == '(' + when PARSER4_SENDER + # d->m_backendObject or only m_backendObject + parserstate = PARSER4_COMMA_1 if token == 'm_backendObject' + parserstate = PARSER4_PRIVATE_SENDER if token == 'd' + when PARSER4_PRIVATE_SENDER + parserstate = PARSER4_SENDER if token == '->' + when PARSER4_COMMA_1 + parserstate = PARSER4_SIGNAL_MACRO if token == ',' + when PARSER4_SIGNAL_MACRO + parserstate = PARSER4_SIGNAL_OPENING_PAREN if token == 'SIGNAL' + when PARSER4_SIGNAL_OPENING_PAREN + parserstate = PARSER4_SIGNAL_SIGNATURE if token == '(' + when PARSER4_SIGNAL_SIGNATURE + signature = token + parserstate = PARSER4_SIGNAL_SIGNATURE_OPENING_PAREN + when PARSER4_SIGNAL_SIGNATURE_OPENING_PAREN + case token + when '(' + signature += '(' + parserstate = PARSER4_SIGNAL_SIGNATURE_CONST + when '()' + signature += '()' + parserstate = PARSER4_SIGNAL_CLOSING_PAREN + end + when PARSER4_SIGNAL_SIGNATURE_CONST + case token + when 'const' + signature += 'const ' + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE1 + when ')' + signature += ')' + parserstate = PARSER4_SIGNAL_CLOSING_PAREN + else + signature += token + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_1 + end + when PARSER4_SIGNAL_SIGNATURE_TYPE1 + case token + when 'const' + when ')' + else + signature += token + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_1 + end + when PARSER4_SIGNAL_SIGNATURE_TYPE2_1 + case token + when ',' + signature += ', ' + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE1 + when ')' + signature += ')' + parserstate = PARSER4_SIGNAL_CLOSING_PAREN + else + signature += token + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_2 + end + when PARSER4_SIGNAL_SIGNATURE_TYPE2_2 + case token + when ',' + signature += ', ' + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE1 + when ')' + signature += ')' + parserstate = PARSER4_SIGNAL_CLOSING_PAREN + else + signature += token + parserstate = PARSER4_SIGNAL_SIGNATURE_TYPE2_1 + end + when PARSER4_SIGNAL_CLOSING_PAREN + addSignal(signature) if token == ')' + end + if parserstate == lastparserstate + inconnect = false + signature = String.new + end + elsif ininvokemethodcall + case parserstate + when PARSER3_BACKENDOBJ + if token == ',' + if invokemethodcallOnBackendObject + parserstate += 1 + else + ininvokemethodcall = false + end + elsif token =~ /backendObject/ + invokemethodcallOnBackendObject = true + end + when PARSER3_SCOPEDELIMIT + if token == '::' + parserstate += 1 + else + ininvokemethodcall = false + end + when PARSER3_INVOKEMETHOD + if token == 'invokeMethod' + parserstate += 1 + else + ininvokemethodcall = false + end + when PARSER3_OPENPARENTH + fail if token != '(' + parserstate += 1 + invokemethodcallOnBackendObject = false + when PARSER3_METHODNAME + case token + when ',' + signature += '(' + parserstate = PARSER3_CONNECTION + else + fail if signature.length > 0 + signature = token[1..-2] + end + when PARSER3_CONNECTION + case token + when ',' + parserstate = PARSER3_RET_OR_ARG + when ')' + parserstate = PARSER3_CLOSE +# the connection is optional + when 'Q_RETURN_ARG' + parserstate = PARSER3_RET_OPEN + when 'Q_ARG' + returnType = '' + parserstate = PARSER3_ARG_OPEN + end + when PARSER3_RET_OR_ARG + if token == 'Q_RETURN_ARG' + parserstate = PARSER3_RET_OPEN + elsif token == 'Q_ARG' + returnType = '' + parserstate = PARSER3_ARG_OPEN + else + fail "unexpected token '#{token}" + end + when PARSER3_RET_TYPE + if token == ',' + parserstate += 1 + else + if token == '*' or token == '&' or token == '<' or token == '>' or token == '::' or returnType.empty? or returnType[-1,1] == '<' or returnType[-2,2] == '::' + returnType += token + else + returnType += ' ' + token + end + end + when PARSER3_RET_NAME + parserstate = PARSER3_RET_CLOSE if token == ')' + when PARSER3_RET_CLOSE + case token + when ')' + parserstate = PARSER3_CLOSE + when ',' + parserstate = PARSER3_ARG + end + when PARSER3_ARG + if token == 'Q_ARG' + parserstate = PARSER3_ARG_OPEN + else + fail "unexpected token '#{token}" + end + when PARSER3_ARG_TYPE + if token == ',' + parserstate += 1 + else + signature += ' ' if signature[-1,1] =~ /\w/ and token[0,1] =~ /\w/ + signature += token + end + when PARSER3_ARG_NAME + case token + when '(' + depth += 1 + when ')' + if depth == 0 + parserstate = PARSER3_ARG_CLOSE + else + depth -= 1 + end + end + when PARSER3_ARG_CLOSE + case token + when ',' + signature += ',' + parserstate = PARSER3_ARG + when ')' + parserstate = PARSER3_CLOSE + else + fail + end + when PARSER3_ARG_OPEN, PARSER3_RET_OPEN + fail if token != '(' + parserstate += 1 + when PARSER3_CLOSE + signature += ')' + addMethod returnType, signature, optionalmethod + ininvokemethodcall = false + returnType = String.new + signature = String.new + end + elsif innamedescriptioncall + case parserstate + when PARSER2_CLASSNAME + parserstate = PARSER2_METHODPREFIX if token == ',' + when PARSER2_METHODPREFIX + addMethod 'QSet<int>', token + 'Indexes()', false + addMethod 'int', token + 'Name()', false + addMethod 'int', token + 'Description()', false + innamedescriptioncall = false + end + elsif inbackendcall + next if token == '(' # skip ( + if token == ';' + if signature.length > 0 + signature += ')' + addMethod returnType, signature, false + signature = String.new + returnType = String.new + end + inbackendcall = false + else + if token == ',' + if parserstate == PARSER_ARGUMENT_VAR + signature += ',' + parserstate = PARSER_ARGUMENT_TYPE + else + parserstate += 1 + end + next + end + case parserstate + when PARSER_RETURN_TYPE + returnType += token + when PARSER_RETURN_VAR + when PARSER_METHOD_NAME + next if token == ')' + fail if token[0,1] != '"' or token[-1,1] != '"' + fail if signature.length > 0 + signature = token[1..-2] + '(' + when PARSER_ARGUMENT_TYPE + signature += token + end + end + end + end + end + + def tokenize + incomment = false + instring = false + laststring = '' + linenum = 0 + @file.each_line do |line| + linenum += 1 + line.strip! + next if line[0..1] == "//" + next if line[0,1] == "#" # ignore preprocessor statements + line.split(/(\b|\s+)/).each do |token| + #STDERR.puts "string: #{instring} comment: #{incomment} token: '#{token}'" + if instring + indexOfEscapedQuote = token.index '\\"' + if indexOfEscapedQuote != nil + laststring += token + next + end + indexOfQuote = token.index '"' + if indexOfQuote and indexOfQuote > 0 + fail if token[indexOfQuote-1,1] == '\\' + laststring += token[0..indexOfQuote-1] + token = token[indexOfQuote..-1] + end + if token[0,2] == '""' + laststring += token[2..-1] + next + elsif token[0,1] == '"' + if laststring[-1,1] == '\\' + laststring[-1,1] = '"' + laststring += token[1..-1] + next + end + instring = false + yield laststring + '"' + token = token[1..-1] + else + laststring += token + next + end + end + token.strip! + next if token.empty? + if incomment + incomment = false if token[0..1] == "*/" + next + else + if token[0..1] == "/*" + incomment = true + next + end + break if token == "//" + end + doublequote = token.index '""' + if doublequote != nil + if doublequote > 0 + yield token[0,doublequote] + end + yield '""' + if token.length > doublequote+2 + token = token[doublequote+2..-1] + else + next + end + end + quote = token.index '"' + if quote != nil + laststring = token[quote..-1] + instring = true + if quote > 0 + token = token[0,quote] + else + next + end + end + semicolon = token.index ';' + if not semicolon + tokenize2(token) { |i| yield i } + elsif semicolon > 0 + tokenize2(token[0..semicolon-1]) { |i| yield i } + yield ';' + if token.length > semicolon + 1 + tokenize2(token[semicolon+1..-1]) { |i| yield i } + end + elsif (semicolon == 0 and token.length > 1) + yield ';' + tokenize2(token[1..-1]) { |i| yield i } + else + yield token # a single ; + end + end + end + end + + def tokenize2(token) + if token.length > 1 + #STDERR.puts "long token: #{token}" + while token[0,1] == '(' or token[0,1] == ')' or token[0,1] == "'" or token[0,1] == '&' + yield token[0,1] + token = token[1..-1] + #STDERR.puts "less long token: #{token}" + end + return if token.empty? + if token.length == 1 + yield token + return + elsif token[-1,1] == ',' or token[-1,1] == "'" + yield token[0..-2] + yield token[-1,1] + return + end + end + yield token + end +end + +p = Parser.new ARGV[0] +p.signatures.each do |signature,method| + if method.class == SignalDef + puts "addSignal(\"#{signature}\");" + else + if method.optional + puts "addMethod(\"#{method.returnType}\", \"#{signature}\", true);" + else + puts "addMethod(\"#{method.returnType}\", \"#{signature}\");" + end + end +end |