Class: MiniHTML::Parser

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source) ⇒ Parser

Returns a new instance of Parser.

Raises:



7
8
9
10
11
12
13
14
# File 'lib/minihtml/parser.rb', line 7

def initialize(source)
  scanner = MiniHTML::Scanner.new(source)
  tokens = scanner.tokenize
  raise ParseError.new(*scanner.errors) unless scanner.errors.empty?

  @stream = MiniHTML::TokenStream.new(tokens)
  @tokens = []
end

Instance Attribute Details

#streamObject (readonly)

Returns the value of attribute stream.



5
6
7
# File 'lib/minihtml/parser.rb', line 5

def stream
  @stream
end

Instance Method Details

#discard_until_tag_endObject



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

def discard_until_tag_end
  stream.consume until stream.empty? || %i[tag_end tag_closing_end].include?(stream.peek_kind)
  stream.consume # Consume tag_end or tag_closing_end
end

#parseObject



16
17
18
19
# File 'lib/minihtml/parser.rb', line 16

def parse
  @tokens << parse_one until stream.empty?
  @tokens
end

#parse_attrObject



104
105
106
107
108
109
110
111
# File 'lib/minihtml/parser.rb', line 104

def parse_attr
  att = AST::Attr.new(stream.consume)
  return att unless stream.peek_kind == :equal

  stream.consume # equal
  att.value = parse_one
  att
end

#parse_commentObject



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

def parse_comment
  stream.consume
  AST::Comment.new(stream.consume) unless stream.empty?
end

#parse_oneObject



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/minihtml/parser.rb', line 21

def parse_one
  case stream.peek_kind
  when :literal
    AST::PlainText.new(stream.consume)
  when :tag_begin
    if stream.peek[:literal] == "<!--"
      parse_comment
    else
      parse_tag
    end
  when :attr_value_unquoted
    AST::Literal.new(stream.consume)
  when :string
    AST::String.new(stream.consume)
  when :executable
    AST::Executable.new(stream.consume)
  when :string_interpolation
    parse_string_interpolation
  when :tag_closing_start
    tag = AST::Tag.new(stream.consume)
    discard_until_tag_end
    tag
  else
    raise "Unexpected token type #{stream.peek_kind} on #parse_one"
  end
end

#parse_string_interpolationObject



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/minihtml/parser.rb', line 53

def parse_string_interpolation
  interp = AST::Interpolation.new(stream.consume)
  until stream.empty?
    case stream.peek_kind
    when :executable
      interp.values << parse_one
    when :string_interpolation
      interp.values << AST::String.new(stream.consume)
    when :string
      interp.values << AST::String.new(stream.consume)
      return interp
    when :interpolated_executable
      interp.values << AST::Executable.new(stream.consume)
    else
      raise "Unexpected token type #{stream.peek_kind} on #parse_string_interpolation"
    end
  end
  interp
end

#parse_tagObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/minihtml/parser.rb', line 78

def parse_tag
  tag = AST::Tag.new(stream.consume)
  until stream.empty?
    case stream.peek_kind
    when :right_angled
      stream.consume
      # This tag has children...
      tag.children << parse_one until stream.peek_kind == :tag_closing_start || stream.empty?
    when :tag_closing_start
      if stream.peek[:literal][2...] == tag.name
        # Consume everything until a closing_end
        discard_until_tag_end
        return tag
      end
    when :tag_end
      stream.consume
      tag.self_closing = true
      return tag
    when :attr_key
      tag.attributes << parse_attr
    else
      raise "Unexpected token type #{stream.peek_kind} on #parse_tag"
    end
  end
end