Sha256: 1eb357fd415ba6c236975b5d077c57740e1f43875d5b9994d7b3f2c5e7ca733a

Contents?: true

Size: 1.73 KB

Versions: 4

Compression:

Stored size: 1.73 KB

Contents

require 'strscan'

class Sapluuna
  class Parser
    CODE_OPEN      = '<%\s*'
    CODE_CLOSE     = '\s*%>'
    TEMPLATE_OPEN  = '[\t ]*{{{[\t ]*'
    TEMPLATE_CLOSE = '[\t ]*}}}[\t ]*\n?'
    NEW_LINE       = "\n"
    class ParserError < Error; end
    class UnterminatedBlock < ParserError; end

    def initialize
      @sc    = StringScanner.new ''
    end

    def parse input
      level      = 0
      cfg        = []
      @sc.string = input
      loop do
        if @sc.scan_until Regexp.new(TEMPLATE_OPEN)
          cfg << [:template, get_labels, get_template(level)]
        else
          break
        end
      end
      @sc.string = '' # no need to keep it in memory
      cfg
    end

    private

    def get_labels
      labels = @sc.scan_until Regexp.new(NEW_LINE)
      labels.strip.split(/\s+/)
    end

    def re_combine *args
      re = args.map do |arg|
        '(?:%s)' % arg
      end.join('|')
      Regexp.new re
    end

    def clean_scan scan
      endstr = -(@sc.matched.size+1)
      scan[0..endstr]
    end

    def get_template level
      cfg = []
      loop do
        scan = @sc.scan_until re_combine(CODE_OPEN, TEMPLATE_OPEN, TEMPLATE_CLOSE)
        raise UnterminatedBlock, "template at #{level}, #{@sc.pos} runs forever" unless scan
        cfg << [:cfg, clean_scan(scan)]
        case @sc.matched

        when Regexp.new(CODE_OPEN)
          scan = @sc.scan_until Regexp.new(CODE_CLOSE)
          raise UnterminatedBlock, "code at #{level}, #{@sc.pos} runs forever" unless scan
          cfg << [:code, clean_scan(scan)]

        when Regexp.new(TEMPLATE_OPEN)
          cfg << [:template, get_labels, get_template(level+1)]

        when Regexp.new(TEMPLATE_CLOSE)
          return cfg
        end
      end
    end

  end
end

Version data entries

4 entries across 4 versions & 1 rubygems

Version Path
sapluuna-0.2.0 lib/sapluuna/parser.rb
sapluuna-0.1.7 lib/sapluuna/parser.rb
sapluuna-0.1.6 lib/sapluuna/parser.rb
sapluuna-0.1.5 lib/sapluuna/parser.rb