minicss 0.1.5 → 0.1.7

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.
@@ -0,0 +1,132 @@
1
+ //
2
+ // Created by Vito Sartori on 11/10/25.
3
+ //
4
+
5
+ #ifndef MINICSS_SCANNER_MINICSS_SCANNER_H
6
+ #define MINICSS_SCANNER_MINICSS_SCANNER_H
7
+
8
+ #define EOF_CP (-1)
9
+ #define NEWLINE 0x0A
10
+ #define CP(c) ((int)(c))
11
+ #define REVERSE_SOLIDUS '\\'
12
+ #define QUOTATION_MARK '"'
13
+ #define APOSTROPHE '\''
14
+ #define NUMBER_SIGN '#'
15
+ #define LEFT_PARENTHESIS '('
16
+ #define RIGHT_PARENTHESIS ')'
17
+ #define PLUS_SIGN '+'
18
+ #define FULL_STOP '.'
19
+ #define HYPHEN_MINUS '-'
20
+ #define PERCENTAGE_SIGN '%'
21
+ #define COMMA ','
22
+ #define GREATER_THAN '>'
23
+ #define COLON ':'
24
+ #define SEMICOLON ';'
25
+ #define LESS_THAN '<'
26
+ #define EXCLAMATION_MARK '!'
27
+ #define COMMERCIAL_AT '@'
28
+ #define LEFT_SQUARE_BRACKET '['
29
+ #define RIGHT_SQUARE_BRACKET ']'
30
+ #define LEFT_CURLY '{'
31
+ #define RIGHT_CURLY '}'
32
+
33
+ #define DEFINE_REUSABLE_SYMBOL(name) static ID id_type_##name; static VALUE sym_##name;
34
+ #define INITIALIZE_REUSABLE_SYMBOL(name) id_type_##name = rb_intern(#name); sym_##name = ID2SYM(id_type_##name);
35
+
36
+ DEFINE_REUSABLE_SYMBOL(line);
37
+ DEFINE_REUSABLE_SYMBOL(column);
38
+ DEFINE_REUSABLE_SYMBOL(offset);
39
+ DEFINE_REUSABLE_SYMBOL(whitespace);
40
+ DEFINE_REUSABLE_SYMBOL(start);
41
+ DEFINE_REUSABLE_SYMBOL(end);
42
+ DEFINE_REUSABLE_SYMBOL(unicode_range);
43
+ DEFINE_REUSABLE_SYMBOL(new);
44
+ DEFINE_REUSABLE_SYMBOL(bad_string);
45
+ DEFINE_REUSABLE_SYMBOL(literal);
46
+ DEFINE_REUSABLE_SYMBOL(quoting);
47
+ DEFINE_REUSABLE_SYMBOL(string);
48
+ DEFINE_REUSABLE_SYMBOL(value);
49
+ DEFINE_REUSABLE_SYMBOL(type);
50
+ DEFINE_REUSABLE_SYMBOL(integer);
51
+ DEFINE_REUSABLE_SYMBOL(number);
52
+ DEFINE_REUSABLE_SYMBOL(sign_character);
53
+ DEFINE_REUSABLE_SYMBOL(unit);
54
+ DEFINE_REUSABLE_SYMBOL(dimension);
55
+ DEFINE_REUSABLE_SYMBOL(percentage);
56
+ DEFINE_REUSABLE_SYMBOL(function);
57
+ DEFINE_REUSABLE_SYMBOL(name);
58
+ DEFINE_REUSABLE_SYMBOL(ident);
59
+ DEFINE_REUSABLE_SYMBOL(url);
60
+ DEFINE_REUSABLE_SYMBOL(bad_url);
61
+ DEFINE_REUSABLE_SYMBOL(flag);
62
+ DEFINE_REUSABLE_SYMBOL(hash);
63
+ DEFINE_REUSABLE_SYMBOL(delim);
64
+ DEFINE_REUSABLE_SYMBOL(left_parenthesis);
65
+ DEFINE_REUSABLE_SYMBOL(right_parenthesis);
66
+ DEFINE_REUSABLE_SYMBOL(comma);
67
+ DEFINE_REUSABLE_SYMBOL(cdc);
68
+ DEFINE_REUSABLE_SYMBOL(colon);
69
+ DEFINE_REUSABLE_SYMBOL(semicolon);
70
+ DEFINE_REUSABLE_SYMBOL(cdo);
71
+ DEFINE_REUSABLE_SYMBOL(at_keyword);
72
+ DEFINE_REUSABLE_SYMBOL(left_square_bracket);
73
+ DEFINE_REUSABLE_SYMBOL(right_square_bracket);
74
+ DEFINE_REUSABLE_SYMBOL(left_curly);
75
+ DEFINE_REUSABLE_SYMBOL(right_curly);
76
+
77
+ // Definitions -----------------------------------------------------------------
78
+
79
+ /**
80
+ * scanner_t - State for a CSS tokenizer scanner.
81
+ *
82
+ * Holds the current position, lookahead, and bookkeeping needed to
83
+ * tokenize a UTF-8 encoded CSS source string. This structure is the
84
+ * central state passed around by the tokenizer.
85
+ *
86
+ * Fields:
87
+ * str - Ruby String VALUE containing the source (kept alive
88
+ * to ensure the underlying buffer remains valid).
89
+ *
90
+ * p - Current byte pointer into the UTF-8 source.
91
+ * end - Pointer to one past the last byte of the source.
92
+ *
93
+ * idx_cp - Index of the current code point (0-based).
94
+ * line - Current line number (1-based, for error reporting).
95
+ * col - Current column number (1-based, for error reporting).
96
+ *
97
+ * look - Lookahead buffer of decoded code points:
98
+ * look[0] = next code point (peek)
99
+ * look[1] = second ahead
100
+ * look[2] = third ahead
101
+ * look[3] = fourth ahead
102
+ * Used for disambiguating tokens (e.g. distinguishing
103
+ * between `--ident` and `-->`).
104
+ *
105
+ * Notes:
106
+ * - `p` is advanced as tokens are consumed.
107
+ * - `line` and `col` are updated to provide CSS-spec-compliant
108
+ * source location information.
109
+ * - Lookahead avoids re-decoding UTF-8 sequences during parsing.
110
+ */
111
+ typedef struct {
112
+ VALUE str;
113
+ VALUE owner;
114
+ VALUE tokens;
115
+ bool allow_unicode_ranges;
116
+ const uint8_t *p;
117
+ const uint8_t *end;
118
+ long idx_cp;
119
+ long line;
120
+ long col;
121
+ int look[4];
122
+ long start_token_offset;
123
+ long start_token_line;
124
+ long start_token_column;
125
+ } scanner_t;
126
+
127
+ // Forward definitions ---------------------------------------------------------
128
+ static void scanner_consume_ident_like_token(scanner_t *sc);
129
+ static void scanner_consume_url_token(scanner_t *sc);
130
+ static void scanner_consume_bad_url(scanner_t *sc);
131
+
132
+ #endif //MINICSS_SCANNER_MINICSS_SCANNER_H
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mkmf"
4
+
5
+ create_makefile("minicss_token_stream")
@@ -0,0 +1,195 @@
1
+ #include "ruby.h"
2
+ #include "ruby/encoding.h"
3
+ #include <stdint.h>
4
+ #include <string.h>
5
+
6
+ #define DEFINE_REUSABLE_SYMBOL(name) static ID id_type_##name; static VALUE sym_##name;
7
+ #define INITIALIZE_REUSABLE_SYMBOL(name) id_type_##name = rb_intern(#name); sym_##name = ID2SYM(id_type_##name);
8
+
9
+ DEFINE_REUSABLE_SYMBOL(whitespace);
10
+ DEFINE_REUSABLE_SYMBOL(eof);
11
+ static VALUE cTokenClass;
12
+
13
+ typedef struct {
14
+ VALUE eof;
15
+ VALUE tokens;
16
+ int tokens_idx;
17
+ long tokens_len;
18
+ VALUE look[2];
19
+ int marks[128];
20
+ int marks_idx;
21
+ } stream_t;
22
+
23
+ static void stream_free(void *ptr) {
24
+ xfree(ptr);
25
+ }
26
+
27
+ static size_t stream_memsize(const void *ptr) {
28
+ return sizeof(stream_t);
29
+ }
30
+
31
+ static void stream_mark(void *ptr) {
32
+ const stream_t *s = ptr;
33
+ if (s->tokens) rb_gc_mark(s->tokens);
34
+ if (s->eof) rb_gc_mark(s->eof);
35
+ }
36
+
37
+ static const rb_data_type_t stream_type = {
38
+ "MiniCSS::CSS::TokenStream",
39
+ {stream_mark, stream_free, stream_memsize,},
40
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
41
+ };
42
+
43
+ static VALUE stream_alloc(const VALUE klass) {
44
+ stream_t *s = ALLOC(stream_t);
45
+ memset(s, 0, sizeof(stream_t));
46
+ return TypedData_Wrap_Struct(klass, &stream_type, s);
47
+ }
48
+
49
+ static VALUE stream_initialize(const VALUE self, VALUE tokens) {
50
+ Check_Type(tokens, T_ARRAY);
51
+ stream_t *s;
52
+ TypedData_Get_Struct(self, stream_t, &stream_type, s);
53
+ s->tokens = tokens;
54
+ s->tokens_idx = 0;
55
+ s->marks_idx = 0;
56
+ s->tokens_len = RARRAY_LEN(tokens);
57
+ s->eof = rb_const_get(cTokenClass, rb_intern("EOF"));
58
+
59
+ // prime lookahead
60
+ s->look[0] = s->tokens_len >= 1 ? rb_ary_entry(tokens, 0) : s->eof;
61
+ s->look[1] = s->tokens_len >= 2 ? rb_ary_entry(tokens, 1) : s->eof;
62
+ return self;
63
+ }
64
+
65
+ static void rotate(stream_t *s) {
66
+ s->look[0] = s->look[1];
67
+ s->look[1] = s->tokens_idx + 1 < s->tokens_len ? rb_ary_entry(s->tokens, s->tokens_idx + 1) : s->eof;
68
+ }
69
+
70
+ #define UNWRAP_STREAM stream_t *s; TypedData_Get_Struct(self, stream_t, &stream_type, s);
71
+
72
+ static VALUE stream_peek(const VALUE self) {
73
+ UNWRAP_STREAM;
74
+ return s->look[0];
75
+ }
76
+
77
+ static void stream_consume_c(stream_t *s) {
78
+ if (s->tokens_idx < s->tokens_len && s->tokens_idx + 1 < s->tokens_len) {
79
+ s->tokens_idx++;
80
+ }
81
+ rotate(s);
82
+ }
83
+
84
+ static VALUE stream_consume(const VALUE self) {
85
+ UNWRAP_STREAM;
86
+ const VALUE peek = s->look[0];
87
+ stream_consume_c(s);
88
+ return peek;
89
+ }
90
+
91
+ static VALUE stream_discard(const VALUE self) {
92
+ UNWRAP_STREAM;
93
+ stream_consume_c(s);
94
+ return Qnil;
95
+ }
96
+
97
+ static VALUE stream_discard_whitespace(const VALUE self) {
98
+ UNWRAP_STREAM;
99
+ for (;;) {
100
+ const VALUE k = rb_funcall(s->look[0], rb_intern("kind"), 0);
101
+ Check_Type(k, T_SYMBOL);
102
+ if (rb_sym2id(k) != id_type_whitespace) break;
103
+ stream_consume_c(s);
104
+ }
105
+ return Qnil;
106
+ }
107
+
108
+ static VALUE stream_create_mark(const VALUE self) {
109
+ UNWRAP_STREAM;
110
+ if (s->marks_idx >= 127) {
111
+ rb_raise(rb_eRuntimeError, "Too many marks in stream");
112
+ }
113
+
114
+ s->marks[s->marks_idx++] = s->tokens_idx;
115
+ return Qnil;
116
+ }
117
+
118
+ static VALUE stream_mark_restore(const VALUE self) {
119
+ UNWRAP_STREAM;
120
+ if (s->marks_idx == 0) {
121
+ rb_raise(rb_eRuntimeError, "BUG: No mark to restore");
122
+ }
123
+ const int mark = s->marks[s->marks_idx - 1];
124
+ s->tokens_idx = mark;
125
+ s->look[0] = s->tokens_len > mark ? rb_ary_entry(s->tokens, mark) : s->eof;
126
+ s->look[1] = s->tokens_len > mark + 1 ? rb_ary_entry(s->tokens, mark + 1) : s->eof;
127
+ s->marks_idx--;
128
+ return Qnil;
129
+ }
130
+
131
+ static VALUE stream_mark_pop(const VALUE self) {
132
+ UNWRAP_STREAM;
133
+ if (s->marks_idx == 0) {
134
+ rb_raise(rb_eRuntimeError, "BUG: No mark to pop");
135
+ }
136
+ s->marks_idx--;
137
+ return Qnil;
138
+ }
139
+
140
+ static bool is_eof(const VALUE v) {
141
+ const VALUE k = rb_funcall(v, rb_intern("kind"), 0);
142
+ Check_Type(k, T_SYMBOL);
143
+ return rb_sym2id(k) == id_type_eof;
144
+ }
145
+
146
+ static VALUE stream_is_empty(const VALUE self) {
147
+ UNWRAP_STREAM;
148
+ if (s->tokens_idx >= s->tokens_len || is_eof(s->look[0]))
149
+ return Qtrue;
150
+ return Qfalse;
151
+ }
152
+
153
+ static VALUE stream_peek_kind(const VALUE self) {
154
+ UNWRAP_STREAM;
155
+ const VALUE k = rb_funcall(s->look[0], rb_intern("kind"), 0);
156
+ Check_Type(k, T_SYMBOL);
157
+ return k;
158
+ }
159
+
160
+ static VALUE stream_status(const VALUE self) {
161
+ UNWRAP_STREAM;
162
+ const VALUE h = rb_hash_new();
163
+ rb_hash_aset(h, ID2SYM(rb_intern("eof")), s->eof);
164
+ rb_hash_aset(h, ID2SYM(rb_intern("tokens")), s->tokens);
165
+ rb_hash_aset(h, ID2SYM(rb_intern("tokens_idx")), INT2NUM(s->tokens_idx));
166
+ rb_hash_aset(h, ID2SYM(rb_intern("tokens_len")), INT2NUM((int)s->tokens_len));
167
+ rb_hash_aset(h, ID2SYM(rb_intern("look0")), s->look[0]);
168
+ rb_hash_aset(h, ID2SYM(rb_intern("look1")), s->look[1]);
169
+ rb_hash_aset(h, ID2SYM(rb_intern("marks_idx")), INT2NUM(s->marks_idx));
170
+ return h;
171
+ }
172
+
173
+ void Init_minicss_token_stream(void) {
174
+ const VALUE mMiniCSS = rb_define_module("MiniCSS");
175
+ const VALUE mCSS = rb_define_module_under(mMiniCSS, "CSS");
176
+ const VALUE cStream = rb_define_class_under(mCSS, "TokenStream", rb_cObject);
177
+ cTokenClass = rb_path2class("MiniCSS::CSS::Token");
178
+
179
+ INITIALIZE_REUSABLE_SYMBOL(whitespace);
180
+ INITIALIZE_REUSABLE_SYMBOL(eof);
181
+
182
+ rb_define_alloc_func(cStream, stream_alloc);
183
+ rb_define_method(cStream, "initialize", stream_initialize, 1);
184
+ rb_define_method(cStream, "peek", stream_peek, 0);
185
+ rb_define_method(cStream, "peek_kind", stream_peek_kind, 0);
186
+ rb_define_method(cStream, "consume", stream_consume, 0);
187
+ rb_define_method(cStream, "discard_whitespace", stream_discard_whitespace, 0);
188
+ rb_define_method(cStream, "discard", stream_discard, 0);
189
+
190
+ rb_define_method(cStream, "mark", stream_create_mark, 0);
191
+ rb_define_method(cStream, "restore", stream_mark_restore, 0);
192
+ rb_define_method(cStream, "pop", stream_mark_pop, 0);
193
+ rb_define_method(cStream, "empty?", stream_is_empty, 0);
194
+ rb_define_method(cStream, "status", stream_status, 0);
195
+ }
@@ -13,7 +13,7 @@ module MiniCSS
13
13
 
14
14
  def kind = :function
15
15
 
16
- def literal = [name.literal, value.map(&:literal)].join
16
+ def literal = [name.literal, value.map(&:literal), ")"].join
17
17
  end
18
18
  end
19
19
  end
@@ -5,8 +5,6 @@ module MiniCSS
5
5
  class Parser
6
6
  using StringRefinements
7
7
 
8
- attr_reader :stream
9
-
10
8
  def initialize(tokens)
11
9
  @stream = TokenStream.new(tokens)
12
10
  @tokens = tokens
@@ -27,25 +25,25 @@ module MiniCSS
27
25
  end
28
26
 
29
27
  def parse_rule
30
- stream.discard_whitespace
31
- return SyntaxError.new("empty") if stream.empty?
28
+ @stream.discard_whitespace
29
+ return SyntaxError.new("empty") if @stream.empty?
32
30
 
33
- result = if stream.peek.kind == :at_keyword
31
+ result = if @stream.peek.kind == :at_keyword
34
32
  consume_at_rule
35
33
  else
36
34
  consume_qualified_rule
37
35
  end
38
36
  return SyntaxError.new("invalid") unless result
39
37
 
40
- stream.discard_whitespace
41
- return SyntaxError.new("extra-input") unless stream.empty?
38
+ @stream.discard_whitespace
39
+ return SyntaxError.new("extra-input") unless @stream.empty?
42
40
 
43
41
  result
44
42
  end
45
43
 
46
44
  def parse_declaration
47
- stream.discard_whitespace
48
- return SyntaxError.new("empty") if stream.empty?
45
+ @stream.discard_whitespace
46
+ return SyntaxError.new("empty") if @stream.empty?
49
47
 
50
48
  decl = consume_declaration
51
49
  return SyntaxError.new("invalid") unless decl
@@ -54,25 +52,23 @@ module MiniCSS
54
52
  end
55
53
 
56
54
  def parse_component_value
57
- stream.discard_whitespace
58
- return SyntaxError.new("empty") if stream.empty?
55
+ @stream.discard_whitespace
56
+ return SyntaxError.new("empty") if @stream.empty?
59
57
 
60
58
  value = consume_component_value
61
- stream.discard_whitespace
62
- return SyntaxError.new("extra-input") unless stream.empty?
59
+ @stream.discard_whitespace
60
+ return SyntaxError.new("extra-input") unless @stream.empty?
63
61
 
64
62
  value
65
63
  end
66
64
 
67
- def parse_component_value_list
68
- consume_component_value_list
69
- end
65
+ def parse_component_value_list = consume_component_value_list
70
66
 
71
67
  def parse_component_value_comma_list
72
68
  groups = []
73
- until stream.empty?
69
+ until @stream.empty?
74
70
  groups << consume_component_value_list(stop: :comma)
75
- stream.discard
71
+ @stream.discard
76
72
  end
77
73
  groups
78
74
  end
@@ -80,7 +76,7 @@ module MiniCSS
80
76
  # Helpers
81
77
 
82
78
  def assert_next_token(kind)
83
- stream.peek.kind == kind
79
+ @stream.peek.kind == kind
84
80
  end
85
81
 
86
82
  # Parsers
@@ -88,9 +84,9 @@ module MiniCSS
88
84
  def consume_stylesheet_contents
89
85
  rules = []
90
86
  loop do
91
- case stream.peek.kind
87
+ case @stream.peek.kind
92
88
  when :whitespace, :cdo, :cdc
93
- stream.discard
89
+ @stream.discard
94
90
 
95
91
  when :eof
96
92
  return rules
@@ -109,11 +105,11 @@ module MiniCSS
109
105
  def consume_at_rule(nested: false)
110
106
  return unless assert_next_token(:at_keyword)
111
107
 
112
- rule = AST::AtRule.new(name: stream.consume)
108
+ rule = AST::AtRule.new(name: @stream.consume)
113
109
  loop do
114
- case stream.peek.kind
110
+ case @stream.peek.kind
115
111
  when :semicolon, :eof
116
- stream.discard
112
+ @stream.discard
117
113
  # TODO: If rule is valid in the current context, return it; otherwise return nothing.
118
114
  return rule
119
115
 
@@ -123,10 +119,10 @@ module MiniCSS
123
119
  return rule
124
120
  end
125
121
 
126
- rule.prelude << consume
122
+ rule.prelude << @stream.consume
127
123
 
128
124
  when :left_curly
129
- consume_block.each { rule.child_rules << it }
125
+ rule.child_rules.append(*consume_block)
130
126
  return rule
131
127
 
132
128
  else
@@ -139,14 +135,14 @@ module MiniCSS
139
135
  rule = AST::QualifiedRule.new
140
136
 
141
137
  loop do
142
- case stream.peek.kind
138
+ case @stream.peek.kind
143
139
  when :eof, stop
144
140
  return nil
145
141
 
146
142
  when :right_curly
147
143
  return nil if nested
148
144
 
149
- rule.prelude << consume
145
+ rule.prelude << @stream.consume
150
146
 
151
147
  when :left_curly
152
148
  non_ws = rule.prelude.reject { it.kind == :whitespace }
@@ -179,9 +175,9 @@ module MiniCSS
179
175
  def consume_block
180
176
  return unless assert_next_token(:left_curly)
181
177
 
182
- stream.discard
178
+ @stream.discard
183
179
  rules = consume_block_contents
184
- stream.discard
180
+ @stream.discard
185
181
  rules
186
182
  end
187
183
 
@@ -190,9 +186,9 @@ module MiniCSS
190
186
  decls = AST::DeclarationList.new
191
187
 
192
188
  loop do
193
- case stream.peek.kind
189
+ case @stream.peek.kind
194
190
  when :whitespace, :semicolon
195
- stream.discard
191
+ @stream.discard
196
192
  when :eof, :right_curly
197
193
  rules << decls unless decls.empty?
198
194
  return rules
@@ -204,15 +200,15 @@ module MiniCSS
204
200
  at = consume_at_rule(nested: true)
205
201
  rules << at if at.is_a? AST::AtRule
206
202
  else
207
- stream.mark
203
+ @stream.mark
208
204
  decl = consume_declaration(nested: true)
209
205
  if decl.is_a? AST::Declaration
210
206
  decls << decl
211
- stream.pop
207
+ @stream.pop
212
208
  next
213
209
  end
214
210
 
215
- stream.restore
211
+ @stream.restore
216
212
  rule = consume_qualified_rule(nested: true)
217
213
  if rule.is_a? InvalidRuleError
218
214
  unless decls.empty?
@@ -232,23 +228,23 @@ module MiniCSS
232
228
 
233
229
  def consume_declaration(nested: false)
234
230
  decl = AST::Declaration.new
235
- if stream.peek.kind == :ident
236
- decl.name = stream.consume
231
+ if @stream.peek.kind == :ident
232
+ decl.name = @stream.consume
237
233
  else
238
234
  consume_bad_declaration(nested:)
239
235
  return nil
240
236
  end
241
237
 
242
- stream.discard_whitespace
238
+ @stream.discard_whitespace
243
239
 
244
- if stream.peek.kind == :colon
245
- stream.discard
240
+ if @stream.peek.kind == :colon
241
+ @stream.discard
246
242
  else
247
243
  consume_bad_declaration(nested:)
248
244
  return nil
249
245
  end
250
246
 
251
- stream.discard_whitespace
247
+ @stream.discard_whitespace
252
248
 
253
249
  decl.value = consume_component_value_list(nested:, stop: :semicolon)
254
250
 
@@ -276,14 +272,14 @@ module MiniCSS
276
272
 
277
273
  def consume_bad_declaration(nested:)
278
274
  loop do
279
- case stream.peek.kind
275
+ case @stream.peek.kind
280
276
  when :eof, :semicolon
281
- stream.discard
277
+ @stream.discard
282
278
  return nil
283
279
  when :right_curly
284
280
  return if nested
285
281
 
286
- stream.discard
282
+ @stream.discard
287
283
  else
288
284
  consume_component_value
289
285
  end
@@ -293,14 +289,14 @@ module MiniCSS
293
289
  def consume_component_value_list(stop: nil, nested: false)
294
290
  values = []
295
291
  loop do
296
- case stream.peek.kind
292
+ case @stream.peek.kind
297
293
  when :eof, stop
298
294
  return values
299
295
 
300
296
  when :right_curly
301
297
  return values if nested
302
298
 
303
- values << stream.consume
299
+ values << @stream.consume
304
300
 
305
301
  else
306
302
  values << consume_component_value
@@ -309,20 +305,20 @@ module MiniCSS
309
305
  end
310
306
 
311
307
  def consume_component_value
312
- case stream.peek.kind
308
+ case @stream.peek_kind
313
309
  when :left_curly, :left_square_bracket, :left_parenthesis
314
310
  consume_simple_block
315
311
  when :function
316
312
  consume_function
317
313
  else
318
- stream.consume
314
+ @stream.consume
319
315
  end
320
316
  end
321
317
 
322
318
  def consume_simple_block
323
319
  return if !assert_next_token(:left_curly) && !assert_next_token(:left_square_bracket) && !assert_next_token(:left_parenthesis)
324
320
 
325
- block = AST::SimpleBlock.new(associated_token: stream.consume.kind)
321
+ block = AST::SimpleBlock.new(associated_token: @stream.consume.kind)
326
322
  ending_token = {
327
323
  left_curly: :right_curly,
328
324
  left_parenthesis: :right_parenthesis,
@@ -330,9 +326,9 @@ module MiniCSS
330
326
  }[block.associated_token]
331
327
 
332
328
  loop do
333
- case stream.peek.kind
329
+ case @stream.peek.kind
334
330
  when :eof, ending_token
335
- stream.discard
331
+ @stream.discard
336
332
  return block
337
333
  else
338
334
  block.value << consume_component_value
@@ -343,12 +339,12 @@ module MiniCSS
343
339
  def consume_function
344
340
  return unless assert_next_token(:function)
345
341
 
346
- func = AST::Function.new(name: stream.consume)
342
+ func = AST::Function.new(name: @stream.consume)
347
343
 
348
344
  loop do
349
- case stream.peek.kind
345
+ case @stream.peek.kind
350
346
  when :eof, :right_parenthesis
351
- stream.discard
347
+ @stream.discard
352
348
  return func
353
349
  else
354
350
  func.value << consume_component_value