class Frepl::Classifier

Constants

ARRAY_VALUE_REGEX
ASSIGNABLE_REGEX
ASSIGNABLE_VALUE_REGEX

TODO this regex seems incorrect, e.g. assignable value can't start with most punctuation

ASSIGNMENT_REGEX
BUILTIN_TYPE_REGEX
DECLARABLE_TYPE_REGEX
DECLARATION_REGEX

TODO: parameter/dimension order shouldn't matter here

DERIVED_TYPE_IDENTIFIER_REGEX
DERIVED_TYPE_REGEX
DO_LOOP_REGEX
F2003_ARRAY_VALUE_REGEX
FUNCTION_REGEX
IF_STATEMENT_REGEX
OLDSKOOL_ARRAY_VALUE_REGEX
SUBROUTINE_REGEX
VARIABLE_NAME_REGEX
WHERE_REGEX

Public Class Methods

new() click to toggle source
# File lib/frepl/classifier.rb, line 23
def initialize
  @all_lines = []
  @current_lines = []
  @current_multiline_obj = nil
end

Public Instance Methods

allocation?() click to toggle source
# File lib/frepl/classifier.rb, line 90
def allocation?
  current_line.match(/allocate\(/) != nil
end
assignment?() click to toggle source
# File lib/frepl/classifier.rb, line 98
def assignment?
  current_line.match(ASSIGNMENT_REGEX)
end
classify(line) click to toggle source
# File lib/frepl/classifier.rb, line 29
def classify(line)
  if @current_multiline_obj && !@current_multiline_obj.incomplete?
    @current_multiline_obj = nil
    @current_lines = []
  end

  @all_lines << line
  @current_lines << line

  if multiline?(line)
    Frepl.log("MULTILINE")
    classify_multiline(line)
    return @current_multiline_obj
  else
    return classify_single_line(line)
  end
end
declaration?() click to toggle source

TODO this is stupid, may need real parser here

# File lib/frepl/classifier.rb, line 80
def declaration?
  m = current_line.match(DECLARATION_REGEX)
  return false unless m
  if m[7].gsub(ARRAY_VALUE_REGEX, '').count(',') == 0
    true
  else
    false
  end
end
executable?() click to toggle source
# File lib/frepl/classifier.rb, line 52
def executable?
  !get_more_lines?
end
indentation_level() click to toggle source
# File lib/frepl/classifier.rb, line 106
def indentation_level
  if @current_multiline_obj && @current_multiline_obj.incomplete?
    2
  else
    0
  end
end
interrupt() click to toggle source
# File lib/frepl/classifier.rb, line 47
def interrupt
  @current_multiline_obj = nil
  @current_lines = []
end
lines_to_execute() click to toggle source
# File lib/frepl/classifier.rb, line 56
def lines_to_execute
  @current_lines
end
multi_declaration?() click to toggle source

TODO this is stupid, may need real parser here

# File lib/frepl/classifier.rb, line 69
def multi_declaration?
  m = current_line.match(DECLARATION_REGEX)
  return false unless m
  if m[7].gsub(ARRAY_VALUE_REGEX, '').count(',') > 0
    true
  else
    false
  end
end
multiline?(line) click to toggle source
# File lib/frepl/classifier.rb, line 60
def multiline?(line)
  line.match(/\Asubroutine|function|(?:#{IF_STATEMENT_REGEX})|(?:#{DO_LOOP_REGEX})|(?:#{DERIVED_TYPE_REGEX})|(?:#{WHERE_REGEX})\z/i) || @current_multiline_obj != nil
end
repl_command?() click to toggle source
# File lib/frepl/classifier.rb, line 64
def repl_command?
  current_line.start_with?('f:')
end
run?() click to toggle source
# File lib/frepl/classifier.rb, line 94
def run?
  current_line.match(/\s*write|print|read|call/i) != nil
end
standalone_variable?() click to toggle source
# File lib/frepl/classifier.rb, line 102
def standalone_variable?
  current_line.match(/\A#{VARIABLE_NAME_REGEX}\z/)
end

Private Instance Methods

blank?() click to toggle source
# File lib/frepl/classifier.rb, line 182
def blank?
  current_line.match(/\A\s*\z/)
end
classify_multiline(line) click to toggle source
# File lib/frepl/classifier.rb, line 116
def classify_multiline(line)
  if @current_lines.size == 1
    raise 'Already have multiline obj' unless @current_multiline_obj.nil?
    if line.match(/function/)
      @current_multiline_obj = Function.new
    elsif line.match(/subroutine/)
      @current_multiline_obj = Subroutine.new
    elsif line.match(IF_STATEMENT_REGEX)
      @current_multiline_obj = IfStatement.new
    elsif line.match(DO_LOOP_REGEX)
      @current_multiline_obj = DoLoop.new
    elsif line.match(/\A#{DERIVED_TYPE_REGEX}\z/)
      @current_multiline_obj = DerivedType.new
    elsif line.match(/\A#{WHERE_REGEX}\z/)
      @current_multiline_obj = Where.new
    end
  end
  @current_multiline_obj.lines << line
end
classify_single_line(line) click to toggle source
# File lib/frepl/classifier.rb, line 136
def classify_single_line(line)
  obj = if repl_command?
    ReplCommand.new(line)
  elsif multi_declaration?
    MultiDeclaration.new(line)
  elsif declaration?
    Declaration.new(line)
  elsif run?
    Execution.new(line)
  elsif assignment?
    Assignment.new(line)
  elsif allocation?
    Allocation.new(line)
  elsif standalone_variable?
    StandaloneVariable.new(line)
  elsif ignorable?
    nil
  else
    puts "I don't think `#{line}` is valid Fortran. You made a mistake, or, more likely, I'm dumb."
    @all_lines.pop
    obj = nil
  end
  @current_lines = []
  obj
end
comment?() click to toggle source
# File lib/frepl/classifier.rb, line 186
def comment?
  current_line.match(/\A!/)
end
current_line() click to toggle source
# File lib/frepl/classifier.rb, line 162
def current_line
  @current_lines.last
end
done_multiline?() click to toggle source
# File lib/frepl/classifier.rb, line 170
def done_multiline?
  @current_lines.size > 0 && @current_lines.last.match(/end subroutine|end function/)
end
get_more_lines?() click to toggle source
# File lib/frepl/classifier.rb, line 166
def get_more_lines?
  @current_lines.size > 0 || @current_lines.last.match(/subroutine|function/)
end
ignorable?() click to toggle source
# File lib/frepl/classifier.rb, line 174
def ignorable?
  program_statements? || blank? || comment?
end
program_statements?() click to toggle source
# File lib/frepl/classifier.rb, line 178
def program_statements?
  current_line.match(/\Aprogram .+|implicit .+|\Aend program/) != nil
end