Browse Source

added call custom tag (based on patch from Jeremey Latt) - not complete yet - test case missing

Roberto Saccon 17 years ago
parent
commit
e1c0e96b33
3 changed files with 56 additions and 12 deletions
  1. 37 3
      src/erlydtl/erlydtl_compiler.erl
  2. 18 8
      src/erlydtl/erlydtl_parser.yrl
  3. 1 1
      src/erlydtl/erlydtl_scanner.erl

+ 37 - 3
src/erlydtl/erlydtl_compiler.erl

@@ -246,7 +246,7 @@ body_ast(DjangoParseTree, Context, TreeWalker) ->
                 ifequalelse_ast(Args, IfAstInfo, ElseAstInfo, Context, TreeWalker2);                
             ({'ifnotequal', Args, Contents}, TreeWalkerAcc) ->
                 {IfAstInfo, TreeWalker1} = empty_ast(TreeWalkerAcc),
-                {ElseAstInfo, TreeWalker2} = body_ast(Contents, Context,TreeWalker1),
+                {ElseAstInfo, TreeWalker2} = body_ast(Contents, Context, TreeWalker1),
                 ifequalelse_ast(Args, IfAstInfo, ElseAstInfo, Context, TreeWalker2);
             ({'ifnotequalelse', Args, IfContents, ElseContents}, TreeWalkerAcc) ->
                 {IfAstInfo, TreeWalker1} = body_ast(ElseContents, Context, TreeWalkerAcc),
@@ -259,7 +259,11 @@ body_ast(DjangoParseTree, Context, TreeWalker) ->
             ({'load', Names}, TreeWalkerAcc) ->
                 load_ast(Names, Context, TreeWalkerAcc);
             ({'tag', {identifier, _, Name}, Args}, TreeWalkerAcc) ->
-                tag_ast(Name, Args, Context, TreeWalkerAcc)
+                tag_ast(Name, Args, Context, TreeWalkerAcc);            
+            ({'call', {'identifier', _, Name}}, TreeWalkerAcc) ->
+            	call_ast(Name, TreeWalkerAcc);
+            ({'call', {'identifier', _, Name}, {variable, With}}, TreeWalkerAcc) ->
+            	call_with_ast(Name, With, Context, TreeWalkerAcc)                
         end, TreeWalker, DjangoParseTree),   
     {AstList, {Info, TreeWalker3}} = lists:mapfoldl(
         fun({Ast, Info}, {InfoAcc, TreeWalkerAcc}) -> 
@@ -564,4 +568,34 @@ tag_ast(Name, Args, Context, TreeWalker) ->
  tag_ast2(Source, TagParseTree, InterpretedArgs, Context, TreeWalker) ->
     with_dependency(Source, body_ast(TagParseTree, Context#dtl_context{
         local_scopes = [ InterpretedArgs | Context#dtl_context.local_scopes ],
-        parse_trail = [ Source | Context#dtl_context.parse_trail ]}, TreeWalker)).
+        parse_trail = [ Source | Context#dtl_context.parse_trail ]}, TreeWalker)).
+
+
+call_ast(Module, TreeWalkerAcc) ->
+    call_ast(Module, erl_syntax:variable("Variables"), #ast_info{}, TreeWalkerAcc).
+
+call_with_ast(Module, Variable, Context, TreeWalker) ->
+    {VarAst, VarName} = resolve_variable_ast(Variable, Context),
+    call_ast(Module, VarAst, #ast_info{var_names=[VarName]}, TreeWalker).
+        
+call_ast(Module, Variable, AstInfo, TreeWalker) ->
+     AppAst = erl_syntax:application(
+		erl_syntax:atom(Module),
+		erl_syntax:atom(render),
+		[Variable]),
+    RenderedAst = erl_syntax:variable("Rendered"),
+    OkAst = erl_syntax:clause(
+	      [erl_syntax:tuple([erl_syntax:atom(ok), RenderedAst])], 
+	      none,
+	      [RenderedAst]),
+    ReasonAst = erl_syntax:variable("Reason"),
+    ErrStrAst = erl_syntax:application(
+		  erl_syntax:atom(io_lib),
+		  erl_syntax:atom(format),
+		  [erl_syntax:string("error: ~p"), erl_syntax:list([ReasonAst])]),
+    ErrorAst = erl_syntax:clause(
+		 [erl_syntax:tuple([erl_syntax:atom(error), ReasonAst])], 
+		 none,
+		 [ErrStrAst]),
+    CallAst = erl_syntax:case_expr(AppAst, [OkAst, ErrorAst]),
+    {{CallAst, AstInfo}, TreeWalker}.

+ 18 - 8
src/erlydtl/erlydtl_parser.yrl

@@ -82,11 +82,15 @@ Nonterminals
     LoadNames
     
     CustomTag
-    Args.
+    Args
+    
+    CallTag
+    CallWithTag.
 
 Terminals
     autoescape_keyword
     block_keyword
+    call_keyword
     close_tag
     close_var
     comment_keyword
@@ -117,7 +121,8 @@ Terminals
     open_var
     pipe
     string_literal
-    text.
+    text
+    with_keyword.
 
 Rootsymbol
     Elements.
@@ -128,7 +133,6 @@ Elements -> Elements VariableBraced : '$1' ++ ['$2'].
 Elements -> Elements ExtendsTag : '$1' ++ ['$2'].
 Elements -> Elements IncludeTag : '$1' ++ ['$2'].
 Elements -> Elements LoadTag : '$1' ++ ['$2'].
-Elements -> Elements CustomTag : '$1' ++ ['$2'].
 Elements -> Elements BlockBlock : '$1' ++ ['$2'].
 Elements -> Elements ForBlock : '$1' ++ ['$2'].
 Elements -> Elements IfBlock : '$1' ++ ['$2'].
@@ -136,6 +140,9 @@ Elements -> Elements IfEqualBlock : '$1' ++ ['$2'].
 Elements -> Elements IfNotEqualBlock : '$1' ++ ['$2'].
 Elements -> Elements AutoEscapeBlock : '$1' ++ ['$2'].
 Elements -> Elements CommentBlock : '$1' ++ ['$2'].
+Elements -> Elements CustomTag : '$1' ++ ['$2'].
+Elements -> Elements CallTag : '$1' ++ ['$2'].
+Elements -> Elements CallWithTag : '$1' ++ ['$2'].
 
 VariableBraced -> open_var Variable close_var : '$2'.
 
@@ -152,11 +159,6 @@ LoadTag -> open_tag load_keyword LoadNames close_tag : {load, '$3'}.
 LoadNames -> identifier : ['$1'].
 LoadNames -> LoadNames identifier : '$1' ++ ['$2'].
 
-CustomTag -> open_tag identifier Args close_tag : {tag, '$2', '$3'}.
-
-Args -> '$empty' : [].
-Args -> Args identifier equal Variable : '$1' ++ [{'$2', '$4'}].
-
 BlockBlock -> BlockBraced Elements EndBlockBraced : {block, '$1', '$2'}.
 BlockBraced -> open_tag block_keyword identifier close_tag : '$3'.
 EndBlockBraced -> open_tag endblock_keyword close_tag.
@@ -203,3 +205,11 @@ Filter -> identifier colon Literal : ['$1', '$3'].
 
 Literal -> string_literal : '$1'.
 Literal -> number_literal : '$1'.
+
+CustomTag -> open_tag identifier Args close_tag : {tag, '$2', '$3'}.
+
+Args -> '$empty' : [].
+Args -> Args identifier equal Variable : '$1' ++ [{'$2', '$4'}].
+
+CallTag -> open_tag call_keyword identifier close_tag : {call, '$3'}.
+CallWithTag -> open_tag call_keyword identifier with_keyword Variable close_tag: {call, '$3', '$5'}.

+ 1 - 1
src/erlydtl/erlydtl_scanner.erl

@@ -62,7 +62,7 @@ scan([], Scanned, _, in_text) ->
                             "not", "or", "and", "comment", "endcomment", "cycle", "firstof",
                             "ifchanged", "ifequal", "endifequal", "ifnotequal", "endifnotequal",
                             "now", "regroup", "spaceless", "endspaceless", "ssi", "templatetag",
-                            "load"], 
+                            "load", "call", "with"], 
                         Type = case lists:member(RevString, Keywords) of
                             true ->
                                 list_to_atom(RevString ++ "_keyword");