Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

. comments

  • Loading branch information...
commit 46525cea2d6e2adc987f7e4d19d438b4dc83086b 1 parent 68d7aa3
Kaspar Schiess authored
Showing with 32 additions and 1 deletion.
  1. +32 −1 lib/parslet/atoms/transform.rb
33 lib/parslet/atoms/transform.rb
View
@@ -1,9 +1,36 @@
require 'parslet/atoms/visitor'
-# A helper class that allows transforming one grammar into another.
+# A helper class that allows transforming one grammar into another. You can
+# use this class as a base class:
+#
+# Example:
+# class MyTransform < Parslet::Atoms::Transform
+# def visit_str(str)
+# # mangle string here
+# super(str)
+# end
+# end
+#
+# Note that all the methods in a Transform must return parser atoms. The
+# quickest way to do so is to call super with your own arguments. This will
+# just create the same kind of atom that was just visited.
+#
+# In essence, this base class performs what is called an 'identity transform'
+# with one small caveat: It returns a brand new grammar composed of brand new
+# parser atoms. This is like a deep clone of your grammar.
+#
+# But nothing stops you from doing something that is far from a deep clone.
+# You can totally transform the language your grammar accepts. Or maybe
+# turn all repetitions into non-greedy ones? Go wild.
#
class Parslet::Atoms::Transform
+ # Applies a transformation to a grammar and returns a new grammar that
+ # is the result of the transform.
+ #
+ # Example:
+ # Parslet::Atoms::Transform.new.apply(my_grammar) # => deep clone of my_grammar
+ #
def apply(grammar)
grammar.accept(self)
end
@@ -29,6 +56,10 @@ def visit_lookahead(positive, parslet)
end
def visit_entity(name, block)
+ # NOTE: This is kinda tricky. We return a new entity that keeps a reference
+ # to the transformer around. Once somebody accesses the parslet in that
+ # entity, the original block will produce the original parslet, and then
+ # we transform that then and there. Its lazy and futuristic!
transformer = self
transformed_block = proc { block.call.accept(transformer) }
Parslet::Atoms::Entity.new(name, &transformed_block)
Please sign in to comment.
Something went wrong with that request. Please try again.