Class: Talk::Parser

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

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeParser

Returns a new instance of Parser.



17
18
19
20
21
22
# File 'lib/parser.rb', line 17

def initialize
  @contexts = [ Context.context_for_name(:base).new("base", "n/a", "0") ]
  @base = @contexts.first
  @finalized = false
  @closed_contexts = []
end

Instance Attribute Details

#basepathObject

Returns the value of attribute basepath.



10
11
12
# File 'lib/parser.rb', line 10

def basepath
  @basepath
end

Class Method Details

.error(tag, file, line, message) ⇒ Object

Raises:



12
13
14
15
# File 'lib/parser.rb', line 12

def self.error(tag, file, line, message)
  near_msg = tag.nil? ? "" : " near @#{tag}"
  raise ParseError, "#{file}:#{line}  parse error#{near_msg}: #{message}"
end

Instance Method Details

#close_active_contextObject



98
99
100
101
# File 'lib/parser.rb', line 98

def close_active_context
  @closed_contexts.push @contexts.pop
  @contexts.last.end_tag(@closed_contexts.last) unless @contexts.empty?
end

#finalizeObject

signal that we are done parsing files, and it is time to do final validation



25
26
27
28
29
# File 'lib/parser.rb', line 25

def finalize
  close_active_context until @contexts.empty?
  @closed_contexts.each { |ctx| ctx.finalize }
  finalized = true
end

#identifier_from_tag_word(word) ⇒ Object



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

def identifier_from_tag_word(word)
  word[1..-1].to_sym
end

#line_is_comment?(line) ⇒ Boolean

Returns:

  • (Boolean)


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

def line_is_comment?(line)
  line.length > 0 and line[0].length > 0 and line[0][0] == '#'
end

#parse(filename, contents) ⇒ Object



49
50
51
52
# File 'lib/parser.rb', line 49

def parse(filename, contents)
  contents = contents.split("\n") unless contents.is_a? Array
  contents.each_with_index { |line, line_num| parse_line(line.strip.split, filename, line_num+1) }
end

#parse_error(message) ⇒ Object



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

def parse_error(message)
  raise Talk::Parser.error(@tag, @file, @line, message)
end

#parse_file(filename) ⇒ Object



45
46
47
# File 'lib/parser.rb', line 45

def parse_file(filename)
  parse(filename, IO.read(filename))
end

#parse_line(words, file, line) ⇒ Object



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

def parse_line(words, file, line)
  return if line_is_comment?(words)

  @file = trim_filename(file)
  @line = line
  words.each { |word| parse_word(word) }
end

#parse_supported_tagObject



77
78
79
80
81
82
83
84
85
# File 'lib/parser.rb', line 77

def parse_supported_tag
  new_context = @contexts.last.start_tag(@tag, @file, @line)
  if new_context.nil? then
    close_active_context
  else
    @contexts.push new_context
    @closed_contexts.push new_context
  end
end

#parse_tag(tag) ⇒ Object



72
73
74
75
# File 'lib/parser.rb', line 72

def parse_tag(tag)
  @tag = tag
  @contexts.last.has_tag?(tag) ? parse_supported_tag : parse_unsupported_tag
end

#parse_unsupported_tagObject



87
88
89
90
91
92
93
94
95
96
# File 'lib/parser.rb', line 87

def parse_unsupported_tag
  stack = Array.new(@contexts)
  stack.pop until stack.empty? or stack.last.has_tag? @tag

  parse_error("tag not supported in @#{@contexts.last.tag.to_s}") if stack.empty?

  close_active_context until @contexts.last == stack.last

  parse_supported_tag
end

#parse_word(word) ⇒ Object



62
63
64
65
66
67
68
69
70
# File 'lib/parser.rb', line 62

def parse_word(word)
  @word = word

  if word_is_tag?(word) then
    parse_tag(identifier_from_tag_word(word))
  else
    @contexts.last.parse(word, @file, @line)
  end
end

#resultsObject



31
32
33
34
# File 'lib/parser.rb', line 31

def results
  finalize unless @finalized
  @base.to_h
end

#trim_filename(filename) ⇒ Object



36
37
38
39
40
41
42
43
# File 'lib/parser.rb', line 36

def trim_filename(filename)
  if @basepath.nil? == false and filename.start_with? @basepath then
    filename = filename[@basepath.length .. -1]
    filename = filename[1..-1] while filename.start_with? "/"
  end

  filename
end

#word_is_tag?(word) ⇒ Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/parser.rb', line 103

def word_is_tag?(word)
  word[0] == '@'
end