class ZRB::Parser

Constants

EXPR_CLOSE
SPACE
TOKEN

Attributes

data[R]
filename[R]
lineno[R]
source[R]

Public Class Methods

new(data, filename, lineno) click to toggle source
# File lib/zrb.rb, line 5
def initialize(data, filename, lineno)
  @data = data
  @filename = filename
  @lineno = lineno
  @source = ""
  @state = :ruby
  generate
end

Public Instance Methods

append_expr(ruby) click to toggle source
# File lib/zrb.rb, line 103
def append_expr(ruby)
  ensure_string
  source << "\#{buffer.escape((#{ruby}))}"
end
append_newline() click to toggle source
# File lib/zrb.rb, line 114
def append_newline
  if @state == :string
    source << "\"\\\n\""
  else
    source << "\n"
  end
end
append_ruby(ruby) click to toggle source
# File lib/zrb.rb, line 108
def append_ruby(ruby)
  source << '";' if @state == :string
  source << ruby
  @state = :ruby
end
append_text(text) click to toggle source
# File lib/zrb.rb, line 96
def append_text(text)
  escaped = text.split("\n", -1).map { |part| part.inspect[1..-2] }.join("\n")

  ensure_string
  source << escaped
end
ensure_string() click to toggle source
# File lib/zrb.rb, line 89
def ensure_string
  if @state != :string
    source << 'buffer << "'
    @state = :string
  end
end
generate() click to toggle source
# File lib/zrb.rb, line 122
def generate
  append_ruby('buffer = build_zrb_buffer;')

  parse do |type, value|
    case type
    when :text
      append_text(value)
    when :expression
      append_expr(value)
    when :block_expression
      append_ruby("buffer.safe_append=#{value};")
    when :statement
      append_ruby("#{value};")
    when :newline
      append_newline
    when :comment
      # no nothing
    else
      raise "internal error: unknown parsing type"
    end
  end

  append_ruby('buffer')
end
parse() { |:text, text| ... } click to toggle source
# File lib/zrb.rb, line 34
def parse
  pos = 0
  while pos < data.size
    match = data.match(TOKEN, pos)
    raise SyntaxError, "#{filename}:#{lineno}: parse error" unless match
    all, text, expr, _, statement, statement_space = *match
    pos += all.size

    yield :text, text unless text.empty?

    if expr
      # Start looking for a closing brace
      closing_pos = pos
      begin
        closing_pos = data.index(EXPR_CLOSE, closing_pos + 1)
        break unless closing_pos
        expr = data[pos...closing_pos]
      end until valid_ruby?(expr)

      if !closing_pos
        raise SyntaxError, "#{filename}:#{lineno}: unclosed brace"
      end

      yield :expression, expr

      pos = closing_pos + 1
    end

    if statement
      case statement[0]
      when ?=
        # block expression
        yield :block_expression, statement[1..-1]
      when ?#
        # comment
        yield :comment, statement[1..-1]
      else
        yield :statement, statement
      end
    end

    yield :newline if statement_space
  end 
end
valid_ruby?(text) click to toggle source
# File lib/zrb.rb, line 79
def valid_ruby?(text)
  catch(:halt) do
    eval("BEGIN{throw :halt};#{text}")
  end
rescue SyntaxError
  false
else
  true
end