Class: ReVIEW::Compiler

Inherits:
Object show all
Includes:
Loggable
Defined in:
lib/review/compiler.rb

Defined Under Namespace

Classes: InlineSyntaxElement, SyntaxElement

Constant Summary collapse

MAX_HEADLINE_LEVEL =
6
SYNTAX =
{}
INLINE =
{}

Instance Attribute Summary collapse

Attributes included from Loggable

#logger

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Loggable

#app_error, #debug, #error!, #warn

Constructor Details

#initialize(builder) ⇒ Compiler

Returns a new instance of Compiler.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/review/compiler.rb', line 22

def initialize(builder)
  @builder = builder

  ## commands which do not parse block lines in compiler
  @non_parsed_commands = %i[embed texequation graph]

  ## to decide escaping/non-escaping for text
  @command_name_stack = []

  @logger = ReVIEW.logger

  @ignore_errors = builder.is_a?(ReVIEW::IndexBuilder)

  @compile_errors = nil
end

Instance Attribute Details

#builderObject (readonly)

Returns the value of attribute builder.



38
39
40
# File 'lib/review/compiler.rb', line 38

def builder
  @builder
end

#previous_list_typeObject (readonly)

Returns the value of attribute previous_list_type.



38
39
40
# File 'lib/review/compiler.rb', line 38

def previous_list_type
  @previous_list_type
end

Class Method Details

.defblock(name, argc, optional = false, &block) ⇒ Object



107
108
109
# File 'lib/review/compiler.rb', line 107

def self.defblock(name, argc, optional = false, &block)
  defsyntax(name, (optional ? :optional : :block), argc, &block)
end

.definline(name) ⇒ Object



123
124
125
# File 'lib/review/compiler.rb', line 123

def self.definline(name)
  INLINE[name] = InlineSyntaxElement.new(name)
end

.defminicolumn(name, argc, _optional = false, &block) ⇒ Object



111
112
113
# File 'lib/review/compiler.rb', line 111

def self.defminicolumn(name, argc, _optional = false, &block)
  defsyntax(name, :minicolumn, argc, &block)
end

.defsingle(name, argc, &block) ⇒ Object



115
116
117
# File 'lib/review/compiler.rb', line 115

def self.defsingle(name, argc, &block)
  defsyntax(name, :line, argc, &block)
end

.defsyntax(name, type, argc, &block) ⇒ Object



119
120
121
# File 'lib/review/compiler.rb', line 119

def self.defsyntax(name, type, argc, &block)
  SYNTAX[name] = SyntaxElement.new(name, type, argc, &block)
end

.minicolumn_namesObject



127
128
129
130
131
132
133
134
135
# File 'lib/review/compiler.rb', line 127

def self.minicolumn_names
  buf = []
  SYNTAX.each do |name, syntax|
    if syntax.minicolumn?
      buf << name.to_s
    end
  end
  buf
end

Instance Method Details

#compile(chap) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/review/compiler.rb', line 53

def compile(chap)
  @chapter = chap
  do_compile
  if @compile_errors
    raise ApplicationError, "#{location.filename} cannot be compiled."
  end

  @builder.result
end

#inline_defined?(name) ⇒ Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/review/compiler.rb', line 155

def inline_defined?(name)
  INLINE.key?(name.to_sym)
end

#non_escaped_commandsObject



45
46
47
48
49
50
51
# File 'lib/review/compiler.rb', line 45

def non_escaped_commands
  if @builder.highlight?
    %i[list emlist listnum emlistnum cmd source]
  else
    []
  end
end

#strategyObject



40
41
42
43
# File 'lib/review/compiler.rb', line 40

def strategy
  error 'Compiler#strategy is obsoleted. Use Compiler#builder.'
  @builder
end

#syntax_defined?(name) ⇒ Boolean

Returns:

  • (Boolean)


137
138
139
# File 'lib/review/compiler.rb', line 137

def syntax_defined?(name)
  SYNTAX.key?(name.to_sym)
end

#syntax_descriptor(name) ⇒ Object



141
142
143
# File 'lib/review/compiler.rb', line 141

def syntax_descriptor(name)
  SYNTAX[name.to_sym]
end

#text(str, block_mode = false) ⇒ Object



666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
# File 'lib/review/compiler.rb', line 666

def text(str, block_mode = false)
  return '' if str.empty?

  words = replace_fence(str).split(/(@<\w+>\{(?:[^}\\]|\\.)*?\})/, -1)
  words.each do |w|
    if w.scan(/@<\w+>/).size > 1 && !/\A@<raw>/.match(w)
      error "`@<xxx>' seen but is not valid inline op: #{w}", location: location
    end
  end
  result = ''
  until words.empty?
    result << if in_non_escaped_command? && block_mode
                revert_replace_fence(words.shift)
              else
                @builder.nofunc_text(revert_replace_fence(words.shift))
              end
    break if words.empty?

    result << compile_inline(revert_replace_fence(words.shift.gsub(/\\\}/, '}').gsub(/\\\\/, '\\')))
  end
  result
rescue StandardError => e
  error e.message, location: location
end