Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit e7ca9ead0d1f92d994a2e26421d6c238b93f335e @tadzik committed May 2, 2012
Showing with 119 additions and 0 deletions.
  1. +7 −0 META.info
  2. +1 −0 README
  3. +95 −0 lib/Template/Mojo.pm
  4. +16 −0 t/00-basic.t
@@ -0,0 +1,7 @@
+{
+ "name" : "Template::Mojo",
+ "version" : "*",
+ "description" : "A templating system similar to Perl 5's Mojo::Template",
+ "depends" : [],
+ "source-url" : "git://github.com/tadzik/Template-Mojo.git"
+}
1 README
@@ -0,0 +1 @@
+Modeled after https://metacpan.org/module/Mojo::Template
@@ -0,0 +1,95 @@
+grammar Template::Mojo::Grammar {
+ token TOP {
+ ^ <expression>* $
+ }
+
+ token expression {
+ || <perlline>
+ || <perlexpr>
+ || <characters>
+ }
+
+ token perlline {
+ ^^ \h* '%' $<get-result>=['=']? $<expr>=[ <-[\n]>* ] \s+
+ }
+
+ token perlexpr {
+ '<%' $<get-result>=['=']? $<expr>=[ [ <!before '%>' > . ]* ] '%>'
+ }
+
+ token characters {
+ [ <!before '<%' || \n > . ]+ \n?
+ }
+}
+
+class Template::Mojo::Actions {
+ method TOP($/) {
+ my @exprs = $<expression>».ast;
+ @exprs.unshift: 'my $_M = "";';
+ @exprs.push: ';return $_M;';
+ my $code = 'sub { ' ~ @exprs.join ~ '}';
+ make $code;
+ }
+
+ method expression($/) {
+ if $<perlline> {
+ make $<perlline>.ast
+ }
+ elsif $<perlexpr> {
+ make $<perlexpr>.ast
+ }
+ else {
+ make sprintf q[;$_M ~= '%s';], $<characters>.Str;
+ }
+ }
+
+ method perlline($/) {
+ make expr($/) ~ "\n"
+ }
+
+ method perlexpr($/) {
+ make expr($/)
+ }
+
+ sub expr($/) {
+ if $<expr> ne '' {
+ if $<get-result> ne '' {
+ return ';$_M ~= ' ~ $<expr> ~ ';'
+ }
+ else {
+ return $<expr>.Str
+ }
+ }
+ else {
+ return ''
+ }
+ }
+}
+
+class Template::Mojo {
+ has &.code;
+
+ method new(Str $tmpl) {
+ my $m = Template::Mojo::Grammar.parse(
+ $tmpl, :actions(Template::Mojo::Actions.new)
+ );
+ unless $m {
+ die "Failed to parse the template"
+ }
+ self.bless: *, :code(eval $m.ast)
+ }
+
+ method render(*@a) {
+ &.code.(|@a)
+ }
+}
+
+sub compile(Str $tmpl) {
+ my $m = Template::Mojo::Grammar.parse(
+ $tmpl, :actions(Template::Mojo::Actions.new)
+ );
+ if $m {
+ say $m.ast;
+ return eval $m.ast;
+ }
+}
@@ -0,0 +1,16 @@
+use Test;
+use Template::Mojo;
+plan 8;
+
+sub render($tmpl, *@a) {
+ Template::Mojo.new($tmpl).render(|@a)
+}
+
+is render(''), '';
+is render('hello'), 'hello';
+is render('hello <%%> world'), 'hello world';
+is render('hello <%= "world" %>'), 'hello world';
+is render('answer = <%= $^a + $^b %>', 40, 2), 'answer = 42';
+is render('hello <% "blarg" %> world'), 'hello world';
+is render("% for 1..3 \{\nhello\n% \}\n"), "hello\nhello\nhello\n";
+is render("hello\n%# die 'this is an harmless comment'\nworld"), "hello\nworld";

0 comments on commit e7ca9ea

Please sign in to comment.