Class: SexpistolParser

Inherits:
StringScanner
  • Object
show all
Defined in:
lib/vendor/sexpistol/sexpistol/sexpistol_parser.rb

Instance Method Summary collapse

Constructor Details

#initialize(string) ⇒ SexpistolParser

Returns a new instance of SexpistolParser.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/vendor/sexpistol/sexpistol/sexpistol_parser.rb', line 5

def initialize(string)
  # step through string counting closing parens, exclude parens in string literals
  in_string_literal = false
  escape_char = false
  paren_count = 0
  string.bytes.each do |byte|
    if escape_char
      escape_char = false
      next
    end

    case byte.chr
    when '\\'
      escape_char = true
      next
    when '('
      if !in_string_literal
        paren_count += 1
      end
    when ')'
      if !in_string_literal
        paren_count -= 1
      end
    when '"'
      in_string_literal = !in_string_literal
    end
  end

  if paren_count > 0
    raise Exception, "Missing closing parentheses"
  elsif paren_count < 0
    raise Exception, "Missing opening parentheses"
  end

  super(string)
end

Instance Method Details

#fetch_tokenObject



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/vendor/sexpistol/sexpistol/sexpistol_parser.rb', line 64

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]+)?))(\)| )(\s|$)/x)
    matched.to_f
  # Match an integer literal
  elsif scan(/[\-\+]?[0-9]+(\)| )(\s|$)/x)
    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

#parseObject



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/vendor/sexpistol/sexpistol/sexpistol_parser.rb', line 42

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, Float, Symbol
        exp << @token
      when nil
        break
    end
  end
  exp
end