class Korekto::Main

Constants

BACKUPS
MD_FILENAME
MD_KEY_VALUE
MD_KLASS_METHOD_DEFINITION
MD_RULE
MD_STATEMENT_CODE_TITLE
MD_TYPE_PATTERN
MD_TYPE_VARIABLES
M_COMMENT_LINE
M_FENCE

Public Class Methods

new(filename='-', statements: Statements.new, imports: []) click to toggle source
# File lib/korekto/main.rb, line 16
def initialize(filename='-', statements: Statements.new, imports: [])
  @filename,@statements,@imports = filename,statements,imports
  @imports.push @filename.freeze
  @line,@active = nil,false
  @section = File.basename(@filename,'.*')
  @m_fence_korekto = /^```korekto$/
end

Public Instance Methods

active?() click to toggle source
# File lib/korekto/main.rb, line 40
def active?
  case @line
  when @m_fence_korekto
    raise Error, 'unexpected fence' if @active
    @active = true
    false
  when M_FENCE
    @active = false
    false
  else
    @active and not M_COMMENT_LINE.match?(@line)
  end
end
key_value(key, value) click to toggle source
# File lib/korekto/main.rb, line 63
def key_value(key, value)
  case key
  when 'scanner'
    @statements.symbols.set_scanner value
  when 'fence'
    @m_fence_korekto = Regexp.new "^```#{value}$"
  when 'section'
    @section = value
  when 'save'
    BACKUPS[value] = Marshal.dump(@statements)
  when 'restore'
    if backup = BACKUPS[value]
      @statements = Marshal.load(backup)
    else
      raise Error, "nothing saved as '#{value}'"
    end
  else
    raise Error, "key '#{key}' not implemented"
  end
end
parse(lines) click to toggle source
# File lib/korekto/main.rb, line 107
def parse(lines)
  statement_number = line_number = 0
  while @line = lines.shift
    begin
      line_number += 1
      next unless active?
      next if preprocess?
      if md = MD_STATEMENT_CODE_TITLE.match(@line)
        code,title = @statements.add(md[:statement].strip,
                                     md[:code],
                                     md[:title],
                                     @section){ statement_number += 1 }
        if not OPTIONS.edits? or (@filename=='-' and not (md[:code]==code and md[:title]==title))
          puts "#{@filename}:#{line_number}:#{code}:#{title}"
        end
      else
        raise Error, 'unrecognized korekto line'
      end
    rescue Error
      puts "#{@filename}:#{line_number}:!:#{$!.message}"
      exit 65
    rescue Exception
      puts "#{@filename}:#{line_number}:?:#{$!.message}"
      $stderr.puts $!.backtrace
      exit 1
    end
  end
end
patch(klass, method, definition) click to toggle source
# File lib/korekto/main.rb, line 54
  def patch(klass, method, definition)
    raise Error, "overrides: #{klass}##{method}" if eval(klass).method_defined? method
    eval <<~EVAL
      class #{klass}
        def #{method}#{definition}
      end
    EVAL
  end
preprocess?() click to toggle source
# File lib/korekto/main.rb, line 84
def preprocess?
  case @line
  when MD_FILENAME
    filename = $~[:filename].strip
    unless @imports.include? filename
      Main.new(filename, statements:@statements, imports:@imports).run
    end
  when MD_KLASS_METHOD_DEFINITION
    patch($~[:klass],$~[:method],$~[:definition])
  when MD_RULE
    @statements.syntax.push $~[:rule].strip
  when MD_TYPE_PATTERN
    type_pattern($~[:type], $~[:pattern])
  when MD_TYPE_VARIABLES
    type_variables($~[:type], $~[:variables].split)
  when MD_KEY_VALUE
    key_value($~[:key], $~[:value])
  else
    return false
  end
  true
end
run() click to toggle source
# File lib/korekto/main.rb, line 136
def run
  if @filename=='-'
    parse $stdin.readlines(chomp: true)
  else
    parse IO.readlines(@filename, chomp: true)
  end
end
type_pattern(type, pattern) click to toggle source
# File lib/korekto/main.rb, line 24
def type_pattern(type, pattern)
  t2p = @statements.symbols.t2p
  raise Error, "type #{type} in use" if t2p.has_key? type
  t2p[type] = pattern
end
type_variables(type, variables) click to toggle source
# File lib/korekto/main.rb, line 30
def type_variables(type, variables)
  v2t,t2p = @statements.symbols.v2t,@statements.symbols.t2p
  pattern = t2p[type]
  raise Error, "type #{type} not defined" unless pattern
  variables.each do |variable|
    raise Error, "variable #{variable} in use" if v2t.has_key? variable
    v2t[variable] = type
  end
end