hotcell 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }%%