rux 1.1.2 → 1.3.0

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.
@@ -1,39 +1,51 @@
1
- ,[<],[a-zA-Z0-9_-_---:-:],[>],[/],(space),[=],"[""]",['],"[^""]",[^'],[{],[}],(default)
2
- start,tag_open_test,,,,,,,,,,literal_ruby_code_start,,literal_body
3
- tag_open_test,,tag_open_start[0],,tag_close_start,,,,,,,,,
4
- tag_open_start*,,tag_open_body,,,,,,,,,,,
5
- tag_open_body,,tag_open_body,tag_open[0],tag_self_closing[0],tag_open[0],,,,,,,,
6
- tag_open*,,,tag_open_end,,attribute_spaces_body,,,,,,,,
7
- tag_open_end*,,,,,,,,,,,,,
8
- tag_close_start*,,tag_close_body,,,,,,,,,,,
9
- tag_close_body,,tag_close_body,tag_close[0],,tag_close[0],,,,,,,,
10
- tag_close*,,,tag_close_end,tag_self_closing[0],tag_close_spaces_body,,,,,,,,
11
- tag_close_spaces_body,,,tag_close_spaces[0],,tag_close_spaces_body,,,,,,,,
12
- tag_close_spaces*,,,tag_close_end,,,,,,,,,,
13
- tag_close_end*,,,,,,,,,,,,,
14
- tag_self_closing*,,,,tag_self_closing_start,,,,,,,,,
15
- tag_self_closing_start,,,tag_self_closing_end,,,,,,,,,,
16
- tag_self_closing_end*,,,,,,,,,,,,,
17
- ,,,,,,,,,,,,,
18
- attribute_spaces_body,,attribute_spaces[0],attribute_spaces[0],attribute_spaces[0],attribute_spaces_body,,,,,,,,
19
- attribute_spaces*,,attribute_name_body,tag_close_start,tag_self_closing_start,,,,,,,,,
20
- attribute_name_body,,attribute_name_body,attribute_name[0],attribute_name[0],attribute_name[0],attribute_name[0],,,,,,,
21
- attribute_name*,,,tag_open_end,tag_self_closing_start,attribute_equals_spaces_body,attribute_equals,,,,,,,
22
- attribute_equals_spaces_body,,,attribute_equals_spaces[0],,attribute_equals_spaces_body,attribute_equals_spaces[0],,,,,,,attribute_equals_spaces[0]
23
- attribute_equals_spaces*,,,tag_open_end,tag_self_closing_start,,attribute_equals,,,,,,,attribute_name_body
24
- attribute_equals*,,attribute_uq_body,,,attribute_value_spaces_body[0],,attribute_dq_body,attribute_sq_body,,,attribute_value_ruby_code_start,,
25
- attribute_value_spaces_body,,attribute_value_spaces[0],,,attribute_value_spaces_body,,attribute_value_spaces[0],attribute_value_spaces[0],,,attribute_value_spaces[0],,
26
- attribute_value_spaces*,,attribute_uq_body,,,,,attribute_dq_body,attribute_sq_body,,,attribute_value_ruby_code_start,,
27
- attribute_dq_body,,,,,,,attribute_value,,attribute_dq_body,,,,
28
- attribute_sq_body,,,,,,,,attribute_value,,attribute_sq_body,,,
29
- attribute_uq_body,,attribute_uq_body,,,attribute_value,,,,,,,,
30
- attribute_value_ruby_code_start*,,,,,,,,,,,,,attribute_value_ruby_code
31
- attribute_value_ruby_code*,,,,,,,,,,,,attribute_value_ruby_code_end,
32
- attribute_value_ruby_code_end*,,attribute_name,tag_open_end,tag_self_closing_start,attribute_spaces_body,,,,,,,,
33
- attribute_value*,,attribute_name,tag_open_end,tag_self_closing_start,attribute_spaces_body,,attribute_value_ending,attribute_value_ending,,,,,
34
- ,,,,,,,,,,,,,
35
- literal_body,literal[0],,,,,,,,,,literal[0],,literal_body
36
- literal*,,,,,,,,,,,literal_ruby_code_start,,
37
- literal_ruby_code_start*,,,,,,,,,,,,,literal_ruby_code[0]
38
- literal_ruby_code*,,,,,,,,,,,,literal_ruby_code_end,
39
- literal_ruby_code_end*,,,,,,,,,,,,,
1
+ ,[<],[@-@.-.],[a-zA-Z0-9_-_---:-:],[>],[/],(space),[=],"[""]",['],"[^""]",[^'],[{],[}],(default)
2
+ start,tag_open_test,,,,,,,,,,,literal_ruby_code_start,,literal_body
3
+ tag_open_test,,,tag_open_start[0],fragment_open,tag_close_start,,,,,,,,,
4
+ tag_open_start*,,,tag_open_body,,,,,,,,,,,
5
+ tag_open_body,,,tag_open_body,tag_open[0],tag_self_closing[0],tag_open[0],,,,,,,,
6
+ tag_open*,,,,tag_open_end,,attribute_spaces_body,,,,,,,,
7
+ tag_open_end*,,,,,,,,,,,,,,
8
+ tag_close_start*,,,tag_close_body,fragment_close,,,,,,,,,,
9
+ tag_close_body,,,tag_close_body,tag_close[0],,tag_close[0],,,,,,,,
10
+ tag_close*,,,,tag_close_end,tag_self_closing[0],tag_close_spaces_body,,,,,,,,
11
+ tag_close_spaces_body,,,,tag_close_spaces[0],,tag_close_spaces_body,,,,,,,,
12
+ tag_close_spaces*,,,,tag_close_end,,,,,,,,,,
13
+ tag_close_end*,,,,,,,,,,,,,,
14
+ tag_self_closing*,,,,,tag_self_closing_start,,,,,,,,,
15
+ tag_self_closing_start,,,,tag_self_closing_end,,,,,,,,,,
16
+ tag_self_closing_end*,,,,,,,,,,,,,,
17
+ fragment_open*,,,,,,,,,,,,,,
18
+ fragment_close*,,,,,,,,,,,,,,
19
+ ,,,,,,,,,,,,,,
20
+ attribute_spaces_body,,attribute_spaces[0],attribute_spaces[0],attribute_spaces[0],attribute_spaces[0],attribute_spaces_body,,,,,,attribute_spaces[0],,
21
+ attribute_spaces*,,attribute_name_sigil,attribute_name_body,tag_open_end,tag_self_closing_start,,,,,,,attribute_ruby_code_start,,
22
+ attribute_name_sigil,,,,,,,,,,,,,,attribute_name_body
23
+ attribute_name_body,,,attribute_name_body,attribute_name[0],attribute_name[0],attribute_name[0],attribute_name[0],,,,,,,
24
+ attribute_name*,,,,tag_open_end,tag_self_closing_start,attribute_equals_spaces_body,attribute_equals,,,,,,,
25
+ attribute_equals_spaces_body,,,,attribute_equals_spaces[0],,attribute_equals_spaces_body,attribute_equals_spaces[0],,,,,,,attribute_equals_spaces[0]
26
+ attribute_equals_spaces*,,,,tag_open_end,tag_self_closing_start,,attribute_equals,,,,,,,attribute_name_sigil
27
+ attribute_equals*,,,attribute_value_uq_body,,,attribute_value_spaces_body[0],,attribute_value_dq_start,attribute_value_sq_start,,,attribute_value_ruby_code_start,,
28
+ attribute_value_spaces_body,,,attribute_value_spaces[0],attribute_value_spaces[0],attribute_value_spaces[0],attribute_value_spaces_body,,attribute_value_spaces[0],attribute_value_spaces[0],,,attribute_value_spaces[0],,
29
+ attribute_value_spaces*,,,attribute_value_uq_body,tag_open_end,tag_self_closing_start,,,attribute_value_dq_start,attribute_value_sq_start,,,attribute_value_ruby_code_start,,
30
+ attribute_value_dq_start*,,,,,,,,,,attribute_value_dq_body,,,,
31
+ attribute_value_sq_start*,,,,,,,,,,,attribute_value_sq_body,,,
32
+ attribute_value_dq_body,,,,,,,,attribute_dq_value[0],,attribute_value_dq_body,,,,
33
+ attribute_value_sq_body,,,,,,,,,attribute_sq_value[0],,attribute_value_sq_body,,,
34
+ attribute_value_uq_body,,,attribute_value_uq_body,attribute_uq_value[0],attrIbute_uq_value[0],attribute_uq_value[0],,,,,,,,
35
+ attribute_value_dq_end*,,,attribute_name,tag_open_end,tag_self_closing_start,attribute_spaces_body,,,,,,,,
36
+ attribute_value_sq_end*,,,attribute_name,tag_open_end,tag_self_closing_start,attribute_spaces_body,,,,,,,,
37
+ attribute_value_ruby_code_start*,,,,,,,,,,,,,,attribute_value_ruby_code
38
+ attribute_value_ruby_code*,,,,,,,,,,,,,attribute_value_ruby_code_end,
39
+ attribute_value_ruby_code_end*,,,attribute_name,tag_open_end,tag_self_closing_start,attribute_spaces_body,,,,,,,,
40
+ attribute_dq_value*,,,,,,,,attribute_value_dq_end,,,,,,
41
+ attribute_sq_value*,,,,,,,,,attribute_value_sq_end,,,,,
42
+ attribute_uq_value*,,,attribute_name,tag_open_end,tag_self_closing_start,attribute_spaces_body,,,,,,,,
43
+ attribute_ruby_code_start*,,,,,,,,,,,,,,attribute_ruby_code[0]
44
+ attribute_ruby_code*,,,,,,,,,,,,,attribute_ruby_code_end,
45
+ attribute_ruby_code_end*,,,attribute_name,tag_open_end,tag_self_closing_start,attribute_spaces_body,,,,,,,,
46
+ ,,,,,,,,,,,,,,
47
+ literal_body,literal[0],,,,,,,,,,,literal[0],,literal_body
48
+ literal*,,,,,,,,,,,,literal_ruby_code_start,,
49
+ literal_ruby_code_start*,,,,,,,,,,,,,,literal_ruby_code[0]
50
+ literal_ruby_code*,,,,,,,,,,,,,literal_ruby_code_end,
51
+ literal_ruby_code_end*,,,,,,,,,,,,,,
data/lib/rux/lexer.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'parser'
2
+
1
3
  module Rux
2
4
  class Lexer
3
5
  class EOFError < StandardError; end
@@ -5,6 +7,13 @@ module Rux
5
7
 
6
8
  attr_reader :source_buffer
7
9
 
10
+ class << self
11
+ def lex(str)
12
+ buffer = ::Parser::Source::Buffer.new('(source)', source: str)
13
+ new(buffer).to_a
14
+ end
15
+ end
16
+
8
17
  def initialize(source_buffer)
9
18
  @source_buffer = source_buffer
10
19
  @stack = [RubyLexer.new(source_buffer, 0)]
@@ -17,6 +26,10 @@ module Rux
17
26
  [nil, ['$eof']]
18
27
  end
19
28
 
29
+ def to_a
30
+ @generator.to_a
31
+ end
32
+
20
33
  private
21
34
 
22
35
  def each_token
data/lib/rux/parser.rb CHANGED
@@ -8,14 +8,18 @@ module Rux
8
8
  class << self
9
9
  def parse_file(path)
10
10
  buffer = ::Parser::Source::Buffer.new(path).read
11
- lexer = ::Rux::Lexer.new(buffer)
12
- new(lexer).parse
11
+ new(make_lexer(buffer)).parse
13
12
  end
14
13
 
15
14
  def parse(str)
16
15
  buffer = ::Parser::Source::Buffer.new('(source)', source: str)
17
- lexer = ::Rux::Lexer.new(buffer)
18
- new(lexer).parse
16
+ new(make_lexer(buffer)).parse
17
+ end
18
+
19
+ private
20
+
21
+ def make_lexer(buffer)
22
+ ::Rux::Lexer.new(buffer)
19
23
  end
20
24
  end
21
25
 
@@ -26,6 +30,12 @@ module Rux
26
30
  end
27
31
 
28
32
  def parse
33
+ AST::RootNode.new(list)
34
+ end
35
+
36
+ private
37
+
38
+ def list
29
39
  curlies = 1
30
40
  children = []
31
41
 
@@ -34,9 +44,9 @@ module Rux
34
44
  break unless type
35
45
 
36
46
  case type
37
- when :tLCURLY, :tLBRACE, :tRUX_LITERAL_RUBY_CODE_START
47
+ when :tLCURLY, :tLBRACE, :tRUX_LITERAL_RUBY_CODE_START, :tRUX_ATTRIBUTE_RUBY_CODE_START
38
48
  curlies += 1
39
- when :tRCURLY, :tRBRACE, :tRUX_LITERAL_RUBY_CODE_END
49
+ when :tRCURLY, :tRBRACE, :tRUX_LITERAL_RUBY_CODE_END, :tRUX_ATTRIBUTE_RUBY_CODE_END
40
50
  curlies -= 1
41
51
  end
42
52
 
@@ -46,6 +56,8 @@ module Rux
46
56
  children << rb
47
57
  elsif type_of(current) == :tRUX_TAG_OPEN_START
48
58
  children << tag
59
+ elsif type_of(current) == :tRUX_FRAGMENT_OPEN
60
+ children << fragment
49
61
  else
50
62
  raise UnexpectedTokenError,
51
63
  'expected ruby code or the start of a rux tag but found '\
@@ -56,8 +68,6 @@ module Rux
56
68
  AST::ListNode.new(children)
57
69
  end
58
70
 
59
- private
60
-
61
71
  def ruby
62
72
  ruby_start = pos_of(current).begin_pos
63
73
 
@@ -79,7 +89,7 @@ module Rux
79
89
 
80
90
  if pos_of(current).begin_pos != ruby_start
81
91
  AST::RubyNode.new(
82
- @lexer.source_buffer.source[ruby_start...(pos_of(current).end_pos - 1)]
92
+ @lexer.source_buffer.source[ruby_start...(pos_of(current).begin_pos)]
83
93
  )
84
94
  end
85
95
  end
@@ -93,7 +103,8 @@ module Rux
93
103
  attrs = attributes
94
104
  maybe_consume(:tRUX_ATTRIBUTE_SPACES)
95
105
  maybe_consume(:tRUX_TAG_OPEN_END)
96
- tag_node = AST::TagNode.new(tag_name, attrs)
106
+ tag_node = AST::TagNode.new(tag_name, attrs, tag_pos)
107
+ attrs.each { |attr_node| attr_node.tag_node = tag_node }
97
108
 
98
109
  if is?(:tRUX_TAG_SELF_CLOSING_END)
99
110
  consume(:tRUX_TAG_SELF_CLOSING_END)
@@ -103,12 +114,7 @@ module Rux
103
114
  @stack.push(tag_name)
104
115
 
105
116
  until is?(:tRUX_TAG_CLOSE_START)
106
- if is?(:tRUX_LITERAL, :tRUX_LITERAL_RUBY_CODE_START)
107
- lit = literal
108
- tag_node.children << lit if lit
109
- else
110
- tag_node.children << tag
111
- end
117
+ populate_next_child(tag_node)
112
118
  end
113
119
 
114
120
  consume(:tRUX_TAG_CLOSE_START)
@@ -131,44 +137,108 @@ module Rux
131
137
  tag_node
132
138
  end
133
139
 
140
+ def populate_next_child(node)
141
+ if is?(:tRUX_LITERAL, :tRUX_LITERAL_RUBY_CODE_START)
142
+ lit = literal
143
+ node.children << lit if lit
144
+ elsif is?(:tRUX_FRAGMENT_OPEN)
145
+ node.children << fragment
146
+ else
147
+ node.children << tag
148
+ end
149
+ end
150
+
134
151
  def attributes
135
- {}.tap do |attrs|
136
- while is?(:tRUX_ATTRIBUTE_NAME)
137
- key, value = attribute
138
- attrs[key] = value
152
+ pos = pos_of(current)
153
+
154
+ attrs = [].tap do |attrs|
155
+ loop do
156
+ attr = case type_of(current)
157
+ when :tRUX_ATTRIBUTE_NAME
158
+ attribute
159
+ when :tRUX_ATTRIBUTE_RUBY_CODE_START
160
+ ruby_attribute
161
+ end
139
162
 
140
163
  maybe_consume(:tRUX_ATTRIBUTE_SPACES)
164
+
165
+ if attr
166
+ attrs << attr
167
+ else
168
+ break
169
+ end
141
170
  end
142
171
  end
172
+
173
+ AST::AttrsNode.new(attrs, pos)
143
174
  end
144
175
 
145
176
  def attribute
146
- maybe_consume(:tRUX_ATTRIBUTE_SPACES)
147
177
  attr_name = text_of(current)
178
+ attr_pos = pos_of(current)
148
179
  consume(:tRUX_ATTRIBUTE_NAME)
149
180
  maybe_consume(:tRUX_ATTRIBUTE_EQUALS_SPACES)
150
181
 
151
182
  attr_value = if maybe_consume(:tRUX_ATTRIBUTE_EQUALS)
152
183
  maybe_consume(:tRUX_ATTRIBUTE_VALUE_SPACES)
153
- attribute_value
184
+ attribute_value.tap do
185
+ maybe_consume(:tRUX_ATTRIBUTE_VALUE_SPACES)
186
+ end
154
187
  else
155
188
  # if no equals sign, assume boolean attribute
156
- AST::StringNode.new("\"true\"")
189
+ AST::StringNode.new('true', :none, nil)
157
190
  end
158
191
 
159
- [attr_name, attr_value]
192
+ AST::AttrNode.new(attr_name, attr_value, attr_pos)
193
+ end
194
+
195
+ def ruby_attribute
196
+ consume(:tRUX_ATTRIBUTE_RUBY_CODE_START)
197
+
198
+ AST::RubyAttrNode.new(ruby).tap do
199
+ consume(:tRUX_ATTRIBUTE_RUBY_CODE_END)
200
+ end
160
201
  end
161
202
 
162
203
  def attribute_value
163
204
  if is?(:tRUX_ATTRIBUTE_VALUE_RUBY_CODE_START)
164
205
  attr_ruby_code
165
206
  else
166
- AST::StringNode.new(text_of(current)).tap do
167
- consume(:tRUX_ATTRIBUTE_VALUE)
207
+ case type_of(current)
208
+ when :tRUX_ATTRIBUTE_VALUE_DQ_START
209
+ attribute_value_dq
210
+ when :tRUX_ATTRIBUTE_VALUE_SQ_START
211
+ attribute_value_sq
212
+ when :tRUX_ATTRIBUTE_UQ_VALUE
213
+ attribute_value_uq
168
214
  end
169
215
  end
170
216
  end
171
217
 
218
+ def attribute_value_dq
219
+ consume(:tRUX_ATTRIBUTE_VALUE_DQ_START)
220
+
221
+ AST::StringNode.new(text_of(current), :double, pos_of(current)).tap do
222
+ consume(:tRUX_ATTRIBUTE_DQ_VALUE)
223
+ consume(:tRUX_ATTRIBUTE_VALUE_DQ_END)
224
+ end
225
+ end
226
+
227
+ def attribute_value_sq
228
+ consume(:tRUX_ATTRIBUTE_VALUE_SQ_START)
229
+
230
+ AST::StringNode.new(text_of(current), :single, pos_of(current)).tap do
231
+ consume(:tRUX_ATTRIBUTE_SQ_VALUE)
232
+ consume(:tRUX_ATTRIBUTE_VALUE_SQ_END)
233
+ end
234
+ end
235
+
236
+ def attribute_value_uq
237
+ AST::StringNode.new(text_of(current), :none, pos_of(current)).tap do
238
+ consume(:tRUX_ATTRIBUTE_UQ_VALUE)
239
+ end
240
+ end
241
+
172
242
  def attr_ruby_code
173
243
  consume(:tRUX_ATTRIBUTE_VALUE_RUBY_CODE_START)
174
244
 
@@ -177,13 +247,27 @@ module Rux
177
247
  end
178
248
  end
179
249
 
250
+ def fragment
251
+ consume(:tRUX_FRAGMENT_OPEN)
252
+
253
+ AST::FragmentNode.new.tap do |fragment_node|
254
+ until is?(:tRUX_TAG_CLOSE_START)
255
+ populate_next_child(fragment_node)
256
+ end
257
+
258
+ consume(:tRUX_TAG_CLOSE_START)
259
+ consume(:tRUX_FRAGMENT_CLOSE)
260
+ end
261
+ end
262
+
180
263
  def literal
181
264
  if is?(:tRUX_LITERAL_RUBY_CODE_START)
182
265
  literal_ruby_code
183
266
  else
184
267
  lit = squeeze_lit(text_of(current))
268
+ pos = pos_of(current)
185
269
  consume(:tRUX_LITERAL)
186
- AST::TextNode.new(lit) unless lit.empty?
270
+ AST::TextNode.new(lit, pos) unless lit.empty?
187
271
  end
188
272
  end
189
273
 
@@ -197,7 +281,7 @@ module Rux
197
281
  def literal_ruby_code
198
282
  consume(:tRUX_LITERAL_RUBY_CODE_START)
199
283
 
200
- parse.tap do |res|
284
+ list.tap do
201
285
  consume(:tRUX_LITERAL_RUBY_CODE_END)
202
286
  end
203
287
  end
@@ -1,4 +1,18 @@
1
1
  module Rux
2
+ class TokenArrayProxy < Array
3
+ def initialize(rux_token_queue)
4
+ @rux_token_queue = rux_token_queue
5
+ end
6
+
7
+ def push(token)
8
+ if token[0] == :tCOMMENT
9
+ @rux_token_queue.push(token)
10
+ end
11
+
12
+ super
13
+ end
14
+ end
15
+
2
16
  class RubyLexer < ::Parser::Lexer
3
17
  # These are populated when ::Parser::Lexer loads and are therefore
4
18
  # not inherited. We have to copy them over manually.
@@ -15,6 +29,8 @@ module Rux
15
29
  @generator = to_enum(:each_token)
16
30
  @rux_token_queue = []
17
31
  @p = init_pos
32
+
33
+ self.tokens = TokenArrayProxy.new(@rux_token_queue)
18
34
  end
19
35
 
20
36
  alias_method :advance_orig, :advance
@@ -27,6 +43,7 @@ module Rux
27
43
  @ts = @te = @p = pos
28
44
  @eof = false
29
45
  @rux_token_queue.clear
46
+ clear_queue
30
47
  populate_queue
31
48
  end
32
49
 
@@ -44,13 +61,7 @@ module Rux
44
61
  end
45
62
 
46
63
  def each_token(&block)
47
- # We detect whether or not we're at the beginning of a rux tag by looking
48
- # ahead by 1 token; that's why the first element in @rux_token_queue is
49
- # yielded immediately. If the lexer _starts_ at a rux tag however,
50
- # lookahead is a lot more difficult. To mitigate, we insert a dummy skip
51
- # token here. That way, at_rux? checks the right tokens in the queue and
52
- # correctly identifies the start of a rux tag.
53
- @rux_token_queue << [:tSKIP, ['$skip', make_range(@p, @p)]]
64
+ clear_queue
54
65
 
55
66
  @eof = false
56
67
  curlies = 1
@@ -74,7 +85,7 @@ module Rux
74
85
  type, (_, pos) = token
75
86
 
76
87
  case type
77
- when :tLCURLY, :tLBRACE
88
+ when :tLCURLY, :tLBRACE, :tLAMBEG
78
89
  curlies += 1
79
90
  when :tRCURLY, :tRBRACE
80
91
  curlies -= 1
@@ -111,12 +122,25 @@ module Rux
111
122
  end
112
123
  end
113
124
 
125
+ def clear_queue
126
+ @rux_token_queue.clear
127
+
128
+ # We detect whether or not we're at the beginning of a rux tag by looking
129
+ # ahead by 1 token; that's why the first element in @rux_token_queue is
130
+ # yielded immediately. If the lexer _starts_ at a rux tag however,
131
+ # lookahead is a lot more difficult. To mitigate, we insert a dummy skip
132
+ # token here. That way, at_rux? checks the right tokens in the queue and
133
+ # correctly identifies the start of a rux tag.
134
+ @rux_token_queue << [:tSKIP, ['$skip', make_range(@p, @p)]]
135
+ end
136
+
114
137
  def at_rux?
115
138
  at_lt? && !at_inheritance?
116
139
  end
117
140
 
118
141
  def at_lt?
119
142
  is?(@rux_token_queue[1], :tLT) && (
143
+ is?(@rux_token_queue[2], :tGT) ||
120
144
  is?(@rux_token_queue[2], :tCONSTANT) ||
121
145
  is?(@rux_token_queue[2], :tIDENTIFIER)
122
146
  )
data/lib/rux/rux_lexer.rb CHANGED
@@ -2,6 +2,17 @@ require 'csv'
2
2
 
3
3
  module Rux
4
4
  class RuxLexer
5
+ RUBY_CODE_STATES = [
6
+ # ruby code in attributes, eg. <div {**kwargs}>
7
+ :tRUX_ATTRIBUTE_RUBY_CODE,
8
+
9
+ # ruby code in attribute values, eg. <div foo={bar}>
10
+ :tRUX_ATTRIBUTE_VALUE_RUBY_CODE,
11
+
12
+ # ruby code in tag bodies, eg. <div>{foo}</div>
13
+ :tRUX_LITERAL_RUBY_CODE
14
+ ].freeze
15
+
5
16
  class << self
6
17
  # See: https://docs.google.com/spreadsheets/d/11ikKuySIKoaj-kFIfhlzebUwH31cRt_1flGjWfk7RMg
7
18
  def state_table
@@ -87,11 +98,13 @@ module Rux
87
98
  case state
88
99
  when :tRUX_TAG_OPEN, :tRUX_TAG_SELF_CLOSING
89
100
  tag_stack.push(text)
101
+ when :tRUX_FRAGMENT_OPEN
102
+ tag_stack.push(:__fragment)
90
103
  when :tRUX_TAG_CLOSE
91
104
  tag_stack.pop
92
105
  when :tRUX_TAG_CLOSE_END
93
106
  break if tag_stack.empty?
94
- when :tRUX_TAG_SELF_CLOSING_END
107
+ when :tRUX_TAG_SELF_CLOSING_END, :tRUX_FRAGMENT_CLOSE
95
108
  tag_stack.pop
96
109
  break if tag_stack.empty?
97
110
  end
@@ -110,7 +123,7 @@ module Rux
110
123
 
111
124
  unless cur_trans
112
125
  raise Rux::Lexer::TransitionError,
113
- "no transition found from #{cur_state} at position #{@p} while "\
126
+ "no transition found from #{cur_state} for #{chr.inspect} at position #{@p} while "\
114
127
  'lexing rux code'
115
128
  end
116
129
 
@@ -150,8 +163,7 @@ module Rux
150
163
  # bodies. Eventually I'd like to also allow passing a Ruby hash to
151
164
  # dynamically specify attributes, but we're not there yet.
152
165
  def ruby_code?(state)
153
- state == :tRUX_ATTRIBUTE_VALUE_RUBY_CODE ||
154
- state == :tRUX_LITERAL_RUBY_CODE
166
+ RUBY_CODE_STATES.include?(state)
155
167
  end
156
168
  end
157
169
  end
data/lib/rux/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Rux
2
- VERSION = '1.1.2'
2
+ VERSION = '1.3.0'
3
3
  end
data/lib/rux/visitor.rb CHANGED
@@ -4,6 +4,10 @@ module Rux
4
4
  node.accept(self)
5
5
  end
6
6
 
7
+ def visit_root(node)
8
+ visit_children(node)
9
+ end
10
+
7
11
  def visit_list(node)
8
12
  visit_children(node)
9
13
  end
@@ -20,6 +24,18 @@ module Rux
20
24
  visit_children(node)
21
25
  end
22
26
 
27
+ def visit_attrs(node)
28
+ visit_children(node)
29
+ end
30
+
31
+ def visit_attr(node)
32
+ visit_children(node)
33
+ end
34
+
35
+ def visit_fragment(node)
36
+ visit_children(node)
37
+ end
38
+
23
39
  def visit_text(node)
24
40
  visit_children(node)
25
41
  end
data/lib/rux.rb CHANGED
@@ -38,9 +38,8 @@ module Rux
38
38
  ruby_code = visitor.visit(Parser.parse(str))
39
39
  return ruby_code unless pretty
40
40
 
41
- ::Unparser.unparse(
42
- ::Parser::CurrentRuby.parse(ruby_code)
43
- )
41
+ ast, comments = *::Parser::CurrentRuby.parse_with_comments(ruby_code)
42
+ ::Unparser.unparse(ast, comments: comments)
44
43
  end
45
44
 
46
45
  def default_visitor
data/rux.gemspec CHANGED
@@ -10,11 +10,13 @@ Gem::Specification.new do |s|
10
10
  s.description = s.summary = 'A jsx-inspired way to write view components.'
11
11
  s.platform = Gem::Platform::RUBY
12
12
 
13
+ s.add_dependency 'onload', '~> 1.1'
13
14
  s.add_dependency 'parser', '~> 3.0'
14
- s.add_dependency 'unparser', '~> 0.6'
15
+ s.add_dependency 'unparser', '~> 0.8'
15
16
 
16
17
  s.require_path = 'lib'
17
18
  s.executables << 'ruxc'
19
+ s.executables << 'ruxlex'
18
20
 
19
21
  s.files = Dir['{lib,spec}/**/*', 'Gemfile', 'LICENSE', 'CHANGELOG.md', 'README.md', 'Rakefile', 'rux.gemspec']
20
22
  end