hotcell 0.1.0 → 0.2.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.
data/ext/lexerc/lexerc.h CHANGED
@@ -1,3 +1,5 @@
1
+ #define regexp_possible rb_funcall(self, rb_intern("regexp_possible"), 0)
2
+
1
3
  #define emit_tag rb_funcall(self, rb_intern("emit_tag"), 0)
2
4
  #define emit_operator rb_funcall(self, rb_intern("emit_operator"), 0)
3
5
  #define emit_numeric rb_funcall(self, rb_intern("emit_numeric"), 0)
@@ -11,10 +13,3 @@
11
13
  #define raise_unterminated_string rb_funcall(self, rb_intern("raise_unterminated_string"), 0)
12
14
  #define raise_unterminated_regexp rb_funcall(self, rb_intern("raise_unterminated_regexp"), 0)
13
15
  #define raise_unexpected_symbol rb_funcall(self, rb_intern("raise_unexpected_symbol"), 0)
14
-
15
- #define regexp_ambiguity(block) { \
16
- if (rb_funcall(self, rb_intern("regexp_possible?"), 0) == Qfalse) { \
17
- emit_operator; \
18
- block; \
19
- } \
20
- }
data/ext/lexerc/lexerc.rl CHANGED
@@ -1,98 +1,17 @@
1
1
  %%{
2
2
  machine puffer_lexer;
3
3
 
4
- plus = '+';
5
- minus = '-';
6
- multiply = '*';
7
- power = '**';
8
- divide = '/';
9
- modulo = '%';
10
- arithmetic = plus | minus | multiply | power | divide | modulo;
11
-
12
- and = '&&';
13
- or = '||';
14
- not = '!';
15
- equal = '==';
16
- inequal = '!=';
17
- gt = '>';
18
- gte = '>=';
19
- lt = '<';
20
- lte = '<=';
21
- logic = and | or | not | equal | inequal | gt | gte | lt | lte;
22
-
23
- assign = '=';
24
- comma = ',';
25
- period = '.';
26
- colon = ':';
27
- question = '?';
28
- semicolon = ';';
29
- newline = '\n';
30
- flow = assign | comma | period | colon | question | semicolon | newline;
31
-
32
- array_open = '[';
33
- array_close = ']';
34
- hash_open = '{';
35
- hash_close = '}';
36
- bracket_open = '(';
37
- bracket_close = ')';
38
- structure = array_open | array_close | hash_open | hash_close | bracket_open | bracket_close;
39
-
40
-
41
- escaped_symbol = '\\' any;
42
-
43
- squote = "'";
44
- snon_quote = [^\\'];
45
- sstring = squote (snon_quote | escaped_symbol)* squote @lerr{ raise_unterminated_string; };
46
-
47
- dquote = '"';
48
- dnon_quote = [^\\"];
49
- dstring = dquote (dnon_quote | escaped_symbol)* dquote @lerr{ raise_unterminated_string; };
50
-
51
- rquote = '/';
52
- rnon_quote = [^\\/];
53
- regexp = rquote @{ regexp_ambiguity(fgoto expression;) }
54
- (rnon_quote | escaped_symbol)* rquote alpha* @lerr{ raise_unterminated_regexp; };
55
-
56
-
57
- numeric = '-'? digit* ('.' digit+)?;
58
- identifer = (alpha | '_') (alnum | '_')* [?!]?;
59
- operator = arithmetic | logic | flow | structure;
60
- comment = '#' ([^\n}]+ | '}' [^}])*;
61
- blank = [\t\v\f\r ];
62
-
63
- tag_open = '{{' '!'?;
64
- tag_close = '}}';
65
- template = [^{]+ | '{';
66
-
67
- template_comment_open = '{{#';
68
- template_comment_close = '#}}';
69
- template_comment_body = [^\#]+ | '#';
70
-
71
-
72
- expression := |*
73
- tag_close => { emit_tag; fret; };
74
- operator => { emit_operator; };
75
- numeric => { emit_numeric; };
76
- identifer => { emit_identifer; };
77
- sstring => { emit_sstring; };
78
- dstring => { emit_dstring; };
79
- regexp => { emit_regexp; };
80
- comment => { emit_comment; };
81
- blank;
82
- *|;
83
-
84
- template_comment := |*
85
- template_comment_close => { emit_comment; fret; };
86
- template_comment_body => { emit_comment; };
87
- *|;
88
-
89
- main := |*
90
- tag_open => { emit_tag; fcall expression; };
91
- template_comment_open => { emit_comment; fcall template_comment; };
92
- template => { emit_template; };
93
- *|;
4
+ action RegexpCheck {
5
+ if (regexp_possible == Qfalse) {
6
+ emit_operator;
7
+ fgoto expression;
8
+ }
9
+ }
10
+
11
+ include "lexer.rl";
94
12
  }%%
95
13
 
14
+
96
15
  #include <ruby.h>
97
16
  #include <lexerc.h>
98
17
 
@@ -15,7 +15,12 @@ module Hotcell
15
15
 
16
16
  def process context, variable, options
17
17
  forloop = options['loop'] == true ? 'loop' : options['loop']
18
- items = Array.wrap(options['in'])
18
+ items = case options['in']
19
+ when Range, Hash
20
+ options['in'].to_a
21
+ else
22
+ Array.wrap(options['in'])
23
+ end
19
24
  length = items.size
20
25
 
21
26
  items.map.with_index do |item, index|
@@ -25,7 +30,7 @@ module Hotcell
25
30
  context.scoped scope do
26
31
  subnodes.first.try(:render, context)
27
32
  end
28
- end
33
+ end.join
29
34
  end
30
35
 
31
36
  class Forloop < Hotcell::Manipulator
@@ -5,13 +5,14 @@ module Hotcell
5
5
  include Singleton
6
6
 
7
7
  attr_reader :commands, :blocks, :helpers
8
- attr_accessor :resolver
8
+ attr_accessor :resolver, :escape_tags
9
9
 
10
10
  def initialize
11
11
  @commands = {}
12
12
  @blocks = {}
13
13
  @helpers = []
14
14
  @resolver = Hotcell::Resolver.new
15
+ @escape_tags = false
15
16
  end
16
17
 
17
18
  # Adds command or block to the list of default commands or blocks returned
@@ -16,6 +16,8 @@ end
16
16
 
17
17
  String.class_eval do
18
18
  include Hotcell::Manipulator::Mixin
19
+
20
+ manipulate :size, :length
19
21
  end
20
22
 
21
23
  Regexp.class_eval do
@@ -32,13 +34,23 @@ end
32
34
 
33
35
  Array.class_eval do
34
36
  include Hotcell::Manipulator::Mixin
37
+
38
+ manipulate :first, :last, :count, :size, :length
35
39
  end
36
40
 
37
41
  Hash.class_eval do
38
42
  include Hotcell::Manipulator::Mixin
39
43
 
44
+ manipulate :keys, :values, :count, :size, :length
45
+
40
46
  def manipulator_invoke method, *arguments
41
- arguments.size == 0 && key?(method) ? self[method] : super
47
+ if method == '[]'
48
+ manipulator_invoke_brackets *arguments
49
+ elsif manipulator_invokable? method
50
+ send(method, *arguments)
51
+ elsif arguments.count == 0
52
+ self[method]
53
+ end
42
54
  end
43
55
  end
44
56
 
data/lib/hotcell/lexer.rb CHANGED
@@ -6,8 +6,8 @@ module Hotcell
6
6
  '&&' => :AND, '||' => :OR, '!' => :NOT, '==' => :EQUAL, '!=' => :INEQUAL,
7
7
  '>' => :GT, '>=' => :GTE, '<' => :LT, '<=' => :LTE,
8
8
 
9
- '=' => :ASSIGN, ',' => :COMMA, '.' => :PERIOD, ':' => :COLON, '?' => :QUESTION,
10
- ';' => :SEMICOLON
9
+ '=' => :ASSIGN, ',' => :COMMA, '.' => :PERIOD, '..' => :RANGE, '...' => :RANGE,
10
+ ':' => :COLON, '?' => :QUESTION, ';' => :SEMICOLON
11
11
  }
12
12
 
13
13
  BOPEN = { '[' => :AOPEN, '{' => :HOPEN, '(' => :POPEN }
@@ -30,11 +30,6 @@ module Hotcell
30
30
  '\s' => "\s", '\r' => "\r", '\t' => "\t"
31
31
  }
32
32
 
33
- TAGS = {
34
- '{{' => :TOPEN, '{{!' => :TOPEN,
35
- '}}' => :TCLOSE
36
- }
37
-
38
33
  PREREGEXP = Set.new [
39
34
  :TOPEN, :NEWLINE, :SEMICOLON,
40
35
  :COLON, :COMMA, :PERIOD,
@@ -83,13 +78,13 @@ module Hotcell
83
78
  end
84
79
 
85
80
  def regexp_ambiguity
86
- unless regexp_possible?
81
+ unless regexp_possible
87
82
  emit_operator
88
83
  yield
89
84
  end
90
85
  end
91
86
 
92
- def regexp_possible?
87
+ def regexp_possible
93
88
  last = @token_array[-1]
94
89
  # Need more rules!
95
90
  !last || PREREGEXP.include?(last[0])
@@ -120,7 +115,7 @@ module Hotcell
120
115
 
121
116
  def emit_tag
122
117
  value = current_value
123
- emit TAGS[value], value
118
+ emit (value == '}}' ? :TCLOSE : :TOPEN), value
124
119
  end
125
120
 
126
121
  def emit_comment
@@ -0,0 +1,95 @@
1
+ %%{
2
+ machine puffer_lexer;
3
+
4
+ plus = '+';
5
+ minus = '-';
6
+ multiply = '*';
7
+ power = '**';
8
+ divide = '/';
9
+ modulo = '%';
10
+ arithmetic = plus | minus | multiply | power | divide | modulo;
11
+
12
+ and = '&&';
13
+ or = '||';
14
+ not = '!';
15
+ equal = '==';
16
+ inequal = '!=';
17
+ gt = '>';
18
+ gte = '>=';
19
+ lt = '<';
20
+ lte = '<=';
21
+ logic = and | or | not | equal | inequal | gt | gte | lt | lte;
22
+
23
+ assign = '=';
24
+ comma = ',';
25
+ period = '.';
26
+ range = '..' '.'?;
27
+ colon = ':';
28
+ question = '?';
29
+ semicolon = ';';
30
+ newline = '\n';
31
+ flow = assign | comma | period | range | colon | question | semicolon | newline;
32
+
33
+ array_open = '[';
34
+ array_close = ']';
35
+ hash_open = '{';
36
+ hash_close = '}';
37
+ bracket_open = '(';
38
+ bracket_close = ')';
39
+ structure = array_open | array_close | hash_open | hash_close | bracket_open | bracket_close;
40
+
41
+
42
+ escaped_symbol = '\\' any;
43
+
44
+ squote = "'";
45
+ snon_quote = [^\\'];
46
+ sstring = squote (snon_quote | escaped_symbol)* squote @lerr{ raise_unterminated_string; };
47
+
48
+ dquote = '"';
49
+ dnon_quote = [^\\"];
50
+ dstring = dquote (dnon_quote | escaped_symbol)* dquote @lerr{ raise_unterminated_string; };
51
+
52
+ rquote = '/';
53
+ rnon_quote = [^\\/];
54
+ regexp = rquote @RegexpCheck
55
+ (rnon_quote | escaped_symbol)* rquote alpha* @lerr{ raise_unterminated_regexp; };
56
+
57
+
58
+ numeric = '-'? digit* ('.' digit+)?;
59
+ identifer = (alpha | '_') (alnum | '_')* [?!]?;
60
+ operator = arithmetic | logic | flow | structure;
61
+ comment = '#' ([^\n}]+ | '}' [^}])*;
62
+ blank = [\t\v\f\r ];
63
+
64
+ tag_open = '{{' ([!~^] | [re] ' ')?;
65
+ tag_close = '}}';
66
+ template = [^{]+ | '{';
67
+
68
+ template_comment_open = '{{#';
69
+ template_comment_close = '#}}';
70
+ template_comment_body = [^\#]+ | '#';
71
+
72
+
73
+ expression := |*
74
+ tag_close => { emit_tag; fret; };
75
+ operator => { emit_operator; };
76
+ numeric => { emit_numeric; };
77
+ identifer => { emit_identifer; };
78
+ sstring => { emit_sstring; };
79
+ dstring => { emit_dstring; };
80
+ regexp => { emit_regexp; };
81
+ comment => { emit_comment; };
82
+ blank;
83
+ *|;
84
+
85
+ template_comment := |*
86
+ template_comment_close => { emit_comment; fret; };
87
+ template_comment_body => { emit_comment; };
88
+ *|;
89
+
90
+ main := |*
91
+ tag_open => { emit_tag; fcall expression; };
92
+ template_comment_open => { emit_comment; fcall template_comment; };
93
+ template => { emit_template; };
94
+ *|;
95
+ }%%