redjazz96/liquidscript

View on GitHub
lib/liquidscript/scanner/base/lexer.rb

Summary

Maintainability
A
25 mins
Test Coverage
module Liquidscript
  module Scanner
    class Base
      module Lexer

        def perform_with_context(context, scanner = @scanner)
          key, value = context.find_matcher(scanner)

          if value.nil? && scanner.rest?
            error scanner, context
          end

          normalize_action key, value, scanner if scanner.rest?
        end

        def lex(*args)
          args.flatten!
          to_lex = args.pop

          context, body = if to_lex.is_a? Hash
            to_lex.to_a.first
          else
            [to_lex, nil]
          end

          scanner = if body
            StringScanner.new(body)
          else
            @scanner
          end
          out = []

          context = find_context(context)
          instance_exec(*args, &context.init)

          while scanner.rest? && out.last != EXIT
            out << perform_with_context(context, scanner)
          end

          out
        end

        def error(scanner = @scanner, context = @context,
                  file = @metadata[:file])
          raise SyntaxError, "Unexpected " +
            "#{scanner.matched}#{scanner.peek(2)}".inspect +
            " (line: #{line}, column: #{column}, file: #{file})"
        end

        private

        def find_context(name)
          context = contexts.dup.keep_if { |c|
            c.name == name
          }.to_a.first

          if context.nil?
            raise NoContextError.new(name)
          end

          context
        end

        def exit
          EXIT
        end

        def normalize_action(key, value, scanner)
          body = scanner.scan(key)

          case value
          when Proc
            instance_exec(*body.match(key), &value)
          when Symbol
            lex(*body.match(key), value)
          when EXIT
            EXIT
          end
        end

      end
    end
  end
end