Sha256: 65dcd5cbc50d769628972da080d761424b85eaaed5da9acbb38e97b00a4c04db

Contents?: true

Size: 1.37 KB

Versions: 1

Compression:

Stored size: 1.37 KB

Contents

require 'strscan'	

class SexpistolParser < StringScanner

  def initialize(string)
    unless(string.count('(') == string.count(')'))
      raise Exception, "Missing closing parentheses"
    end
    super(string)
  end

  def parse
    exp = []
    while true
      case fetch_token
        when '('
          exp << parse
        when ')'
          break
        when :"'"
          case fetch_token
          when '(' then exp << [:quote].concat([parse])
          else exp << [:quote, @token]
          end
        when String, Fixnum, Bignum, Float, Symbol
          exp << @token
        when nil
          break
      end
    end
    exp
  end
  
  def fetch_token
    skip(/\s+/)
    return nil if(eos?)

    @token =
    # Match parentheses
    if scan(/[\(\)]/)
      matched
    # Match a string literal
    elsif scan(/"([^"\\]|\\.)*"/)
      eval(matched)
    # Match a float literal
    elsif scan(/[\-\+]? [0-9]+ ((e[0-9]+) | (\.[0-9]+(e[0-9]+)?))/x)
      matched.to_f
    # Match an integer literal
    elsif scan(/[\-\+]?[0-9]+/)
      matched.to_i
    # Match a comma (for comma quoting)
    elsif scan(/'/)
      matched.to_sym
    # Match a symbol
    elsif scan(/[^\(\)\s]+/)
      matched.to_sym
    # If we've gotten here then we have an invalid token
    else
      near = scan %r{.{0,20}}
      raise "Invalid character at position #{pos} near '#{near}'."
    end
  end

end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
deil_sexpistol-0.0.9 lib/sexpistol/sexpistol_parser.rb