Zhiqim Markup Language是知启蒙定义的、类似于JavaJavascript语法的语句和表达式,通常和XML/HTML混编在一起形成的一种新的标记语言。 ZML力求简单易用,目前支持常用的十二种标记语句和五十种表达式,在知启蒙技术体系中被用来代替JSP。

森中灵 最后提交于1年前 整理V8.0.6
StatementParser.java28KB
/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙,邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_zml.htm
 *
 * Zhiqim Zml is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.zml;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.zhiqim.kernel.constants.SignConstants;
import org.zhiqim.kernel.util.Classes;
import org.zhiqim.kernel.util.Strings;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.zml.exception.StatementException;
import org.zhiqim.zml.statement._Break;
import org.zhiqim.zml.statement._Call;
import org.zhiqim.zml.statement._Comment;
import org.zhiqim.zml.statement._Continue;
import org.zhiqim.zml.statement._Top;
import org.zhiqim.zml.statement._Echo;
import org.zhiqim.zml.statement._For;
import org.zhiqim.zml.statement._Format;
import org.zhiqim.zml.statement._Function;
import org.zhiqim.zml.statement._If;
import org.zhiqim.zml.statement._Include;
import org.zhiqim.zml.statement._Interceptor;
import org.zhiqim.zml.statement._Return;
import org.zhiqim.zml.statement._Text;
import org.zhiqim.zml.statement._Var;

/**
 * 语句解析静态类
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
public class StatementParser implements ZmlConstants, SignConstants
{
    /**
     * 解析全局定义文件,得到函数列表
     * 
     * @param zml                   全局定义文件
     * @param _functionList         函数列表
     * @param _varList              变量列表
     * @param _includeList          包含列表
     * @throws StatementException   语句异常
     */
    public static void parseContextZml(Zml zml, List<_Function> _functionList, List<_Var> _varList, List<_Include> _includeList) throws StatementException
    {
        List<_Function> functionList = getStatementOutLineAndNesting(zml, _Function.class, FUNCTION, FUNCTION_BEGIN, FUNCTION_END);
        List<_Comment> commentList = getStatementOutLineAndNesting(zml, _Comment.class, COMMENT, COMMENT_BEGIN, COMMENT_END);
        
        List<_Var> varList = getStatementListInLine(zml, _Var.class, VAR, VAR_BEGIN, VAR_END);
        List<_Include> includeList = getStatementListInLine(zml, _Include.class, INCLUDE, INCLUDE_BEGIN, INCLUDE_END);
        
        for (Iterator<_Function> it=functionList.iterator();it.hasNext();)
        {
            _Function _function = it.next();
            if (isInCommentStatement(_function, commentList))
            {//_function在comment中,则删除该function
                it.remove();
            }
        }
        
        for (Iterator<_Var> it=varList.iterator();it.hasNext();)
        {
            _Var _var = it.next();
            if (isInFunctionStatement(_var, functionList) || isInCommentStatement(_var, commentList))
            {//_var在function或comment里,则删除该var
                it.remove();
            }
        }
        
        for (Iterator<_Include> it=includeList.iterator();it.hasNext();)
        {
            _Include _include = it.next();
            if (isInFunctionStatement(_include, functionList) || isInCommentStatement(_include, commentList))
            {//_include在function或comment则删除该<#include>
                it.remove();
            }
        }
        
        _functionList.addAll(functionList);
        _varList.addAll(varList);
        _includeList.addAll(includeList);
    }
    
    /**
     * 解析ZML中的第一层的嵌套,得到嵌套列表,第一层以下的嵌套的在第一层嵌套中递归处理
     * 
     * @param nesting               嵌套ZML或嵌套语句
     * @return                      得到第一层的嵌套列表
     * @throws StatementException   语句异常
     */
    public static List<Statement> parseStatementNesting(StatementNesting nesting) throws StatementException
    {
        //第一步,得到除_Text外的所有语句
        List<_Function> functionList = getStatementOutLineAndNesting(nesting, _Function.class, FUNCTION, FUNCTION_BEGIN, FUNCTION_END);
        List<_For> forList = getStatementOutLineAndNesting(nesting, _For.class, FOR, FOR_BEGIN, FOR_END);
        List<_If> ifList = getStatementOutLineAndNesting(nesting, _If.class, IF, IF_BEGIN, IF_END);
        List<_Comment> commentList = getStatementOutLineAndNesting(nesting, _Comment.class, COMMENT, COMMENT_BEGIN, COMMENT_END);
        
        List<_Include> includeList = getStatementListInLine(nesting, _Include.class, INCLUDE, INCLUDE_BEGIN, INCLUDE_END);
        List<_Interceptor> interceptorList = getStatementListInLine(nesting, _Interceptor.class, INTERCEPTOR, INTERCEPTOR_BEGIN, INTERCEPTOR_END);
        List<_Var> varList = getStatementListInLine(nesting, _Var.class, VAR, VAR_BEGIN, VAR_END);
        List<_Top> topList = getStatementListInLine(nesting, _Top.class, TOP, TOP_BEGIN, TOP_END);
        List<_Echo> echoList = getStatementListInLine(nesting, _Echo.class, ECHO, ECHO_BEGIN, ECHO_END);
        List<_Format> formatList = getStatementListInLine(nesting, _Format.class, FORMAT, FORMAT_BEGIN, FORMAT_END);
        List<_Call> callList = getStatementListInLine(nesting, _Call.class, CALL, CALL_BEGIN, CALL_END);
        List<_Return> returnList = getStatementListInLine(nesting, _Return.class, RETURN, RETURN_BEGIN, RETURN_END);
        List<_Break> breakList = getStatementListInLine(nesting, _Break.class, BREAK, BREAK_BEGIN, BREAK_END);
        List<_Continue> continueList = getStatementListInLine(nesting, _Continue.class, CONTINUE, CONTINUE_BEGIN, CONTINUE_END);
        
        //第二步,去掉孙语句,得到ZML的第一层子语句
        for (Iterator<_Return> it=returnList.iterator();it.hasNext();)
        {
            _Return _return = it.next();
            if (isInFunctionStatement(_return, functionList) || isInForStatement(_return, forList) || isInIfStatement(_return, ifList) || isInCommentStatement(_return, commentList))
            {//_return在function,for,if或comment则删除该<#include>
                it.remove();
            }
        }
        
        for (Iterator<_Break> it=breakList.iterator();it.hasNext();)
        {
            _Break _break = it.next();
            if (isInFunctionStatement(_break, functionList) || isInForStatement(_break, forList) || isInIfStatement(_break, ifList) || isInCommentStatement(_break, commentList))
            {//_break在function,for,if或comment则删除该<#include>
                it.remove();
            }
        }
        
        for (Iterator<_Continue> it=continueList.iterator();it.hasNext();)
        {
            _Continue _continue = it.next();
            if (isInFunctionStatement(_continue, functionList) || isInForStatement(_continue, forList) || isInIfStatement(_continue, ifList) || isInCommentStatement(_continue, commentList))
            {//_continue在function,for,if或comment则删除该<#continue>
                it.remove();
            }
        }
        
        for (Iterator<_Include> it=includeList.iterator();it.hasNext();)
        {
            _Include _include = it.next();
            if (isInFunctionStatement(_include, functionList) || isInForStatement(_include, forList) || isInIfStatement(_include, ifList) || isInCommentStatement(_include, commentList))
            {//_include在function,for,if或comment则删除该<#include>
                it.remove();
            }
        }
        
        for (Iterator<_Var> it=varList.iterator();it.hasNext();)
        {
            _Var _var = it.next();
            if (isInFunctionStatement(_var, functionList) || isInForStatement(_var, forList) || isInIfStatement(_var, ifList) || isInCommentStatement(_var, commentList))
            {//_var在function,for,if或comment里,则删除该var
                it.remove();
            }
        }
        
        for (Iterator<_Top> it=topList.iterator();it.hasNext();)
        {
            _Top _top = it.next();
            if (isInFunctionStatement(_top, functionList) || isInForStatement(_top, forList) || isInIfStatement(_top, ifList) || isInCommentStatement(_top, commentList))
            {//_top在function,for,if或comment里,则删除该top
                it.remove();
            }
        }
        
        for (Iterator<_Echo> it=echoList.iterator();it.hasNext();)
        {
            _Echo _echo = it.next();
            if (isInFunctionStatement(_echo, functionList) || isInForStatement(_echo, forList) || isInIfStatement(_echo, ifList) || isInCommentStatement(_echo, commentList))
            {//_echo在function,for,if或comment里,则删除该${}
                it.remove();
            }
        }
        
        for (Iterator<_Format> it=formatList.iterator();it.hasNext();)
        {
            _Format _format = it.next();
            if (isInFunctionStatement(_format, functionList) || isInForStatement(_format, forList) || isInIfStatement(_format, ifList) || isInCommentStatement(_format, commentList))
            {//_format在function,for,if或comment里,则删除该#{}
                it.remove();
            }
        }
        
        for (Iterator<_Call> it=callList.iterator();it.hasNext();)
        {
            _Call _call = it.next();
            if (isInFunctionStatement(_call, functionList) || isInForStatement(_call, forList) || isInIfStatement(_call, ifList) || isInCommentStatement(_call, commentList))
            {//_call在function,for,if或comment里,则删除该@{}
                it.remove();
            }
        }
        
        for (Iterator<_Function> it=functionList.iterator();it.hasNext();)
        {
            _Function _function = it.next();
            if (isInIfStatement(_function, ifList) || isInForStatement(_function, forList) || isInCommentStatement(_function, commentList))
            {//_function在if,for或comment中,则删除该function
                it.remove();
            }
        }
        
        for (Iterator<_If> it=ifList.iterator();it.hasNext();)
        {
            _If _if = it.next();
            if (isInFunctionStatement(_if, functionList) || isInForStatement(_if, forList) || isInCommentStatement(_if, commentList))
            {//_if在function,for或comment中,则删除该if
                it.remove();
            }
        }
        
        for (Iterator<_For> it=forList.iterator();it.hasNext();)
        {
            _For _for = it.next();
            if (isInFunctionStatement(_for, functionList) || isInIfStatement(_for, ifList) || isInCommentStatement(_for, commentList))
            {//_for在function,if或comment中,则删除该for
                it.remove();
            }
        }
        
        //第三步,把<#for>、<#if>、<#include>、<#var>和${}整理到一个列表中,并把未在列表中的,使用_Text加入填充
        ArrayList<Statement> statementList = new ArrayList<Statement>();
        statementList.addAll(functionList);
        statementList.addAll(forList);
        statementList.addAll(ifList);
        statementList.addAll(commentList);
        statementList.addAll(includeList);
        statementList.addAll(interceptorList);
        statementList.addAll(varList);
        statementList.addAll(topList);
        statementList.addAll(echoList);
        statementList.addAll(formatList);
        statementList.addAll(callList);
        statementList.addAll(returnList);
        statementList.addAll(breakList);
        statementList.addAll(continueList);
        statementList.trimToSize();
        Collections.sort(statementList, Statement.COMPARATOR);
        
        //把未在语句中的HTML转化成_Text补全到语句列表中
        if (statementList.isEmpty())
        {//如果没有一条语句,则全是html
            String content = nesting.getContent();
            _Text _txt = new _Text();
            _txt.setStatement(nesting.getZml(), nesting, content);
            _txt.setIndexInner(0, content.length());
            _txt.setIndexAll(nesting.getContentBeginIndex(), nesting.getContentBeginIndex() + content.length());
            
            List<Statement> tsList = new ArrayList<Statement>(1);
            tsList.add(_txt);
            return tsList;
        }
        else
        {
            ArrayList<Statement> tsList = new ArrayList<Statement>(statementList.size()*2);
            
            //第一个
            String content = nesting.getContent();
            Statement lastTs = statementList.get(0);
            if (lastTs.getBeginIndex() > 0)
            {
                String statement = content.substring(0, lastTs.getInnerBeginIndex());
                if (!Validates.isEmpty(statement))
                {
                    _Text _txt = new _Text();
                    _txt.setStatement(nesting.getZml(), nesting, statement);
                    _txt.setIndexInner(0, lastTs.getInnerBeginIndex());
                    _txt.setIndexAll(nesting.getContentBeginIndex(), nesting.getContentBeginIndex() + lastTs.getInnerBeginIndex());
                    
                    tsList.add(_txt);
                }
            }
            tsList.add(lastTs);
            
            //中间的
            for (int i=1;i<statementList.size();i++)
            {
                Statement ts = statementList.get(i);
                if (ts.getBeginIndex() > lastTs.getEndIndex())
                {
                    String statement = content.substring(lastTs.getInnerEndIndex(), ts.getInnerBeginIndex());
                    if (!Validates.isEmpty(statement))
                    {
                        _Text _txt = new _Text();
                        _txt.setStatement(nesting.getZml(), nesting, statement);
                        _txt.setIndexInner(lastTs.getInnerEndIndex(), ts.getInnerBeginIndex());
                        _txt.setIndexAll(nesting.getContentBeginIndex() + lastTs.getInnerEndIndex(), nesting.getContentBeginIndex() + ts.getInnerBeginIndex());
                        
                        tsList.add(_txt);
                    }
                }
                
                tsList.add(ts);
                lastTs = ts;
            }
            
            //最后一个
            if (lastTs.getInnerEndIndex() < content.length())
            {
                String statement = content.substring(lastTs.getInnerEndIndex(), content.length());
                if (!Validates.isEmpty(statement))
                {
                    _Text _txt = new _Text();
                    _txt.setStatement(nesting.getZml(), nesting, statement);
                    _txt.setIndexInner(lastTs.getInnerEndIndex(), content.length());
                    _txt.setIndexAll(nesting.getContentBeginIndex() + lastTs.getInnerEndIndex(), nesting.getContentBeginIndex() + content.length());
                    
                    tsList.add(_txt);
                }
            }
            
            tsList.trimToSize();
            return tsList;
        }
    }
    
    /**
     * 获取指定语句类型,且语句类型一行不能表达的语句,且可能存在嵌套的语句列表
     * 
     * @see _If                     判断语句,里面可能还有判断,如<#if a = "a"><#if b = "b">bb</#if></#if>
     * @see _For                    循环语句,里面可能还有循环,如<#for item : list><#for sub : item.list()>${sub}</#for></#for>
     * 
     * @param nesting               嵌套ZML对象或嵌套语句,Zml,_Include,_If,_For,_Function等
     * @param cls                   语句类
     * @param name                  语句名称
     * @param begin                 语句起始标志
     * @param end                   语句结束标志
     * @return                      得到嵌套语句列表,如_If,_For
     * @throws StatementException   语句异常
     */
    public static <T> List<T> getStatementOutLineAndNesting(StatementNesting nesting, Class<T> cls, String name, String begin, String end) throws StatementException
    {
        String content = nesting.getContent();
        List<ZmlLineIndex> indexList = nesting.getIndexList();
        
        int indBegin = 0, indEnd = 0;
        ArrayList<T> statementList = new ArrayList<T>();
        while(true)
        {
            indBegin = content.indexOf(begin, indEnd);
            if (indBegin == -1)
                break;
            
            int indBeginTemp = indBegin;int indNest = indBegin;
            while(true)
            {
                int indEndTemp = content.indexOf(end, indBeginTemp);
                if (indEndTemp == -1)
                {
                    int[] begins = getLineColumnNoByIndex(indexList, indBegin + nesting.getContentBeginIndex());
                    throw new StatementException(nesting.getPath(), begins[0], begins[1], "检查"+name+"时未找到"+end+"结尾");
                }
                
                //查看下一个开始是否嵌套
                indNest = content.indexOf(begin, indNest+begin.length());
                if (indNest == -1 || indNest > indEndTemp)
                {//未找到下一个开始或下一个对在结束之后,表示没有嵌套
                    indEnd = indEndTemp + end.length();
                    break;
                }
                else
                {//找到了,并且小于结束,则该开始和结束成对,是嵌套,那么设置开始为结束之后继续查找
                    indBeginTemp = indEndTemp + end.length();
                }
            }
            
            String statement = content.substring(indBegin, indEnd);
            T obj = Classes.newInstance(cls);
            Statement stmt = (Statement)obj;
            stmt.setStatement(nesting.getZml(), nesting, statement);
            stmt.setIndexInner(indBegin, indEnd);
            stmt.setIndexAll(nesting.getContentBeginIndex() + indBegin, nesting.getContentBeginIndex() + indEnd);
            stmt.parseStatement();
            statementList.add(obj);
        }
        
        return statementList;
    }
    
    /**
     * 获取指定语句类型,且语句类型一行即可表达的语句列表
     * 
     * @see _Echo                   表达式语句,格式如:${obj.getName()}
     * @see _Var                    变量语句,格式如:<#var abc="ddd"/>
     * @see _Include                包含语句,格式如:<#include "/zview/include.zml"/>
     * 
     * @param nesting               嵌套ZML对象或嵌套语句,Zml,_Include,_Interceptor,_If,_For,_Function等
     * @param cls                   语句类
     * @param name                  语句名称
     * @param begin                 语句起始标志
     * @param end                   语句结束标志
     * @return                      得到非嵌套语句列表
     * @throws StatementException   语句异常
     */
    public static <T> List<T> getStatementListInLine(StatementNesting nesting, Class<T> cls, String name, String begin, String end) throws StatementException
    {
        String content = nesting.getContent();
        List<ZmlLineIndex> indexList = nesting.getIndexList();

        int indBegin = 0, indEnd = 0;
        ArrayList<T> list = new ArrayList<T>();
        while(true)
        {
            indBegin = content.indexOf(begin, indEnd);
            if (indBegin == -1)
                break;
            
            int indBeginEnd = indBegin;
            while (true)
            {//对end("/>"和"}")简单检查从indBegin到indEnd是否双引号成对,如果不成对则认为在字符串中,继续向后找,直到结束
                indEnd = content.indexOf(end, indBeginEnd);
                if (indEnd == -1)
                {
                    int[] begins = getLineColumnNoByIndex(indexList, indBegin + nesting.getContentBeginIndex());
                    throw new StatementException(nesting.getPath(), begins[0], begins[1], "检查"+name+"时未找到"+end+"结尾");
                }
                
                int times = getTimes(content, '\"', indBegin, indEnd);
                if (times % 2 == 0)
                    break;
                
                //不成对,跳过end再找
                indBeginEnd += end.length();
            }
            
            indEnd = indEnd + end.length();
            int[] begins = getLineColumnNoByIndex(indexList, indBegin + nesting.getContentBeginIndex());
            int[] ends = getLineColumnNoByIndex(indexList, indEnd + nesting.getContentBeginIndex());
            if (begins[0] != ends[0])
                throw new StatementException(nesting.getPath(), begins[0], begins[1], "检查"+name+"时找到"+end+"不在同一行");
            
            String statement = content.substring(indBegin, indEnd);
            T obj = Classes.newInstance(cls);
            Statement stmt = (Statement)obj;
            stmt.setStatement(nesting.getZml(), nesting, statement);
            stmt.setIndexInner(indBegin, indEnd);
            stmt.setIndexAll(nesting.getContentBeginIndex() + indBegin, nesting.getContentBeginIndex() + indEnd);
            stmt.parseStatement();
            list.add(obj);
        }
        
        list.trimToSize();
        return list;
    }
    
    /**
     * 指定内容,得到每行的起始和结尾在内容的总索引位置列表
     * 
     * @param content 需要指定的内容
     * @return List<ZmlLineIndex> 行索引号列表
     */
    public static List<ZmlLineIndex> getIndexList(String content)
    {
        int index = 0, lineNo = 0;
        ArrayList<ZmlLineIndex> indexList = new ArrayList<ZmlLineIndex>();
        StringTokenizer tokener = new StringTokenizer(content, _BR_, true);
        while(tokener.hasMoreTokens())
        {//注意转化为第一行开始
            String line = tokener.nextToken();
            if (_LN_.equals(line) || _LR_.equals(line))
            {//空行不加入
                index++;
                continue;
            }
            
            lineNo++;
            ZmlLineIndex lineIndex = new ZmlLineIndex();
            lineIndex.setLineNo(lineNo);
            lineIndex.setBeginIndex(index);
            
            index += line.length();
            lineIndex.setEndIndex(index);
            indexList.add(lineIndex);
        }
        
        indexList.trimToSize();
        return indexList;
    }
    
    /**
     * 指定行索引号列表和索引号,取得该索引号对应的行列号
     * 
     * @param indexList 行索引列表
     * @param index     当前行号
     * @return          得到当前行号对应的行列号
     */
    public static int[] getLineColumnNoByIndex(List<ZmlLineIndex> indexList, int index)
    {
        int lineNo = -1,columnNo = -1;
        for (ZmlLineIndex lineIndex : indexList)
        {
            lineNo = lineIndex.getLineNo(index);
            if (lineNo == -1)
                continue;
            
            columnNo = lineIndex.getColumnNo(index);
            break;
        }
        
        return new int[]{lineNo, columnNo};
    }
    
    /** 是否其语语句嵌套在<#if>语句中 */
    public static boolean isInFunctionStatement(Statement ts, List<_Function> functionList)
    {
        for (_Function _function : functionList)
        {
            if (ts.getBeginIndex() <= _function.getBeginIndex())
                continue;//<#var>在<#function之前
            
            if (ts.getEndIndex() >= _function.getEndIndex())
                continue;//<#var>在</#function>之后
            
            //<#var>在<#function之间
            return true;
        }
        
        return false;
    }
    
    /** 是否其语语句嵌套在<#if>语句中 */
    public static boolean isInIfStatement(Statement ts, List<_If> ifList)
    {
        for (_If _if : ifList)
        {
            if (ts.getBeginIndex() <= _if.getBeginIndex())
                continue;//ts在<#if之前
            
            if (ts.getEndIndex() >= _if.getEndIndex())
                continue;//ts在</#if>之后
            
            //ts在<#if>在</#if>之间
            return true;
        }
        
        return false;
    }
    
    /** 是否其语语句嵌套在<#for>语句中 */
    public static boolean isInForStatement(Statement ts, List<_For> forList)
    {
        for (_For _for : forList)
        {
            if (ts.getBeginIndex() < _for.getBeginIndex())
                continue;//ts在<#for之前
            
            if (ts.getEndIndex() > _for.getEndIndex())
                continue;//ts在</#for>之后
            
            //ts在<#for>在</#for>之间
            return true;
        }
        
        return false;
    }
    
    /** 是否其语语句嵌套在<#---->语句中 */
    public static boolean isInCommentStatement(Statement ts, List<_Comment> commentList)
    {
        for (_Comment _comment : commentList)
        {
            if (ts.getBeginIndex() <= _comment.getBeginIndex())
                continue;//<#var>在<#--之前
            
            if (ts.getEndIndex() >= _comment.getEndIndex())
                continue;//<#var>在-->之后
            
            //<#var>在<#-->之间
            return true;
        }
        
        return false;
    }
       
    /** 判断是否含有定义变量语句 */
    public static boolean hasVar(List<Statement> stList)
    {
        for (Statement st : stList)
        {
            if (st instanceof _Var)
                return true;
        }
        return false;
    }
    
    public static void processStatementList(List<Statement> statementList, ZmlVariable variableMap, StringBuilder strb) throws StatementException
    {
        Statement last = null;
        for (Statement stmt : statementList)
        {
            if (stmt instanceof _Return)
            {//处理return,可能是返回值
                last = stmt;
                throw new _Return.ReturnException(((_Return)stmt).build(variableMap));
            }
            else if (stmt instanceof _Break)
            {//处理break;
                last = stmt;
                _For _for = stmt.getNearestNestingFor();
                if (_for != null)
                {//找到嵌套的_For抛异常到_For处理,跳过中间的所有环节
                    throw new _Break.BreakException();
                }
            }
            else if (stmt instanceof _Continue)
            {//处理continue;
                last = stmt;
                _For _for = stmt.getNearestNestingFor();
                if (_for != null)
                {//找到嵌套的_For抛异常到_For处理,跳过中间的所有环节
                    throw new _Continue.ContinueException();
                }
            }
            else
            {//正常语句
                String text = stmt.process(variableMap);
                if (Validates.isEmpty(text))
                {//为null和为空不写入,如_Var,或者结果是空字符串
                    if (stmt.isExclusiveLine())
                    {//如果是独占一行,则删除独占行
                        Zmls.removeRightMaybeEmptyBlankLine(strb);
                    }
                }
                else
                {
                    if (stmt.isNesting() && stmt.isExclusiveLine())
                    {//删除独占行前的空白,如_For,_If,保留\r\n
                        Zmls.removeRightMaybeEmptyBlank(strb);
                    }
                    
                    if ((stmt instanceof _Text) && strb.length() == 0 && last != null && last.isExclusiveLine())
                    {//首行文本时,检查前面是否有独占行的语句,有则删除多余的第一个\r\n
                        text = Strings.trimLeftOneBR(text);
                    }
                    
                    strb.append(text);
                }
                
                last = stmt;
            }
        }
    }
    
    /** 获取一个字符在字符串出现的次数 */
    public static int getTimes(String src, char c, int begin, int end)
    {
        int times = 0;
        for (int i=begin;i<src.length() && i < end;i++)
        {
            if (c == src.charAt(i))
                times++;
        }
        
        return times;
    }
}