Class: Clojure::Reader
- Inherits:
-
Object
- Object
- Clojure::Reader
- Defined in:
- lib/clojure/reader.rb
Overview
read Clojure as Ruby’s data-structures
Instance Attribute Summary collapse
-
#ast ⇒ Object
readonly
Returns the value of attribute ast.
Instance Method Summary collapse
- #cursor ⇒ Object
- #eof? ⇒ Boolean
-
#initialize(source) ⇒ Reader
constructor
A new instance of Reader.
- #inspect ⇒ Object
- #next_char ⇒ Object
- #read_form(till: ")", into: []) ⇒ Object
- #read_keyword ⇒ Object
-
#read_next ⇒ Object
rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/AbcSize.
- #read_number ⇒ Object
- #read_quote ⇒ Object
- #read_sexp_comment ⇒ Object
-
#read_special ⇒ Object
rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/AbcSize.
-
#read_string ⇒ Object
rubocop:disable Metrics/AbcSize.
-
#read_symbol ⇒ Object
rubocop:enable Metrics/AbcSize.
- #skip_char ⇒ Object
- #skip_comment ⇒ Object
Constructor Details
#initialize(source) ⇒ Reader
Returns a new instance of Reader.
6 7 8 9 10 11 12 13 14 15 16 |
# File 'lib/clojure/reader.rb', line 6 def initialize(source) @source = source @io = StringIO.new source @ast = [] loop do break if eof? r = read_next @ast << r if r end end |
Instance Attribute Details
#ast ⇒ Object (readonly)
Returns the value of attribute ast.
22 23 24 |
# File 'lib/clojure/reader.rb', line 22 def ast @ast end |
Instance Method Details
#cursor ⇒ Object
24 25 26 |
# File 'lib/clojure/reader.rb', line 24 def cursor @cursor || next_char end |
#eof? ⇒ Boolean
28 29 30 |
# File 'lib/clojure/reader.rb', line 28 def eof? @cursor == :eof end |
#inspect ⇒ Object
18 19 20 |
# File 'lib/clojure/reader.rb', line 18 def inspect @ast end |
#next_char ⇒ Object
32 33 34 |
# File 'lib/clojure/reader.rb', line 32 def next_char @cursor = @io.getc || :eof end |
#read_form(till: ")", into: []) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/clojure/reader.rb', line 83 def read_form(till: ")", into: []) opening = cursor skip_char # opening parenthesis ast = into until cursor == till raise StandardError, "Unbalanced #{opening}#{till}" if eof? r = read_next ast << r if r end skip_char # closing parenthesis ast end |
#read_keyword ⇒ Object
107 108 109 110 111 112 |
# File 'lib/clojure/reader.rb', line 107 def read_keyword next_char k = cursor k << cursor while next_char.match(/\w|\.|#|-|_/) k.to_sym end |
#read_next ⇒ Object
rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/AbcSize
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/clojure/reader.rb', line 38 def read_next # puts "reading next" # puts "-> #{cursor}" case cursor when :eof then nil when /\s|,/ then skip_char when /;/ then skip_comment when /\d/ then read_number when /\(/ then read_form when /\[/ then read_form till: "]", into: ["vector"] when /\{/ then read_form till: "}", into: ["hash-map"] when /:/ then read_keyword when /"/ then read_string when /'/ then read_quote when /\#/ then read_special when /\S/ then read_symbol else raise StandardError, "Unexpected symbol: #{cursor}" end end |
#read_number ⇒ Object
97 98 99 100 101 102 103 104 105 |
# File 'lib/clojure/reader.rb', line 97 def read_number n = cursor n << cursor while next_char.match(/[\d|.]/) begin Integer(n) rescue StandardError Float(n) end end |
#read_quote ⇒ Object
114 115 116 117 |
# File 'lib/clojure/reader.rb', line 114 def read_quote skip_char # ' ["quote", read_next] end |
#read_sexp_comment ⇒ Object
67 68 69 70 71 |
# File 'lib/clojure/reader.rb', line 67 def read_sexp_comment next_char read_next nil end |
#read_special ⇒ Object
rubocop:enable Metrics/CyclomaticComplexity rubocop:enable Metrics/AbcSize
60 61 62 63 64 65 |
# File 'lib/clojure/reader.rb', line 60 def read_special case next_char when /_/ then read_sexp_comment else raise StandardError, "Unknown token: ##{cursor}" end end |
#read_string ⇒ Object
rubocop:disable Metrics/AbcSize
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/clojure/reader.rb', line 120 def read_string next_char if cursor == '"' next_char return ["str", ["quote", ""]] end s = cursor.dup prev = cursor until next_char == '"' && prev != "\\" if cursor != "\\" s << if prev == "\\" && cursor != '"' "\\#{cursor}" else cursor end end prev = cursor end next_char ["str", ["quote", s]] end |
#read_symbol ⇒ Object
rubocop:enable Metrics/AbcSize
143 144 145 146 147 |
# File 'lib/clojure/reader.rb', line 143 def read_symbol symbol = cursor symbol << cursor while next_char.match(%r{\w|-|\.|\?|\+|/}) symbol end |
#skip_char ⇒ Object
73 74 75 76 |
# File 'lib/clojure/reader.rb', line 73 def skip_char next_char nil end |
#skip_comment ⇒ Object
78 79 80 81 |
# File 'lib/clojure/reader.rb', line 78 def skip_comment next_char until cursor == "\n" || eof? nil end |