Преглед на файлове

Add a working preliminary version of the ruby parser. Still need to add

a rule for running it in the Rakefile.

Add:
    parser_server.rb:
        - listens for connections from the python client process

    parser.rb:
        - creates a syntax tree from the input and returns relevant data
          about it to the client
tags/v1.0^2
Benjamin Attal преди 10 години
родител
ревизия
7f1d9dd2d3
променени са 3 файла, в които са добавени 152 реда и са изтрити 2 реда
  1. +5
    -2
      .gitignore
  2. +22
    -0
      parsers/ruby/lib/parse_server.rb
  3. +125
    -0
      parsers/ruby/lib/parser.rb

+ 5
- 2
.gitignore Целия файл

@@ -42,8 +42,11 @@ nosetests.xml
.pydevproject

# Maven
parsers/java/target/*
target

# Ruby
!parsers/ruby/lib

# Ctags
*/tags
logs/*
log

+ 22
- 0
parsers/ruby/lib/parse_server.rb Целия файл

@@ -0,0 +1,22 @@
require 'socket'
require File.expand_path('../parser.rb', __FILE__)

server = TCPServer.new 5003

loop do
# Start a new thread for each client accepted
Thread.start(server.accept) do |client|
begin
# Get the amount of data to be read
size = (client.readline).to_i
p = Bitshift::Parser.new client.read(size)
# Get the parsed result
symbols = p.parse.to_s
client.puts [symbols.length].pack('c')
client.puts symbols
ensure
# Close the socket
client.close
end
end
end

+ 125
- 0
parsers/ruby/lib/parser.rb Целия файл

@@ -0,0 +1,125 @@
require 'socket'
require 'ruby_parser'
require 'sexp_processor'

module Bitshift
class Parser
def initialize(source)
@source = source
end

def parse
parser = RubyParser.new
tree = parser.parse(@source)
offset = tree.line - 1
processor = NodeVisitor.new offset
processor.process tree
return processor.symbols
end
end

class NodeVisitor < SexpProcessor
attr_accessor :symbols
attr_accessor :offset

def initialize(offset)
super()
@require_empty = false
@offset = offset

module_hash = Hash.new {|hash, key| hash[key] = Hash.new}
class_hash = module_hash.clone
function_hash = Hash.new {|hash, key| hash[key] = { calls: [] } }
var_hash = Hash.new {|hash, key| hash[key] = [] }

@symbols = {
modules: module_hash,
classes: class_hash,
functions: function_hash,
vars: var_hash
}
end

def block_position(exp)
pos = Hash.new
end_ln = (start_ln = exp.line - offset)
cur_exp = exp

while cur_exp.is_a? Sexp
end_ln = cur_exp.line - offset
cur_exp = cur_exp.last
break if cur_exp == nil
end

pos[:coord] = {
start_ln: start_ln,
end_ln: end_ln }
return pos
end

def statement_position(exp)
pos = Hash.new
end_ln = start_ln = exp.line - offset

pos[:coord] = {
start_ln: start_ln,
end_ln: end_ln }
return pos
end

def process_module(exp)
pos = block_position exp
exp.shift
name = exp.shift
symbols[:modules][name] = pos
exp.each_sexp {|s| process(s)}
return exp.clear
end

def process_class(exp)
pos = block_position exp
exp.shift
name = exp.shift
symbols[:classes][name] = pos
exp.each_sexp {|s| process(s)}
return exp.clear
end

def process_defn(exp)
pos = block_position exp
exp.shift
name = exp.shift
symbols[:functions][name][:declaration] = pos
exp.each_sexp {|s| process(s)}
return exp.clear
end

def process_call(exp)
pos = statement_position exp
exp.shift
exp.shift
name = exp.shift
symbols[:functions][name][:calls] << pos
exp.each_sexp {|s| process(s)}
return exp.clear
end

def process_iasgn(exp)
pos = statement_position exp
exp.shift
name = exp.shift
symbols[:vars][name] << pos
exp.each_sexp {|s| process(s)}
return exp.clear
end

def process_lasgn(exp)
pos = statement_position exp
exp.shift
name = exp.shift
symbols[:vars][name] << pos
exp.each_sexp {|s| process(s)}
return exp.clear
end
end
end

Зареждане…
Отказ
Запис