module FStrings::Parser

@private

Constants

NOVALUE

Public Class Methods

str2code(string) click to toggle source
# File lib/fstrings/parser.rb, line 33
def str2code(string)
  scan = StringScanner.new(string)
  Enumerator.produce {
    [
      scan_simple(scan).inspect,
      (statement2code(**scan_statement(scan)) unless scan.eos?)
    ]
  }.slice_after { scan.eos? }.first.flatten.compact.join(' + ')
end

Private Class Methods

scan_simple(scan) click to toggle source
# File lib/fstrings/parser.rb, line 45
def scan_simple(scan)
  str = scan.scan_until(/\{|$/)
  if scan.peek(1) == '{'
    str + scan.scan(/\{/) + scan_simple(scan)
  else
    str.sub(/\{$/, '')
  end
end
scan_statement(scan) click to toggle source
# File lib/fstrings/parser.rb, line 54
def scan_statement(scan)
  expr, char = scan.scan_until(/[}%]/).then { |str| [str[0...-1], str[-1]] }
  # fmt will include the first %-char which also signifies it
  fmt, = scan.scan_until(/\}/).then { |str| [str[0...-1], str[-1]] } if char == '%'
  if expr.match?(/\s*=\s*$/)
    prefix = expr
    expr = expr.sub(/\s*=\s*$/, '')
  end
  {expr: expr.strip, fmt: fmt&.then(&'%%%s'), prefix: prefix}
end
statement2code(expr:, fmt:, prefix:) click to toggle source
# File lib/fstrings/parser.rb, line 65
def statement2code(expr:, fmt:, prefix:)
  [
    prefix&.then(&'%p +'),
    fmt&.then { 'FStrings::Formats.apply(' },
    '(',
    expr,
    ')',
    fmt&.then(&', %p)'),
    '.to_s'
  ].compact.join
end

Public Instance Methods

produce(initial = NOVALUE) { || ... } click to toggle source
# File lib/fstrings/parser.rb, line 18
def produce(initial = NOVALUE)
  Enumerator.new do |y|
    val = initial == NOVALUE ? yield() : initial

    loop do
      y << val
      val = yield(val)
    end
  end
end
to_proc() click to toggle source
# File lib/fstrings/parser.rb, line 8
def to_proc
  method(:%).to_proc
end