lib/liquidscript/compiler/base/helpers.rb in liquidscript-0.0.1 vs lib/liquidscript/compiler/base/helpers.rb in liquidscript-0.1.0

- old
+ new

@@ -81,10 +81,79 @@ # matches any of the given types. def peek?(*types) types.any? { |type| peek.type == type } end + # @overload collect_compiles(compile, *end_on) + # Calls the method `:compile_#{compile}` for every peeked + # token that isn't a part of `end_on`. Once it encounters + # that, it returns the values of all of those calls. If the + # last element of `end_on` is a Hash, it is merged with the + # default actions that this takes and passes it to `expect`. + # + # @example + # def compile_if + # shift :if + # shift :lparen + # conditional = compile_expression + # shift :rparen + # shift :lbrack + # body = collect_compiles(:expression, :rbrack) + # [:if, conditional, body] + # end + # @param compile [Symbol] the method to call. + # @param end_on [Array<Symbol>] an array of symbols to end + # the loop. + # @return [Array<Object>] + # + # @overload collect_compiles(*end_on, &block) + # Calls the block for every peeked token that isn't in + # `end_on`. Once it encounters a token that it, it returns + # the value of all of the block calls. If the + # last element of `end_on` is a Hash, it is merged with the + # default actions that this takes and passes it to `expect`. + # + # @example + # collect_compiles(:test) { shift :_ } + # + # @yieldreturn The value you want to be placed in the + # array. + # @param end_on [Array<Symbol>] an array of symbols to end + # the loop. + # @return [Array<Object>] the results of all of the block + # calls. + def collect_compiles(*end_on) + compiles = [] + + if block_given? + compile = Proc.new + else + compile = end_on.shift + end + + block = Callable.new(self, compile) + + hash = if end_on.last.is_a? Hash + end_on.pop.dup + else + {} + end + + do_compile = action do + compiles << block.call + end + + hash.merge! end_on => action.end_loop, + :_ => do_compile + + loop do + expect hash + end + + compiles + end + # 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, @@ -174,10 +243,10 @@ # # @param args [Array<Hash, Symbol>] # @return [Hash] def normalize_arguments(args) hash = if args.last.is_a? Hash - args.pop + args.pop.dup else {} end args.inject(hash) do |h, a|