Module: Liquidscript::Compiler::Base::Helpers

Included in:
Liquidscript::Compiler::Base
Defined in:
lib/liquidscript/compiler/base/helpers.rb

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



21
22
23
# File 'lib/liquidscript/compiler/base/helpers.rb', line 21

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

Instance Method Details

#action(act = nil) { ... } ⇒ Proc, Action

Normalizes an action for the hash passed to #expect. If a block is given, it returns that block. If the argument is a proc, it returns that proc. If none of those conditions are met, it returns the Action.

Parameters:

  • act (Proc, nil) (defaults to: nil)

    the proc to return, if it is a proc.

Yields:

  • nothing.

Returns:



33
34
35
36
37
38
39
40
41
# File 'lib/liquidscript/compiler/base/helpers.rb', line 33

def action(act = nil)
  if block_given?
    Proc.new
  elsif act.is_a? Proc
    act
  else
    @action
  end
end

#expect(*args) ⇒ Object

The meat and potatos of the compiler. This maps actions to tokens. In its basic form, it is passed a hash, with the keys being token types, and the values the corresponding actions to take. It can be passed individual types, from which it’ll assume the method name (normally, ‘compile_<type>`); or, you can pass it a symbol key, which is the last part of the method name (i.e., not including `compile_`). It will check the next token, and look for the correct action; if the next token doesn’t match any of the given keys, it checks for the special type ‘:_` (which is basically a catch-all), and if it still doesn’t get it, it raises an UnexpectedError. From there, it calls the corresponding block.

If the block or method accepts one argument, it Liquidscript::Compiler::Base#pops the token, and passes it in as an argument. If it accepts no arguments, it doesn’t.

Examples:

# If the next token has type `:test`, it will output
# "hello!"  If the next token has any other type, it
# raises an error.
expect :test => action { puts "hello!" }
# If the next token has the type `:number`, it calls
# the method `compile_number`; if the next token has
# the type `:dstring`, it calls the method
# `compile_string`.
expect :number, :dstring => :string
# Just pops the comma token.
expect :comma => action.shift
# When given a hash with one of the keys as an array, each
# element of that array is treated as a token type, and
# that token type is mapped to the value as an action.
expect [:identifier, :dstring] => action.end_loop
# When given `:_` as an argument, it'll map the next token
# to its corresponding compile function.
expect :_
# If the next token's type is `:identifier`, it will call
# `compile_identifier`.

Parameters:

  • *args (Array<Symbol, Hash<Symbol, Object>>)

Returns:

  • (Object)

    the result of the block/method call.

Raises:

  • (UnexpectedError)

    if the next token’s type didn’t match any of the given types, and the ‘:_` type wasn’t given.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/liquidscript/compiler/base/helpers.rb', line 134

def expect(*args)
  hash = normalize_arguments(args)
  allowable = false

  block = hash.fetch(peek.type) do
    hash.fetch(:_) do
      allowable = true
      self.allowable.fetch(peek.type)
    end
  end

  out = if block.arity == 1
    block.call pop
  else
    block.call
  end

  if allowable
    expect(*args)
  else
    out
  end

rescue KeyError
  raise UnexpectedError.new(hash.keys, peek)
end

#loopvoid

This method returns an undefined value.

Performs a loop while the yield returns true. This overwrites the core loop on purpose.

Yield Returns:

  • (Boolean)

    whether or not to continue looping.



48
49
50
51
52
53
54
# File 'lib/liquidscript/compiler/base/helpers.rb', line 48

def loop
  result = true

  while result
    result = yield
  end
end

#maybe(*types) ⇒ #type

Shifts a token if its one of the given types; if it’s not, it returns the value of Liquidscript::Compiler::Base#scanner_nil.

Parameters:

  • types (Symbol)

    the token types to look for.

Returns:

  • (#type)

    the token.



72
73
74
# File 'lib/liquidscript/compiler/base/helpers.rb', line 72

def maybe(*types)
  expect types => action.shift, :_ => action { scanner_nil }
end

#peek?(*types) ⇒ Boolean

Checks to see if the next token is of any of the given types. Note that the special type ‘:_` does not work here.

Parameters:

  • types (Symbol)

    the token types to match.

Returns:

  • (Boolean)

    whether or not the next token’s type matches any of the given types.



82
83
84
# File 'lib/liquidscript/compiler/base/helpers.rb', line 82

def peek?(*types)
  types.any? { |type| peek.type == type }
end

#shift(*types) ⇒ #type

Shift a token over. The given types can be any types. If the next token’s type doesn’t match any of the types, then it will raise an error. In order to shift any token, use the special type ‘:_`.

Parameters:

  • types (Symbol)

    the token types to look for.

Returns:

  • (#type)

    the token.



63
64
65
# File 'lib/liquidscript/compiler/base/helpers.rb', line 63

def shift(*types)
  expect types => action.shift
end