Created
April 26, 2015 03:28
-
-
Save JoshCheek/2b30b052560337522f94 to your computer and use it in GitHub Desktop.
A shitty ERB parser. Procedural vs OO. I like procedural better.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class EmbeddedRuby | |
def initialize(erb) | |
@code = Parse.new(erb).code | |
end | |
def render(context) | |
context.instance_eval @code | |
end | |
end | |
class EmbeddedRuby | |
class Parse | |
def initialize(erb) | |
@erb = erb | |
@parts = ["_out = String.new\n"] | |
@current = Template.new | |
end | |
def code | |
@code ||= begin | |
@erb.scan(/<%=?|%>|./m).each do |token| | |
case token | |
when '<%=' then begin_code true | |
when '<%' then begin_code false | |
when '%>' then end_code | |
else add_char token | |
end | |
end | |
finalize | |
end | |
end | |
private | |
def begin_code(do_embed_result) | |
@parts << @current | |
@current = Code.new(do_embed_result) | |
end | |
def end_code | |
@parts << @current | |
@current = Template.new | |
end | |
def add_char(char) | |
@current << char | |
end | |
def finalize | |
@parts << @current | |
@parts << "_out\n" | |
@parts.join | |
end | |
end | |
end | |
class EmbeddedRuby | |
class Template | |
def initialize | |
@text = '' | |
end | |
def <<(text) | |
@text << text | |
end | |
def to_s | |
"_out << #{@text.inspect}\n" | |
end | |
end | |
end | |
class EmbeddedRuby | |
class Code | |
def initialize(embed_result) | |
@text = '' | |
@embed_result = embed_result | |
end | |
def <<(text) | |
@text << text | |
end | |
def to_s | |
code = '' | |
code << '_out << (' if @embed_result | |
code << @text | |
code << ')' if @embed_result | |
code << "\n" | |
code | |
end | |
end | |
end | |
erb = EmbeddedRuby.new <<-CODE | |
<ul> | |
<% @names.each do |name| %> | |
<li><%= name %></li> | |
<% end %> | |
</ul> | |
CODE | |
@names = %w[name1 name2 name3] | |
puts erb.render(self) | |
# >> <ul> | |
# >> | |
# >> <li>name1</li> | |
# >> | |
# >> <li>name2</li> | |
# >> | |
# >> <li>name3</li> | |
# >> | |
# >> </ul> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class EmbeddedRuby | |
def initialize(erb) | |
@code = self.class.parse erb | |
end | |
def render(context) | |
context.instance_eval @code | |
end | |
def self.parse(erb) | |
code = "_out = String.new\n" | |
type, text = :template, '' | |
erb.scan(/<%=?|%>|./m).each do |token| | |
case token | |
when '<%=' then code << code_for(type, text) | |
type, text = :calculation, '' | |
when '<%' then code << code_for(type, text) | |
type, text = :control, '' | |
when '%>' then code << code_for(type, text) | |
type, text = :template, '' | |
when // then text << token | |
end | |
end | |
code << code_for(type, text) << "_out\n" | |
end | |
def self.code_for(type, text) | |
case type | |
when :calculation then "_out << (#{text})\n" | |
when :control then "#{text}\n" | |
when :template then "_out << #{text.inspect}\n" | |
else raise "Unknown type: #{type.inspect}" | |
end | |
end | |
end | |
@names = %w[name1 name2 name3] | |
puts EmbeddedRuby.new(<<-CODE).render(self) | |
<ul> | |
<% @names.each do |name| %> | |
<li><%= name %></li> | |
<% end %> | |
</ul> | |
CODE | |
# >> <ul> | |
# >> | |
# >> <li>name1</li> | |
# >> | |
# >> <li>name2</li> | |
# >> | |
# >> <li>name3</li> | |
# >> | |
# >> </ul> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment