Class: Luoma::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/luoma/parser.rb,
sig/luoma/parser.rbs

Direct Known Subclasses

UnifiedParser

Constant Summary collapse

TERMINATE_EXPRESSION =

Returns:

  • (Set[t_token_kind])
Set.new(%i[
  token_wc
  token_out_end
  token_tag_end
  token_text
  token_rparen
  token_eoi
  token_if
  token_else
  token_interpolation_end
]).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env, source, template_name, tokens) ⇒ Parser

(Environment, String, String, Array) -> void

Parameters:

  • env (Environment)
  • source (String)
  • template_name (String)
  • tokens (Array[t_token])


25
26
27
28
29
30
31
32
33
34
# File 'lib/luoma/parser.rb', line 25

def initialize(env, source, template_name, tokens)
  @env = env
  @source = source
  @template_name = template_name
  @tokens = tokens

  @pos = 0
  @eoi = [:token_eoi, source.length, source.length]
  @whitespace_control_carry = nil #: "-" | "+" | "~" | nil
end

Instance Attribute Details

#envEnvironment (readonly)

Returns the value of attribute env.

Returns:



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

def env
  @env
end

#sourceString (readonly)

Returns the value of attribute source.

Returns:

  • (String)


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

def source
  @source
end

#template_nameString (readonly)

Returns the value of attribute template_name.

Returns:

  • (String)


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

def template_name
  @template_name
end

Class Method Details

.parse(env, source, template_name, tokens) ⇒ t_block

(Environment, String, String, Array) -> t_block

Parameters:

  • env (Environment)
  • source (String)
  • template_name (String)
  • tokens (Array[t_token])

Returns:

  • (t_block)


20
21
22
# File 'lib/luoma/parser.rb', line 20

def self.parse(env, source, template_name, tokens)
  new(env, source, template_name, tokens).parse_block
end

Instance Method Details

#carry_whitespace_controlvoid

This method returns an undefined value.

() -> void



37
38
39
# File 'lib/luoma/parser.rb', line 37

def carry_whitespace_control
  @whitespace_control_carry = (Luoma.get_token_value(self.next, @source) if kind == :token_wc)
end

#currentt_token

() -> t_token

Returns:

  • (t_token)


42
43
44
# File 'lib/luoma/parser.rb', line 42

def current
  @tokens[@pos] || @eoi
end

#current_valueString

() -> String

Returns:

  • (String)


52
53
54
# File 'lib/luoma/parser.rb', line 52

def current_value
  Luoma.get_token_value(@tokens[@pos] || @eoi, @source)
end

#eat(kind, message: nil) ⇒ t_token

(t_token_kind, ?message: String?) -> t_token

Parameters:

  • kind (t_token_kind)
  • message: (String, nil) (defaults to: nil)

Returns:

  • (t_token)


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/luoma/parser.rb', line 68

def eat(kind, message: nil)
  token = @tokens[@pos] || @eoi
  unless token.first == kind
    kind_ = Luoma::TOKEN_KIND_MAP[token.first]
    value = Luoma.get_token_value(token, @source).inspect
    raise TemplateSyntaxError.new(
      message || "unexpected #{kind_} (#{value})",
      token,
      @source,
      @template_name
    )
  end

  @pos += 1
  token
end

#eat_empty_tag(name) ⇒ t_token

(String) -> t_token

Parameters:

  • name (String)

Returns:

  • (t_token)


86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/luoma/parser.rb', line 86

def eat_empty_tag(name)
  eat(:token_tag_start, message: "expected tag #{name}")
  @pos += 1 if kind == :token_wc # steep:ignore
  token = eat(:token_tag_name, message: "expected tag #{name}")
  got = Luoma.get_token_value(token, @source)

  unless got == name
    raise TemplateSyntaxError.new(
      "unexpected tag #{got.inspect}",
      token,
      @source,
      @template_name
    )
  end

  carry_whitespace_control
  eat(:token_tag_end, message: "expected a closing tag delimiter")
  token
end

#eat_one_of(kinds) ⇒ t_token

(Set) -> t_token

Parameters:

  • kinds (Set[t_token_kind])

Returns:

  • (t_token)


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/luoma/parser.rb', line 107

def eat_one_of(kinds)
  token = @tokens[@pos] || @eoi
  unless kinds.include?(token.first)
    kind_ = Luoma::TOKEN_KIND_MAP[token.first]
    value = Luoma.get_token_value(token, @source).inspect
    raise TemplateSyntaxError.new(
      "unexpected #{kind_} (#{value})",
      token,
      @source,
      @template_name
    )
  end

  @pos += 1
  token
end

#eat_tag(name) ⇒ t_token

(String) -> t_token

Parameters:

  • name (String)

Returns:

  • (t_token)


125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/luoma/parser.rb', line 125

def eat_tag(name)
  eat(:token_tag_start, message: "expected tag #{name}")
  @pos += 1 if kind == :token_wc # steep:ignore
  token = eat(:token_tag_name, message: "expected tag #{name}")
  got = Luoma.get_token_value(token, @source)

  unless got == name
    raise TemplateSyntaxError.new(
      "unexpected tag #{got.inspect}",
      token,
      @source,
      @template_name
    )
  end

  # Ignore everything between the tag name and the closing tag delimiter.
  @pos += 1 until TERMINATE_EXPRESSION.include?(kind)

  carry_whitespace_control
  eat(:token_tag_end, message: "expected a closing tag delimiter")
  token
end

#expect_expressionvoid

This method returns an undefined value.

Raise an error if we're not at the start of an expression. () -> void



150
151
152
153
154
155
156
157
158
159
# File 'lib/luoma/parser.rb', line 150

def expect_expression
  if TERMINATE_EXPRESSION.include?(kind)
    raise TemplateSyntaxError.new(
      "missing expression",
      current,
      @source,
      @template_name
    )
  end
end

#kindt_token_kind

() -> t_token_kind

Returns:

  • (t_token_kind)


47
48
49
# File 'lib/luoma/parser.rb', line 47

def kind
  (@tokens[@pos] || @eoi).first #: t_token_kind
end

#nextt_token

() -> t_token

Returns:

  • (t_token)


57
58
59
60
61
# File 'lib/luoma/parser.rb', line 57

def next
  token = @tokens[@pos] || @eoi
  @pos += 1
  token
end

#parse_arguments(require_commas: nil) ⇒ Array[Expression | KeywordArgument]

(?require_commas: bool?) -> Array[Expression | KeywordArgument]

Parameters:

  • require_commas: (Boolean, nil) (defaults to: nil)

Returns:



162
163
164
# File 'lib/luoma/parser.rb', line 162

def parse_arguments(require_commas: nil)
  raise "not implemented"
end

#parse_block(stop: nil) ⇒ t_block

(?stop: Set?) -> t_block

Parameters:

  • stop: (Set[String], nil) (defaults to: nil)

Returns:

  • (t_block)


167
168
169
# File 'lib/luoma/parser.rb', line 167

def parse_block(stop: nil)
  raise "not implemented"
end

#parse_expression(precedence: 1) ⇒ Expression

(?precedence: Integer) -> Expression

Parameters:

  • precedence: (Integer) (defaults to: 1)

Returns:



172
173
174
# File 'lib/luoma/parser.rb', line 172

def parse_expression(precedence: 1)
  raise "not implemented"
end

#parse_identName

() -> Name

Returns:



177
178
179
# File 'lib/luoma/parser.rb', line 177

def parse_ident
  raise "not implemented"
end

#parse_keyword_arguments(require_commas: nil) ⇒ Array[KeywordArgument]

(?require_commas: bool?) -> Array

Parameters:

  • require_commas: (Boolean, nil) (defaults to: nil)

Returns:



182
183
184
# File 'lib/luoma/parser.rb', line 182

def parse_keyword_arguments(require_commas: nil)
  raise "not implemented"
end

#parse_nameName

Parse an identifier, possibly surrounded by quotes. () -> Name

Returns:



188
189
190
# File 'lib/luoma/parser.rb', line 188

def parse_name
  raise "not implemented"
end

#parse_positional_arguments(require_commas: nil) ⇒ Array[Expression]

(?require_commas: bool?) -> Array

Parameters:

  • require_commas: (Boolean, nil) (defaults to: nil)

Returns:



193
194
195
# File 'lib/luoma/parser.rb', line 193

def parse_positional_arguments(require_commas: nil)
  raise "not implemented"
end

#parse_string_literalStringLiteral

() -> StringLiteral

Returns:



198
199
200
# File 'lib/luoma/parser.rb', line 198

def parse_string_literal
  raise "not implemented"
end

#peek(offset = 1) ⇒ t_token

Parameters:

  • offset (::Integer) (defaults to: 1)

Returns:

  • (t_token)


63
64
65
# File 'lib/luoma/parser.rb', line 63

def peek(offset = 1)
  @tokens[@pos + offset] || @eoi
end

#peek_tag_nameString

() -> String

Returns:

  • (String)


203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/luoma/parser.rb', line 203

def peek_tag_name
  token = current
  token = peek if token.first == :token_wc

  unless token.first == :token_tag_name
    raise TemplateSyntaxError.new(
      "missing tag name",
      token,
      @source,
      @template_name
    )
  end

  Luoma.get_token_value(token, @source)
end

#peek_whitespace_controlString?

() -> String?

Returns:

  • (String, nil)


220
221
222
223
# File 'lib/luoma/parser.rb', line 220

def peek_whitespace_control
  token = peek
  Luoma.get_token_value(token, @source) if token.first == :token_wc
end

#skip_whitespace_controlvoid

This method returns an undefined value.

() -> void



226
227
228
# File 'lib/luoma/parser.rb', line 226

def skip_whitespace_control
  @pos += 1 if kind == :token_wc
end

#tag?(name) ⇒ Boolean

Return true if we're at the start of a tag named name. (String) -> bool

Parameters:

  • name (String)

Returns:

  • (Boolean)


232
233
234
235
236
237
# File 'lib/luoma/parser.rb', line 232

def tag?(name)
  token = peek
  token = peek(2) if token.first == :token_wc

  token.first == :token_tag_name && Luoma.get_token_value(token, @source) == name
end

#tags(names) ⇒ String?

(Set) -> String?

Parameters:

  • names (Set[String])

Returns:

  • (String, nil)


242
243
244
245
246
247
248
249
250
# File 'lib/luoma/parser.rb', line 242

def tags(names)
  token = peek
  token = peek(2) if token.first == :token_wc

  return unless token.first == :token_tag_name

  name = Luoma.get_token_value(token, @source)
  name if names.include?(name)
end