Module: Yoga::Parser::Helpers

Defined in:
lib/yoga/parser/helpers.rb

Overview

helpers that manage the state of the parser. This can be things like peeking, shifting, and erroring.

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Internal ruby construct.


260
261
262
# File 'lib/yoga/parser/helpers.rb', line 260

def self.included(base)
  base.extend ClassMethods
end

Instance Method Details

#collect(ending, join = nil) ⇒ ::Array

"Collects" a set of nodes until a terminating token. It yields until the peek is the token.

Parameters:

  • ending (::Symbol)

    The terminating token.

  • join (::Symbol, nil) (defaults to: nil)

    The token that joins each of the children. This is the comma between arguments.

Returns:

  • (::Array)

    The collected nodes from the yielding process.


174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/yoga/parser/helpers.rb', line 174

def collect(ending, join = nil)
  children = []
  join = Utils.flatten_into_set([join]) if join
  ending = Utils.flatten_into_set([ending]) if ending

  return [] if (ending && peek?(ending)) || (!ending && !join)

  children << yield

  cond = proc do
    (join ? peek?(join) && expect(join) : true) &&
      !(ending && peek?(ending))
  end

  (children << yield) while cond.call
  children
end

#error(tokens) ⇒ void

This method returns an undefined value.

Errors, noting the expected tokens, the given token, the location of given tokens. It does this by failing.

Parameters:

  • tokens (<::Symbol>)

    The expected tokens.


251
252
253
254
# File 'lib/yoga/parser/helpers.rb', line 251

def error(tokens)
  fail Yoga::UnexpectedTokenError, expected: tokens, got: peek.kind,
    location: peek.location
end

#expect(*tokens) ⇒ Yoga::Token

Sets up an expectation for a given token. If the next token is an expected token, it shifts, returning the token; otherwise, it #errors with the token information.

Parameters:

  • tokens (<::Symbol>)

    The expected tokens.

Returns:


232
233
234
235
236
# File 'lib/yoga/parser/helpers.rb', line 232

def expect(*tokens)
  tokens = Utils.flatten_into_set(tokens)
  return shift if peek?(*tokens)
  error(tokens.flatten)
end

#first(name) ⇒ ::Set<::Symbol>

Retrieves the first set for the given node name.

Parameters:

  • name (::Symbol)

Returns:

  • (::Set<::Symbol>)

242
243
244
# File 'lib/yoga/parser/helpers.rb', line 242

def first(name)
  self.class.first(name)
end

#peekYoga::Token

Peeks to the next token. If peeking would cause a StopIteration error, it instead returns the last value that was peeked.

Returns:


114
115
116
117
118
# File 'lib/yoga/parser/helpers.rb', line 114

def peek
  @_last = (@buffer.any? ? @buffer.first : @tokens.peek)
rescue ::StopIteration
  @_last
end

#peek?(*tokens) ⇒ ::Boolean

Checks to see if any of the given kinds includes the next token.

Parameters:

  • tokens (<::Symbol>)

    The possible kinds.

Returns:

  • (::Boolean)

199
200
201
202
# File 'lib/yoga/parser/helpers.rb', line 199

def peek?(*tokens)
  tokens = Utils.flatten_into_set(tokens)
  tokens.include?(peek.kind)
end

#peek_out(to) ⇒ Yoga::Token

Peeks out to a given token. If peeking would cause a StopIteration error, it instead returns the last value that was peeked. This is an expensive operation, and should be used sparingly. All other methods work as normal, even after this.

Parameters:

  • to (::Numeric)

    The distance to peek to.

Returns:


127
128
129
130
131
132
133
# File 'lib/yoga/parser/helpers.rb', line 127

def peek_out(to)
  return @buffer[to] if to <= @buffer.size
  (to - @buffer.size + 1).times { @buffer << @tokens.next }
  @buffer.last
rescue ::StopIteration
  @buffer.last
end

#peek_out?(to, tokens) ⇒ ::Boolean

Peeks out to a specific point in the future to match. This is an expensive operation.

Parameters:

  • to (::Numeric)

    The distance to peek to.

  • tokens (<::Symbol>)

    The kinds of tokens to check for.

Returns:

  • (::Boolean)

See Also:


212
213
214
215
# File 'lib/yoga/parser/helpers.rb', line 212

def peek_out?(to, tokens)
  tokens = Utils.flatten_into_set([tokens])
  tokens.include?(peek_out(to).kind)
end

#push(*tokens) ⇒ self Also known as: <<

Pushes back tokens onto the buffer. These, in reverse order, are the tokens that are pulled out by peek/1, peek_to/1, expect/1, and shift/1.

Parameters:

Returns:

  • (self)

141
142
143
144
# File 'lib/yoga/parser/helpers.rb', line 141

def push(*tokens)
  tokens.each { |t| @buffer.push(t) }
  self
end

#shiftYoga::Token

Shifts to the next token, and returns the old token.

Returns:


220
221
222
223
224
# File 'lib/yoga/parser/helpers.rb', line 220

def shift
  @buffer.any? ? @buffer.shift : @tokens.next
rescue ::StopIteration
  fail InvalidShiftError, location: peek.location
end

#switch(name, *param, token: peek) ⇒ ::Object

Switches the function executed based on the given nodes. If the peeked node matches one of the mappings, it calls the resulting block or method.

If the peeked token is not in the map, then #error is called.

Parameters:

  • name (::Symbol)

    The name of the switch to use.

Returns:

  • (::Object)

    The result of calling the block.

See Also:


157
158
159
160
161
162
# File 'lib/yoga/parser/helpers.rb', line 157

def switch(name, *param, token: peek)
  switch = self.class.switch(name)
  block = switch
          .fetch(token.kind) { switch.fetch(:$else) { error(switch.keys) } }
  instance_exec(*param, &block)
end