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

