rbscmlex 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +1 -1
- data/lib/rbscmlex/lexer.rb +108 -26
- data/lib/rbscmlex/token.rb +48 -22
- data/lib/rbscmlex/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec8d6513252c0196840bfc388ab2cb429d5d1cb579e5fb23d034e6509ab24bf5
|
4
|
+
data.tar.gz: fd952eecb26646994dcfe9786fa5678b68f5ab04191009079f47acedaba1af3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6344300170f133448eb6f6b1646ffa0e617a900c3df87b00f9a48cd6c008da73e8b9161cac4afb4d752a37c3981cd7ad1fa324c48044d484c26cd836bcfe5cc9
|
7
|
+
data.tar.gz: ecf7e267663faa64023c1f72ed82fac38b799d2fd370d7a6725e512780618ebbd70f121bf8031abb3738f9827dbd5e7c855ad700055b18dbbec2b79356d3f16b
|
data/CHANGELOG.md
CHANGED
@@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
## [Unreleased]
|
8
8
|
- (nothing to record here)
|
9
9
|
|
10
|
+
## [0.1.2] - 2021-05-07
|
11
|
+
### Added
|
12
|
+
- Add a mechanism to initialize a Parser instance from an array of
|
13
|
+
tokens, which already created from source of Scheme.
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
- Fix issue #3: a wrong link in `README.md`.
|
17
|
+
|
10
18
|
## [0.1.1] - 2021-05-06
|
11
19
|
### Fixed
|
12
20
|
- Fix issue #1: `rbscmlex` fails to read from STDIN.
|
data/README.md
CHANGED
@@ -28,7 +28,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
28
28
|
|
29
29
|
## Contributing
|
30
30
|
|
31
|
-
Bug reports and pull requests are welcome on GitHub at [https://github.com/mnbi/
|
31
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/mnbi/rbscmlex](https://github.com/mnbi/rbscmlex).
|
32
32
|
|
33
33
|
|
34
34
|
## License
|
data/lib/rbscmlex/lexer.rb
CHANGED
@@ -64,56 +64,136 @@ module Rbscmlex
|
|
64
64
|
|
65
65
|
include Enumerable
|
66
66
|
|
67
|
-
def initialize(
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
def initialize(obj, form: TOKEN_DEFAULT_FORM)
|
68
|
+
set_form(form)
|
69
|
+
init_pos
|
70
|
+
case obj
|
71
|
+
when String
|
72
|
+
# obj must be source program of Scheme.
|
73
|
+
@tokens = tokenize(obj)
|
74
|
+
when Array
|
75
|
+
# obj might be an array of tokens.
|
76
|
+
input_form = detect_form(obj[0])
|
77
|
+
case input_form
|
78
|
+
when :hash, :json, :token
|
79
|
+
@tokens = read_tokens(obj, form: input_form)
|
80
|
+
else
|
81
|
+
raise InvalidConversionTypeError, "cannot convert #{obj[0]} as token"
|
82
|
+
end
|
83
|
+
else
|
84
|
+
raise InvalidConversionTypeError, "cannot convert #{obj} as tokens"
|
85
|
+
end
|
86
|
+
end
|
71
87
|
|
72
|
-
|
88
|
+
def [](index)
|
89
|
+
convert(@tokens[index])
|
73
90
|
end
|
74
91
|
|
75
92
|
def each(&blk)
|
76
93
|
if block_given?
|
77
|
-
@tokens.each
|
94
|
+
@tokens.each { |tk|
|
95
|
+
yield convert(tk)
|
96
|
+
}
|
78
97
|
self
|
79
98
|
else
|
80
|
-
|
99
|
+
to_a.to_enum
|
81
100
|
end
|
82
101
|
end
|
83
102
|
|
84
103
|
def to_a
|
85
|
-
@tokens
|
104
|
+
convert_all(@tokens)
|
86
105
|
end
|
87
106
|
|
88
107
|
def size
|
89
|
-
@size
|
108
|
+
@tokens.size
|
90
109
|
end
|
91
110
|
|
92
111
|
def current_token
|
93
|
-
|
112
|
+
self[@current_pos]
|
94
113
|
end
|
95
114
|
|
96
115
|
def next_token
|
97
116
|
check_pos
|
98
117
|
@current_pos = @next_pos
|
99
118
|
@next_pos += 1
|
100
|
-
|
119
|
+
self[@current_pos]
|
101
120
|
end
|
102
121
|
|
103
122
|
def peek_token(num = 0)
|
104
123
|
check_pos
|
105
|
-
|
124
|
+
self[@next_pos + num]
|
106
125
|
end
|
107
126
|
|
108
127
|
def rewind
|
109
|
-
|
128
|
+
init_pos
|
110
129
|
self
|
111
130
|
end
|
112
131
|
|
132
|
+
# :stopdoc:
|
133
|
+
|
113
134
|
private
|
114
135
|
|
136
|
+
def set_form(form)
|
137
|
+
if TOKEN_FORMS.include?(form)
|
138
|
+
@form = form
|
139
|
+
else
|
140
|
+
raise InvalidConversionTypeError, "cannot generate #{form} as token"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def init_pos
|
145
|
+
@current_pos = @next_pos = 0
|
146
|
+
end
|
147
|
+
|
148
|
+
def read_tokens(ary, form: :token)
|
149
|
+
conv_proc ={hash: :hash2token, json: :json2token, token: nil}[form]
|
150
|
+
conv_proc ? ary.map{|e| Rbscmlex.send(conv_proc, e)} : ary.dup
|
151
|
+
end
|
152
|
+
|
153
|
+
def detect_form(obj)
|
154
|
+
case obj
|
155
|
+
when Hash
|
156
|
+
valid_token?(obj) ? :hash : nil
|
157
|
+
when Token
|
158
|
+
:token
|
159
|
+
when String
|
160
|
+
begin
|
161
|
+
JSON.parse(obj, symbolize_names: true)
|
162
|
+
rescue JSON::ParserError => _
|
163
|
+
nil
|
164
|
+
else
|
165
|
+
:json
|
166
|
+
end
|
167
|
+
else
|
168
|
+
nil
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def valid_token?(obj)
|
173
|
+
case obj
|
174
|
+
when Hash
|
175
|
+
obj.key?(:type) and obj.key?(:literal)
|
176
|
+
when Token
|
177
|
+
Rbscmlex.token_type?(obj.type)
|
178
|
+
else
|
179
|
+
false
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def converter
|
184
|
+
{ hash: :to_h, json: :to_json, token: nil}[@form]
|
185
|
+
end
|
186
|
+
|
187
|
+
def convert(token)
|
188
|
+
converter ? token.send(converter) : token
|
189
|
+
end
|
190
|
+
|
191
|
+
def convert_all(tokens)
|
192
|
+
converter ? token.map(&converter) : tokens
|
193
|
+
end
|
194
|
+
|
115
195
|
def check_pos
|
116
|
-
raise StopIteration if @next_pos >=
|
196
|
+
raise StopIteration if @next_pos >= size
|
117
197
|
end
|
118
198
|
|
119
199
|
S2R_MAP = { "(" => "( ", ")" => " ) ", "'" => " ' " } # :nodoc:
|
@@ -124,32 +204,34 @@ module Rbscmlex
|
|
124
204
|
cooked.split(" ").map { |literal|
|
125
205
|
case literal
|
126
206
|
when "("
|
127
|
-
Rbscmlex.new_token(:lparen, literal
|
207
|
+
Rbscmlex.new_token(:lparen, literal)
|
128
208
|
when ")"
|
129
|
-
Rbscmlex.new_token(:rparen, literal
|
209
|
+
Rbscmlex.new_token(:rparen, literal)
|
130
210
|
when "."
|
131
|
-
Rbscmlex.new_token(:dot, literal
|
211
|
+
Rbscmlex.new_token(:dot, literal)
|
132
212
|
when "'"
|
133
|
-
Rbscmlex.new_token(:quotation, literal
|
213
|
+
Rbscmlex.new_token(:quotation, literal)
|
134
214
|
when "#("
|
135
|
-
Rbscmlex.new_token(:vec_lparen, literal
|
215
|
+
Rbscmlex.new_token(:vec_lparen, literal)
|
136
216
|
when BOOLEAN
|
137
|
-
Rbscmlex.new_token(:boolean, literal
|
217
|
+
Rbscmlex.new_token(:boolean, literal)
|
138
218
|
when IDENTIFIER
|
139
|
-
Rbscmlex.new_token(:identifier, literal
|
219
|
+
Rbscmlex.new_token(:identifier, literal)
|
140
220
|
when CHAR
|
141
|
-
Rbscmlex.new_token(:character, literal
|
221
|
+
Rbscmlex.new_token(:character, literal)
|
142
222
|
when STRING
|
143
|
-
Rbscmlex.new_token(:string, literal
|
223
|
+
Rbscmlex.new_token(:string, literal)
|
144
224
|
when ARITHMETIC_OPS, COMPARISON_OPS
|
145
|
-
Rbscmlex.new_token(:op_proc, literal
|
225
|
+
Rbscmlex.new_token(:op_proc, literal)
|
146
226
|
when REAL_NUM, RATIONAL, COMPLEX, PURE_IMAG
|
147
|
-
Rbscmlex.new_token(:number, literal
|
227
|
+
Rbscmlex.new_token(:number, literal)
|
148
228
|
else
|
149
|
-
Rbscmlex.new_token(:illegal, literal
|
229
|
+
Rbscmlex.new_token(:illegal, literal)
|
150
230
|
end
|
151
231
|
}
|
152
232
|
end
|
153
233
|
|
234
|
+
# :startdoc:
|
235
|
+
|
154
236
|
end
|
155
237
|
end
|
data/lib/rbscmlex/token.rb
CHANGED
@@ -36,26 +36,26 @@ module Rbscmlex
|
|
36
36
|
# a structure to store properties of a token of Scheme program.
|
37
37
|
|
38
38
|
Token = Struct.new(:type, :literal) {
|
39
|
+
# :stopdoc:
|
40
|
+
# `to_a` and `to_h` are automatically defined for a class
|
41
|
+
# generated from Struct.
|
42
|
+
# :startdoc:
|
43
|
+
|
39
44
|
alias :to_s :literal
|
45
|
+
|
46
|
+
# Generates a new string of JSON notation, which has "type" and
|
47
|
+
# "literal" as its key.
|
48
|
+
def to_json
|
49
|
+
JSON.generate(to_h)
|
50
|
+
end
|
40
51
|
}
|
41
52
|
|
42
53
|
class << self
|
43
54
|
|
44
|
-
# Instantiates a new token object form type and literal.
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
def new_token(type, literal = nil, form = :token)
|
49
|
-
case form
|
50
|
-
when :token
|
51
|
-
Token.new(type, literal)
|
52
|
-
when :hash
|
53
|
-
make_hash(type, literal)
|
54
|
-
when :json
|
55
|
-
JSON.generate(make_hash(type, literal))
|
56
|
-
else
|
57
|
-
raise InvalidConversionTypeError, "cannot generate #{type} as token"
|
58
|
-
end
|
55
|
+
# Instantiates a new token object form type and literal.
|
56
|
+
|
57
|
+
def new_token(type, literal = nil)
|
58
|
+
Token.new(type, literal)
|
59
59
|
end
|
60
60
|
|
61
61
|
# Returns true when the argument is valid token type.
|
@@ -64,7 +64,7 @@ module Rbscmlex
|
|
64
64
|
TOKEN_TYPES.include?(type)
|
65
65
|
end
|
66
66
|
|
67
|
-
# Returns a new Hash object with type and literal.
|
67
|
+
# Returns a new Hash object with type and literal as its keys.
|
68
68
|
|
69
69
|
def make_hash(type, literal)
|
70
70
|
{type: type, literal: literal}
|
@@ -75,28 +75,54 @@ module Rbscmlex
|
|
75
75
|
# must be valid token type. Otherwise, raises UnknownTokenTypeError.
|
76
76
|
|
77
77
|
def hash2token(hash)
|
78
|
-
if
|
79
|
-
type =
|
78
|
+
if hash.key?(:type) and hash.key?(:literal)
|
79
|
+
type = hash[:type].intern
|
80
80
|
raise UnknownTokenTypeError, ("got=%s" % type) unless token_type?(type)
|
81
|
-
literal =
|
82
|
-
|
81
|
+
literal = hash[:literal]
|
82
|
+
new_token(type, literal)
|
83
83
|
else
|
84
84
|
raise InvalidHashError, ("got=%s" % hash)
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
88
|
# Converts a JSON notation, which hash type and literal, to a new
|
89
|
-
# token object. The value associated to type of the
|
89
|
+
# token object. The value associated to type of the JSON must be
|
90
90
|
# valid token type. Otherwise, raises UnknownTokenTypeError.
|
91
91
|
|
92
92
|
def json2token(json)
|
93
|
-
h = JSON.parse(json)
|
93
|
+
h = JSON.parse(json, symbolize_names: true)
|
94
94
|
begin
|
95
95
|
hash2token(h)
|
96
96
|
rescue InvalidHashError => _
|
97
97
|
raise InvalidJsonError, ("got=%s" % json)
|
98
98
|
end
|
99
99
|
end
|
100
|
+
|
101
|
+
# Converts a Token object to a Hash object.
|
102
|
+
|
103
|
+
def token2hash(token)
|
104
|
+
token.to_h
|
105
|
+
end
|
106
|
+
|
107
|
+
# Converts a Token object to a string of JSON notation.
|
108
|
+
|
109
|
+
def token2json(token)
|
110
|
+
token.to_json
|
111
|
+
end
|
112
|
+
|
113
|
+
# Converts a Hash object to a string of JSON notation.
|
114
|
+
|
115
|
+
def hash2json(hash)
|
116
|
+
JSON.generate(hash)
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
# Converts a JSON notation to a new Hash object.
|
121
|
+
|
122
|
+
def json2hash(json)
|
123
|
+
JSON.parse(json)
|
124
|
+
end
|
125
|
+
|
100
126
|
end
|
101
127
|
|
102
128
|
end
|
data/lib/rbscmlex/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbscmlex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mnbi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A simple lexical analyzer for Scheme
|
14
14
|
email:
|