summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--lib/erb.rb300
2 files changed, 173 insertions, 131 deletions
diff --git a/ChangeLog b/ChangeLog
index d54a64579e..716f92331a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Wed Jul 23 18:43:00 2003 Masatoshi SEKI <m_seki@mva.biglobe.ne.jp>
+
+ * lib/erb.rb: import erb-2.0.4b1.
+
Wed Jul 23 18:21:52 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* ext/io/wait: imported.
diff --git a/lib/erb.rb b/lib/erb.rb
index 9d6dc9dfd4..7fa5f2db1d 100644
--- a/lib/erb.rb
+++ b/lib/erb.rb
@@ -6,193 +6,231 @@ class ERB
Revision = '$Date$' #'
def self.version
- "erb.rb [2.0.2 #{ERB::Revision.split[1]}]"
+ "erb.rb [2.0.4 #{ERB::Revision.split[1]}]"
end
end
# ERB::Compiler
class ERB
class Compiler
- class ParcentLine
- def initialize(compiler, str)
+ class Scanner
+ SplitRegexp = /(<%%)|(%%>)|(<%=)|(<%#)|(<%)|(%>)|(\n)/
+
+ def initialize(compiler, src)
@compiler = compiler
- @line = str
+ @src = src
+ @stag = nil
end
+ attr_accessor :stag
+
+ def scan; end
+ end
- def expand(list)
- str = @line.dup
- str[0] = ''
- if /^%%/ === @line
- list.unshift("\n")
- list.unshift(str)
+ class TrimScanner < Scanner
+ def initialize(compiler, src)
+ super(compiler, src)
+ @trim_mode = compiler.trim_mode
+ @percent = compiler.percent
+ if @trim_mode
+ @scan_line = self.method(:trim_line)
else
- list.unshift('%>')
- list.unshift(str)
- list.unshift('<%')
+ @scan_line = self.method(:scan_line)
end
- list
end
+ attr_accessor :stag
- def expand_in_script(list)
- ary = []
- @compiler.push_line(ary, @line)
- ary.reverse_each do |x|
- list.unshift(x)
+ def scan(&block)
+ @stag = nil
+ if @percent
+ @src.each do |line|
+ percent_line(line, &block)
+ end
+ else
+ @src.each do |line|
+ trim_line(line, &block)
+ end
end
+ nil
end
- end
- ERbTag = "<%% %%> <%= <%# <% %>".split
- def is_erb_tag?(s)
- ERbTag.member?(s)
- end
-
- SplitRegexp = /(<%%)|(%%>)|(<%=)|(<%#)|(<%)|(%>)|(\n)/
+ def percent_line(line, &block)
+ if @stag || line[0] != ?%
+ return @scan_line.call(line, &block)
+ end
- def prepare_trim_mode(mode)
- case mode
- when 1
- return [false, '>']
- when 2
- return [false, '<>']
- when 0
- return [false, nil]
- when String
- perc = mode.include?('%')
- if mode.include?('<>')
- return [perc, '<>']
- elsif mode.include?('>')
- return [perc, '>']
+ line[0] = ''
+ if line[0] == ?%
+ @scan_line.call(line, &block)
else
- [perc, nil]
+ yield('<%')
+ yield(' ' +line.chomp)
+ yield('%>')
+ end
+ end
+
+ def scan_line(line)
+ line.split(SplitRegexp).each do |token|
+ next if token.empty?
+ yield(token)
end
- else
- return [false, nil]
+ end
+
+ def trim_line(line)
+ head = nil
+ last = nil
+ line.split(SplitRegexp).each do |token|
+ next if token.empty?
+ head = token unless head
+ if token == "\n" && last == '%>'
+ next if @trim_mode == '>'
+ next if @trim_mode == '<>' && is_erb_stag?(head)
+ yield("\n")
+ break
+ end
+ yield(token)
+ last = token
+ end
+ end
+
+ ERB_STAG = %w(<%= <%# <%)
+ def is_erb_stag?(s)
+ ERB_STAG.member?(s)
end
end
- def pre_compile(s)
- re = SplitRegexp
- if @trim_mode.nil? && !@perc
- list = s.split(re)
- else
- list = []
- has_cr = (s[-1] == ?\n)
- s.each do |line|
- line = line.chomp
- if @perc && (/^%/ =~ line)
- list.push(ParcentLine.new(self, line))
- else
- push_line(list, line)
+ class SimpleScanner < Scanner
+ def scan
+ @src.each do |line|
+ line.split(SplitRegexp).each do |token|
+ next if token.empty?
+ yield(token)
end
end
- list.pop if list[-1] == "\n" && !has_cr
end
- list
end
- def push_line(list, line)
- re = SplitRegexp
- line = line.split(re)
- line.shift if line[0]==''
- list.concat(line)
- unless ((@trim_mode == '>' && line[-1] == '%>') ||
- (@trim_mode == '<>' && (is_erb_tag?(line[0])) &&
- line[-1] == '%>'))
- list.push("\n")
+ class Buffer
+ def initialize(compiler)
+ @compiler = compiler
+ @line = []
+ @script = ""
+ @compiler.pre_cmd.each do |x|
+ push(x)
+ end
+ end
+ attr_reader :script
+
+ def push(cmd)
+ @line << cmd
+ end
+
+ def cr
+ @script << (@line.join('; '))
+ @line = []
+ @script << "\n"
+ end
+
+ def close
+ return unless @line
+ @compiler.post_cmd.each do |x|
+ push(x)
+ end
+ @script << (@line.join('; '))
+ @line = nil
end
end
def compile(s)
- list = pre_compile(s)
- cmd = []
- cmd.concat(@pre_cmd)
+ out = Buffer.new(self)
- stag = nil
- content = []
- while (token = list.shift)
- if token == '<%%'
- token = '<'
- list.unshift '%'
- elsif token == '%%>'
- token = '%'
- list.unshift '>'
- end
- if stag.nil?
- if ['<%', '<%=', '<%#'].include?(token)
- stag = token
- str = content.join('')
- if str.size > 0
- cmd.push("#{@put_cmd} #{str.dump}")
- end
- content = []
- elsif token == "\n"
- content.push("\n")
- cmd.push("#{@put_cmd} #{content.join('').dump}")
- cmd.push(:cr)
- content = []
- elsif ParcentLine === token
- token.expand(list)
- next
+ content = ''
+ scanner = make_scanner(s)
+ scanner.scan do |token|
+ if scanner.stag.nil?
+ case token
+ when '<%', '<%=', '<%#'
+ scanner.stag = token
+ out.push("#{@put_cmd} #{content.dump}") if content.size > 0
+ content = ''
+ when "\n"
+ content << "\n"
+ out.push("#{@put_cmd} #{content.dump}")
+ out.cr
+ content = ''
+ when '<%%'
+ content << '<%'
else
- content.push(token)
+ content << token
end
else
- if token == '%>'
- case stag
+ case token
+ when '%>'
+ case scanner.stag
when '<%'
- str = content.join('')
- if str[-1] == ?\n
- str.chop!
- cmd.push(str)
- cmd.push(:cr)
+ if content[-1] == ?\n
+ content.chop!
+ out.push(content)
+ out.cr
else
- cmd.push(str)
+ out.push(content)
end
when '<%='
- cmd.push("#{@put_cmd}((#{content.join('')}).to_s)")
+ out.push("#{@put_cmd}((#{content}).to_s)")
when '<%#'
- # cmd.push("# #{content.dump}")
+ # out.push("# #{content.dump}")
end
- stag = nil
- content = []
- elsif ParcentLine === token
- token.expand_in_script(list)
- next
+ scanner.stag = nil
+ content = ''
+ when '%%>'
+ content << '%>'
else
- content.push(token)
+ content << token
end
end
end
- if content.size > 0
- cmd.push("#{@put_cmd} #{content.join('').dump}")
- end
- cmd.push(:cr)
- cmd.concat(@post_cmd)
+ out.push("#{@put_cmd} #{content.dump}") if content.size > 0
+ out.close
+ out.script
+ end
- ary = []
- cmd.each do |x|
- if x == :cr
- ary.pop
- ary.push("\n")
+ def prepare_trim_mode(mode)
+ case mode
+ when 1
+ return [false, '>']
+ when 2
+ return [false, '<>']
+ when 0
+ return [false, nil]
+ when String
+ perc = mode.include?('%')
+ if mode.include?('<>')
+ return [perc, '<>']
+ elsif mode.include?('>')
+ return [perc, '>']
else
- ary.push(x)
- ary.push('; ')
+ [perc, nil]
end
+ else
+ return [false, nil]
+ end
+ end
+
+ def make_scanner(src)
+ if @percent || @trim_mode
+ TrimScanner.new(self, src)
+ else
+ SimpleScanner.new(self, src)
end
- ary.join('')
end
def initialize(trim_mode)
- @perc, @trim_mode = prepare_trim_mode(trim_mode)
+ @percent, @trim_mode = prepare_trim_mode(trim_mode)
@put_cmd = 'print'
@pre_cmd = []
@post_cmd = []
end
-
- attr_accessor(:put_cmd)
- attr_accessor(:pre_cmd)
- attr_accessor(:post_cmd)
+ attr_reader :percent, :trim_mode
+ attr_accessor :put_cmd, :pre_cmd, :post_cmd
end
end