Java tutorial
/** * jetbrick-template * http://subchen.github.io/jetbrick-template/ * * Copyright 2010-2014 Guoqiang Chen. All rights reserved. * Email: subchen@gmail.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.tinygroup.template.parser; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.misc.NotNull; import org.antlr.v4.runtime.misc.Nullable; import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.TerminalNode; import org.antlr.v4.runtime.tree.TerminalNodeImpl; import org.tinygroup.template.loader.ResourceCompilerUtils; import org.tinygroup.template.parser.grammer.TinyTemplateParser; import org.tinygroup.template.parser.grammer.TinyTemplateParserVisitor; import java.util.List; import java.util.Stack; // Visitor ??? Java ? public class TinyTemplateCodeVisitor extends AbstractParseTreeVisitor<CodeBlock> implements TinyTemplateParserVisitor<CodeBlock> { private static final String[] RESERVED_WORDS = { "set", "if", "elseif", "for", "foreach", "break", "continue", "stop", "include", "call", "layout", "macro", "b", "eol", "t", "bodyContent", "import" }; private TinyTemplateParser parser = null; private Stack<CodeBlock> codeBlocks = new Stack<CodeBlock>(); private Stack<CodeLet> codeLets = new Stack<CodeLet>(); private CodeBlock initCodeBlock = null; private CodeBlock macroCodeBlock = null; /** * ???trim() */ public static boolean strictFormat = false; public TinyTemplateCodeVisitor(TinyTemplateParser parser) { this.parser = parser; } public CodeBlock visitExpression_list(@NotNull TinyTemplateParser.Expression_listContext ctx) { List<TinyTemplateParser.ExpressionContext> expressionList = ctx.expression(); int i = 0; for (TinyTemplateParser.ExpressionContext expression : expressionList) { CodeLet exp = pushPeekCodeLet(); expression.accept(this); popCodeLet(); if (i > 0) { peekCodeLet().code(","); } peekCodeLet().code(exp); i++; } return null; } public CodeBlock visitInvalid_directive(@NotNull TinyTemplateParser.Invalid_directiveContext ctx) { throw reportError("Missing arguments for " + ctx.getText() + " directive.", ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine(), ctx); } public CodeBlock visitCall_directive(@NotNull TinyTemplateParser.Call_directiveContext ctx) { CodeBlock callMacro = processVisitCallHead(ctx.expression(), ctx.para_expression_list()); callMacro.subCode("$macro.render($template,$context,$newContext,$writer);"); return callMacro; } private CodeBlock processVisitCallHead(TinyTemplateParser.ExpressionContext macroName, TinyTemplateParser.Para_expression_listContext paraExpressionListContext) { CodeBlock callMacro = new CodeBlock(); CodeLet nameCodeBlock = pushPeekCodeLet(); macroName.accept(this); popCodeLet(); String name = nameCodeBlock.toString(); callMacro.subCode(String.format("$macro=getTemplateEngine().findMacro(%s,$template,$context);", name)); callMacro.subCode("$newContext=new TemplateContextDefault();"); callMacro.subCode("$paraList=new ArrayList();"); callMacro.subCode("$newContext.put(" + name + "+\"ParameterList\",$paraList);"); callMacro.subCode("$newContext.setParent($context);"); if (paraExpressionListContext != null) { List<TinyTemplateParser.Para_expressionContext> expList = paraExpressionListContext.para_expression(); if (expList != null) { pushCodeBlock(callMacro); int i = 0; for (TinyTemplateParser.Para_expressionContext visitParaExpression : expList) { processVisitPara(i, visitParaExpression, name); i++; } popCodeBlock(); } } return callMacro; } public CodeBlock visitElse_directive(@NotNull TinyTemplateParser.Else_directiveContext ctx) { CodeBlock elseBlock = new CodeBlock().subCode(new CodeLet().lineCode("}else{")).tabIndent(-1); peekCodeBlock().subCode(elseBlock); ctx.block().accept(this); return null; } public CodeBlock visitExpr_hash_map(@NotNull TinyTemplateParser.Expr_hash_mapContext ctx) { TinyTemplateParser.Hash_map_entry_listContext hashMapEntryListContext = ctx.hash_map_entry_list(); if (hashMapEntryListContext != null) { peekCodeLet().code("new TemplateMap()").code(hashMapEntryListContext.accept(this).toString()).code(""); } return null; } public CodeBlock visitContinue_directive(@NotNull TinyTemplateParser.Continue_directiveContext ctx) { TinyTemplateParser.ExpressionContext expression = ctx.expression(); processorConditionDirective(expression, "continue;"); return null; } public CodeBlock visitExpr_field_access(@NotNull TinyTemplateParser.Expr_field_accessContext ctx) { CodeLet exp = pushPeekCodeLet(); ctx.expression().accept(this); popCodeLet(); peekCodeLet().code(ctx.getChild(1).getText().equals("?.") ? "U.sp(" : "U.p(").code(exp).code(",\"") .code(ctx.IDENTIFIER().getText()).code("\")"); return null; } public CodeBlock visitExpr_compare_condition(@NotNull TinyTemplateParser.Expr_compare_conditionContext ctx) { CodeLet left = pushPeekCodeLet(); ctx.expression(0).accept(this); popCodeLet(); left.codeBefore("U.b(").code(")"); CodeLet right = pushPeekCodeLet(); ctx.expression(1).accept(this); popCodeLet(); right.codeBefore("U.b(").code(")"); String op = ctx.getChild(1).getText(); peekCodeLet().code(left).code(op).code(right); return null; } public CodeBlock visitExpr_function_call(@NotNull TinyTemplateParser.Expr_function_callContext ctx) { String functionName = ctx.getChild(0).getText(); peekCodeLet().codeBefore("getTemplateEngine().executeFunction($template,$context,\"").code(functionName) .code("\""); TinyTemplateParser.Expression_listContext list = ctx.expression_list(); if (list != null) { peekCodeLet().code(","); list.accept(this); } peekCodeLet().code(")"); return null; } public CodeBlock visitIndent_directive(@NotNull TinyTemplateParser.Indent_directiveContext ctx) { CodeBlock block = new CodeBlock(); block.subCode("U.indent($context);"); return block; } public CodeBlock visitMacro_directive(@NotNull TinyTemplateParser.Macro_directiveContext ctx) { String name = ctx.getChild(0).getText(); name = name.substring(6, name.length() - 1).trim(); //? boolean isReserve = false; for (String word : RESERVED_WORDS) { if (name.equals(word)) { TerminalNodeImpl terminalNode = (TerminalNodeImpl) ctx.getChild(0); throw new SyntaxErrorException("Macro name<" + name + "> is reserved word.", terminalNode.getSymbol().getLine(), terminalNode.getSymbol().getStartIndex()); } } name = ResourceCompilerUtils.getClassNameGetter().getClassName(name).getSimpleClassName(); initCodeBlock.subCode(new CodeLet().lineCode("addMacro(new %s());", name)); CodeBlock macro = new CodeBlock(); TinyTemplateParser.Define_expression_listContext defineExpressionListContext = ctx.define_expression_list(); pushPeekCodeLet(); if (defineExpressionListContext != null) { defineExpressionListContext.accept(this); } macro.header(new CodeLet().lineCode("class %s extends AbstractMacro {", name)); macro.footer(new CodeLet().lineCode("}")); macro.subCode(constructMethod(name)); popCodeLet(); CodeBlock render = getMacroRenderCodeBlock(); pushCodeBlock(render); macro.subCode(render); ctx.block().accept(this); popCodeBlock(); macroCodeBlock.subCode(macro); return null; } private CodeBlock constructMethod(String name) { CodeBlock block = new CodeBlock(); block.header(CodeLet.lineCodeLet("public %s() {", name)); block.subCode(String.format("super(\"%s\");", name)); block.subCode(peekCodeLet()); block.subCode(String.format("init(\"%s\");", name)); block.footer(CodeLet.lineCodeLet("}")); return block; } public CodeBlock visitExpr_compare_equality(@NotNull TinyTemplateParser.Expr_compare_equalityContext ctx) { peekCodeLet().code("O.e(\"").code(ctx.getChild(1).getText()).code("\","); ctx.expression(0).accept(this); peekCodeLet().code(","); ctx.expression(1).accept(this); peekCodeLet().code(")"); return null; } public CodeBlock visitValue(@NotNull TinyTemplateParser.ValueContext ctx) { CodeBlock valueCodeBlock = new CodeBlock(); pushCodeLet(); if (ctx.getChild(0).getText().equals("$${")) { peekCodeLet().code("write($writer,U.getI18n($template.getTemplateEngine().getI18nVistor(),$context,\"") .code(ctx.identify_list().getText()).lineCode("\"));"); } else { ctx.expression().accept(this); Token token = ((TerminalNode) ctx.getChild(0)).getSymbol(); if (token.getType() == TinyTemplateParser.VALUE_ESCAPED_OPEN) { peekCodeLet().codeBefore("U.escapeHtml((").code("))"); } peekCodeLet().codeBefore("write($writer,").lineCode(");"); } valueCodeBlock.subCode(peekCodeLet()); popCodeLet(); return valueCodeBlock; } public CodeBlock visitExpr_math_binary_bitwise( @NotNull TinyTemplateParser.Expr_math_binary_bitwiseContext ctx) { peekCodeLet().code("O.e(\"").code(ctx.getChild(1).getText()).code("\","); ctx.expression(0).accept(this); peekCodeLet().code(","); ctx.expression(1).accept(this); peekCodeLet().code(")"); return null; } public CodeBlock visitHash_map_entry_list(@NotNull TinyTemplateParser.Hash_map_entry_listContext ctx) { List<TinyTemplateParser.ExpressionContext> expressionContexts = ctx.expression(); CodeLet keyPair = new CodeLet(); CodeBlock result = new CodeBlock().subCode(keyPair); for (int i = 0; i < expressionContexts.size(); i += 2) { CodeBlock codeBlock = new CodeBlock(); CodeLet keyCodeLet = pushPeekCodeLet(); expressionContexts.get(i).accept(this); popCodeLet(); CodeLet valueCodeLet = pushPeekCodeLet(); expressionContexts.get(i + 1).accept(this); popCodeLet(); codeBlock.subCode(new CodeLet().code(keyCodeLet).code(":").code(valueCodeLet)); keyPair.code(".putItem(").code(keyCodeLet).code(",").code(valueCodeLet).code(")"); } return result; } public CodeBlock visitDirective(@NotNull TinyTemplateParser.DirectiveContext ctx) { return ctx.getChild(0).accept(this); } public CodeBlock visitDent_directive(@NotNull TinyTemplateParser.Dent_directiveContext ctx) { CodeBlock block = new CodeBlock(); block.subCode("U.dent($context);"); return block; } public CodeBlock visitTemplate(@NotNull TinyTemplateParser.TemplateContext ctx) { CodeBlock templateCodeBlock = getTemplateCodeBlock(); CodeBlock classCodeBlock = getClassCodeBlock(); templateCodeBlock.subCode(classCodeBlock); CodeBlock renderMethodCodeBlock = getTemplateRenderCodeBlock(); classCodeBlock.subCode(renderMethodCodeBlock); CodeBlock getTemplatePathMethod = getTemplatePathMethodCodeBlock(); classCodeBlock.subCode(getTemplatePathMethod); pushCodeBlock(renderMethodCodeBlock); renderMethodCodeBlock.subCode(ctx.block().accept(this)); popCodeBlock(); return templateCodeBlock; } private CodeBlock getTemplateRenderCodeBlock() { CodeBlock renderMethod = new CodeBlock(); renderMethod.header(new CodeLet().lineCode( "protected void renderContent(TemplateContext $context, Writer $writer) throws IOException, TemplateException{")) .footer(new CodeLet().lineCode("}")); renderMethod.subCode("Macro $macro=null;"); renderMethod.subCode("Macro $bodyMacro=null;"); renderMethod.subCode("Template $template=this;"); renderMethod.subCode("TemplateContext $pageContext=$context;"); renderMethod.subCode("TemplateContext $newContext=null;"); renderMethod.subCode("List $paraList=null;"); return renderMethod; } private CodeBlock getMacroRenderCodeBlock() { CodeBlock renderMethod = new CodeBlock(); renderMethod.header(new CodeLet().lineCode( "protected void renderMacro(Template $template,TemplateContext $pageContext, TemplateContext $context, Writer $writer) throws IOException, TemplateException{")) .footer(new CodeLet().lineCode("}")); renderMethod.subCode("Macro $macro=null;"); renderMethod.subCode("Macro $bodyMacro=null;"); renderMethod.subCode("TemplateContext $newContext=null;"); renderMethod.subCode("List $paraList=null;"); return renderMethod; } private CodeBlock getTemplatePathMethodCodeBlock() { CodeBlock renderMethod = new CodeBlock(); renderMethod.header(new CodeLet().lineCode("public String getPath(){")).footer(new CodeLet().lineCode("}")); renderMethod.subCode(new CodeLet().lineCode("return \"$TEMPLATE_PATH\";")); return renderMethod; } private CodeBlock getClassCodeBlock() { CodeBlock templateClass = new CodeBlock(); initCodeBlock = new CodeBlock().header(new CodeLet("{").endLine()).footer(new CodeLet("}").endLine()); templateClass.header(new CodeLet().lineCode("public class $TEMPLATE_CLASS_NAME extends AbstractTemplate{")); templateClass.subCode(initCodeBlock); macroCodeBlock = new CodeBlock(); templateClass.subCode(macroCodeBlock); templateClass.footer(new CodeLet().lineCode("}")); return templateClass; } private CodeBlock getTemplateCodeBlock() { CodeBlock codeBlock = new CodeBlock(); codeBlock.subCode(new CodeLet().lineCode("import java.io.IOException;")); codeBlock.subCode(new CodeLet().lineCode("import java.util.*;")); codeBlock.subCode(new CodeLet().lineCode("import org.tinygroup.template.rumtime.*;")); codeBlock.subCode(new CodeLet().lineCode("import org.tinygroup.template.*;")); codeBlock.subCode(new CodeLet().lineCode("import java.io.Writer;")); codeBlock.subCode(new CodeLet().lineCode("import org.tinygroup.template.impl.*;")); return codeBlock; } public CodeBlock visitIdentify_list(@NotNull TinyTemplateParser.Identify_listContext ctx) { return null; } public CodeBlock visitText(@NotNull TinyTemplateParser.TextContext ctx) { Token token = ((TerminalNode) ctx.getChild(0)).getSymbol(); String text = token.getText(); switch (token.getType()) { case TinyTemplateParser.TEXT_PLAIN: if (strictFormat) text = text.trim(); break; case TinyTemplateParser.TEXT_CDATA: text = text.substring(3, text.length() - 3); break; case TinyTemplateParser.TEXT_ESCAPED_CHAR: text = text.substring(1); break; default: break; } if (text.length() == 0) { return null; } return new CodeBlock().header(new CodeLet().code("write($writer,\"") .code(escapeJavaStyleString(text).toString()).lineCode("\");")); } private static StringBuffer escapeJavaStyleString(String str) { StringBuffer stringBuffer = new StringBuffer(); int sz; sz = str.length(); for (int i = 0; i < sz; i++) { char ch = str.charAt(i); switch (ch) { case '\b': escapeChar(stringBuffer, 'b'); break; case '\n': escapeChar(stringBuffer, 'n'); break; case '\t': escapeChar(stringBuffer, 't'); break; case '\f': escapeChar(stringBuffer, 'f'); break; case '\r': escapeChar(stringBuffer, 'r'); break; case '"': escapeChar(stringBuffer, '"'); break; case '\\': escapeChar(stringBuffer, '\\'); break; default: stringBuffer.append(ch); break; } } return stringBuffer; } private static void escapeChar(StringBuffer stringBuffer, char ch) { stringBuffer.append('\\'); stringBuffer.append(ch); } public CodeBlock visitExpr_identifier(@NotNull TinyTemplateParser.Expr_identifierContext ctx) { String name = ctx.IDENTIFIER().getText(); peekCodeLet().code("U.v($context,\"" + name + "\")"); return null; } public CodeBlock visitIf_directive(@NotNull TinyTemplateParser.If_directiveContext ctx) { CodeBlock ifCodeBlock = pushPeekCodeBlock(); pushCodeLet(); ctx.expression().accept(this); ifCodeBlock.header(peekCodeLet().codeBefore("if(U.b(").lineCode(")){")); popCodeLet(); ifCodeBlock.footer(new CodeLet().lineCode("}")); ctx.block().accept(this); List<TinyTemplateParser.Elseif_directiveContext> elseifDirectiveContexts = ctx.elseif_directive(); for (TinyTemplateParser.Elseif_directiveContext elseifDirectiveContext : elseifDirectiveContexts) { elseifDirectiveContext.accept(this); } TinyTemplateParser.Else_directiveContext elseDirectiveContext = ctx.else_directive(); if (elseDirectiveContext != null) { elseDirectiveContext.accept(this); } popCodeBlock(); return ifCodeBlock; } public CodeBlock visitLayout_directive(@NotNull TinyTemplateParser.Layout_directiveContext ctx) { String name = "$" + ctx.IDENTIFIER().getText(); CodeBlock positionCodeBlock = new CodeBlock(); positionCodeBlock.subCode("if($context.exist(\"" + name + "\")){"); positionCodeBlock.subCode(" write($writer,$context.get(\"" + name + "\"));"); positionCodeBlock.subCode("}else {"); positionCodeBlock.subCode(" new AbstractMacro(\"" + name + "\") {"); positionCodeBlock.subCode( " protected void renderMacro(Template $template, TemplateContext $context,TemplateContext $newContext, Writer $writer) throws IOException, TemplateException {"); CodeBlock subCodeBlock = pushPeekCodeBlock(); ctx.block().accept(this); popCodeBlock(); positionCodeBlock.subCode(subCodeBlock); positionCodeBlock.subCode(" }"); positionCodeBlock.subCode(" }.renderMacro($template, $context, $newContext,$writer);"); positionCodeBlock.subCode("}"); return positionCodeBlock; } // public CodeBlock visitExpr_math_unary_suffix(@NotNull TinyTemplateParser.Expr_math_unary_suffixContext ctx) { // peekCodeLet().code("O.e(\"l").code(ctx.getChild(1).getText()).code("\","); // ctx.expression().accept(this); // peekCodeLet().code(")"); // return null; // } public CodeBlock visitBodycontent_directive(@NotNull TinyTemplateParser.Bodycontent_directiveContext ctx) { CodeBlock codeBlock = new CodeBlock(); codeBlock.subCode("$macro= getMacro($context);"); codeBlock.subCode("if($macro!=null) {"); codeBlock.subCode(" $newContext=new TemplateContextDefault();"); codeBlock.subCode(" $newContext.setParent($context);"); codeBlock.subCode(" $macro.render($template,$context,$newContext,$writer);"); codeBlock.subCode("}"); return codeBlock; } public CodeBlock visitDefine_expression_list(@NotNull TinyTemplateParser.Define_expression_listContext ctx) { for (TinyTemplateParser.Define_expressionContext exp : ctx.define_expression()) { if (exp.expression() == null) { peekCodeLet().code("addParameter(\"%s\",null);", exp.IDENTIFIER().getText()); } else { peekCodeLet().code( "addParameter(\"%s\",new EvaluateExpression() {public Object evaluate(TemplateContext $context)throws TemplateException{return ", exp.IDENTIFIER().getText()); exp.expression().accept(this); peekCodeLet().code(";}});"); } } peekCodeLet().code("\n"); return null; } public CodeBlock visitCall_macro_directive(@NotNull TinyTemplateParser.Call_macro_directiveContext ctx) { CodeBlock callMacro = new CodeBlock(); String name = ctx.getChild(0).getText(); name = name.substring(1, name.length()); if (name.endsWith("(")) { name = name.substring(0, name.length() - 1).trim(); } if (name.equals("macro")) { TerminalNodeImpl terminalNode = (TerminalNodeImpl) ctx.getChild(0); throw new SyntaxErrorException("Missing macro name for #macro directive.", terminalNode.getSymbol().getLine(), terminalNode.getSymbol().getStartIndex()); } processCallMacro(ctx.para_expression_list(), callMacro, "\"" + name + "\""); callMacro.subCode(String.format("$macro.render($template,$context,$newContext,$writer);")); return callMacro; } public CodeBlock visitExpression_range(@NotNull TinyTemplateParser.Expression_rangeContext ctx) { return null; } public CodeBlock visitComment(@NotNull TinyTemplateParser.CommentContext ctx) { return null; } public CodeBlock visitCall_macro_block_directive( @NotNull TinyTemplateParser.Call_macro_block_directiveContext ctx) { CodeBlock callMacro = new CodeBlock(); String name = ctx.getChild(0).getText(); name = name.substring(2, name.length() - 1).trim(); processCallMacro(ctx.para_expression_list(), callMacro, "\"" + name + "\""); CodeBlock bodyContentMacro = new CodeBlock(); //callMacro.subCode("$bodyMacro= (Macro) $context.getItemMap().get(\"bodyContent\");"); //callMacro.subCode("if($bodyMacro==null){"); callMacro.subCode(bodyContentMacro); bodyContentMacro.header( "$bodyMacro=new AbstractMacro(\"bodyContent\",(Macro)$context.getItemMap().get(\"bodyContent\")) {"); CodeBlock render = getMacroRenderCodeBlock(); bodyContentMacro.subCode(render); pushCodeBlock(render); ctx.block().accept(this); popCodeBlock(); bodyContentMacro.footer("};"); callMacro.subCode("$newContext.put(\"bodyContent\",$bodyMacro);"); //callMacro.subCode("}"); callMacro.subCode("$bodyMacro.setTemplateEngine(this.getTemplateEngine());"); callMacro.subCode("$macro.render($template,$context,$newContext,$writer);"); //Body??? return callMacro; } private void processCallMacro(TinyTemplateParser.Para_expression_listContext listContext, CodeBlock callMacro, String name) { callMacro.subCode(String.format("$macro=getTemplateEngine().findMacro(%s,$template,$context);", name)); callMacro.subCode("$newContext=new TemplateContextDefault();"); callMacro.subCode("$paraList=new ArrayList();"); callMacro.subCode("$newContext.put(" + name + "+\"ParameterList\",$paraList);"); callMacro.subCode("$newContext.setParent($context);"); TinyTemplateParser.Para_expression_listContext expList = listContext; if (expList != null) { pushCodeBlock(callMacro); int i = 0; for (TinyTemplateParser.Para_expressionContext paraExpressionContext : expList.para_expression()) { processVisitPara(i, paraExpressionContext, name); i++; } popCodeBlock(); } } private void processVisitPara(int i, TinyTemplateParser.Para_expressionContext visitParaExpression, String name) { CodeLet expression = new CodeLet(); pushCodeLet(expression); if (visitParaExpression.getChildCount() == 3) { //? visitParaExpression.getChild(2).accept(this); peekCodeBlock().subCode(String.format("$newContext.put(\"%s\",%s);", visitParaExpression.getChild(0).getText(), expression)); } else { visitParaExpression.getChild(0).accept(this); peekCodeBlock() .subCode(String.format("$newContext.put($macro.getParameterName(%d),%s);", i, expression)); } peekCodeBlock().subCode( String.format("((List)$newContext.get(" + name + "+\"ParameterList\")).add(%s);", expression)); popCodeLet(); } public CodeBlock visitInclude_directive(@NotNull TinyTemplateParser.Include_directiveContext ctx) { CodeBlock include = new CodeBlock(); CodeLet path = pushPeekCodeLet(); ctx.expression().accept(this); popCodeLet(); CodeLet map = pushPeekCodeLet(); if (ctx.hash_map_entry_list() != null) { peekCodeLet().code("new TemplateMap()").code(ctx.hash_map_entry_list().accept(this).toString()) .code(""); } popCodeLet(); include.subCode("$newContext = new TemplateContextDefault();"); if (map.length() > 0) { include.subCode(String.format("$newContext.putAll(%s);", map)); } include.subCode("$context.putSubContext(\"$newContext\",$newContext);"); include.subCode(String.format( "getTemplateEngine().renderTemplateWithOutLayout(U.getPath(getPath(),%s),$newContext,$writer);", path)); include.subCode("$context.removeSubContext(\"$newContext\");"); return include; } public CodeBlock visitPara_expression(@NotNull TinyTemplateParser.Para_expressionContext ctx) { return null; } public CodeBlock visitTabs_directive(@NotNull TinyTemplateParser.Tabs_directiveContext ctx) { CodeBlock tab = new CodeBlock(); tab.subCode("write($writer,U.getBlanks($context));"); return tab; } public CodeBlock visitCall_block_directive(@NotNull TinyTemplateParser.Call_block_directiveContext ctx) { CodeBlock callMacro = processVisitCallHead(ctx.expression(), ctx.para_expression_list()); CodeBlock bodyContentMacro = new CodeBlock(); callMacro.subCode(bodyContentMacro); callMacro.subCode("$macro.render($template,$context,$newContext,$writer);"); bodyContentMacro.header( "$newContext.put(\"bodyContent\",new AbstractMacro(\"bodyContent\",(Macro)$context.getItemMap().get(\"bodyContent\")) {"); CodeBlock render = getMacroRenderCodeBlock(); bodyContentMacro.subCode(render); pushCodeBlock(render); ctx.block().accept(this); popCodeBlock(); bodyContentMacro.footer("});"); callMacro.subCode("$context.removeSubContext(\"$newContext\");"); //Body??? return callMacro; } public CodeBlock visitExpr_array_get(@NotNull TinyTemplateParser.Expr_array_getContext ctx) { ctx.expression(0).accept(this); if (ctx.children.get(1).getText().equals("?")) { peekCodeLet().codeBefore("U.sa(").code(","); } else { peekCodeLet().codeBefore("U.a(").code(","); } ctx.expression(1).accept(this); peekCodeLet().code(")"); return null; } public CodeBlock visitBlock(@NotNull TinyTemplateParser.BlockContext ctx) { for (int i = 0; i < ctx.getChildCount(); i++) { ParseTree node = ctx.children.get(i); CodeBlock codeBlock = node.accept(this); if (codeBlock != null) { peekCodeBlock().subCode(codeBlock); } } return null; } public CodeBlock visitExpr_compare_relational(@NotNull TinyTemplateParser.Expr_compare_relationalContext ctx) { peekCodeLet().code("O.e(\"").code(ctx.getChild(1).getText()).code("\","); ctx.expression(0).accept(this); peekCodeLet().code(","); ctx.expression(1).accept(this); peekCodeLet().code(")"); return null; } public CodeBlock visitExpr_math_binary_basic(@NotNull TinyTemplateParser.Expr_math_binary_basicContext ctx) { peekCodeLet().code("O.e(\"").code(ctx.getChild(1).getText()).code("\","); ctx.expression(0).accept(this); peekCodeLet().code(","); ctx.expression(1).accept(this); peekCodeLet().code(")"); return null; } public CodeBlock visitPara_expression_list(@NotNull TinyTemplateParser.Para_expression_listContext ctx) { return null; } public CodeBlock visitSet_expression(@NotNull TinyTemplateParser.Set_expressionContext ctx) { CodeBlock codeBlock = new CodeBlock(); CodeLet codeLet = pushPeekCodeLet(); codeBlock.header(codeLet); ctx.expression().accept(this); popCodeLet(); codeLet.codeBefore("$context.put(\"" + ctx.getChild(0).getText() + "\",").lineCode(");"); return codeBlock; } public CodeBlock visitTerminal(@org.antlr.v4.runtime.misc.NotNull org.antlr.v4.runtime.tree.TerminalNode node) { peekCodeLet().code(node.getText()); return null; } public CodeBlock visitSet_directive(@NotNull TinyTemplateParser.Set_directiveContext ctx) { List<TinyTemplateParser.Set_expressionContext> setExpressionContexts = ctx.set_expression(); for (TinyTemplateParser.Set_expressionContext node : setExpressionContexts) { CodeBlock codeBlock = new CodeBlock(); CodeLet codeLet = pushPeekCodeLet(); codeBlock.header(codeLet); node.getChild(2).accept(this); popCodeLet(); if (ctx.getChild(0).getText().equals("#set(")) { codeLet.codeBefore("$context.put(\"" + node.getChild(0) + "\",").lineCode(");"); } else { codeLet.codeBefore("$pageContext.put(\"" + node.getChild(0) + "\",").lineCode(");"); } peekCodeBlock().subCode(codeBlock); } return null; } public CodeBlock visitImport_directive(@NotNull TinyTemplateParser.Import_directiveContext ctx) { pushCodeBlock(initCodeBlock); pushCodeLet(); ctx.expression().accept(this); initCodeBlock.subCode(peekCodeLet().codeBefore("addImport(").lineCode(");")); popCodeLet(); popCodeBlock(); return null; } public CodeBlock visitConstant(@NotNull TinyTemplateParser.ConstantContext ctx) { return null; } public CodeBlock visitExpr_member_function_call( @NotNull TinyTemplateParser.Expr_member_function_callContext ctx) { CodeLet codeLet = new CodeLet(); pushCodeLet(codeLet); ctx.expression().accept(this); String functionName = ctx.IDENTIFIER().getText(); peekCodeLet().codeBefore( ctx.getChild(1).getText().equals(".") ? "U.c($template,$context," : "U.sc($template,$context,") .code(",\"").code(functionName).code("\""); TinyTemplateParser.Expression_listContext list = ctx.expression_list(); if (list != null) { peekCodeLet().code(","); list.accept(this); } peekCodeLet().code(")"); popCodeLet(); peekCodeLet().code(codeLet); return null; } public CodeBlock visitExpr_single_right(@NotNull TinyTemplateParser.Expr_single_rightContext ctx) { peekCodeLet().code("O.ce($context,\"").code(ctx.getChild(1).getText()).code("\",") .code("\"" + ctx.getChild(0).getText() + "\","); ctx.expression().accept(this); peekCodeLet().code(")"); return null; } public CodeBlock visitBlank_directive(@NotNull TinyTemplateParser.Blank_directiveContext ctx) { CodeBlock blank = new CodeBlock(); blank.subCode("write($writer,\" \");"); return blank; } public CodeBlock visitExpr_array_list(@NotNull TinyTemplateParser.Expr_array_listContext ctx) { if (ctx.expression_range() != null) { CodeLet startExp = pushPeekCodeLet(); ctx.expression_range().expression().get(0).accept(this); popCodeLet(); CodeLet endExp = pushPeekCodeLet(); ctx.expression_range().expression().get(1).accept(this); popCodeLet(); peekCodeLet().code("new RangeList(%s,%s)", startExp.toString(), endExp.toString()); } else { ParseTree items = ctx.getChild(1); for (int i = 0; i < items.getChildCount(); i++) { CodeLet tmp = pushPeekCodeLet(); items.getChild(i).accept(this); popCodeLet(); peekCodeLet().code(tmp); } peekCodeLet().codeBefore("new Object[]{").code("}"); } return null; } public CodeBlock visitLayout_impl_directive(@NotNull TinyTemplateParser.Layout_impl_directiveContext ctx) { String name = "$" + ctx.IDENTIFIER().getText(); CodeBlock positionCodeBlock = new CodeBlock(); positionCodeBlock.subCode("if(!$context.exist(\"" + name + "\")){"); positionCodeBlock.subCode(" Writer templateWriter = new java.io.CharArrayWriter();"); positionCodeBlock.subCode(" new AbstractMacro(\"" + name + "\") {"); positionCodeBlock.subCode( " protected void renderMacro(Template $template, TemplateContext $context, TemplateContext $newContext,Writer $writer) throws IOException, TemplateException {"); CodeBlock subCodeBlock = pushPeekCodeBlock(); ctx.block().accept(this); popCodeBlock(); positionCodeBlock.subCode(subCodeBlock); positionCodeBlock.subCode(" }"); positionCodeBlock.subCode(" }.renderMacro($template, $context, $newContext,templateWriter);"); positionCodeBlock.subCode(" $context.put(\"" + name + "\",templateWriter);"); positionCodeBlock.subCode("}"); return positionCodeBlock; } public CodeBlock visitExpr_single_left(@NotNull TinyTemplateParser.Expr_single_leftContext ctx) { peekCodeLet().code("O.ce($context,\"l").code(ctx.getChild(0).getText()).code("\",") .code("\"" + ctx.getChild(1).getText() + "\","); ctx.expression().accept(this); peekCodeLet().code(")"); return null; } public CodeBlock visitExpr_conditional_ternary( @NotNull TinyTemplateParser.Expr_conditional_ternaryContext ctx) { CodeLet condition = new CodeLet(); pushCodeLet(condition); ctx.expression(0).accept(this); popCodeLet(); CodeLet left = new CodeLet(); pushCodeLet(left); ctx.expression(1).accept(this); popCodeLet(); CodeLet right = new CodeLet(); pushCodeLet(right); ctx.expression(2).accept(this); popCodeLet(); peekCodeLet().code("U.b(%s)?%s:%s", condition, left, right); return null; } private RuntimeException reportError(String message, int col, int rol, Object node) { if (node instanceof ParserRuleContext) { parser.notifyErrorListeners(((ParserRuleContext) node).getStart(), message, null); } else if (node instanceof TerminalNode) { parser.notifyErrorListeners(((TerminalNode) node).getSymbol(), message, null); } else if (node instanceof Token) { parser.notifyErrorListeners((Token) node, message, null); } return new SyntaxErrorException(message, col, rol); } public CodeBlock visitFor_expression(@NotNull TinyTemplateParser.For_expressionContext ctx) { String name = ctx.IDENTIFIER().getText(); pushCodeLet(); ctx.expression().accept(this); peekCodeBlock().subCode(new CodeLet().code("$context.put(\"").code(name).code("For\",new ForIterator(") .code(peekCodeLet()).lineCode("));")); peekCodeBlock().subCode(new CodeLet().code("while(((ForIterator)$context.get(\"").code(name) .lineCode("For\")).hasNext()){")); CodeBlock assign = new CodeBlock().tabIndent(1); assign.footer(new CodeLet().code("$context.put(\"").code(name).code("\",((ForIterator)$context.get(\"") .code(name).lineCode("For\")).next());")).tabIndent(1); peekCodeBlock().subCode(assign); popCodeLet(); return null; } public CodeBlock visitDefine_expression(@NotNull TinyTemplateParser.Define_expressionContext ctx) { return null; } public CodeBlock visitExpr_math_binary_shift(@NotNull TinyTemplateParser.Expr_math_binary_shiftContext ctx) { peekCodeLet().code("O.e(\"").code(ctx.getChild(1).getText()).code("\","); ctx.expression(0).accept(this); peekCodeLet().code(","); ctx.expression(1).accept(this); peekCodeLet().code(")"); return null; } public CodeBlock visitEndofline_directive(@NotNull TinyTemplateParser.Endofline_directiveContext ctx) { peekCodeBlock().subCode("if(!getTemplateEngine().isCompactMode())write($writer,\"\\r\\n\");"); return null; } public CodeBlock visitStop_directive(@NotNull TinyTemplateParser.Stop_directiveContext ctx) { TinyTemplateParser.ExpressionContext expression = ctx.expression(); processorConditionDirective(expression, "return;"); return null; } public CodeBlock visitBreak_directive(@NotNull TinyTemplateParser.Break_directiveContext ctx) { TinyTemplateParser.ExpressionContext expression = ctx.expression(); processorConditionDirective(expression, "break;"); return null; } private void processorConditionDirective(TinyTemplateParser.ExpressionContext expression, String directive) { if (expression != null) { pushCodeLet(); expression.accept(this); CodeBlock ifCodeBlock = new CodeBlock().header(peekCodeLet().codeBefore("if(U.b(").lineCode(")){")) .footer(new CodeLet().lineCode("}")); popCodeLet(); ifCodeBlock.subCode(new CodeLet().lineCode(directive)); peekCodeBlock().subCode(ifCodeBlock); } else { peekCodeBlock().subCode(new CodeLet().lineCode("if(true)" + directive + ";")); } } public CodeBlock visitFor_directive(@NotNull TinyTemplateParser.For_directiveContext ctx) { String varName = ctx.getChild(1).getChild(0).getText(); ctx.for_expression().accept(this); CodeBlock forCodeBlock = new CodeBlock(); peekCodeBlock().subCode(forCodeBlock); forCodeBlock.footer(new CodeLet().lineCode("}")); pushCodeBlock(forCodeBlock); ctx.block().accept(this); popCodeBlock(); TinyTemplateParser.Else_directiveContext elseDirectiveContext = ctx.else_directive(); if (elseDirectiveContext != null) { CodeBlock elseCodeBlock = pushPeekCodeBlock() .header("if(U.b(((ForIterator)$context.get(\"" + varName + "For\")).getSize()==0)){") .footer("}"); elseDirectiveContext.block().accept(this); popCodeBlock(); peekCodeBlock().subCode(elseCodeBlock); } //?? return null; } void pushCodeBlock(CodeBlock codeBlock) { codeBlocks.push(codeBlock); } void pushCodeBlock() { pushCodeBlock(new CodeBlock()); } void popCodeBlock() { codeBlocks.pop(); } void popCodeLet() { codeLets.pop(); } void pushCodeLet(CodeLet codeLet) { codeLets.push(codeLet); } void pushCodeLet() { pushCodeLet(new CodeLet()); } CodeLet peekCodeLet() { return codeLets.peek(); } CodeLet pushPeekCodeLet() { pushCodeLet(); return codeLets.peek(); } CodeBlock peekCodeBlock() { return codeBlocks.peek(); } CodeBlock pushPeekCodeBlock() { pushCodeBlock(); return codeBlocks.peek(); } public CodeBlock visitElseif_directive(@NotNull TinyTemplateParser.Elseif_directiveContext ctx) { pushCodeLet(); ctx.expression().accept(this); CodeBlock elseifBlock = new CodeBlock().header(peekCodeLet().codeBefore("}else if(U.b(").lineCode(")){")) .tabIndent(-1); popCodeLet(); peekCodeBlock().subCode(elseifBlock); ctx.block().accept(this); return null; } public CodeBlock visitExpr_math_unary_prefix(@NotNull TinyTemplateParser.Expr_math_unary_prefixContext ctx) { peekCodeLet().code("O.e(\"l").code(ctx.getChild(0).getText()).code("\","); ctx.expression().accept(this); peekCodeLet().code(")"); return null; } public CodeBlock visitExpr_group(@NotNull TinyTemplateParser.Expr_groupContext ctx) { peekCodeLet().code("("); ctx.expression().accept(this); peekCodeLet().code(")"); return null; } public CodeBlock visitExpr_constant(@NotNull TinyTemplateParser.Expr_constantContext ctx) { String text = ctx.getText(); if (text.startsWith("\'")) { text = text.substring(1, text.length() - 1); text = text.replaceAll("\\\\'", "'"); text = text.replaceAll("\\\\\"", "\""); text = text.replaceAll("\"", "\\\\\""); peekCodeLet().code("\"").code(text).code("\""); } else { peekCodeLet().code(text); } return null; } public CodeBlock visitExpr_simple_condition_ternary( @NotNull TinyTemplateParser.Expr_simple_condition_ternaryContext ctx) { peekCodeLet().code("O.e(\"").code(ctx.getChild(1).getText()).code("\","); ctx.expression(0).accept(this); peekCodeLet().code(","); ctx.expression(1).accept(this); peekCodeLet().code(")"); return null; } }