lokar 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lokar.rb +90 -74
  2. metadata +16 -5
data/lokar.rb CHANGED
@@ -2,133 +2,149 @@ require 'strscan'
2
2
 
3
3
  module Lokar
4
4
  def self.render(string, filename = '<Lokar>', binding = nil)
5
- output = ["__output__ = []", *parse(string, filename), "\n__output__"]
6
-
7
- eval(output.join, binding, filename).join
5
+ eval("__output__ = []#{parse(string, filename).join}; __output__", binding, filename).join
8
6
  end
9
7
 
10
8
  def self.compile(string, filename = '<Lokar>', binding = nil)
11
- output = ["Proc.new do __output__ = []", *parse(string, filename), "\n__output__ end"]
12
-
13
- eval output.join, binding, filename
9
+ eval "Proc.new do __output__ = []#{parse(string, filename).join}; __output__ end", binding, filename
14
10
  end
15
11
 
16
12
  def self.parse(string, filename)
17
13
  scanner = StringScanner.new(string)
18
- output = []
19
14
  prev_text = false
20
15
  prev_output = true
16
+ output = []
17
+ line = 1
18
+ flushed = 1
21
19
 
22
20
  while true
23
- match = scanner.scan_until(/(?=<\?r[ \t]|\#{|^[ \t]*%)/m)
21
+ match = scanner.scan_until(/(?=<\?r(?:[ \t]|$)|\#?\#{|^[ \t]*%|(?:\r\n?|\n))/m)
24
22
  if match
25
23
  # Add the text before the match
26
- if prev_text
27
- output.insert(-1, match.inspect)
28
- else
24
+ unless prev_text
29
25
  if prev_output
30
- output << " << "
26
+ output << "<<"
31
27
  else
32
- output << "\n__output__ << "
28
+ output << ";__output__<<"
33
29
  prev_output = true
34
30
  end
35
- output << match.inspect
36
31
  prev_text = true
37
32
  end
33
+ output << match.inspect
38
34
 
39
35
  case # Find out what of the regular expression matched
40
- when scanner.match?(/</) # Parse <?r ?> tags
36
+ when match = scanner.scan(/\r\n?|\n/) # Parse newlines
37
+ unless prev_text
38
+ if prev_output
39
+ output << "<<"
40
+ else
41
+ output << ";__output__<<"
42
+ prev_output = true
43
+ end
44
+ prev_text = true
45
+ end
46
+ output << match.inspect
47
+ line += 1
48
+
49
+ when scanner.match?(/</) # Parse <?r?> tags
41
50
  scanner.pos += 3
42
51
  result = scanner.scan_until(/(?=\?>)/m)
43
- raise "#{filename}: Unterminated <?r ?> tag" unless result
44
-
45
- output << "\n"
46
- output << result
52
+ raise "#{filename}:#{line}: Unterminated <\?r ?> tag" unless result
47
53
 
54
+ output << ("\n" * (line - flushed)) << ";" << result
55
+ flushed = line
48
56
  prev_text = false
49
57
  prev_output = false
50
58
 
51
59
  scanner.pos += 2
52
60
 
53
- when scanner.match?(/\#/) # Parse #{ } tags
54
- index = 1
55
- scanner.pos += 2
56
-
57
- if prev_output
58
- output << " << ("
61
+ when scanner.skip(/\#/) # Parse #{ } tags
62
+ if scanner.skip(/\#/)
63
+ unless prev_text
64
+ if prev_output
65
+ output << "<<"
66
+ else
67
+ output << ";__output__<<"
68
+ prev_output = true
69
+ end
70
+ prev_text = true
71
+ end
72
+ output << '#'.inspect
59
73
  else
60
- output << "\n__output__ << ("
61
- prev_output = true
62
- end
63
-
64
- while true
65
- result = scanner.scan_until(/(?=}|{)/m)
66
- raise "#{filename}: Unterminated \#{ } tag" unless result
67
- output << result
68
- case
69
- when scanner.scan(/{/)
70
- index += 1
71
- output << '{'
72
-
73
- when scanner.scan(/}/)
74
- index -= 1
75
- break if index == 0
76
- output << '}'
74
+ index = 1
75
+ scanner.pos += 1
76
+
77
+ if prev_output
78
+ output << "<<" << ("\n" * (line - flushed)) << "("
79
+ else
80
+ output << ("\n" * (line - flushed)) << ";__output__<<("
81
+ prev_output = true
82
+ end
83
+ flushed = line
84
+ prev_text = false
85
+
86
+ while true
87
+ result = scanner.scan_until(/(?=}|{)/m)
88
+ raise "#{filename}:#{line}: Unterminated \#\{ } tag" unless result
89
+ output << result
90
+ case
91
+ when scanner.skip(/{/)
92
+ index += 1
93
+ output << '{'
94
+
95
+ when scanner.skip(/}/)
96
+ index -= 1
97
+ break if index == 0
98
+ output << '}'
99
+ end
77
100
  end
101
+
102
+ output << ")"
78
103
  end
79
-
80
- output << ")"
81
-
82
- prev_output = true
83
- prev_text = false
84
104
 
85
105
  else # Parse %, %% and %= lines
86
106
  result = scanner.scan(/[ \t]*%/)
87
- if scanner.scan(/%/)
88
- result = result.inspect
89
- if prev_text
90
- output << result
91
- else
107
+ if scanner.skip(/%/)
108
+ unless prev_text
92
109
  if prev_output
93
- output << " << "
110
+ output << "<<"
94
111
  else
95
- output << "\n__output__ << "
112
+ output << ";__output__<<"
96
113
  prev_output = true
97
114
  end
98
- output << result
99
115
  prev_text = true
100
116
  end
101
- else
102
- if scanner.scan(/=/)
103
- if prev_output
104
- output << " << ("
105
- else
106
- output << "\n__output__ << ("
107
- prev_output = true
108
- end
109
- output << scanner.scan_until(/(\r\n|\n|\Z)/)
110
- output << ")"
117
+ output << result.inspect
118
+ elsif scanner.skip(/=/)
119
+ if prev_output
120
+ output << "<<" << ("\n" * (line - flushed)) << "("
111
121
  else
112
- output << "\n"
113
- output << scanner.scan_until(/(\r\n|\n|\Z)/)
114
- prev_output = false
122
+ output << ("\n" * (line - flushed)) << ";__output__<<("
123
+ prev_output = true
115
124
  end
125
+ flushed = line
126
+ prev_text = false
127
+ output << scanner.scan_until(/(?=\r\n|\n|\Z)/) << ")"
128
+ else
129
+ output << ("\n" * (line - flushed)) << ";" << scanner.scan_until(/\r\n|\n|\Z/)
130
+ flushed = line
116
131
  prev_text = false
132
+ prev_output = false
117
133
  end
118
134
  end
119
135
  else # End of file
120
136
  unless scanner.eos?
121
137
  # Add the pending text
122
- if prev_text
123
- output << scanner.rest.inspect
124
- else
138
+ unless prev_text
125
139
  if prev_output
126
- output << " << "
140
+ output << "<<"
127
141
  else
128
- output << "\n__output__ << "
142
+ output << ";__output__<<"
143
+ prev_output = true
129
144
  end
130
- output << scanner.rest.inspect
145
+ prev_text = true
131
146
  end
147
+ output << scanner.rest.inspect
132
148
  end
133
149
  break
134
150
  end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lokar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Zoxc
@@ -9,7 +14,7 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-01-05 00:00:00 +01:00
17
+ date: 2010-09-20 00:00:00 +02:00
13
18
  default_executable:
14
19
  dependencies: []
15
20
 
@@ -34,21 +39,27 @@ rdoc_options: []
34
39
  require_paths:
35
40
  - .
36
41
  required_ruby_version: !ruby/object:Gem::Requirement
42
+ none: false
37
43
  requirements:
38
44
  - - ">="
39
45
  - !ruby/object:Gem::Version
46
+ segments:
47
+ - 1
48
+ - 9
49
+ - 0
40
50
  version: 1.9.0
41
- version:
42
51
  required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
43
53
  requirements:
44
54
  - - ">="
45
55
  - !ruby/object:Gem::Version
56
+ segments:
57
+ - 0
46
58
  version: "0"
47
- version:
48
59
  requirements: []
49
60
 
50
61
  rubyforge_project:
51
- rubygems_version: 1.3.5
62
+ rubygems_version: 1.3.7
52
63
  signing_key:
53
64
  specification_version: 3
54
65
  summary: Lokar is a simple fast template engine.