Class: Korekto::Main

Inherits:
Object
  • Object
show all
Defined in:
lib/korekto/main.rb

Constant Summary collapse

MD_STATEMENT_CODE_TITLE =
%r{^(?<statement>.*)\s#(?<code>[A-Z](\d+(/[\w,.]+)?)?)( (?<title>\S.*?\S))?$}
MD_FILENAME =
%r{^< (?<filename>[/\w\-.]+)$}
MD_KLASS_METHOD_DEFINITION =

patch

/^(?<klass>::[A-Z]\w+)#(?<method>\w+)(?<definition>[^=]*=.+)$/
MD_RULE =
/^[?] (?<rule>\S.*)$/
MD_TYPE_PATTERN =
%r{^! (?<type>\S+)\s*/(?<pattern>.*)/$}
MD_TYPE_VARIABLES =
/^! (?<type>\S+)\s*\{(?<variables>\S+( \S+)*)\}$/
MD_KEY_VALUE =
/^! (?<key>\w+):\s*'(?<value>.*)'$/
M_FENCE =
/^```\s*$/
M_COMMENT_LINE =
/^\s*#/
BACKUPS =
{}

Instance Method Summary collapse

Constructor Details

#initialize(filename = '-', statements: Statements.new, imports: []) ⇒ Main

Returns a new instance of Main.



16
17
18
19
20
21
22
# 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

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


40
41
42
43
44
45
46
47
48
49
50
51
52
# 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) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 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) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# 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)
        statement_number += 1
        code,title = @statements.add(md[:statement].strip,
                                     md[:code],
                                     md[:title],
                                     @section,
                                     statement_number)
        puts "#{@filename}:#{line_number}:#{code}:#{title}"
      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) ⇒ Object

Raises:



54
55
56
57
58
59
60
61
# File 'lib/korekto/main.rb', line 54

def patch(klass, method, definition)
  raise Error, "overrides: #{klass}##{method}" if eval(klass).method_defined? method
  eval "    class \#{klass}\n      def \#{method}\#{definition}\n    end\n  EVAL\nend\n"

#preprocess?Boolean

Returns:

  • (Boolean)


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# 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

#runObject



136
137
138
139
140
141
142
# 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) ⇒ Object

Raises:



24
25
26
27
28
# 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) ⇒ Object

Raises:



30
31
32
33
34
35
36
37
38
# 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